feat(amd64): LOCK and REP prefixes, literal data pseudo-ops and ADJSP
Assisted-by: GLM 5.3 Flash
This commit is contained in:
Vendored
+103
@@ -0,0 +1,103 @@
|
||||
// Instruction prefixes: LOCK, REP and REPN. go tool asm encodes each
|
||||
// statement as a standalone one-byte instruction with a PC of its own (F0,
|
||||
// F3 and F2 respectively); the statement that follows is encoded unaware of
|
||||
// it, and nothing validates the pairing. The shapes are the runtime's
|
||||
// atomic read-modify-write family and the string moves, every result folded
|
||||
// back.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// func cas64(ptr *uint64, old, new uint64) bool
|
||||
TEXT ·cas64(SB), NOSPLIT, $0-25
|
||||
MOVQ ptr+0(FP), BX
|
||||
MOVQ old+8(FP), AX
|
||||
MOVQ new+16(FP), CX
|
||||
LOCK
|
||||
CMPXCHGQ CX, 0(BX)
|
||||
SETEQ ret+24(FP)
|
||||
RET
|
||||
|
||||
// func casloop(addr *uint64, v uint64) uint64
|
||||
// The runtime's Or64 shape: a LOCK inside a branch loop, the backward jump
|
||||
// measuring over the prefix statement's own byte.
|
||||
TEXT ·casloop(SB), NOSPLIT, $0-24
|
||||
MOVQ addr+0(FP), BX
|
||||
MOVQ v+8(FP), CX
|
||||
|
||||
loop:
|
||||
MOVQ CX, DX
|
||||
MOVQ (BX), AX
|
||||
ORQ AX, DX
|
||||
LOCK
|
||||
CMPXCHGQ DX, (BX)
|
||||
JNZ loop
|
||||
MOVQ AX, ret+16(FP)
|
||||
RET
|
||||
|
||||
// func xadd64(p *uint64, v uint64) uint64
|
||||
TEXT ·xadd64(SB), NOSPLIT, $0-24
|
||||
MOVQ p+0(FP), AX
|
||||
MOVQ v+8(FP), BX
|
||||
LOCK
|
||||
XADDQ BX, (AX)
|
||||
MOVQ AX, ret+16(FP)
|
||||
RET
|
||||
|
||||
// func xaddw(p *uint16, v uint16) uint16
|
||||
TEXT ·xaddw(SB), NOSPLIT, $0-12
|
||||
MOVQ p+0(FP), AX
|
||||
MOVW v+8(FP), BX
|
||||
LOCK
|
||||
XADDW BX, (AX)
|
||||
MOVW AX, ret+8(FP)
|
||||
RET
|
||||
|
||||
// func lockarith(p *uint64)
|
||||
TEXT ·lockarith(SB), NOSPLIT, $0-8
|
||||
MOVQ p+0(FP), AX
|
||||
LOCK
|
||||
ORQ CX, (AX)
|
||||
LOCK
|
||||
ANDL CX, (AX)
|
||||
LOCK
|
||||
INCQ (AX)
|
||||
LOCK
|
||||
DECQ (AX)
|
||||
LOCK
|
||||
ORB BX, (AX)
|
||||
RET
|
||||
|
||||
// func repstring(dst, src *byte, n int)
|
||||
// The memmove shapes: forward copy by quadwords, backward tails.
|
||||
TEXT ·repstring(SB), NOSPLIT, $0-24
|
||||
MOVQ dst+0(FP), DI
|
||||
MOVQ src+8(FP), SI
|
||||
REP
|
||||
MOVSQ
|
||||
REP
|
||||
MOVSB
|
||||
REPN
|
||||
MOVSB
|
||||
REP
|
||||
STOSQ
|
||||
REP
|
||||
STOSB
|
||||
RET
|
||||
|
||||
// func pfxlabel()
|
||||
// Labels pinned on prefix statements' own bytes: pfx: sits on the LOCK,
|
||||
// mid: on the REPN.
|
||||
TEXT ·pfxlabel(SB), NOSPLIT, $0-0
|
||||
pfx:
|
||||
LOCK
|
||||
XCHGL BX, (AX)
|
||||
JMP done
|
||||
|
||||
mid:
|
||||
REPN
|
||||
MOVSB
|
||||
|
||||
done:
|
||||
REP
|
||||
STOSB
|
||||
RET
|
||||
Vendored
+62
@@ -0,0 +1,62 @@
|
||||
// Literal data emission: BYTE, WORD, LONG and QUAD write the immediate
|
||||
// into the text stream as 1, 2, 4 or 8 little-endian bytes with no opcode
|
||||
// lookup, truncated to the width rather than range-checked; END is
|
||||
// accepted and ignored, contributing no bytes and ending nothing. The
|
||||
// shapes mirror the runtime's hand-laid markers
|
||||
// (crypto/internal/boring/sig/sig_amd64.s) and its syscall stubs
|
||||
// (runtime/sys_linux_amd64.s).
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// func marker()
|
||||
// A boring/crypto-style marker: a hand-laid forward branch whose skip
|
||||
// distance is patched at runtime. One BYTE per statement, as the
|
||||
// runtime's own file spells it: the semicolon-separated one-liner the
|
||||
// sys_linux_amd64.s stub uses does not survive gasm fmt, which drops the
|
||||
// statement separators.
|
||||
TEXT ·marker(SB), NOSPLIT, $0-0
|
||||
BYTE $0xEB
|
||||
BYTE $0x1D
|
||||
BYTE $0xF4
|
||||
BYTE $0x48
|
||||
BYTE $0xF4
|
||||
BYTE $0x4B
|
||||
BYTE $0xC3
|
||||
RET
|
||||
|
||||
// func stub()
|
||||
// The sys_linux_amd64.s stub bytes: the sign-extended
|
||||
// "48 c7 c0 0f 00 00 00" form of MOVQ $rt_sigreturn, AX.
|
||||
TEXT ·stub(SB), NOSPLIT, $0-0
|
||||
BYTE $0x48
|
||||
BYTE $0xc7
|
||||
BYTE $0xc0
|
||||
BYTE $0x0f
|
||||
BYTE $0x00
|
||||
BYTE $0x00
|
||||
BYTE $0x00
|
||||
RET
|
||||
|
||||
// func words()
|
||||
// The wider literals, and an END that ends nothing: the WORD after it
|
||||
// still lands in this function.
|
||||
TEXT ·words(SB), NOSPLIT, $0-0
|
||||
WORD $0x1234
|
||||
WORD $-1
|
||||
LONG $0x11223344
|
||||
LONG $-1
|
||||
QUAD $0x1122334455667788
|
||||
QUAD $-2
|
||||
END
|
||||
WORD $0xBEEF
|
||||
RET
|
||||
|
||||
// func trunc()
|
||||
// Truncation, not a range check: each literal keeps its low bytes, exactly
|
||||
// as go tool asm emits them.
|
||||
TEXT ·trunc(SB), NOSPLIT, $0-0
|
||||
BYTE $0x1FF
|
||||
WORD $0x12345
|
||||
LONG $0x123456789
|
||||
QUAD $-2
|
||||
RET
|
||||
Reference in New Issue
Block a user