diff --git a/examples/stadtx/asm.go b/examples/stadtx/asm.go new file mode 100644 index 0000000..bd9b3c6 --- /dev/null +++ b/examples/stadtx/asm.go @@ -0,0 +1,394 @@ +// +build ignore + +package main + +import ( + "strconv" + + . "github.com/mmcloughlin/avo/build" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" +) + +const ( + k0U64 = 0xb89b0f8e1655514f + k1U64 = 0x8c6f736011bd5127 + k2U64 = 0x8f29bd94edce7b39 + k3U64 = 0x9c1b8e1e9628323f + + k2U32 = 0x802910e3 + k3U32 = 0x819b13af + k4U32 = 0x91cb27e5 + k5U32 = 0xc1a269c1 +) + +func imul(k uint64, r Register) { + t := GP64v() + MOVQ(Imm(k), t) + IMULQ(t, r) +} + +func makelabels(name string, n int) []string { + l := make([]string, n) + for i := 0; i < n; i++ { + l[i] = name + strconv.Itoa(i) + } + return l +} + +func main() { + Package("github.com/mmcloughlin/avo/examples/stadtx") + TEXT("Hash", "func(state *State, key []byte) uint64") + + statePtr := Load(Param("state"), GP64v()) + ptr := Load(Param("key").Base(), GP64v()) + n := Load(Param("key").Len(), GP64v()) + + v0 := GP64v() // reg_v0 = GeneralPurposeRegister64() + v1 := GP64v() // reg_v1 = GeneralPurposeRegister64() + MOVQ(Mem{Base: statePtr}, v0) // MOV(reg_v0, [reg_state_ptr]) + MOVQ(Mem{Base: statePtr, Disp: 8}, v1) // MOV(reg_v1, [reg_state_ptr+8]) + + t := GP64v() // t = GeneralPurposeRegister64() + MOVQ(n, t) // MOV(t, reg_ptr_len) + ADDQ(Imm(1), t) // ADD(t, 1) + imul(k0U64, t) // imul(t, k0U64) + XORQ(t, v0) // XOR(reg_v0, t) + + MOVQ(n, t) // MOV(t, reg_ptr_len) + ADDQ(Imm(2), t) // ADD(t, 2) + imul(k1U64, t) // imul(t, k1U64) + XORQ(t, v1) // XOR(reg_v1, t) + + long := "coreLong" // coreLong = Label("coreLong") + CMPQ(n, Imm(32)) // CMP(reg_ptr_len, 32) + JGE(LabelRef(long)) // JGE(coreLong) + // + u64s := GP64v() // reg_u64s = GeneralPurposeRegister64() + MOVQ(n, u64s) // MOV(reg_u64s, reg_ptr_len) + SHRQ(Imm(3), u64s) // SHR(reg_u64s, 3) + // + labels := makelabels("shortCore", 4) // labels = [Label("shortCore%d" % i) for i in range(4)] + // + for i := 0; i < 4; i++ { // for i in range(4): + CMPQ(u64s, Imm(i)) // CMP(reg_u64s, i) + JE(LabelRef(labels[i])) // JE(labels[i]) + } // + for i := 3; i > 0; i-- { // for i in range(3, 0, -1): + LABEL(labels[i]) // LABEL(labels[i]) + r := GP64v() // r = GeneralPurposeRegister64() + MOVQ(Mem{Base: ptr}, r) // MOV(r, [reg_ptr]) + imul(k3U64, r) // imul(r, k3U64) + ADDQ(r, v0) // ADD(reg_v0, r) + RORQ(Imm(17), v0) // ROR(reg_v0, 17) + XORQ(v1, v0) // XOR(reg_v0, reg_v1) + RORQ(Imm(53), v1) // ROR(reg_v1, 53) + ADDQ(v0, v1) // ADD(reg_v1, reg_v0) + ADDQ(Imm(8), ptr) // ADD(reg_ptr,8) + SUBQ(Imm(8), n) // SUB(reg_ptr_len,8) + } // + LABEL(labels[0]) // LABEL(labels[0]) + // + labels = makelabels("shortTail", 8) // labels = [Label("shortTail%d" % i) for i in range(8)] + // + // split(labels, reg_ptr_len,0,7) + for i := 0; i < 8; i++ { + CMPQ(n, Imm(i)) + JE(LabelRef(labels[i])) + } + // + after := "shortAfter" // after = Label("shortAfter") + // + ch := GP64v() // reg_ch = GeneralPurposeRegister64() + // + LABEL(labels[7]) // LABEL(labels[7]) + MOVBQZX(Mem{Base: ptr, Disp: 6}, ch) // MOVZX(reg_ch, byte[reg_ptr+6]) + SHLQ(Imm(32), ch) // SHL(reg_ch, 32) + ADDQ(ch, v0) // ADD(reg_v0, reg_ch) + // + LABEL(labels[6]) // LABEL(labels[6]) + MOVBQZX(Mem{Base: ptr, Disp: 5}, ch) // MOVZX(reg_ch, byte[reg_ptr+5]) + SHLQ(Imm(48), ch) // SHL(reg_ch, 48) + ADDQ(ch, v1) // ADD(reg_v1, reg_ch) + // + LABEL(labels[5]) // LABEL(labels[5]) + MOVBQZX(Mem{Base: ptr, Disp: 4}, ch) // MOVZX(reg_ch, byte[reg_ptr+4]) + SHLQ(Imm(16), ch) // SHL(reg_ch, 16) + ADDQ(ch, v0) // ADD(reg_v0, reg_ch) + // + LABEL(labels[4]) // LABEL(labels[4]) + // XOR(reg_ch, reg_ch) + MOVLQZX(Mem{Base: ptr}, ch) // MOV(reg_ch.as_dword, dword[reg_ptr]) + ADDQ(ch, v1) // ADD(reg_v1, reg_ch) + // + JMP(LabelRef(after)) // JMP(after) + // + LABEL(labels[3]) // LABEL(labels[3]) + MOVBQZX(Mem{Base: ptr, Disp: 2}, ch) // MOVZX(reg_ch, byte[reg_ptr+2]) + SHLQ(Imm(48), ch) // SHL(reg_ch, 48) + ADDQ(ch, v0) // ADD(reg_v0, reg_ch) + // + LABEL(labels[2]) // LABEL(labels[2]) + // XOR(reg_ch, reg_ch) + MOVWQZX(Mem{Base: ptr}, ch) // MOV(reg_ch.as_word, word[reg_ptr]) + ADDQ(ch, v1) // ADD(reg_v1, reg_ch) + // + JMP(LabelRef(after)) // JMP(after) + // + LABEL(labels[1]) // LABEL(labels[1]) + MOVBQZX(Mem{Base: ptr}, ch) // MOVZX(reg_ch, byte[reg_ptr]) + ADDQ(ch, v0) // ADD(reg_v0, reg_ch) + // + LABEL(labels[0]) // LABEL(labels[0]) + RORQ(Imm(32), v1) // ROR(reg_v1, 32) + XORQ(Imm(0xff), v1) // XOR(reg_v1, 0xFF) + // + LABEL(after) // LABEL(after) + // + XORQ(v0, v1) // XOR(reg_v1, reg_v0) + // + RORQ(Imm(33), v0) // ROR(reg_v0, 33) + ADDQ(v1, v0) // ADD(reg_v0, reg_v1) + // + ROLQ(Imm(17), v1) // ROL(reg_v1, 17) + XORQ(v0, v1) // XOR(reg_v1, reg_v0) + // + ROLQ(Imm(43), v0) // ROL(reg_v0, 43) + ADDQ(v1, v0) // ADD(reg_v0, reg_v1) + // + ROLQ(Imm(31), v1) // ROL(reg_v1, 31) + SUBQ(v0, v1) // SUB(reg_v1, reg_v0) + // + ROLQ(Imm(13), v0) // ROL(reg_v0, 13) + XORQ(v1, v0) // XOR(reg_v0, reg_v1) + // + SUBQ(v0, v1) // SUB(reg_v1, reg_v0) + // + ROLQ(Imm(41), v0) // ROL(reg_v0, 41) + ADDQ(v1, v0) // ADD(reg_v0, reg_v1) + // + ROLQ(Imm(37), v1) // ROL(reg_v1, 37) + XORQ(v0, v1) // XOR(reg_v1, reg_v0) + // + RORQ(Imm(39), v0) // ROR(reg_v0, 39) + ADDQ(v1, v0) // ADD(reg_v0, reg_v1) + // + RORQ(Imm(15), v1) // ROR(reg_v1, 15) + ADDQ(v0, v1) // ADD(reg_v1, reg_v0) + // + ROLQ(Imm(15), v0) // ROL(reg_v0, 15) + XORQ(v1, v0) // XOR(reg_v0, reg_v1) + // + RORQ(Imm(5), v1) // ROR(reg_v1, 5) + // + XORQ(v1, v0) // XOR(reg_v0, reg_v1) + // + Store(v0, ReturnIndex(0)) + RET() // RETURN(reg_v0) + // + LABEL(long) // LABEL(coreLong) + // + v2 := GP64v() // reg_v2 = GeneralPurposeRegister64() + v3 := GP64v() // reg_v3 = GeneralPurposeRegister64() + // + MOVQ(Mem{Base: statePtr, Disp: 16}, v2) // MOV(reg_v2, [reg_state_ptr+16]) + MOVQ(Mem{Base: statePtr, Disp: 24}, v3) // MOV(reg_v3, [reg_state_ptr+24]) + // + // t = GeneralPurposeRegister64() + MOVQ(n, t) // MOV(t, reg_ptr_len) + ADDQ(Imm(3), t) // ADD(t, 3) + imul(k2U64, t) // imul(t, k2U64) + XORQ(t, v2) // XOR(reg_v2, t) + // + MOVQ(n, t) // MOV(t, reg_ptr_len) + ADDQ(Imm(4), t) // ADD(t, 4) + imul(k3U64, t) // imul(t, k3U64) + XORQ(t, v3) // XOR(reg_v3, t) + // + r := GP64v() // r = GeneralPurposeRegister64() + loop := "block" // with Loop() as loop: + LABEL(loop) + MOVQ(Mem{Base: ptr}, r) // MOV(r, [reg_ptr]) + imul(k2U32, r) // imul(r, k2U32) + ADDQ(r, v0) // ADD(reg_v0, r) + ROLQ(Imm(57), v0) // ROL(reg_v0, 57) + XORQ(v3, v0) // XOR(reg_v0, reg_v3) + // + MOVQ(Mem{Base: ptr, Disp: 8}, r) // MOV(r, [reg_ptr + 8]) + imul(k3U32, r) // imul(r, k3U32) + ADDQ(r, v1) // ADD(reg_v1, r) + ROLQ(Imm(63), v1) // ROL(reg_v1, 63) + XORQ(v2, v1) // XOR(reg_v1, reg_v2) + // + MOVQ(Mem{Base: ptr, Disp: 16}, r) // MOV(r, [reg_ptr + 16]) + imul(k4U32, r) // imul(r, k4U32) + ADDQ(r, v2) // ADD(reg_v2, r) + RORQ(Imm(47), v2) // ROR(reg_v2, 47) + ADDQ(v0, v2) // ADD(reg_v2, reg_v0) + // + MOVQ(Mem{Base: ptr, Disp: 24}, r) // MOV(r, [reg_ptr + 24]) + imul(k5U32, r) // imul(r, k5U32) + ADDQ(r, v3) // ADD(reg_v3, r) + RORQ(Imm(11), v3) // ROR(reg_v3, 11) + SUBQ(v1, v3) // SUB(reg_v3, reg_v1) + // + ADDQ(Imm(32), ptr) // ADD(reg_ptr, 32) + SUBQ(Imm(32), n) // SUB(reg_ptr_len, 32) + // + CMPQ(n, Imm(32)) // CMP(reg_ptr_len, 32) + JGE(LabelRef(loop)) // JGE(loop.begin) + // + // + nsave := GP64v() // reg_ptr_len_saved = GeneralPurposeRegister64() + MOVQ(n, nsave) // MOV(reg_ptr_len_saved, reg_ptr_len) + // + // reg_u64s = GeneralPurposeRegister64() + MOVQ(n, u64s) // MOV(reg_u64s, reg_ptr_len) + SHRQ(Imm(3), u64s) // SHR(reg_u64s, 3) + // + labels = makelabels("longCore", 4) // labels = [Label("longCore%d" % i) for i in range(4)] + // + for i := 0; i < 4; i++ { // for i in range(4): + CMPQ(u64s, Imm(i)) // CMP(reg_u64s, i) + JE(LabelRef(labels[i])) // JE(labels[i]) + } // + LABEL(labels[3]) // LABEL(labels[3]) + // + MOVQ(Mem{Base: ptr}, r) // MOV(r, [reg_ptr]) + imul(k2U32, r) // imul(r, k2U32) + ADDQ(r, v0) // ADD(reg_v0, r) + ROLQ(Imm(57), v0) // ROL(reg_v0, 57) + XORQ(v3, v0) // XOR(reg_v0, reg_v3) + ADDQ(Imm(8), ptr) // ADD(reg_ptr, 8) + SUBQ(Imm(8), n) // SUB(reg_ptr_len, 8) + // + LABEL(labels[2]) // LABEL(labels[2]) + // + MOVQ(Mem{Base: ptr}, r) // MOV(r, [reg_ptr]) + imul(k3U32, r) // imul(r, k3U32) + ADDQ(r, v1) // ADD(reg_v1, r) + ROLQ(Imm(63), v1) // ROL(reg_v1, 63) + XORQ(v2, v1) // XOR(reg_v1, reg_v2) + ADDQ(Imm(8), ptr) // ADD(reg_ptr, 8) + SUBQ(Imm(8), n) // SUB(reg_ptr_len, 8) + // + LABEL(labels[1]) // LABEL(labels[1]) + // + MOVQ(Mem{Base: ptr}, r) // MOV(r, [reg_ptr]) + imul(k4U32, r) // imul(r, k4U32) + ADDQ(r, v2) // ADD(reg_v2, r) + RORQ(Imm(47), v2) // ROR(reg_v2, 47) + ADDQ(v0, v2) // ADD(reg_v2, reg_v0) + ADDQ(Imm(8), ptr) // ADD(reg_ptr, 8) + SUBQ(Imm(8), n) // SUB(reg_ptr_len, 8) + // + LABEL(labels[0]) // LABEL(labels[0]) + // + RORQ(Imm(11), v3) // ROR(reg_v3, 11) + SUBQ(v1, v3) // SUB(reg_v3, reg_v1) + // + ADDQ(Imm(1), nsave) // ADD(reg_ptr_len_saved, 1) + imul(k3U64, nsave) // imul(reg_ptr_len_saved, k3U64) + XORQ(nsave, v0) // XOR(reg_v0, reg_ptr_len_saved) + // + labels = makelabels("longTail", 8) // labels = [Label("longTail%d" % i) for i in range(8)] + // + // split(labels, reg_ptr_len, 0, 7) + for i := 0; i < 8; i++ { + CMPQ(n, Imm(i)) + JE(LabelRef(labels[i])) + } + // + after = "longAfter" // after = Label("longAfter") + // + // reg_ch = GeneralPurposeRegister64() + // + LABEL(labels[7]) // LABEL(labels[7]) + MOVBQZX(Mem{Base: ptr, Disp: 6}, ch) // MOVZX(reg_ch, byte[reg_ptr+6]) + ADDQ(ch, v1) // ADD(reg_v1, reg_ch) + // + LABEL(labels[6]) // LABEL(labels[6]) + // XOR(reg_ch, reg_ch) + MOVWQZX(Mem{Base: ptr, Disp: 4}, ch) // MOV(reg_ch.as_word, word[reg_ptr + 4]) + ADDQ(ch, v2) // ADD(reg_v2, reg_ch) + MOVLQZX(Mem{Base: ptr}, ch) // MOV(reg_ch.as_dword, dword[reg_ptr]) + ADDQ(ch, v3) // ADD(reg_v3, reg_ch) + JMP(LabelRef(after)) // JMP(after) + // + LABEL(labels[5]) // LABEL(labels[5]) + MOVBQZX(Mem{Base: ptr, Disp: 4}, ch) // MOVZX(reg_ch, byte[reg_ptr+4]) + ADDQ(ch, v1) // ADD(reg_v1, reg_ch) + // + LABEL(labels[4]) // LABEL(labels[4]) + // XOR(reg_ch, reg_ch) + MOVLQZX(Mem{Base: ptr}, ch) // MOV(reg_ch.as_dword, dword[reg_ptr]) + ADDQ(ch, v2) // ADD(reg_v2, reg_ch) + // + JMP(LabelRef(after)) // JMP(after) + // + LABEL(labels[3]) // LABEL(labels[3]) + MOVBQZX(Mem{Base: ptr, Disp: 2}, ch) // MOVZX(reg_ch, byte[reg_ptr+2]) + ADDQ(ch, v3) // ADD(reg_v3, reg_ch) + // + LABEL(labels[2]) // LABEL(labels[2]) + // XOR(reg_ch, reg_ch) + MOVWQZX(Mem{Base: ptr}, ch) // MOV(reg_ch.as_word, word[reg_ptr]) + ADDQ(ch, v1) // ADD(reg_v1, reg_ch) + // + JMP(LabelRef(after)) // JMP(after) + // + LABEL(labels[1]) // LABEL(labels[1]) + MOVBQZX(Mem{Base: ptr}, ch) // MOVZX(reg_ch, byte[reg_ptr]) + ADDQ(ch, v2) // ADD(reg_v2, reg_ch) + // + LABEL(labels[0]) // LABEL(labels[0]) + ROLQ(Imm(32), v3) // ROL(reg_v3, 32) + XORQ(Imm(0xff), v3) // XOR(reg_v3, 0xFF) + // + LABEL(after) // LABEL(after) + // + // ## finalize + // + SUBQ(v2, v1) // SUB(reg_v1, reg_v2) + RORQ(Imm(19), v0) // ROR(reg_v0, 19) + SUBQ(v0, v1) // SUB(reg_v1, reg_v0) + RORQ(Imm(53), v1) // ROR(reg_v1, 53) + XORQ(v1, v3) // XOR(reg_v3, reg_v1) + SUBQ(v3, v0) // SUB(reg_v0, reg_v3) + ROLQ(Imm(43), v3) // ROL(reg_v3, 43) + ADDQ(v3, v0) // ADD(reg_v0, reg_v3) + RORQ(Imm(3), v0) // ROR(reg_v0, 3) + SUBQ(v0, v3) // SUB(reg_v3, reg_v0) + RORQ(Imm(43), v2) // ROR(reg_v2, 43) + SUBQ(v3, v2) // SUB(reg_v2, reg_v3) + ROLQ(Imm(55), v2) // ROL(reg_v2, 55) + XORQ(v0, v2) // XOR(reg_v2, reg_v0) + SUBQ(v2, v1) // SUB(reg_v1, reg_v2) + RORQ(Imm(7), v3) // ROR(reg_v3, 7) + SUBQ(v2, v3) // SUB(reg_v3, reg_v2) + RORQ(Imm(31), v2) // ROR(reg_v2, 31) + ADDQ(v2, v3) // ADD(reg_v3, reg_v2) + SUBQ(v1, v2) // SUB(reg_v2, reg_v1) + RORQ(Imm(39), v3) // ROR(reg_v3, 39) + XORQ(v3, v2) // XOR(reg_v2, reg_v3) + RORQ(Imm(17), v3) // ROR(reg_v3, 17) + XORQ(v2, v3) // XOR(reg_v3, reg_v2) + ADDQ(v3, v1) // ADD(reg_v1, reg_v3) + RORQ(Imm(9), v1) // ROR(reg_v1, 9) + XORQ(v1, v2) // XOR(reg_v2, reg_v1) + ROLQ(Imm(24), v2) // ROL(reg_v2, 24) + XORQ(v2, v3) // XOR(reg_v3, reg_v2) + RORQ(Imm(59), v3) // ROR(reg_v3, 59) + RORQ(Imm(1), v0) // ROR(reg_v0, 1) + SUBQ(v1, v0) // SUB(reg_v0, reg_v1) + // + XORQ(v1, v0) // XOR(reg_v0, reg_v1) + XORQ(v3, v2) // XOR(reg_v2, reg_v3) + // + XORQ(v2, v0) // XOR(reg_v0, reg_v2) + // + Store(v0, ReturnIndex(0)) + RET() // RETURN(reg_v0) + + Generate() +} diff --git a/examples/stadtx/stadtx.go b/examples/stadtx/stadtx.go new file mode 100644 index 0000000..77a7557 --- /dev/null +++ b/examples/stadtx/stadtx.go @@ -0,0 +1,3 @@ +package stadtx + +type State [4]uint64 diff --git a/examples/stadtx/stadtx.s b/examples/stadtx/stadtx.s new file mode 100644 index 0000000..1107bb8 --- /dev/null +++ b/examples/stadtx/stadtx.s @@ -0,0 +1,310 @@ +// Code generated by command: go run asm.go -out stadtx.s -stubs stub.go. DO NOT EDIT. + +#include "textflag.h" + +// func Hash(state *State, key []byte) uint64 +TEXT ·Hash(SB),0,$0-40 + MOVQ state(FP), AX + MOVQ key_base+8(FP), CX + MOVQ key_len+16(FP), DX + MOVQ (AX), BX + MOVQ 8(AX), BP + MOVQ DX, SI + ADDQ $0x1, SI + MOVQ $0xb89b0f8e1655514f, DI + IMULQ DI, SI + XORQ SI, BX + MOVQ DX, SI + ADDQ $0x2, SI + MOVQ $0x8c6f736011bd5127, DI + IMULQ DI, SI + XORQ SI, BP + CMPQ DX, $0x20 + JGE coreLong + MOVQ DX, SI + SHRQ $0x3, SI + CMPQ SI, $0x0 + JE shortCore0 + CMPQ SI, $0x1 + JE shortCore1 + CMPQ SI, $0x2 + JE shortCore2 + CMPQ SI, $0x3 + JE shortCore3 +shortCore3: + MOVQ (CX), SI + MOVQ $0x9c1b8e1e9628323f, DI + IMULQ DI, SI + ADDQ SI, BX + RORQ $0x11, BX + XORQ BP, BX + RORQ $0x35, BP + ADDQ BX, BP + ADDQ $0x8, CX + SUBQ $0x8, DX +shortCore2: + MOVQ (CX), SI + MOVQ $0x9c1b8e1e9628323f, DI + IMULQ DI, SI + ADDQ SI, BX + RORQ $0x11, BX + XORQ BP, BX + RORQ $0x35, BP + ADDQ BX, BP + ADDQ $0x8, CX + SUBQ $0x8, DX +shortCore1: + MOVQ (CX), SI + MOVQ $0x9c1b8e1e9628323f, DI + IMULQ DI, SI + ADDQ SI, BX + RORQ $0x11, BX + XORQ BP, BX + RORQ $0x35, BP + ADDQ BX, BP + ADDQ $0x8, CX + SUBQ $0x8, DX +shortCore0: + CMPQ DX, $0x0 + JE shortTail0 + CMPQ DX, $0x1 + JE shortTail1 + CMPQ DX, $0x2 + JE shortTail2 + CMPQ DX, $0x3 + JE shortTail3 + CMPQ DX, $0x4 + JE shortTail4 + CMPQ DX, $0x5 + JE shortTail5 + CMPQ DX, $0x6 + JE shortTail6 + CMPQ DX, $0x7 + JE shortTail7 +shortTail7: + MOVBQZX 6(CX), SI + SHLQ $0x20, SI + ADDQ SI, BX +shortTail6: + MOVBQZX 5(CX), SI + SHLQ $0x30, SI + ADDQ SI, BP +shortTail5: + MOVBQZX 4(CX), SI + SHLQ $0x10, SI + ADDQ SI, BX +shortTail4: + MOVLQZX (CX), SI + ADDQ SI, BP + JMP shortAfter +shortTail3: + MOVBQZX 2(CX), SI + SHLQ $0x30, SI + ADDQ SI, BX +shortTail2: + MOVWQZX (CX), SI + ADDQ SI, BP + JMP shortAfter +shortTail1: + MOVBQZX (CX), SI + ADDQ SI, BX +shortTail0: + RORQ $0x20, BP + XORQ $0xff, BP +shortAfter: + XORQ BX, BP + RORQ $0x21, BX + ADDQ BP, BX + ROLQ $0x11, BP + XORQ BX, BP + ROLQ $0x2b, BX + ADDQ BP, BX + ROLQ $0x1f, BP + SUBQ BX, BP + ROLQ $0xd, BX + XORQ BP, BX + SUBQ BX, BP + ROLQ $0x29, BX + ADDQ BP, BX + ROLQ $0x25, BP + XORQ BX, BP + RORQ $0x27, BX + ADDQ BP, BX + RORQ $0xf, BP + ADDQ BX, BP + ROLQ $0xf, BX + XORQ BP, BX + RORQ $0x5, BP + XORQ BP, BX + MOVQ BX, ret+32(FP) + RET +coreLong: + MOVQ 16(AX), DI + MOVQ 24(AX), AX + MOVQ DX, SI + ADDQ $0x3, SI + MOVQ $0x8f29bd94edce7b39, R8 + IMULQ R8, SI + XORQ SI, DI + MOVQ DX, SI + ADDQ $0x4, SI + MOVQ $0x9c1b8e1e9628323f, R8 + IMULQ R8, SI + XORQ SI, AX +block: + MOVQ (CX), SI + MOVQ $0x802910e3, R8 + IMULQ R8, SI + ADDQ SI, BX + ROLQ $0x39, BX + XORQ AX, BX + MOVQ 8(CX), SI + MOVQ $0x819b13af, R8 + IMULQ R8, SI + ADDQ SI, BP + ROLQ $0x3f, BP + XORQ DI, BP + MOVQ 16(CX), SI + MOVQ $0x91cb27e5, R8 + IMULQ R8, SI + ADDQ SI, DI + RORQ $0x2f, DI + ADDQ BX, DI + MOVQ 24(CX), SI + MOVQ $0xc1a269c1, R8 + IMULQ R8, SI + ADDQ SI, AX + RORQ $0xb, AX + SUBQ BP, AX + ADDQ $0x20, CX + SUBQ $0x20, DX + CMPQ DX, $0x20 + JGE block + MOVQ DX, R8 + MOVQ DX, SI + SHRQ $0x3, SI + CMPQ SI, $0x0 + JE longCore0 + CMPQ SI, $0x1 + JE longCore1 + CMPQ SI, $0x2 + JE longCore2 + CMPQ SI, $0x3 + JE longCore3 +longCore3: + MOVQ (CX), SI + MOVQ $0x802910e3, R9 + IMULQ R9, SI + ADDQ SI, BX + ROLQ $0x39, BX + XORQ AX, BX + ADDQ $0x8, CX + SUBQ $0x8, DX +longCore2: + MOVQ (CX), SI + MOVQ $0x819b13af, R9 + IMULQ R9, SI + ADDQ SI, BP + ROLQ $0x3f, BP + XORQ DI, BP + ADDQ $0x8, CX + SUBQ $0x8, DX +longCore1: + MOVQ (CX), SI + MOVQ $0x91cb27e5, R9 + IMULQ R9, SI + ADDQ SI, DI + RORQ $0x2f, DI + ADDQ BX, DI + ADDQ $0x8, CX + SUBQ $0x8, DX +longCore0: + RORQ $0xb, AX + SUBQ BP, AX + ADDQ $0x1, R8 + MOVQ $0x9c1b8e1e9628323f, SI + IMULQ SI, R8 + XORQ R8, BX + CMPQ DX, $0x0 + JE longTail0 + CMPQ DX, $0x1 + JE longTail1 + CMPQ DX, $0x2 + JE longTail2 + CMPQ DX, $0x3 + JE longTail3 + CMPQ DX, $0x4 + JE longTail4 + CMPQ DX, $0x5 + JE longTail5 + CMPQ DX, $0x6 + JE longTail6 + CMPQ DX, $0x7 + JE longTail7 +longTail7: + MOVBQZX 6(CX), SI + ADDQ SI, BP +longTail6: + MOVWQZX 4(CX), SI + ADDQ SI, DI + MOVLQZX (CX), SI + ADDQ SI, AX + JMP longAfter +longTail5: + MOVBQZX 4(CX), SI + ADDQ SI, BP +longTail4: + MOVLQZX (CX), SI + ADDQ SI, DI + JMP longAfter +longTail3: + MOVBQZX 2(CX), SI + ADDQ SI, AX +longTail2: + MOVWQZX (CX), SI + ADDQ SI, BP + JMP longAfter +longTail1: + MOVBQZX (CX), SI + ADDQ SI, DI +longTail0: + ROLQ $0x20, AX + XORQ $0xff, AX +longAfter: + SUBQ DI, BP + RORQ $0x13, BX + SUBQ BX, BP + RORQ $0x35, BP + XORQ BP, AX + SUBQ AX, BX + ROLQ $0x2b, AX + ADDQ AX, BX + RORQ $0x3, BX + SUBQ BX, AX + RORQ $0x2b, DI + SUBQ AX, DI + ROLQ $0x37, DI + XORQ BX, DI + SUBQ DI, BP + RORQ $0x7, AX + SUBQ DI, AX + RORQ $0x1f, DI + ADDQ DI, AX + SUBQ BP, DI + RORQ $0x27, AX + XORQ AX, DI + RORQ $0x11, AX + XORQ DI, AX + ADDQ AX, BP + RORQ $0x9, BP + XORQ BP, DI + ROLQ $0x18, DI + XORQ DI, AX + RORQ $0x3b, AX + RORQ $0x1, BX + SUBQ BP, BX + XORQ BP, BX + XORQ AX, DI + XORQ DI, BX + MOVQ BX, ret+32(FP) + RET diff --git a/examples/stadtx/stadtx_test.go b/examples/stadtx/stadtx_test.go new file mode 100644 index 0000000..a867316 --- /dev/null +++ b/examples/stadtx/stadtx_test.go @@ -0,0 +1,25 @@ +package stadtx + +import ( + "testing" + "testing/quick" + + ref "github.com/dgryski/go-stadtx" +) + +//go:generate go run asm.go -out stadtx.s -stubs stub.go + +func IUT(s State, key []byte) uint64 { + return Hash(&s, key) +} + +func Expect(s State, key []byte) uint64 { + t := ref.State(s) + return ref.Hash(&t, key) +} + +func TestCmp(t *testing.T) { + if err := quick.CheckEqual(IUT, Expect, nil); err != nil { + t.Fatal(err) + } +} diff --git a/examples/stadtx/stub.go b/examples/stadtx/stub.go new file mode 100644 index 0000000..3dd6043 --- /dev/null +++ b/examples/stadtx/stub.go @@ -0,0 +1,5 @@ +// Code generated by command: go run asm.go -out stadtx.s -stubs stub.go. DO NOT EDIT. + +package stadtx + +func Hash(state *State, key []byte) uint64 diff --git a/gotypes/signature.go b/gotypes/signature.go index 555c4ff..667b717 100644 --- a/gotypes/signature.go +++ b/gotypes/signature.go @@ -3,7 +3,6 @@ package gotypes import ( "bytes" "errors" - "fmt" "go/token" "go/types" "strconv" @@ -113,12 +112,17 @@ func newTuple(t *types.Tuple, offsets []int64, size int64, defaultprefix string) func (t *Tuple) Lookup(name string) Component { e := t.byname[name] if e == nil { - return componenterr(fmt.Sprintf("unknown variable \"%s\"", name)) + return errorf("unknown variable \"%s\"", name) } return e } -func (t *Tuple) At(i int) Component { return t.components[i] } +func (t *Tuple) At(i int) Component { + if i >= len(t.components) { + return errorf("index out of range") + } + return t.components[i] +} func (t *Tuple) Bytes() int { return t.size }