-
v0.35.0
StableTest / test (push) Successful in 2m26sRelease / gates (push) Successful in 2m25sRelease / build (amd64, linux) (push) Successful in 1m15sRelease / build (arm64, linux) (push) Successful in 1m16sRelease / build (loong64, linux) (push) Successful in 1m16sRelease / build (riscv64, linux) (push) Successful in 1m16sRelease / release (push) Successful in 34sreleased this
2026-09-21 23:33:11 +00:00 | 0 commits to main since this releaseAdded
- The go_asm.h generator.
gasm asmgenerates the package's go_asm.h
itself when an assembly file includes it: the Go files beside the source
are type-checked for the target architecture and the constants and field
offsets become assembler defines, so package-context files assemble with
no compiler and nogo buildin the loop.-GOOSselects the
type-checking GOOS for GOOS-specific files, and the corpus audit derives
the GOOS from the file name. - ELF data relocations on arm64, riscv64 and loong64.
gasm asm --format elfemits.rela.datafor symbol-valued DATA initialisers on
every architecture (amd64 carried them already), so standalone ELF
objects link on all four targets. - Corpus failure listing.
gasm audit-instructions --corpus --list
prints every failing file with its failure reason, per architecture,
instead of one representative file per reason. - DATA with symbol values and relaxed symbol spellings. DATA
initialisers accept$symbol(SB)values, laid down as an absolute
relocation at the data field (GOOBJ on all four architectures and ELF
on all four as of this release), and U+2215 is accepted inside symbol
package paths. - Macro expansion and include splicing.
gasm asm,gasm diffand
gasm audit-instructionsnow preprocess assembly the way the
toolchain does: object and parameterised#definemacros expand at
the point of use,#undefand the#ifdef/#ifndef/#else/
#endiffamily select branches,#includesplices headers resolved
through the source directory and the new repeatable-Iflag,;
separates statements, and constant expressions left in operands
($(32-7),$~63,(index*4)(base)) fold at parse. Expansion
happens only on the assembly path:gasm lint,gasm fmtand the
language server keep reading the raw file. - Encoder coverage: the instruction families GOROOT's real code
uses. The encoder now covers the
instruction families GOROOT's real code uses that gasm lacked,
byte-verified againstgo tool asm: on amd64 the carry ALU, the
atomics (CMPXCHG, XADD, XCHG), AES-NI, SHA-1/256, PCLMULQDQ, CRC32,
GFNI, ADX, BMI, the string primitives, the system set (CPUID, RDTSC,
SYSCALL, fences, MXCSR) and the SSE/AVX/EVEX gaps; on arm64 the pair
loads and stores (LDP/STP), acquire/release and LSE atomics, AES and
SHA, the system operations, the bit ops and the NEON slice including
structure loads and the literal-pool moves; on riscv64 the RV64A AMO
family with aq/rl ordering, the Zbb pseudos with their RVC
compressions, the FMA forms and the RVV slice withvsetvli/
vsetivli; on loong64 the AM atomics with acquire/release forms, the
LSX/LASX slice, theVMOVQ/XVMOVQtransfer family and FSEL.
Also fixed on the way: arm64CASD/CASWlacked an opcode bit, and
riscv64VSETVLIwith an immediate length now canonicalises to
vsetivlias the toolchain does. - Encoder coverage: quad-register AVX-512 and floating-point
immediates. The encoder gains the
quad-register AVX-512 families (4FMAPS, 4FNMADD, 4VNNIW, VP4DPWSSD,
VP4DPWSSDS) with the register list riding the inverted V'VVVV field,
floating-point immediates on the SSE scalar moves and arithmetic
(the constant lands in a synthesised read-only pool, a positive zero
collapses to XORPS exactly as the toolchain does), accept-and-ignore
FUNCDATA and PCDATA, three-operand double shifts, static-symbol
operands for the legacy SSE moves, and the pooled 64-bit immediate
materialisation on riscv64. The parser carries bracketed register
ranges, index-only VSIB memory operands and bare trailing immediates;
macro substitution reaches parameters used with element suffixes
(A.S4), and;separates statements in plain files. - Per-architecture reference pages. docs/asm/
gains AMD64, ARM64, RISCV64 and LOONG64: the register files and the
roles the ABI fixes, addressing, operand order with every special form,
constants and materialisation, alignment, fences and the relocations
each target emits. An instruction inventory appendix per architecture
is generated from the toolchain's own tables byjust gen, and the
regenerated tables recognise 147 more mnemonics than the previous
release carried (arm64 107, riscv64 31, loong64 9). - The Plan 9 assembly language reference. docs/asm/
opens the complete language reference with its common core: the lexicon,
statement structure and constant expressions, the operand grammar with
the pseudo-registers and symbol naming, the directives and the function
flag vocabulary, preprocessing with#defineand#include, and the
Go-embedded layer (ABI0, prototypes,go_asm.h,funcdata.hand the
runtime contract). Every claim is verified againstgo tool asmof
Go 1.27.1 and gasm's differential tests; the per-architecture pages and
generated instruction appendices follow. - GOOBJ format specification. docs/GOOBJ.md
documents the Go object file format in full: both containers, the 96
byte header and all 19 blocks, every structure with its byte
offsets, symbol kinds and flag bits, all 106 relocation types with
the weak variants, aux symbols, the FuncInfo payload, the pc-value
table encoding, the content hashes and the builtin table, all
verified byte for byte against objects produced by Go 1.27.1's own
tools.
Changed
- The corpus audit measures like a build. Files named for a Go port
gasm does not target (arm, 386, s390x, ...) are never attempted, because
no supported build compiles them; the GOOS comes from the file name; and
each target's go_asm.h is generated on the fly. The headline is reported
over attemptable files: 291 of 353 on the full corpus (82.4 %) assemble
for every target architecture and 295 of 303 on real code (97.4 %),
against 108 of 627 over all files (17.2 %) that the previous release
measured.
Fixed
- The operand forms GOROOT writes. Numeric PC-relative jumps
(JEQ 2(PC), the park loopJMP 0(PC)) resolve with the toolchain's
own instruction counting and fold jump-to-jump chains exactly as its
branch optimiser does; symbol immediates (MOVQ $sym(SB), AX)
assemble to the toolchain's RIP-relative LEA with an R_PCREL
relocation; negated constant expressions in operands (ADJSP $-(REGS - 8), the shape the cgo ABI macros write) fold; the immediate
multiply (IMULQ $1000000000, AX) encodes with the toolchain's
0x69/0x6B selection; the TLS access pair assembles as the toolchain's
one-instruction form (the bareMOVQ TLS, rload nops out and
off(r)(TLS*1)folds to the segment-prefixed absolute whose disp32
carries the R_TLSLE relocation, per-GOOS); arm64 accepts the
bare-register indirect branch (BL R9besideBL (R9), both BLR) and
the zero-immediate store (MOVD $0, memthrough the zero register,
rejecting non-zero immediates as the toolchain does);PCALIGNnow
aligns on amd64, padding with the toolchain's greedy
single-instruction NOPs; the segment-absolute forms (MOVQ 0x30(GS), AXand the store direction) and the absolute crash-store
(MOVL $0xf1, 0xf1) encode; andgasm asmpredefines the
GOARCH_<arch>andGOOS_<goos>macros the go command passes to
go tool asm, so GOROOT headers'#ifdef GOARCH_amd64platform
blocks (go_tls.h'sget_tlsand friends) select as intended. The
GOROOT corpus measure moves to 291 of 353 files assembling for every
target architecture (82.4 %), 97.4 % of the real-code corpus, from
70.8 % and 82.2 %. - Tool corrections across the pipeline. The formatter keeps square
brackets in SIMD operands, statement separators and canonical macro
bodies; the linter drops false positives on shift counts, SETcc
spellings and ABIInternal references; the lexer treats a trailing
carriage return as a line end so comment text stays idempotent; and
arm64 rejects bare BTI with a diagnostic while accepting the full
family.
Downloads
- The go_asm.h generator.
-
v0.34.0
StableTest / test (push) Successful in 2m11sRelease / gates (push) Successful in 2m11sRelease / build (amd64, linux) (push) Successful in 1m13sRelease / build (arm64, linux) (push) Successful in 1m10sRelease / build (loong64, linux) (push) Successful in 1m12sRelease / build (riscv64, linux) (push) Successful in 1m33sRelease / release (push) Successful in 58sreleased this
2026-09-19 23:44:37 +00:00 | 54 commits to main since this releaseAdded
- Indirect JMP and CALL on all four architectures.
JMP AX,
CALL AX,JMP (BX)and the memory forms encode at byte parity with
the toolchain (FF /2 and FF /4 on amd64); arm64 lowersJMP (R0)to
BR and accepts the raw BR/BLR spellings; riscv64 lowersJMP (X5)to
JALR; loong64 accepts the rawJIRL rd, rj, offspelling the Go
assembler cannot express. A frameless amd64 function containing a
CALL now receives the toolchain's forced base-pointer frame. The
riscv64 and loong64 verify trampolines join their ground-truth lists,
and a lint check for control flow through registers and memory extends
to the new forms. gasm asm -GOARCHandgasm diff -GOARCH. The target
architecture can be named explicitly instead of inferred from the
file-name suffix, which is how the suffix-less majority of GOROOT's
.sfiles (cpu_x86.s, stub.s, ...) become assemblable.gasm audit-instructions --corpus [dir]. Assembles every.s
file under a directory (default GOROOT/src) with the gasm encoder
only: suffixed files for their architecture, suffix-less files for
all four, as a GOARCH build would. Reports the headline number (127
of 627 GOROOT files, 20.3 %, assemble for every target architecture),
the per-architecture pass rates and the most common failure reasons
with a representative file each,
which drive the encodability backlog by frequency.- The parser and the formatter are fuzzed. Two targets carry the
guarantee: no input makes the parser panic, and every input yields a
file the rest of the toolkit can work on; formatting twice equals
formatting once, and clean input stays clean. They seed from the
repository's own kernels, andjust fuzzdrives the mutation engine
on demand. - Man pages. docs/man carries gasm(1) and a page for every command
exceptversion, which gasm(1) documents itself, written in roff:
synopsis, description, every flag with its default, exit status,
worked examples and cross-references.
just install-mancompresses them into ~/.local/share/man (MANDIR
overrides) andjust uninstall-manremoves them. A test builds the
binary and compares each page's flags and synopsis with its own-h
output, so the pages cannot drift from the CLI.
Changed
- Go 1.27.1 required. The module declares
go 1.27.1, so building
from source needs that patch release or newer. - Canonical just recipes.
just gatesis the definition of done
(build, fmt-check, vet, test, race).installnow builds and copies
the binary into~/.local/bin(BINDIRoverrides) instead of
downloading module dependencies, andinstall-binis gone. The test
gate sweeps the logic packages (arch through verify; the ptrace-bound
debugand the thincmd/gasmsit outside the coverage profile), so
the coverage floor is computed over the product code and the number is
identical locally and in CI; the two excluded packages' own tests run
in the gate and in the pipelines, outside the floor.fuzzrequires
its target package. - The reported version comes from the build.
gasm --version
prints the version the toolchain recorded: the tag on a tagged
checkout, a pseudo-version naming the commit below one,+dirtyon a
dirty tree and(devel)outside version control. Nothing is
injected with-ldflags -Xany more. - CI realigned with the gate set. The push pipeline runs the gates
minus race in one job, in thegatesorder, with a cached Go setup and
the module as the version source; a superseded run of the same branch
is cancelled instead of queueing; everygo testruns under a
ten-minute bound that matches its job's; the race detector moved to a
hand-dispatched workflow and runs in the local gate before a tag is
cut, never on a push or a tag; the release builds without injection and
its smoke test requires the recorded tag and rejects+dirty. - The documents follow the standard set.
docs/ARCHITECTURE.mdis
organised as Overview, Packages, Data flow, State and lifetime and
Dependencies, and carries a sequence diagram of the assembly path;
docs/DEVELOPMENT.mdlists every recipe in one table and documents the
coverage floor, the CI and the release flow;docs/CLI.mdgives the
synopsis, the commands, every flag with its default, the exit codes and
worked examples;CONTRIBUTING.mdcarries the Contributor terms and
states the commit trailer form, the one-logical-change rule and the
licence header rule;SECURITY.mdstates how a vulnerability is
reported and what to expect. The repository's own assembly (the
verifytrampolines and the test kernels) is ingasm fmtcanonical
form. - The README states the project's purpose and status. It opens with
a warning that the tool is an experiment under active development,
version 0.x.x, free to change without warning, with 1.0.0 far off,
and already in active use on real assembly work. It describes both
goals (tooling for Plan 9 assembly, and Plan 9 assembly outside the
Go toolchain), argues the case for the syntax in a new Why Plan 9
assembly section, and carries a Direction section: extended
instruction support, full GOOBJ and ELF compilation, Linux and
FreeBSD, and the four architectures. A Validation status section
states what has been executed where: amd64 on real hardware, the other
three architectures under qemu-user emulation, the encoding parity on
the host for all four, and the debugger's ptrace path on amd64 only.
Fixed
- riscv64 JALR silently jumped to the wrong register. The trampoline
formJALR X0, 0(X5)read the memory operand's base as the destination,
encoding a jump to X0 with no diagnostic; the destination is the first
operand. The leaf detection shared the confusion, so affected functions
also grew a bogus prologue.JALR X0, 0(X1)as written in the verify
trampoline was mis-encoded since its introduction. - DATA lines demanded their GLOBL first. collectData processed the
declarations in file order, but the Plan 9 convention puts every DATA
line before its symbol's GLOBL; correctly ordered files (most of
GOROOT's) failed with "no matching GLOBL". Two passes: symbols are
registered before initialisers are applied. - The formatter lost idempotency on degenerate lines. Illegal tokens
survived into the output, a label sharing its line with a
non-instruction split into a line the parser rejects, stray-operand
lines entered the alignment width computation, and rendered/ *,
> >sequences re-lexed as comments and shifts. The label, width and
spacing rules now agree between passes. gasm fmtdeleted the|separators from TEXT and GLOBL flag
lists. The lexer had no token for|, the formatter dropped the
resulting illegal token, and an in-place format silently rewrote
NOSPLIT|DUPOKasNOSPLIT DUPOK, which the Go assembler rejects.
The bars now round-trip byte-identically, and·foo<ABIInternal>(SB)
parses its ABI marker instead of swallowingABIInternalandSB
into the flags, which produced false lint warnings on the standard
runtime spelling.- A malformed TEXT declaration crashed
gasm lintand the language
server. A TEXT line without a symbol left a nil name that lint and
the LSP dereferenced; both now carry on with a diagnostic. A branch
to a label at the end of a function body panicked the liveness
analysis the same way. A real NUL byte truncated the token stream
(everything after it was dropped); it is an illegal token now, invalid
UTF-8 no longer inflates byte offsets, and CRLF files format to
uniform LF. - The class-2 stack guard branched four bytes past its target. When
the underflow branch relaxed to its 32-bit form, its displacement was
still computed as if the branch were two bytes long, so it landed
inside the morestack CALL instead of the compare that decides it.
The long form is reachable once a large frame carries a body of roughly
a hundred bytes. - Immediate operands wrapped silently on amd64. Shift counts,
immediates beyond the operand's width and displacements beyond int32
truncated without a diagnostic (SHLQ $300assembled as$44); they
are range-checked now, matchinggo tool asm. EVEX scalar moves
(VMOVSS Z1, Z2) accepted forms the toolchain rejects and emitted
invalid encodings;PUSHW/POPWemit the 0x66-prefixed forms the
toolchain emits;PUSHLis rejected as illegal in 64-bit mode; a bare
zero-operandJEreports a diagnostic instead of panicking. - The arm64 shift and divide instructions encoded entirely different
operations.LSL,LSR,ASRandROR, immediate and register
forms, all encoded asORR;SDIV/UDIVsat in the wrong opcode
space;MADD/MSUBnever encoded the accumulate operand and silently
read X0 for it. All now match the toolchain byte for byte (new
differential kernels cover shifts, divides and multiplies), MADD
takes its four operands in the toolchain's order, and shift amounts at
or above the operand width are rejected. - arm64 multi-chunk immediates corrupted every branch that followed
them. The size pass and the emitter disagreed on the expansion of
constants with three or more non-zero 16-bit chunks and ofMOVW $-1,
so later label displacements were computed against the wrong offsets.
The size now comes from the encoder itself. Large-frame stack guards
(frames from roughly 64 KiB) branched to the wrong morestack entry,
and the pcsp and DWARF CFA boundaries for materialised large frames
are computed from the real prologue word counts. - arm64 immediates and addressing wrapped instead of erroring.
Constants beyond the encodable range (ADD $0x100000000) wrapped to
zero, memory offsets wrapped at 2^31, exclusive and atomic accesses
silently ignored their offsets (LDXR 8(R1)read[R1]), and large
register-based offsets were routed through SP instead of the operand's
base. All four now either encode correctly or produce diagnostics. - riscv64 compressed stores with certain offsets wrote to the wrong
address. The C.SD/C.SW/C.FSD immediate pattern dropped one bit, so
any register-relative store with offset bit 4 or 5 set targeted a
different address than the same-index load beside it.FENCE
assembled asfence 0,0instead offence iorw, iorw. Branch and
jump displacements beyond ±4 KiB / ±1 MiB wrapped silently; they are
diagnostics now. The GOROOT width spellings (MOVW 4(SP), X9)
compress to their C.LW/C.SW forms exactly as the toolchain lowers
them, restoring byte parity for those shapes. - loong64
MOVW $c, Fdwrote a general register. The immediate was
routed to the GPR of the F register's number (MOVW $2, F4clobbered
argument register R4), and the correct R30 +movgr2fr.wsequence was
unreachable. Two-operandBLTU R4, labelencoded asbeqz
(sometimes-taken where the toolchain's form is never-taken), and
out-of-range FP constants and BSTRINS/BSTRPICK bit numbers wrapped
silently; all are corrected or diagnosed. - ELF objects carried wrong relocation records. The amd64
stack-guard TLS load relocated as R_X86_64_PC32 against the null
symbol (every non-NOSPLIT object mislinked); arm64 SB references
applied HI21 twice instead of the HI21/LO12 pair; riscv64 PCREL_LO12
referenced the target instead of its AUIPC site, which the system
linker rejects; riscv64 and loong64 e_flags declared the soft-float
ABI, so standard linkers refused the merge. - ELF DWARF was unparseable. Eight abbrev-table constants were
wrong, the version-5 line header carried DWARF2-shaped tables, the
section count omitted.debug_frame(it sat past the section table,
invisible to every tool), the CIE hardcoded one architecture's
CFA and return-address registers for all four, and no DWARF address
was ever relocated: the.rela.debug_infoand.rela.debug_line
records were computed and then discarded, so every address stayed
zero after linking. The tables parse in readelf, the registers are
per-architecture,.rela.debug_info,.rela.debug_lineand
.rela.debug_frameare emitted, and addresses resolve after the
link; a data-only file emits a valid object instead of panicking, and
the DWARF records the real source path. - GOOBJ cross-package references resolved against the wrong object.
External package indices were zero-based against a table that
reserves zero for the dummy invalid package, and symbol indices
ignored the hashed definition blocks between the sections, so a
reference into the first external package could bind to whatever
object the loader saw first. An end-to-end cross-package link pins
the chain. arm64 ADRP pairs now emit the toolchain's single 8-byte
relocation (the previous twin 4-byte records were a hard link error),
and symbols no longer claim the linkname flag the toolchain reserves
for//go:linknamedeclarations. - The arm64 JIT trampolines saved a scratch register as the stack
pointer.enterJITand its checked twin stored R3, a plain
caller-saved register on arm64, and restored RSP from it, so the
first JIT call would have returned to a garbage stack. The loong64
trampoline hands its leave address through the raw-symbol pattern the
arm64 one uses, avoiding the ABI wrapper's prologue. - The checked-ABI report flagged legal frames. The red-zone canary
sat 64 bytes below the entry stack, so any kernel with a larger
declared frame reported "stack below SP written"; the guard now sizes
itself from the kernel's frame. The amd64 JIT tests are gated to
amd64 hosts (the suite previously SIGILL-crashed on the other three
architectures), fuzz signatures wider than the TEXT frame report
instead of panicking,--bufspecifications are validated strictly
(a typo no longer verifies against a zeroed buffer), and ABI0
parameter sizes coverstringandcomplexcorrectly. - amd64 hardware watchpoints never armed. The debug registers were
poked at offsets insideuser_regs_struct, corrupting five general
registers while the REPL reported success; they now use the real
u_debugreg window and stop on the watched address. loong64 watch
goes through the kernel's HW_WATCH regset (riscv64 reports the
kernel's interface as unsupported instead of failing obscurely). gasm debughung on the first faulting kernel. Genuine
SIGSEGV/SIGBUS/SIGFPE/SIGILL stops were discarded as runtime noise
and the faulting instruction restarted forever; faults now surface as
reported stops. Conditional breakpoints with a false condition
resumed mid-instruction,nextandfinishevaluated traps with
stale registers and landed off instruction boundaries, and the
breakpoint restore covered one byte of the four-byte traps (arm64
silently skipped the instruction under it); the trap PCs follow the
kernel's reporting on every architecture.regsreports YMM from
the xstate (a struct-size overrun crashed FP register reads before),
V register halves print correctly on arm64,unwatchaccepts the
architecture's slot range,x <addr> -8no longer crashes, break
conditions accept memory operands, and session scratch directories
are cleaned up.- The language server died on one malformed frame and corrupted
sources on rename. A badContent-Lengthor an unparsable JSON
body terminated the process instead of answering-32700and
continuing; rename and references covered the stripped name instead
of the full·nametoken, so renaming produced·helperminus its
last letter; documentHighlight never matched middle-dot symbols.
Positions are UTF-16 code units in both directions (astral characters
no longer shift columns) and responses always carry an explicit
resultmember. - The linter now recognises the
gspelling of the goroutine
register.MOVD R0, gclobbered R28 on arm64 (and the equivalents
on the other architectures) unflagged, and the numeric spellings the
linter did track are rejected by the toolchain there, sogwas the
one spelling that escaped the audit. FUNCDATA and PCDATA literal
indices are validated against the ranges the runtime defines. - Usage errors exit 2 uniformly.
audit-instructionsand
scaffoldargument errors and an unknownasm --formatexited 1 (or,
for--formatwithout-o, exited 0 silently); the documented
exit-2 contract now holds,asm -ono longer prints the hex dump it
claimed to replace, andverify --ground-truthworks for amd64
kernels on non-amd64 hosts instead of refusing with JIT advice. - arm64 store-exclusive instructions read their operands in the
toolchain's order.STXRtreated the first register as the status
register wherego tool asmreads it as the data register, so the
same source assembled to different code in the two assemblers; the
pair forms (STXP,LDXPand their acquire/release variants) are
accepted now, in the toolchain spelling. - Large arm64 frames matched the toolchain's sequences. A frame
beyond the immediate range that is not a movcon constant (roughly
64 KiB and up) madegasm verifyreport a false mismatch: the
toolchain splits the prologue subtraction into two 12-bit immediates
and materialises the non-leaf epilogue addition through the temporary
register; gasm emits the same sequences and the spadj boundaries
follow the real word counts. - The width spellings GOROOT uses assemble.
MOVLQZX(four uses in
runtime/asm_amd64.s),MOVBQSX,MOVWQSX,MOVBLSX,MOVBWSX,
MOVBWZXandPMOVMSKB(the bytealg kernels) encode byte-identically
withgo tool asm, and the linter reports them encodable; a
MOVLQZXis the plain 32-bit move, exactly as the toolchain lowers
it. verify --ground-truthno longer reports a mismatch for functions
whose size is not a multiple of 16. The toolchain pads text symbols
to 16-byte boundaries; the comparison now checks the padding is zero
instead of comparing it, the same rule the test suite applies.- riscv64 accepts the
gspelling of the goroutine register, like
the other architectures, and the abi kernels use it; every verify
kernel is now ground-truth checkable (the numericX27spelling the
kernels used is onego tool asmrejects). - Two more spellings GOROOT uses now assemble. riscv64
FCLASSD
(classify a float64 into an integer mask) is encodable, and a
displacement written as a product (0*8(X5), the toolchain's own
spelling in several kernels) parses instead of being rejected. - loong64 JIT execution enabled. The loong64 trampoline is now
validated end to end under qemu-user emulation (plain and ABI-checked
calls, goroutine-clobber detection), sogasm verifyruns the JIT
checks on loong64 hosts instead of forcing every loong64 kernel down
the ground-truth path. The arm64 and riscv64 trampolines carry the
same validation; the arm64 ABI test now seeds its kernel arguments
(a zeroed block made the passthrough check meaningless), and the
loong64 basic kernel's branch maze terminates on every path so the
smoke sweep cannot spin on leftover register values.
Downloads
- Indirect JMP and CALL on all four architectures.
-
v0.33.0
StableRelease / build (amd64, linux) (push) Successful in 49sRelease / build (arm64, linux) (push) Successful in 43sRelease / build (loong64, linux) (push) Successful in 46sRelease / build (riscv64, linux) (push) Successful in 45sTest / vet (push) Successful in 47sRelease / release (push) Successful in 18sTest / test (push) Successful in 2m39sTest / build (push) Successful in 43sreleased this
2026-09-14 21:36:25 +00:00 | 110 commits to main since this releaseAdded
- Stack-split guards in
gasm asm. Every framed function now gets
the morestack prologue check and the trailing morestack block
(CALL runtime.morestack_noctxt), byte-identical to the toolchain's
stacksplitoutput on all four architectures: the small, medium and
big frame classes, auto-NOSPLIT leaves, the materialised constants of
large frames (arm64R27, riscv64X31, loong64R30) and the
arm64 extrasize rule. Assembled objects are therefore linkable for
split functions, not onlyNOSPLITleaves. gasm dis. Standalone disassembly throughgolang.org/x/arch:
a.sfile is assembled and listed perTEXTfunction with local
labels at their real offsets, or raw bytes from a file or stdin are
disassembled linearly (-aselects the architecture). The debugger
shares the same decoder instead of carrying its own.gasm fmt -land-d. Check mode lists files whose formatting
differs; diff mode prints a unified diff from the project's own
LCS-based differ, with GNU header semantics.- LSP cross-file navigation. Go-to-definition and find references
fall back from local labels to theTEXTfunctions of every open
document, and rename follows the same cross-file matching. - Large frame offsets on riscv64 and arm64. Frame-relative loads
and stores beyond the signed 12-bit immediate range materialise the
address through the toolchain temp register (riscv64X31, arm64
R27) instead of silently truncating the offset (riscv64) or
rejecting the instruction (arm64); arm64 frame sizes now add the
toolchain's extrasize exactly (+8 when the frame leaves an alignment
gap, +16 when it is already aligned). - Tail calls
JMP sym(SB)on all four architectures (amd64E9,
arm64B, riscv64JAL X0, loong64B) with the call relocation. - Live oracle-parity tests. Kernel files covering every guard
class, large-offset pattern and tail call are assembled by gasm and
by the installedgo tool asmand compared byte-for-byte on all four
architectures, alongside the existing pinned-byte tests.
Fixed
- The v0.32.0 review findings: the parser rejects malformed
TEXT
frames and parses signed frame sizes; amd64 frame adjustments above
127 bytes encode with imm32; arm64 and loong64 relocation encodings
match the toolchain; the linter guards unnamedTEXTdirectives and
refreshes its textflag table; the LSP recovers from handler panics
and decodes client URIs; watchpoint slot state moved into the debug
session; dead verify code removed; em and en dashes replaced across
sources. gasm asm --format goobj: internal calls toTEXTsymbols of the
same file resolve on every architecture (the reference check accepted
only the amd64 call kind).gasm asm --format elfon loong64: branch relocations now map to
R_LARCH_B26instead of falling intoR_LARCH_PCALA_HI20.- arm64 large-prologue
ADD/SUBuse the extended-register encoding
the toolchain picks, and the morestack block saves the link register
with the toolchain'sORform on loong64.
Downloads
- Stack-split guards in
-
v0.32.0
StableRelease / build (amd64, linux) (push) Successful in 43sRelease / build (arm64, linux) (push) Successful in 42sRelease / build (loong64, linux) (push) Successful in 43sRelease / build (riscv64, linux) (push) Successful in 43sTest / vet (push) Successful in 49sRelease / release (push) Successful in 18sTest / test (push) Successful in 2m40sTest / build (push) Successful in 42sreleased this
2026-08-31 11:10:53 +00:00 | 130 commits to main since this releaseAdded
- Multi-architecture debugger.
gasm debugcarries
per-architecture ptrace register access, disassemblers
(golang.org/x/arch), register display, FP register views and
stop-info handlers for arm64, riscv64 and loong64, and the REPL is
arch-neutral. Sessions are runtime-validated on amd64; the other
hosts execute through the now-working JIT trampolines, but their
ptrace loops have not seen hardware yet. - Headless debugging.
gasm debug --scriptruns REPL commands from a
file (or stdin) and exits;--timeoutkills the debuggee when a run
hangs, with the watchdog armed before the ptrace attach. - Conditional breakpoints.
break <label> if <reg> <op> <val>now also
compares two registers (break loop if RAX > RBX), not only a register
against an immediate. - Instruction-level coverage.
gasm debug --covernow sets a
breakpoint on every instruction (walked by disassembly length), counts
the hits per instruction and reports the executed instructions with
their hit counts, with the label coverage derived from the same run.
Expect the run to slow to ptrace speed. - FP register display on riscv64 and loong64. The debugger
regs
command shows the 32 FP registers plus fcsr (and fcc on loong64) via
PTRACE_GETREGSET. - JIT execution trampolines.
verify.Callnow works on all four
architectures via hand-written assembly trampolines
(trampoline_{arm64,riscv64,loong64}.s) that save the Go stack, switch
to a prepared stack, and branch to the JIT function. - ABI checks on arm64, riscv64 and loong64.
gasm verify -abiand
the ABI half of-fuzznow cover the non-amd64 architectures via
per-architecture checked trampolines: sentinels planted in the
registers the Go ABI fixes across calls (arm64R29/R28, riscv64
X27, loong64R22; amd64 keepsBP/R14) are verified on return
and the saved registers restored before Go code resumes, with the
below-SP canary on every architecture. loong64 kernels are verified
through the toolchain-comparison path only, pending hardware
validation of their trampoline.verify.Loadassembles each file
with the encoder its name suffix calls for. TheABIReportfields
are the architecture-neutralFPClobberedandGClobbered. - Hardware watchpoints on all architectures. arm64 uses DBGWVR/DBGWCR
viaPTRACE_SETREGSETwithNT_ARM_HW_BREAK; riscv64 and loong64 use
PTRACE_POKEUSERto access trigger/debug registers. - Cross-package GOOBJ resolution on arm64 and loong64.
AssembleFileARM64andAssembleFileLOONG64mark external
relocations and populateimg.Externals, so GOOBJ output from those
architectures resolves cross-package symbols like amd64 and riscv64
already do. gasm verify --args. Scalar arguments (name=value, decimal or
0xhex) can now be supplied to a--callinvocation alongside--buf
buffers, closing the gap where only buffers could be supplied.- Fuzz corpus save and replay.
gasm verify --fuzz --save-corpus dir
records every input that crashes or mismatches as replayable JSON (buffer
contents and scalars, not raw pointers), andgasm verify --replay dir
re-runs the saved entries against the kernel in isolated child processes,
reporting whether each one reproduces. gasm audit-instructions. Black-box diff of a gasm encoder
against the installedgo tool asm, for amd64, arm64, riscv64 and
loong64 (gasm audit-instructions <arch>): superset encodings
(gasm-only, shippable viagasm asm --format goobj),
known-but-unencodable names (the backlog) and go-only names
(feature gaps).gasm scaffold differential. Prints a differential test skeleton
for every// funcsignature in a kernel file: random seed states, the
kernel call and a portable reference (<name>Portable), compared
byte-for-byte.- LSP: find references (
textDocument/references). - LSP: rename symbol (
textDocument/rename). - LSP: document formatting (
textDocument/formatting) using the
formatpackage for canonical gofmt-style output. - LSP: inlay hints (
textDocument/inlayHint): frame size hints after
the TEXT directive's argument area. - LSP: workspace symbol search (
workspace/symbol): substring search
over the TEXT functions and GLOBL/DATA symbols of every open document. - LSP: code actions. Quick fixes for
missing-ret(insert the RET)
andunused-label(remove the label) diagnostics. - LSP: signature help (
textDocument/signatureHelp): the callee's
// funcsignature while the cursor is on aCALL. - LSP: document highlights: every reference to the function or label
under the cursor is highlighted. - LSP: pull diagnostics (
textDocument/diagnostic), #include
document links (resolved against the document directory, then
$GOROOT/pkg/include, sotextflag.hopens) and folding ranges
(one collapsible region per TEXT function body). - Lint:
unused-labelrule. Flags labels that are defined but never
referenced by any jump (Hint severity). - Lint:
invalid-textflagrule. Flags TEXT/GLOBL flags not in the
known set fromtextflag.h(Warning severity). - Lint:
stack-imbalancerule. Tracks SP changes and flags if the
net delta at RET does not match the declared frame size. - Lint:
register-width-mismatchrule. Flags amd64 operands whose
register width does not match the width the mnemonic suffix prescribes
(for example a 32-bit register in aMOVQ). - Lint:
abi0-register-argsrule. Flags kernels whose// func
parameters are never read from the FP frame (for example arguments read
from registers instead), which pass every test today and break on a
toolchain upgrade. Shipped with the Go assembler's operand-width model. - Lint:
nonportable-register-namerule. Flags theRAX/EAX-style
register aliases gasm accepts butgo tool asmrejects, so files using
them only link through the gasm GOOBJ path. - Lint:
unencodable-instructionrule. Flags mnemonics the
architecture table knows but the encoder cannot yet emit, at edit time
instead of at assembly time. - Lint:
reserved-register-writerule. Flags writes to arm64 R18,
the platform-reserved register the ABI checks cannot observe at runtime
and the Go assembler cannot even spell. Reads and macro-using files
are exempt. - DWARF5 debug sections in ELF output. All four ELF emitters now emit
.debug_abbrev,.debug_info,.debug_line, and.debug_line_str
sections, enablingaddr2lineand GDB/LLDB source-level debugging, and
the amd64 emitter adds a.debug_frameCFI section for stack unwinding. - amd64: legacy SSE and conversion coverage. The encoder now handles
the legacy (non-VEX) SSE packed binaries and immediate shuffles, the
legacy SSE integer instructions andBSWAP, the scalar and packed
double conversions (CVTSS2SD,CVTSD2SS,CVTPS2PD,CVTPD2PS) and
the prefetch hints. - amd64:
VPCMPand the full opmask set. The EVEX compare with an
opmask destination and the remaining opmask-register instructions are
encoded, byte for byte against the Go assembler.
Changed
- Parallel verify sweeps. The
-smokeand-abiper-function checks
now run in parallel instead of sequentially.
Fixed
- Reliable ptrace sessions. The debugger no longer mistakes runtime
signal-delivery-stops (a Go tracee reports SIGURG preemption to the
tracer) for its launch barrier, runs every ptrace request on the thread
that forked the debuggee (requests from another thread fail with
ESRCH), prefers the debuggee's reported code base over an RWX scan, and
single-steps over a hit breakpoint so resuming cannot re-trap on the
same instruction. A ptrace integration test
(debug/ptrace_integration_test.go) drives a real session end to end. - arm64 BL relocation.
BL sym(SB)now records aRelArm64Branch
relocation instead of emitting a bare instruction with no relocation. - GOOBJ R_ADDRARM64 constant. Corrected from 9 (
R_CALLARM64) to 3
(R_ADDRARM64). - Subprocess-isolated smoke and ABI sweeps. A function that faults
during the-smokeor-abisweep is reported without killing the
parent; each sweep runs in a child process. BSF,BSRandPOPCNTencodings. Corrected to the bytes
go tool asmemits.MOVQimmediates. Compressed to the toolchain's imm32 forms.- Frame adjustments of 128 to 255 bytes. Now use the imm8
ADDQ
stack adjustment. - amd64 encoding parity. A broad pass aligned the remaining encoder
outputs and operand strictness withgo tool asm. - asm help text. Updated to list arm64 as a supported architecture.
Downloads
- Multi-architecture debugger.
-
v0.31.1
StableTest / vet (push) Successful in 47sRelease / build (amd64, linux) (push) Successful in 55sRelease / build (arm64, linux) (push) Successful in 51sRelease / build (loong64, linux) (push) Successful in 46sRelease / build (riscv64, linux) (push) Successful in 42sTest / test (push) Successful in 2m29sRelease / release (push) Successful in 19sTest / build (push) Successful in 42sreleased this
2026-08-20 20:35:11 +00:00 | 195 commits to main since this releaseFixed
- Version stamp. The v0.31.0 release binary reported itself as
0.30.0
because the version variables injustfileandcmd/gasm/main.gowere not
bumped during the release commit.
Downloads
- Version stamp. The v0.31.0 release binary reported itself as
-
v0.31.0
StableRelease / build (amd64, linux) (push) Successful in 42sRelease / build (arm64, linux) (push) Successful in 40sRelease / build (loong64, linux) (push) Successful in 42sRelease / build (riscv64, linux) (push) Successful in 45sRelease / release (push) Successful in 18sreleased this
2026-08-20 14:24:44 +00:00 | 197 commits to main since this releaseThe arm64 encoder (Phase 5 — complete) ships with ELF64 and GOOBJ emission,
verified byte-for-byte againstGOARCH=arm64 go tool asmand linked into a
realgo build. The encoder covers the full integer instruction set, FP
arithmetic, conditional select, CRC32, and the MOV pseudo-instruction with
bitmask immediate encoding. The project now requires Go 1.27.Added
- arm64 encoder (Phase 5 — complete).
gasm asmcan now assemble_arm64.s
files: the AArch64 integer instruction set with the MOV pseudo-instruction and
its immediate-constant expansions (MOVZ/MOVN/MOVK for wide immediates, ORR with
logical bitmask encoding for values like$1), data-processing (shifted
register and immediate forms), load/store (scaled unsigned and unscaled9-bit
immediate), conditional and unconditional branches, FP/SP frame mapping,
SB/global symbol references (ADRP+ADD pairs withR_ADDRARM64relocations),
jump chain folding, and ELF64 emission (gasm asm --format elf). Ground-truth
verification againstGOARCH=arm64 go tool asmmatches byte-for-byte. Phase 5
(the other architectures — RISC-V, LoongArch, arm64) is now complete.
Changed
- Go 1.27 required. The project now requires Go 1.27 (
toolchain go1.27.0).
TheR_DWTXTADDR_U4relocation type is detected at runtime for backward
compatibility.
Downloads
- arm64 encoder (Phase 5 — complete).
-
v0.30.0
StableTest / vet (push) Successful in 43sTest / test (push) Failing after 1m55sTest / build (push) SkippedRelease / build (amd64, linux) (push) Successful in 40sRelease / build (arm64, linux) (push) Successful in 37sRelease / build (loong64, linux) (push) Successful in 38sRelease / build (riscv64, linux) (push) Successful in 58sRelease / release (push) Successful in 22sreleased this
2026-08-13 16:34:20 +00:00 | 206 commits to main since this releaseThe LoongArch encoder (Phase 5) ships with ELF64 and GOOBJ emission, verified
byte-for-byte againstGOARCH=loong64 go tool asmand 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
withgo tool asm: the frame model, operand ordering, RVC compression,
large-immediate andMOV $immmaterialisation, branch/jump encodings, and
CALL sym(SB)(now aJALwith anR_RISCV_JALrelocation). The debugger
tracks four hardware watchpoint slots, and the toolkit is Linux-only.Added
- LoongArch encoder (Phase 5).
gasm asmcan 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 asmmatches byte-for-byte; GOOBJ emission
(gasm asm --format goobj) is proven end-to-end by linking the object
into a cross-compiledgo 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 tocmd/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 layoutcmd/asmwrites, not the ELF HI20/LO12 pair), so the
object links into a cross-compiledgo buildforGOARCH=riscv64. An
end-to-end link test substitutes the gasm object and reads the symbol back
withgo tool nm; the rewrite also corrects the relocationafterfield.
Fixed
- RISC-V frame model and RVC encodings. The riscv64 frame layout now
matchesgo 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;RETemits the uncompressed
JALR X0, 0(X1)the toolchain writes; theC.ADDI/C.LI/C.LUI/C.ADDIW
opcode bit and theC.ADDCR-type encoding are fixed; and theLR/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
takers2, rs1, rdand I-type arithmetic instructions takeimm12, rs1, rd, matching the Go assembler's documented operand order (previously both
were reversed, so non-commutative R-type instructions such asSUBencoded
the wrong operation). The two-operand ternary forms (ADD rs2, rd,
ADDI $imm, rd,SLLI $shamt, rd) are now accepted. RVC compression is
completed forC.ADDI16SP,C.SLLI,C.SRLI,C.SRAI,C.ANDI,
C.NOP,C.EBREAK,C.MV(fromADDI/ADD) and the commutative
AND/OR/XORforms; the byte-exact ground-truth test now covers these. - RISC-V compressed loads/stores and word arithmetic. RVC compression
now also covers the register-relativeC.LW/C.SW/C.LD/C.SD/
C.FLD/C.FSDforms (in addition to the stack-relativeC.LWSP/C.SWSP/
C.LDSP/C.SDSP), plusC.ADDI4SPN,C.ADDWandC.SUBW. The
byte-exact ground-truth test exercises these againstGOARCH=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: twoADDIs for the smallADDIsplit range, and
LUI+ADDIW+<op>otherwise, with theLUIandADDIWcompressed to
C.LUI/C.ADDIWwhen their immediate fits six signed bits. The
byte-exact ground-truth test covers positive, negative, and out-of-range
immediates againstGOARCH=riscv64 go tool asm. - RISC-V
MOV $imm, rdmaterialisation. The immediate-loading
pseudo-instruction now uses the toolchain'sSplit32BitImmediatesplit
(previously it rounded the upper 20 bits, producing wrong results for
negative and bit-11-set immediates) and compresses the emitted
ADDI/LUI/ADDIWtoC.LI/C.LUI/C.ADDIWwhen their immediate
fits six signed bits. A byte-exact ground-truth test covers zero, small,
negative, and 32-bit immediates againstGOARCH=riscv64 go tool asm. - RISC-V branch/jump compression.
JMP/JALwere being compressed to
C.JandBEQ/BNE(withX0) toC.BEQZ/C.BNEZ, butgo tool asm
never emits these compressed forms. They now emit the 32-bitJALand
branch encodings the toolchain writes; the deadC.J/C.BEQZ/C.BNEZ
encoders were removed, and theC.LUIdirect-instruction compression now
uses the correct six-bit signed range. A byte-exact ground-truth test
covers the branch family and jumps againstGOARCH=riscv64 go tool asm. - RISC-V
CALL sym(SB). The call pseudo-instruction now emits the
toolchain'sJAL X1, sym(SB)with a singleR_RISCV_JALrelocation
(previously it emitted anAUIPC+JALRpair against a local branch
label, a formgo tool asmrejects). The GOOBJ and ELF emitters now map
that relocation (Go objabi 59 / ELFR_RISCV_JAL17, 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'swatchcommand always used
hardware watchpoint slot 0, so a secondwatchcall silently overwrote
the first. Watchpoint slots are now tracked in theSession(DR0–DR3);
watchpicks the first free slot and reports an error if all four are in
use, andunwatch <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
- LoongArch encoder (Phase 5).
-
v0.29.0
StableTest / vet (push) Successful in 43sRelease / build (amd64, linux) (push) Successful in 41sRelease / build (arm64, linux) (push) Successful in 38sRelease / build (loong64, linux) (push) Successful in 39sRelease / build (riscv64, linux) (push) Successful in 38sTest / test (push) Successful in 1m58sRelease / release (push) Successful in 18sTest / build (push) Successful in 37sreleased this
2026-08-07 19:34:09 +00:00 | 221 commits to main since this releaseRISC-V GOOBJ emission, YMM vector register display, named buffer allocation
in the debugger, two new CLI commands (diff,profile), go-to-definition in
the LSP, combined ABI+fuzz verification, and did-you-mean label suggestions.
A--mapflag fordiffand--call/--bufflags forverifyextend the
new CLI commands. A signature-parser fix corrects grouped Go parameters.Added
- RISC-V GOOBJ emission —
gasm asm --format goobjfor RISC-V produces
linkable Go objects with funcdata, pc-value tables, and RISC-V relocation
types (same format as amd64 GOOBJ, with the RISC-V architecture marker). gasm diff— compare the machine code of two assembly files byte-for-byte;
shows which functions differ and the first few differing bytes.gasm profile— show the basic-block structure of each function: labels,
offsets, frame size, and NOSPLIT flag.- LSP go-to-definition —
textDocument/definitionnavigates from a label
reference to its definition. - did-you-mean — when the RISC-V assembler encounters an undefined label, it
suggests the closest existing label using Levenshtein distance. - YMM vector register display —
regsin the debugger now shows YMM
registers viaPTRACE_GETFPREGS(falls back to XMM when XSAVE is unavailable). - Named buffer allocation —
gasm debug --buf name:size:patternallocates
buffers in the debuggee filled withzero,ones,seq, or a hex pattern;
buffer pointers are placed into the argument block at the matching positions. - Crash input storage —
FuzzResult.CrashInputstores the input that caused
a crash or mismatch for reproducibility. - ABI + fuzz combined —
gasm verify --fuzznow runs ABI checks (sentinel
registers, canary, stack bounds) alongside differential fuzz testing. gasm diff --map— compare functions whose names differ between files
(e.g.--map wideCopyAVX2=wideCopyAVX512pairs two variants regardless
of suffix). Unmapped functions fall back to the original name match.gasm verify --call— invoke a single function with user-supplied buffers
(--buf name:size:pattern) instead of the smoke/abi/fuzz sweeps. Patterns:
zero,ones,seq, or a hex blob. Useful for partial functions (e.g.
decoders) that crash on random input but should succeed on valid data.
The arg block is printed before and after the call, showing return values.gasm verify --ground-truthnow documented in--help(was already a flag,
just missing from the help text).
Fixed
- Signature parser — grouped Go parameters like
dst, src []byteare now
parsed correctly (both get type[]byte). Previously the first name was
treated as its own type (dstwith size 8), causing wrong ABI0 arg-block
layout in bothverify --calland the fuzzer. - Flaky JIT tests —
runtime.KeepAliveguards and package-level buffers
prevent GC from collecting heap objects whose addresses were passed to JIT
code viaunsafe.Pointer; all verify tests pass 100/100 under-race.
Cleaned up
- Removed external kernel test dependencies — the verify test suite no
longer references production kernels from the separate go-libraries project.
The remaining test suite uses onlytestdata/verify/*.skernels, which are
part of this repository. Coverage is identical locally and in CI (80.3 %).
Verified
gasm diffdetects byte-level differences;--mappairs differently-named
functions for comparison.gasm verify --callinvokes functions with user-supplied buffers; the arg
block is printed before and after the call, showing return values.- LSP go-to-definition resolves labels across functions and files.
Downloads
- RISC-V GOOBJ emission —
-
v0.28.0
StableTest / vet (push) Successful in 44sRelease / build (amd64, linux) (push) Successful in 39sRelease / build (arm64, linux) (push) Successful in 38sRelease / build (loong64, linux) (push) Successful in 39sRelease / build (riscv64, linux) (push) Successful in 39sTest / test (push) Successful in 1m58sRelease / release (push) Successful in 18sTest / build (push) Successful in 37sreleased this
2026-08-03 17:42:05 +00:00 | 240 commits to main since this releaseRISC-V encoder: full RV64IMAFDC instruction set with RVC compression, MOV
pseudo-instruction, SB/global symbol references, ELF64 object emission, and
ground-truth verification againstGOARCH=riscv64 go tool asm.Added
- RISC-V encoder — RV64I, RV64M, RV64A, RV64F/D, FMA, CSR, JALR.
- MOV pseudo-instruction — load, store, reg-to-reg, immediate, frame mapping.
- RVC compression — 22 compressed instruction types (C.LDSP, C.SDSP, C.FLDSP,
C.FSDSP, C.ADDI, C.LI, C.LUI, C.ADDIW, C.MV, C.ADD, C.SUB, C.XOR, C.OR, C.AND,
C.SLLI, C.SRLI, C.SRAI, C.ANDI, C.BEQZ, C.BNEZ, C.J, C.JR). - SB/global symbols —
MOV $sym(SB),MOV sym(SB),MOV rd, sym(SB)
encoded as AUIPC pairs with R_RISCV_PCREL_HI20/LO12 relocations. - GLOBL/DATA — data section layout in
AssembleFileRISCV. - ELF64 emission —
gasm asm --format elfproduces EM_RISCV objects
(.text, .data, .symtab, .rela.text). gasm verify --ground-truth— byte-exact comparison against
GOARCH=riscv64 go tool asm.gasm verify --profile— function layout listing for RISC-V.- CALL — AUIPC + JALR pair encoding.
Fixed
- Parser: bare-number offset before
(SP)no longer misidentified as pseudo. - MOV:
MOV $sym(FP/SP), rdnow returns an explicit error instead of silent fallback. - RVC: C.LDSP/C.SDSP/FLDSP/FSDSP immediate encoding now matches Go toolchain
(bit-interleaved format).
Verified
- 118 RISC-V tests, asm coverage 83.3%.
- Ground-truth: C.LDSP, C.SDSP, C.FLDSP, C.FSDSP byte-exact vs Go toolchain.
Downloads
-
v0.27.0 Stable
released this
2026-08-02 21:11:30 +00:00 | 252 commits to main since this releaseSubprocess isolation for
--fuzz: each function is fuzzed in its own child
process, so a partial function (decoder) that faults on random garbage is
reported as "CRASH (partial function, use --ground-truth)" without killing
the parent. CRASH is informational (exit 0); only MISMATCH is an error.Fixed
gasm verify --fuzzno longer crashes the process on partial functions.
Downloads