From b75d6ab6d82ef5f6e99500e69a04f15a32b1fa26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Sat, 17 Sep 2022 20:38:32 +0800 Subject: [PATCH] fix generic panic, add movbe check --- base14_amd64.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ base14_asm.go | 38 -------------------------------------- base14_generic.go | 10 +++++----- base14_noasm.go | 12 ++++++++++++ cpuid.go | 12 ++++++++++++ cpuid_amd64.s | 15 +++++++++++++++ 6 files changed, 90 insertions(+), 43 deletions(-) create mode 100644 base14_amd64.go delete mode 100644 base14_asm.go create mode 100644 base14_noasm.go create mode 100644 cpuid.go create mode 100644 cpuid_amd64.s diff --git a/base14_amd64.go b/base14_amd64.go new file mode 100644 index 0000000..80675d6 --- /dev/null +++ b/base14_amd64.go @@ -0,0 +1,46 @@ +//go:build amd64 +// +build amd64 + +package base14 + +import ( + "encoding/binary" +) + +//go:noescape +//go:nosplit +func _encode(offset, outlen int, b, encd []byte) (sum uint64, n uint64) + +//go:noescape +//go:nosplit +func _decode(offset, outlen int, b, decd []byte) + +func encode(offset, outlen int, b, encd []byte) { + if movbe { + if len(b) == 7 { + b = append(b, 0) + } + sum, n := _encode(offset, outlen, b, encd) + if offset == 0 { + return + } + var tmp [8]byte + binary.LittleEndian.PutUint64(tmp[:], sum) + copy(encd[n:], tmp[:]) + encd[outlen-2] = '=' + encd[outlen-1] = byte(offset) + } else { + encodeGeneric(offset, outlen, b, encd) + } +} + +func decode(offset, outlen int, b, decd []byte) { + if movbe { + if offset != 0 && cap(b) == len(b) { + b = append(b, make([]byte, 8)...) + } + _decode(offset, outlen, b, decd) + } else { + decodeGeneric(offset, outlen, b, decd) + } +} diff --git a/base14_asm.go b/base14_asm.go deleted file mode 100644 index ae64d06..0000000 --- a/base14_asm.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build amd64 -// +build amd64 - -package base14 - -import ( - "encoding/binary" -) - -//go:noescape -//go:nosplit -func _encode(offset, outlen int, b, encd []byte) (sum uint64, n uint64) - -//go:noescape -//go:nosplit -func _decode(offset, outlen int, b, decd []byte) - -func encode(offset, outlen int, b, encd []byte) { - if len(b) == 7 { - b = append(b, 0) - } - sum, n := _encode(offset, outlen, b, encd) - if offset == 0 { - return - } - var tmp [8]byte - binary.LittleEndian.PutUint64(tmp[:], sum) - copy(encd[n:], tmp[:]) - encd[outlen-2] = '=' - encd[outlen-1] = byte(offset) -} - -func decode(offset, outlen int, b, decd []byte) { - if offset != 0 && cap(b) == len(b) { - b = append(b, make([]byte, 8)...) - } - _decode(offset, outlen, b, decd) -} diff --git a/base14_generic.go b/base14_generic.go index 001ec94..2b00c86 100644 --- a/base14_generic.go +++ b/base14_generic.go @@ -1,12 +1,9 @@ -//go:build !amd64 -// +build !amd64 - package base14 import "encoding/binary" //go:nosplit -func encode(offset, outlen int, b, encd []byte) { +func encodeGeneric(offset, outlen int, b, encd []byte) { var n int i := 0 if len(b) == 7 { @@ -23,6 +20,9 @@ func encode(offset, outlen int, b, encd []byte) { sum += 0x4e004e004e004e00 binary.BigEndian.PutUint64(encd[n:], sum) } else { + if len(b)%7 == 0 { + b = append(b, 0) + } for ; i <= len(b)-7; i += 7 { shift := binary.BigEndian.Uint64(b[i:]) >> 2 sum := shift @@ -71,7 +71,7 @@ func encode(offset, outlen int, b, encd []byte) { } //go:nosplit -func decode(offset, outlen int, b, decd []byte) { +func decodeGeneric(offset, outlen int, b, decd []byte) { var n uintptr i := 0 for ; i <= outlen-7; n += 8 { diff --git a/base14_noasm.go b/base14_noasm.go new file mode 100644 index 0000000..4c8d769 --- /dev/null +++ b/base14_noasm.go @@ -0,0 +1,12 @@ +//go:build !amd64 +// +build !amd64 + +package base14 + +import _ "unsafe" + +//go:linkname encode github.com/fumiama/go-base16384.encodeGeneric +func encode(offset, outlen int, b, encd []byte) + +//go:linkname decode github.com/fumiama/go-base16384.decodeGeneric +func decode(offset, outlen int, b, decd []byte) diff --git a/cpuid.go b/cpuid.go new file mode 100644 index 0000000..acf568f --- /dev/null +++ b/cpuid.go @@ -0,0 +1,12 @@ +//go:build amd64 +// +build amd64 + +package base14 + +func cpuid(op uint32) (eax, ebx, ecx, edx uint32) + +// True when MOVBEx instructions are available. +var movbe = func() bool { + _, _, c, _ := cpuid(1) + return c&(1<<22) > 0 +}() diff --git a/cpuid_amd64.s b/cpuid_amd64.s new file mode 100644 index 0000000..c27e32a --- /dev/null +++ b/cpuid_amd64.s @@ -0,0 +1,15 @@ +//go:build amd64 +// +build amd64 + +// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. + +// func cpuid(op uint32) (eax, ebx, ecx, edx uint32) +TEXT ·cpuid(SB), 7, $0 + XORQ CX, CX + MOVL op+0(FP), AX + CPUID + MOVL AX, eax+8(FP) + MOVL BX, ebx+12(FP) + MOVL CX, ecx+16(FP) + MOVL DX, edx+20(FP) + RET