From b5add4a9ed1e45956d8b0bb699dfc4dd8ae40304 Mon Sep 17 00:00:00 2001 From: Mohamed Mahmoud Date: Tue, 7 Jan 2025 07:07:25 -0500 Subject: [PATCH 1/2] Add peerCIDR flow filter config Signed-off-by: Mohamed Mahmoud --- .../v1beta1/flowcollector_types.go | 4 +++ .../v1beta1/zz_generated.conversion.go | 2 ++ .../v1beta2/flowcollector_types.go | 4 +++ .../flowcollector_validation_webhook.go | 8 +++-- .../flowcollector_validation_webhook_test.go | 4 ++- .../flows.netobserv.io_flowcollectors.yaml | 20 ++++++++++++ .../flows.netobserv.io_flowcollectors.yaml | 20 ++++++++++++ .../samples/flows_v1beta2_flowcollector.yaml | 1 + controllers/ebpf/agent_controller.go | 6 ++++ docs/FlowCollector.md | 32 +++++++++++++++++++ 10 files changed, 97 insertions(+), 4 deletions(-) diff --git a/apis/flowcollector/v1beta1/flowcollector_types.go b/apis/flowcollector/v1beta1/flowcollector_types.go index f6de0a238a..78e45fb195 100644 --- a/apis/flowcollector/v1beta1/flowcollector_types.go +++ b/apis/flowcollector/v1beta1/flowcollector_types.go @@ -246,6 +246,10 @@ type EBPFFlowFilterRule struct { // +optional PeerIP string `json:"peerIP,omitempty"` + // `peerCIDR` defines the Peer IP CIDR to filter flows by. + // Examples: `10.10.10.0/24` or `100:100:100:100::/64` + PeerCIDR string `json:"peerCIDR,omitempty"` + // `icmpCode`, for Internet Control Message Protocol (ICMP) traffic, optionally defines the ICMP code to filter flows by. // +optional ICMPCode *int `json:"icmpCode,omitempty"` diff --git a/apis/flowcollector/v1beta1/zz_generated.conversion.go b/apis/flowcollector/v1beta1/zz_generated.conversion.go index 784d3a19e3..96f30bc6ba 100644 --- a/apis/flowcollector/v1beta1/zz_generated.conversion.go +++ b/apis/flowcollector/v1beta1/zz_generated.conversion.go @@ -563,6 +563,7 @@ func autoConvert_v1beta1_EBPFFlowFilterRule_To_v1beta2_EBPFFlowFilterRule(in *EB out.DestPorts = in.DestPorts out.Ports = in.Ports out.PeerIP = in.PeerIP + out.PeerCIDR = in.PeerCIDR out.ICMPCode = (*int)(unsafe.Pointer(in.ICMPCode)) out.ICMPType = (*int)(unsafe.Pointer(in.ICMPType)) out.PktDrops = (*bool)(unsafe.Pointer(in.PktDrops)) @@ -585,6 +586,7 @@ func autoConvert_v1beta2_EBPFFlowFilterRule_To_v1beta1_EBPFFlowFilterRule(in *v1 out.DestPorts = in.DestPorts out.Ports = in.Ports out.PeerIP = in.PeerIP + out.PeerCIDR = in.PeerCIDR out.ICMPCode = (*int)(unsafe.Pointer(in.ICMPCode)) out.ICMPType = (*int)(unsafe.Pointer(in.ICMPType)) out.PktDrops = (*bool)(unsafe.Pointer(in.PktDrops)) diff --git a/apis/flowcollector/v1beta2/flowcollector_types.go b/apis/flowcollector/v1beta2/flowcollector_types.go index 6dd35c7ee4..16a386539f 100644 --- a/apis/flowcollector/v1beta2/flowcollector_types.go +++ b/apis/flowcollector/v1beta2/flowcollector_types.go @@ -269,6 +269,10 @@ type EBPFFlowFilterRule struct { // +optional PeerIP string `json:"peerIP,omitempty"` + // `peerCIDR` defines the Peer IP CIDR to filter flows by. + // Examples: `10.10.10.0/24` or `100:100:100:100::/64` + PeerCIDR string `json:"peerCIDR,omitempty"` + // `icmpCode`, for Internet Control Message Protocol (ICMP) traffic, optionally defines the ICMP code to filter flows by. // +optional ICMPCode *int `json:"icmpCode,omitempty"` diff --git a/apis/flowcollector/v1beta2/flowcollector_validation_webhook.go b/apis/flowcollector/v1beta2/flowcollector_validation_webhook.go index a163a7a0bb..3d9e66c828 100644 --- a/apis/flowcollector/v1beta2/flowcollector_validation_webhook.go +++ b/apis/flowcollector/v1beta2/flowcollector_validation_webhook.go @@ -121,11 +121,13 @@ func (r *FlowCollector) validateAgent(_ context.Context, fc *FlowCollectorSpec) m := make(map[string]bool) for i := range fc.Agent.EBPF.FlowFilter.FlowFilterRules { rule := fc.Agent.EBPF.FlowFilter.FlowFilterRules[i] - if found := m[rule.CIDR]; found { - errs = append(errs, fmt.Errorf("flow filter rule CIDR %s already exists", rule.CIDR)) + key := rule.CIDR + "-" + rule.PeerCIDR + if found := m[key]; found { + errs = append(errs, fmt.Errorf("flow filter rule CIDR and PeerCIDR %s already exists", + key)) break } - m[rule.CIDR] = true + m[key] = true errs = append(errs, validateFilter(&rule)...) } errs = append(errs, validateFilter(fc.Agent.EBPF.FlowFilter)...) diff --git a/apis/flowcollector/v1beta2/flowcollector_validation_webhook_test.go b/apis/flowcollector/v1beta2/flowcollector_validation_webhook_test.go index d4d9573d92..0ff2dac08a 100644 --- a/apis/flowcollector/v1beta2/flowcollector_validation_webhook_test.go +++ b/apis/flowcollector/v1beta2/flowcollector_validation_webhook_test.go @@ -77,12 +77,14 @@ func TestValidateAgent(t *testing.T) { { Action: "Accept", CIDR: "0.0.0.0/0", + PeerCIDR: "1.1.1.1/24", Direction: "Egress", Protocol: "TCP", }, { Action: "Accept", CIDR: "0.0.0.0/0", + PeerCIDR: "1.1.1.1/24", Direction: "Egress", Protocol: "UDP", }, @@ -92,7 +94,7 @@ func TestValidateAgent(t *testing.T) { }, }, }, - expectedError: "flow filter rule CIDR 0.0.0.0/0 already exists", + expectedError: "flow filter rule CIDR and PeerCIDR 0.0.0.0/0-1.1.1.1/24 already exists", }, { name: "PacketDrop without privilege triggers warning", diff --git a/bundle/manifests/flows.netobserv.io_flowcollectors.yaml b/bundle/manifests/flows.netobserv.io_flowcollectors.yaml index e93202609d..1d0d19fd19 100644 --- a/bundle/manifests/flows.netobserv.io_flowcollectors.yaml +++ b/bundle/manifests/flows.netobserv.io_flowcollectors.yaml @@ -206,6 +206,11 @@ spec: description: '`icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.' type: integer + peerCIDR: + description: |- + `peerCIDR` defines the Peer IP CIDR to filter flows by. + Examples: `10.10.10.0/24` or `100:100:100:100::/64` + type: string peerIP: description: |- `peerIP` optionally defines the remote IP address to filter flows by. @@ -285,6 +290,11 @@ spec: description: '`icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.' type: integer + peerCIDR: + description: |- + `peerCIDR` defines the Peer IP CIDR to filter flows by. + Examples: `10.10.10.0/24` or `100:100:100:100::/64` + type: string peerIP: description: |- `peerIP` optionally defines the remote IP address to filter flows by. @@ -4024,6 +4034,11 @@ spec: description: '`icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.' type: integer + peerCIDR: + description: |- + `peerCIDR` defines the Peer IP CIDR to filter flows by. + Examples: `10.10.10.0/24` or `100:100:100:100::/64` + type: string peerIP: description: |- `peerIP` optionally defines the remote IP address to filter flows by. @@ -4103,6 +4118,11 @@ spec: description: '`icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.' type: integer + peerCIDR: + description: |- + `peerCIDR` defines the Peer IP CIDR to filter flows by. + Examples: `10.10.10.0/24` or `100:100:100:100::/64` + type: string peerIP: description: |- `peerIP` optionally defines the remote IP address to filter flows by. diff --git a/config/crd/bases/flows.netobserv.io_flowcollectors.yaml b/config/crd/bases/flows.netobserv.io_flowcollectors.yaml index b8ef01a651..495a3a5e2d 100644 --- a/config/crd/bases/flows.netobserv.io_flowcollectors.yaml +++ b/config/crd/bases/flows.netobserv.io_flowcollectors.yaml @@ -182,6 +182,11 @@ spec: icmpType: description: '`icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.' type: integer + peerCIDR: + description: |- + `peerCIDR` defines the Peer IP CIDR to filter flows by. + Examples: `10.10.10.0/24` or `100:100:100:100::/64` + type: string peerIP: description: |- `peerIP` optionally defines the remote IP address to filter flows by. @@ -247,6 +252,11 @@ spec: icmpType: description: '`icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.' type: integer + peerCIDR: + description: |- + `peerCIDR` defines the Peer IP CIDR to filter flows by. + Examples: `10.10.10.0/24` or `100:100:100:100::/64` + type: string peerIP: description: |- `peerIP` optionally defines the remote IP address to filter flows by. @@ -3697,6 +3707,11 @@ spec: icmpType: description: '`icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.' type: integer + peerCIDR: + description: |- + `peerCIDR` defines the Peer IP CIDR to filter flows by. + Examples: `10.10.10.0/24` or `100:100:100:100::/64` + type: string peerIP: description: |- `peerIP` optionally defines the remote IP address to filter flows by. @@ -3762,6 +3777,11 @@ spec: icmpType: description: '`icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.' type: integer + peerCIDR: + description: |- + `peerCIDR` defines the Peer IP CIDR to filter flows by. + Examples: `10.10.10.0/24` or `100:100:100:100::/64` + type: string peerIP: description: |- `peerIP` optionally defines the remote IP address to filter flows by. diff --git a/config/samples/flows_v1beta2_flowcollector.yaml b/config/samples/flows_v1beta2_flowcollector.yaml index bb67f8b0fa..eefa02aa48 100644 --- a/config/samples/flows_v1beta2_flowcollector.yaml +++ b/config/samples/flows_v1beta2_flowcollector.yaml @@ -36,6 +36,7 @@ spec: # cidr: 0.0.0.0/0 # - action: Accept # cidr: 10.128.0.1/24 + # peerCIDR: 0.0.0.0/0 # ports: 6443 # protocol: TCP # sampling: 10 diff --git a/controllers/ebpf/agent_controller.go b/controllers/ebpf/agent_controller.go index 3ec6fa3ada..5486c42eef 100644 --- a/controllers/ebpf/agent_controller.go +++ b/controllers/ebpf/agent_controller.go @@ -540,6 +540,9 @@ func mapFlowFilterRuleToFilter(rule *flowslatest.EBPFFlowFilterRule) ebpfconfig. if rule.PeerIP != "" { f.FilterPeerIP = rule.PeerIP } + if rule.PeerCIDR != "" { + f.FilterPeerCIDR = rule.PeerCIDR + } if rule.TCPFlags != "" { f.FilterTCPFlags = rule.TCPFlags } @@ -575,6 +578,9 @@ func mapFlowFilterToFilter(filter *flowslatest.EBPFFlowFilter) ebpfconfig.FlowFi if filter.PeerIP != "" { f.FilterPeerIP = filter.PeerIP } + if filter.PeerCIDR != "" { + f.FilterPeerCIDR = filter.PeerCIDR + } if filter.TCPFlags != "" { f.FilterTCPFlags = filter.TCPFlags } diff --git a/docs/FlowCollector.md b/docs/FlowCollector.md index 77982cd24c..030fecae85 100644 --- a/docs/FlowCollector.md +++ b/docs/FlowCollector.md @@ -491,6 +491,14 @@ To filter two ports, use a "port1,port2" in string format. For example, `ports: `icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.
false + + peerCIDR + string + + `peerCIDR` defines the Peer IP CIDR to filter flows by. +Examples: `10.10.10.0/24` or `100:100:100:100::/64`
+ + false peerIP string @@ -631,6 +639,14 @@ To filter two ports, use a "port1,port2" in string format. For example, `ports: `icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.
false + + peerCIDR + string + + `peerCIDR` defines the Peer IP CIDR to filter flows by. +Examples: `10.10.10.0/24` or `100:100:100:100::/64`
+ + false peerIP string @@ -8221,6 +8237,14 @@ To filter two ports, use a "port1,port2" in string format. For example, `ports: `icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.
false + + peerCIDR + string + + `peerCIDR` defines the Peer IP CIDR to filter flows by. +Examples: `10.10.10.0/24` or `100:100:100:100::/64`
+ + false peerIP string @@ -8361,6 +8385,14 @@ To filter two ports, use a "port1,port2" in string format. For example, `ports: `icmpType`, for ICMP traffic, optionally defines the ICMP type to filter flows by.
false + + peerCIDR + string + + `peerCIDR` defines the Peer IP CIDR to filter flows by. +Examples: `10.10.10.0/24` or `100:100:100:100::/64`
+ + false peerIP string From e882152565cfa210f76aaf8c1cc76d2808811f80 Mon Sep 17 00:00:00 2001 From: Mohamed Mahmoud Date: Tue, 7 Jan 2025 07:07:52 -0500 Subject: [PATCH 2/2] update ebpf agent pkgt and update go mod Signed-off-by: Mohamed Mahmoud --- go.mod | 30 +- go.sum | 62 +- .../grpc-gateway/v2/runtime/convert.go | 6 +- .../grpc-gateway/v2/runtime/errors.go | 15 + .../grpc-gateway/v2/runtime/fieldmask.go | 2 +- .../v2/runtime/marshaler_registry.go | 4 +- .../grpc-gateway/v2/runtime/proto2_convert.go | 4 +- .../grpc-gateway/v2/utilities/pattern.go | 2 +- .../v2/utilities/string_array_flag.go | 2 +- .../klauspost/compress/.goreleaser.yml | 6 +- .../github.com/klauspost/compress/README.md | 29 +- .../klauspost/compress/flate/deflate.go | 2 +- .../klauspost/compress/flate/inflate.go | 74 +- .../klauspost/compress/fse/decompress.go | 2 +- .../klauspost/compress/huff0/decompress.go | 4 +- .../klauspost/compress/s2/encode.go | 25 +- .../klauspost/compress/s2/encode_amd64.go | 201 +- .../klauspost/compress/s2/encode_go.go | 4 +- .../compress/s2/encodeblock_amd64.go | 44 +- .../klauspost/compress/s2/encodeblock_amd64.s | 21920 ++++++++-------- .../klauspost/compress/s2/writer.go | 31 +- .../klauspost/compress/zstd/blockdec.go | 4 +- .../klauspost/compress/zstd/enc_better.go | 32 +- .../klauspost/compress/zstd/enc_dfast.go | 16 +- .../klauspost/compress/zstd/encoder.go | 45 +- .../klauspost/compress/zstd/framedec.go | 4 +- .../klauspost/compress/zstd/seqdec_amd64.go | 4 +- .../klauspost/compress/zstd/seqdec_amd64.s | 8 +- .../klauspost/compress/zstd/zstd.go | 4 + vendor/github.com/minio/minio-go/v7/Makefile | 4 + vendor/github.com/minio/minio-go/v7/README.md | 2 +- .../minio/minio-go/v7/api-datatypes.go | 18 +- .../minio/minio-go/v7/api-get-object.go | 4 +- .../minio/minio-go/v7/api-prompt-object.go | 78 + .../minio/minio-go/v7/api-prompt-options.go | 84 + .../minio-go/v7/api-put-object-fan-out.go | 5 +- .../minio-go/v7/api-put-object-multipart.go | 48 +- .../minio-go/v7/api-put-object-streaming.go | 101 +- .../minio/minio-go/v7/api-put-object.go | 32 +- .../minio/minio-go/v7/api-s3-datatypes.go | 70 +- vendor/github.com/minio/minio-go/v7/api.go | 18 +- .../github.com/minio/minio-go/v7/checksum.go | 210 +- .../minio/minio-go/v7/functional_tests.go | 2000 +- .../v7/pkg/credentials/sts_web_identity.go | 55 +- .../minio-go/v7/pkg/lifecycle/lifecycle.go | 26 + .../minio/minio-go/v7/pkg/tags/tags.go | 2 +- .../minio/minio-go/v7/post-policy.go | 71 +- .../minio/minio-go/v7/retry-continous.go | 10 +- vendor/github.com/minio/minio-go/v7/retry.go | 10 +- vendor/github.com/minio/minio-go/v7/utils.go | 152 +- .../netobserv-ebpf-agent/pkg/agent/agent.go | 76 +- .../netobserv-ebpf-agent/pkg/agent/config.go | 23 +- .../pkg/agent/packets_agent.go | 41 +- .../pkg/decode/decode_protobuf.go | 38 +- .../pkg/ebpf/bpf_arm64_bpfel.go | 115 +- .../pkg/ebpf/bpf_arm64_bpfel.o | Bin 185504 -> 294232 bytes .../pkg/ebpf/bpf_powerpc_bpfel.go | 115 +- .../pkg/ebpf/bpf_powerpc_bpfel.o | Bin 184352 -> 293080 bytes .../pkg/ebpf/bpf_s390_bpfeb.go | 115 +- .../pkg/ebpf/bpf_s390_bpfeb.o | Bin 200920 -> 309304 bytes .../pkg/ebpf/bpf_x86_bpfel.go | 115 +- .../pkg/ebpf/bpf_x86_bpfel.o | Bin 185256 -> 293984 bytes .../netobserv-ebpf-agent/pkg/ebpf/gen.go | 2 +- .../pkg/exporter/grpc_proto.go | 7 +- .../pkg/exporter/ipfix.go | 4 +- .../pkg/exporter/kafka_proto.go | 8 +- .../netobserv-ebpf-agent/pkg/flow/account.go | 7 +- .../pkg/flow/decorator.go | 24 - .../netobserv-ebpf-agent/pkg/flow/deduper.go | 177 - .../pkg/flow/tracer_map.go | 7 +- .../pkg/metrics/metrics.go | 29 +- .../pkg/model/flow_content.go | 58 +- .../netobserv-ebpf-agent/pkg/model/record.go | 123 +- .../pkg/pbflow/flow.pb.go | 265 +- .../netobserv-ebpf-agent/pkg/pbflow/proto.go | 89 +- .../pkg/tracer/flow_filter.go | 94 +- .../netobserv-ebpf-agent/pkg/tracer/tracer.go | 188 +- .../pkg/tracer/tracer_legacy.go | 12 +- .../observability-lib/ovsdb/interface.go | 903 + .../observability-lib/ovsdb/observ_model.go | 1 + .../sampledecoder/db_client.go | 1 + .../sampledecoder/sample_decoder.go | 46 + .../go-controller/pkg/config/config.go | 38 +- .../pkg/libovsdb/ops/db_object_types.go | 18 + .../go-controller/pkg/libovsdb/ops/model.go | 66 +- .../go-controller/pkg/libovsdb/ops/router.go | 130 +- .../go-controller/pkg/libovsdb/ops/switch.go | 66 +- .../go-controller/pkg/types/const.go | 20 +- vendor/go.opentelemetry.io/otel/.gitignore | 8 - vendor/go.opentelemetry.io/otel/.golangci.yml | 2 - vendor/go.opentelemetry.io/otel/CHANGELOG.md | 49 +- .../go.opentelemetry.io/otel/CONTRIBUTING.md | 18 +- vendor/go.opentelemetry.io/otel/Makefile | 2 +- .../otlp/otlpmetric/otlpmetricgrpc/client.go | 7 +- .../otlpmetricgrpc/internal/oconf/options.go | 6 +- .../otlpmetricgrpc/internal/oconf/tls.go | 2 +- .../internal/transform/metricdata.go | 18 +- .../otlp/otlpmetric/otlpmetricgrpc/version.go | 2 +- .../otel/internal/global/instruments.go | 14 +- .../otel/internal/global/meter.go | 69 +- .../otel/internal/global/trace.go | 8 +- .../otel/sdk/instrumentation/scope.go | 4 + .../otel/sdk/metric/config.go | 79 +- .../otel/sdk/metric/exemplar.go | 68 +- .../otel/sdk/metric/exemplar/README.md | 3 + .../sdk/metric/{internal => }/exemplar/doc.go | 2 +- .../{internal => }/exemplar/exemplar.go | 2 +- .../metric/{internal => }/exemplar/filter.go | 11 +- .../fixed_size_reservoir.go} | 118 +- .../metric/exemplar/histogram_reservoir.go | 70 + .../{internal => }/exemplar/reservoir.go | 10 +- .../metric/{internal => }/exemplar/storage.go | 8 +- .../metric/{internal => }/exemplar/value.go | 5 +- .../otel/sdk/metric/instrument.go | 14 +- .../metric/internal/aggregate/aggregate.go | 9 +- .../sdk/metric/internal/aggregate/drop.go | 27 + .../sdk/metric/internal/aggregate/exemplar.go | 3 +- .../aggregate/exponential_histogram.go | 9 +- .../internal/aggregate/filtered_reservoir.go | 50 + .../metric/internal/aggregate/histogram.go | 11 +- .../metric/internal/aggregate/lastvalue.go | 11 +- .../otel/sdk/metric/internal/aggregate/sum.go | 17 +- .../otel/sdk/metric/internal/exemplar/drop.go | 23 - .../internal/exemplar/filtered_reservoir.go | 49 - .../otel/sdk/metric/internal/exemplar/hist.go | 46 - .../otel/sdk/metric/internal/x/x.go | 46 +- .../otel/sdk/metric/manual_reader.go | 9 +- .../otel/sdk/metric/meter.go | 121 +- .../otel/sdk/metric/periodic_reader.go | 9 +- .../otel/sdk/metric/pipeline.go | 132 +- .../otel/sdk/metric/provider.go | 10 +- .../otel/sdk/metric/version.go | 2 +- .../otel/sdk/metric/view.go | 11 +- .../otel/sdk/resource/auto.go | 62 +- .../otel/sdk/resource/builtin.go | 6 +- .../otel/sdk/resource/host_id_windows.go | 7 +- .../otel/sdk/resource/os_windows.go | 1 - .../otel/sdk/trace/batch_span_processor.go | 7 +- .../otel/sdk/trace/evictedqueue.go | 21 +- .../otel/sdk/trace/provider.go | 9 +- .../otel/sdk/trace/span.go | 108 +- .../go.opentelemetry.io/otel/sdk/version.go | 2 +- vendor/go.opentelemetry.io/otel/version.go | 2 +- vendor/go.opentelemetry.io/otel/versions.yaml | 15 +- vendor/modules.txt | 41 +- 145 files changed, 15639 insertions(+), 14443 deletions(-) create mode 100644 vendor/github.com/minio/minio-go/v7/api-prompt-object.go create mode 100644 vendor/github.com/minio/minio-go/v7/api-prompt-options.go delete mode 100644 vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/decorator.go delete mode 100644 vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/deduper.go create mode 100644 vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/ovsdb/interface.go create mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/README.md rename vendor/go.opentelemetry.io/otel/sdk/metric/{internal => }/exemplar/doc.go (93%) rename vendor/go.opentelemetry.io/otel/sdk/metric/{internal => }/exemplar/exemplar.go (98%) rename vendor/go.opentelemetry.io/otel/sdk/metric/{internal => }/exemplar/filter.go (75%) rename vendor/go.opentelemetry.io/otel/sdk/metric/{internal/exemplar/rand.go => exemplar/fixed_size_reservoir.go} (73%) create mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/histogram_reservoir.go rename vendor/go.opentelemetry.io/otel/sdk/metric/{internal => }/exemplar/reservoir.go (73%) rename vendor/go.opentelemetry.io/otel/sdk/metric/{internal => }/exemplar/storage.go (94%) rename vendor/go.opentelemetry.io/otel/sdk/metric/{internal => }/exemplar/value.go (91%) create mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/drop.go create mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/filtered_reservoir.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/drop.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filtered_reservoir.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/hist.go diff --git a/go.mod b/go.mod index 47c71f285c..119e5c2500 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ require ( github.com/coreos/go-semver v0.3.1 github.com/go-logr/logr v1.4.2 github.com/google/go-cmp v0.6.0 - github.com/netobserv/flowlogs-pipeline v1.7.0-community.0.20241126155124-18e017f67001 - github.com/netobserv/netobserv-ebpf-agent v1.6.1-crc2.0.20241008130234-a20397fb8f88 + github.com/netobserv/flowlogs-pipeline v1.7.0-community.0.20241217113023-fa0540a1658e + github.com/netobserv/netobserv-ebpf-agent v1.7.0-community.0.20250122180127-fa88f3515234 github.com/onsi/ginkgo/v2 v2.22.2 github.com/onsi/gomega v1.36.2 github.com/openshift/api v0.0.0-20240722135205-ae4f370f361f @@ -79,20 +79,20 @@ require ( github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect github.com/google/uuid v1.6.0 // indirect github.com/gopacket/gopacket v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/heptiolabs/healthcheck v0.0.0-20211123025425-613501dd5deb // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ip2location/ip2location-go/v9 v9.7.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/libp2p/go-reuseport v0.3.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 // indirect github.com/minio/md5-simd v1.1.2 // indirect - github.com/minio/minio-go/v7 v7.0.77 // indirect + github.com/minio/minio-go/v7 v7.0.82 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -102,7 +102,7 @@ require ( github.com/netobserv/loki-client-go v0.0.0-20220927092034-f37122a54500 // indirect github.com/netsampler/goflow2 v1.3.7 // indirect github.com/ovn-org/libovsdb v0.7.1-0.20240820095311-ce1951614a20 // indirect - github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20241126140656-c95491e46334 // indirect + github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20250116185920-20e7a0e40c93 // indirect github.com/pierrec/lz4/v4 v4.1.17 // indirect github.com/pion/dtls/v2 v2.2.4 // indirect github.com/pion/logging v0.2.2 // indirect @@ -132,16 +132,16 @@ require ( github.com/xdg-go/stringprep v1.0.4 // indirect github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 // indirect + go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 // indirect - go.opentelemetry.io/otel/metric v1.31.0 // indirect - go.opentelemetry.io/otel/sdk v1.29.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect - go.opentelemetry.io/otel/trace v1.31.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -156,8 +156,8 @@ require ( golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.28.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.36.1 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect @@ -177,5 +177,3 @@ require ( ) replace github.com/prometheus/common v0.55.0 => github.com/netobserv/prometheus-common v0.55.0-netobserv - -replace github.com/netobserv/netobserv-ebpf-agent => github.com/msherif1234/netobserv-ebpf-agent v0.0.0-20241213142900-5c07db3a6c0b diff --git a/go.sum b/go.sum index 07cc2afc1b..57aff72741 100644 --- a/go.sum +++ b/go.sum @@ -466,8 +466,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.15.0/go.mod h1:vO11I9oWA+KsxmfFQPhLnnIb1VDE24M+pdxZFiuZcA8= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.7.0/go.mod h1:1NSuaUUkFaJzMasbfq/11wKYWSR67Xn6r2DXKhuDNFg= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -576,8 +576,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= @@ -648,6 +648,8 @@ github.com/mdlayher/packet v1.0.0/go.mod h1:eE7/ctqDhoiRhQ44ko5JZU2zxB88g+JH/6jm github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= +github.com/metallb/frr-k8s v0.0.15 h1:6M3UGhovX1EFoaSGjrRD7djUAx3w2I+g81FH8OVtHkM= +github.com/metallb/frr-k8s v0.0.15/go.mod h1:TjrGoAf+v00hYGlI8jUdyDxY5udMAOs2GWwrvLWnA4E= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= @@ -655,8 +657,8 @@ github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.77 h1:GaGghJRg9nwDVlNbwYjSDJT1rqltQkBFDsypWX1v3Bw= -github.com/minio/minio-go/v7 v7.0.77/go.mod h1:AVM3IUN6WwKzmwBxVdjzhH8xq+f57JSbbvzqvUzR6eg= +github.com/minio/minio-go/v7 v7.0.82 h1:tWfICLhmp2aFPXL8Tli0XDTHj2VB/fNf0PC1f/i1gRo= +github.com/minio/minio-go/v7 v7.0.82/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -684,8 +686,6 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= -github.com/msherif1234/netobserv-ebpf-agent v0.0.0-20241213142900-5c07db3a6c0b h1:E8vhCqGnKNO++9HFup4rXqpl9I1uyTJYpaKetV1elAA= -github.com/msherif1234/netobserv-ebpf-agent v0.0.0-20241213142900-5c07db3a6c0b/go.mod h1:20e1OPAs7h3k9PvNZWS9D6BnXEtkTk2LlfzD66uhvxY= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= @@ -700,12 +700,14 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/netobserv/flowlogs-pipeline v1.7.0-community.0.20241126155124-18e017f67001 h1:Hb5RxMfFafng2+QbnkiEWTS4TUUz7zcpUS8RiauzWXw= -github.com/netobserv/flowlogs-pipeline v1.7.0-community.0.20241126155124-18e017f67001/go.mod h1:wnCpWttAFkLSSxOcfCkd9zA5pwV/1OcxS5tAfAxNWEc= +github.com/netobserv/flowlogs-pipeline v1.7.0-community.0.20241217113023-fa0540a1658e h1:MdCBEv8sbkhWwoKmp99oeg7eS0tRlD1FTZKRg7r5xWA= +github.com/netobserv/flowlogs-pipeline v1.7.0-community.0.20241217113023-fa0540a1658e/go.mod h1:P8Gf2JTrvyHpTVZs/N2M1M9nMk1Uu/uvwhVe11c3b9Y= github.com/netobserv/gopipes v0.3.0 h1:IYmPnnAVCdSK7VmHmpFhrVBOEm45qpgbZmJz1sSW+60= github.com/netobserv/gopipes v0.3.0/go.mod h1:N7/Gz05EOF0CQQSKWsv3eof22Cj2PB08Pbttw98YFYU= github.com/netobserv/loki-client-go v0.0.0-20220927092034-f37122a54500 h1:RmnoJe/ci5q+QdM7upFdxiU+D8F3L3qTd5wXCwwHefw= github.com/netobserv/loki-client-go v0.0.0-20220927092034-f37122a54500/go.mod h1:LHXpc5tjKvsfZn0pwLKrvlgEhZcCaw3Di9mUEZGAI4E= +github.com/netobserv/netobserv-ebpf-agent v1.7.0-community.0.20250122180127-fa88f3515234 h1:qZEb7rbvhzha9ADvj4AwJqgLKK9zP5GRJNiiG1MI9nc= +github.com/netobserv/netobserv-ebpf-agent v1.7.0-community.0.20250122180127-fa88f3515234/go.mod h1:597AfnMX4y2hWk8wuz++qQD4BwSNbHUHdcFbCDnmJrM= github.com/netobserv/prometheus-common v0.55.0-netobserv h1:Fapr74g0S3gRh/kTTyv9Ytm4DJJfFuUTEToiU/np9eg= github.com/netobserv/prometheus-common v0.55.0-netobserv/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/netsampler/goflow2 v1.3.7 h1:XZaTy8kkMnGXpJ9hS3KbO1McyrFTpVNhVFEx9rNhMmc= @@ -759,8 +761,8 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ovn-org/libovsdb v0.7.1-0.20240820095311-ce1951614a20 h1:OoDvzyaK7F/ZANIIFOgb4Haj7mye3Hle0fYZZNdidSs= github.com/ovn-org/libovsdb v0.7.1-0.20240820095311-ce1951614a20/go.mod h1:dJbxEaalQl83nn904K32FaMjlH/qOObZ0bj4ejQ78AI= -github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20241126140656-c95491e46334 h1:DRWKIJpIDHgp9JWOHOwDywnfBnJOyHolGpg3OioY+dI= -github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20241126140656-c95491e46334/go.mod h1:xn0ACVOiv+fi6wJN5y0XeYRbDrAHLgDLCEdageHCObI= +github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20250116185920-20e7a0e40c93 h1:BJxeBVZvLEOOz7TswGbJFC60uOFpqUyJBHp7wvmdVIM= +github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20250116185920-20e7a0e40c93/go.mod h1:9LxDV3rAHlGHAYtVrT62y/fqfIxc5RrDiYi9RVeD0gg= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -846,8 +848,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= @@ -985,10 +987,10 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 h1:k6fQVDQexDE+3jG2SfCQjnHS7OamcP73YMoxEVq5B6k= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0/go.mod h1:t4BrYLHU450Zo9fnydWlIuswB1bm7rM8havDpWOJeDo= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 h1:xvhQxJ/C9+RTnAj5DpTg7LSM1vbbMTiXt7e9hsfqHNw= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0/go.mod h1:Fcvs2Bz1jkDM+Wf5/ozBGmi3tQ/c9zPKLnsipnfhGAo= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= @@ -997,14 +999,14 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffA go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0 h1:1wp/gyxsuYtuE/JFxsQRtcCDtMrO2qMvlfXALU5wkzI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.26.0/go.mod h1:gbTHmghkGgqxMomVQQMur1Nba4M0MQ8AYThXDUjsJ38= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= -go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= -go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= -go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1417,10 +1419,10 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 h1:YcyjlL1PRr2Q17/I0dPk2JmYS5CDXfcdb2Z3YRioEbw= -google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 h1:2035KHhUv+EpyB+hWgJnaWKJOdX1E95w2S8Rr4uWKTs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/convert.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/convert.go index d7b15fcfb3..2e50082ad1 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/convert.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/convert.go @@ -94,7 +94,7 @@ func Int64(val string) (int64, error) { } // Int64Slice converts 'val' where individual integers are separated by -// 'sep' into a int64 slice. +// 'sep' into an int64 slice. func Int64Slice(val, sep string) ([]int64, error) { s := strings.Split(val, sep) values := make([]int64, len(s)) @@ -118,7 +118,7 @@ func Int32(val string) (int32, error) { } // Int32Slice converts 'val' where individual integers are separated by -// 'sep' into a int32 slice. +// 'sep' into an int32 slice. func Int32Slice(val, sep string) ([]int32, error) { s := strings.Split(val, sep) values := make([]int32, len(s)) @@ -190,7 +190,7 @@ func Bytes(val string) ([]byte, error) { } // BytesSlice converts 'val' where individual bytes sequences, encoded in URL-safe -// base64 without padding, are separated by 'sep' into a slice of bytes slices slice. +// base64 without padding, are separated by 'sep' into a slice of byte slices. func BytesSlice(val, sep string) ([][]byte, error) { s := strings.Split(val, sep) values := make([][]byte, len(s)) diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go index 01f5734191..41cd4f5030 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go @@ -81,6 +81,21 @@ func HTTPError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.R mux.errorHandler(ctx, mux, marshaler, w, r, err) } +// HTTPStreamError uses the mux-configured stream error handler to notify error to the client without closing the connection. +func HTTPStreamError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, r *http.Request, err error) { + st := mux.streamErrorHandler(ctx, err) + msg := errorChunk(st) + buf, err := marshaler.Marshal(msg) + if err != nil { + grpclog.Errorf("Failed to marshal an error: %v", err) + return + } + if _, err := w.Write(buf); err != nil { + grpclog.Errorf("Failed to notify error to client: %v", err) + return + } +} + // DefaultHTTPErrorHandler is the default error handler. // If "err" is a gRPC Status, the function replies with the status code mapped by HTTPStatusFromCode. // If "err" is a HTTPStatusError, the function replies with the status code provide by that struct. This is diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go index 9005d6a0bf..2fcd7af3c4 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go @@ -155,7 +155,7 @@ func buildPathsBlindly(name string, in interface{}) []string { return paths } -// fieldMaskPathItem stores a in-progress deconstruction of a path for a fieldmask +// fieldMaskPathItem stores an in-progress deconstruction of a path for a fieldmask type fieldMaskPathItem struct { // the list of prior fields leading up to node connected by dots path string diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshaler_registry.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshaler_registry.go index 0b051e6e89..07c28112c8 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshaler_registry.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshaler_registry.go @@ -86,8 +86,8 @@ func (m marshalerRegistry) add(mime string, marshaler Marshaler) error { // It allows for a mapping of case-sensitive Content-Type MIME type string to runtime.Marshaler interfaces. // // For example, you could allow the client to specify the use of the runtime.JSONPb marshaler -// with a "application/jsonpb" Content-Type and the use of the runtime.JSONBuiltin marshaler -// with a "application/json" Content-Type. +// with an "application/jsonpb" Content-Type and the use of the runtime.JSONBuiltin marshaler +// with an "application/json" Content-Type. // "*" can be used to match any Content-Type. // This can be attached to a ServerMux with the marshaler option. func makeMarshalerMIMERegistry() marshalerRegistry { diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/proto2_convert.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/proto2_convert.go index d549407f20..f710036b35 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/proto2_convert.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/proto2_convert.go @@ -40,7 +40,7 @@ func Float32P(val string) (*float32, error) { } // Int64P parses the given string representation of an integer -// and returns a pointer to a int64 whose value is same as the parsed integer. +// and returns a pointer to an int64 whose value is same as the parsed integer. func Int64P(val string) (*int64, error) { i, err := Int64(val) if err != nil { @@ -50,7 +50,7 @@ func Int64P(val string) (*int64, error) { } // Int32P parses the given string representation of an integer -// and returns a pointer to a int32 whose value is same as the parsed integer. +// and returns a pointer to an int32 whose value is same as the parsed integer. func Int32P(val string) (*int32, error) { i, err := Int32(val) if err != nil { diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/pattern.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/pattern.go index dfe7de4864..38ca39cc53 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/pattern.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/pattern.go @@ -1,6 +1,6 @@ package utilities -// An OpCode is a opcode of compiled path patterns. +// OpCode is an opcode of compiled path patterns. type OpCode int // These constants are the valid values of OpCode. diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/string_array_flag.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/string_array_flag.go index d224ab776c..66aa5f2dcc 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/string_array_flag.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/string_array_flag.go @@ -5,7 +5,7 @@ import ( "strings" ) -// flagInterface is an cut down interface to `flag` +// flagInterface is a cut down interface to `flag` type flagInterface interface { Var(value flag.Value, name string, usage string) } diff --git a/vendor/github.com/klauspost/compress/.goreleaser.yml b/vendor/github.com/klauspost/compress/.goreleaser.yml index a22953805c..4528059ca6 100644 --- a/vendor/github.com/klauspost/compress/.goreleaser.yml +++ b/vendor/github.com/klauspost/compress/.goreleaser.yml @@ -1,5 +1,5 @@ -# This is an example goreleaser.yaml file with some sane defaults. -# Make sure to check the documentation at http://goreleaser.com +version: 2 + before: hooks: - ./gen.sh @@ -99,7 +99,7 @@ archives: checksum: name_template: 'checksums.txt' snapshot: - name_template: "{{ .Tag }}-next" + version_template: "{{ .Tag }}-next" changelog: sort: asc filters: diff --git a/vendor/github.com/klauspost/compress/README.md b/vendor/github.com/klauspost/compress/README.md index 05c7359e48..de264c85a5 100644 --- a/vendor/github.com/klauspost/compress/README.md +++ b/vendor/github.com/klauspost/compress/README.md @@ -16,6 +16,27 @@ This package provides various compression algorithms. # changelog +* Sep 23rd, 2024 - [1.17.10](https://github.com/klauspost/compress/releases/tag/v1.17.10) + * gzhttp: Add TransportAlwaysDecompress option. https://github.com/klauspost/compress/pull/978 + * gzhttp: Add supported decompress request body by @mirecl in https://github.com/klauspost/compress/pull/1002 + * s2: Add EncodeBuffer buffer recycling callback https://github.com/klauspost/compress/pull/982 + * zstd: Improve memory usage on small streaming encodes https://github.com/klauspost/compress/pull/1007 + * flate: read data written with partial flush by @vajexal in https://github.com/klauspost/compress/pull/996 + +* Jun 12th, 2024 - [1.17.9](https://github.com/klauspost/compress/releases/tag/v1.17.9) + * s2: Reduce ReadFrom temporary allocations https://github.com/klauspost/compress/pull/949 + * flate, zstd: Shave some bytes off amd64 matchLen by @greatroar in https://github.com/klauspost/compress/pull/963 + * Upgrade zip/zlib to 1.22.4 upstream https://github.com/klauspost/compress/pull/970 https://github.com/klauspost/compress/pull/971 + * zstd: BuildDict fails with RLE table https://github.com/klauspost/compress/pull/951 + +* Apr 9th, 2024 - [1.17.8](https://github.com/klauspost/compress/releases/tag/v1.17.8) + * zstd: Reject blocks where reserved values are not 0 https://github.com/klauspost/compress/pull/885 + * zstd: Add RLE detection+encoding https://github.com/klauspost/compress/pull/938 + +* Feb 21st, 2024 - [1.17.7](https://github.com/klauspost/compress/releases/tag/v1.17.7) + * s2: Add AsyncFlush method: Complete the block without flushing by @Jille in https://github.com/klauspost/compress/pull/927 + * s2: Fix literal+repeat exceeds dst crash https://github.com/klauspost/compress/pull/930 + * Feb 5th, 2024 - [1.17.6](https://github.com/klauspost/compress/releases/tag/v1.17.6) * zstd: Fix incorrect repeat coding in best mode https://github.com/klauspost/compress/pull/923 * s2: Fix DecodeConcurrent deadlock on errors https://github.com/klauspost/compress/pull/925 @@ -81,7 +102,7 @@ https://github.com/klauspost/compress/pull/919 https://github.com/klauspost/comp * zstd: Various minor improvements by @greatroar in https://github.com/klauspost/compress/pull/788 https://github.com/klauspost/compress/pull/794 https://github.com/klauspost/compress/pull/795 * s2: Fix huge block overflow https://github.com/klauspost/compress/pull/779 * s2: Allow CustomEncoder fallback https://github.com/klauspost/compress/pull/780 - * gzhttp: Suppport ResponseWriter Unwrap() in gzhttp handler by @jgimenez in https://github.com/klauspost/compress/pull/799 + * gzhttp: Support ResponseWriter Unwrap() in gzhttp handler by @jgimenez in https://github.com/klauspost/compress/pull/799 * Mar 13, 2023 - [v1.16.1](https://github.com/klauspost/compress/releases/tag/v1.16.1) * zstd: Speed up + improve best encoder by @greatroar in https://github.com/klauspost/compress/pull/776 @@ -136,7 +157,7 @@ https://github.com/klauspost/compress/pull/919 https://github.com/klauspost/comp * zstd: Add [WithDecodeAllCapLimit](https://pkg.go.dev/github.com/klauspost/compress@v1.15.10/zstd#WithDecodeAllCapLimit) https://github.com/klauspost/compress/pull/649 * Add Go 1.19 - deprecate Go 1.16 https://github.com/klauspost/compress/pull/651 * flate: Improve level 5+6 compression https://github.com/klauspost/compress/pull/656 - * zstd: Improve "better" compresssion https://github.com/klauspost/compress/pull/657 + * zstd: Improve "better" compression https://github.com/klauspost/compress/pull/657 * s2: Improve "best" compression https://github.com/klauspost/compress/pull/658 * s2: Improve "better" compression. https://github.com/klauspost/compress/pull/635 * s2: Slightly faster non-assembly decompression https://github.com/klauspost/compress/pull/646 @@ -339,7 +360,7 @@ While the release has been extensively tested, it is recommended to testing when * s2: Fix binaries. * Feb 25, 2021 (v1.11.8) - * s2: Fixed occational out-of-bounds write on amd64. Upgrade recommended. + * s2: Fixed occasional out-of-bounds write on amd64. Upgrade recommended. * s2: Add AMD64 assembly for better mode. 25-50% faster. [#315](https://github.com/klauspost/compress/pull/315) * s2: Less upfront decoder allocation. [#322](https://github.com/klauspost/compress/pull/322) * zstd: Faster "compression" of incompressible data. [#314](https://github.com/klauspost/compress/pull/314) @@ -518,7 +539,7 @@ While the release has been extensively tested, it is recommended to testing when * Feb 19, 2016: Faster bit writer, level -2 is 15% faster, level 1 is 4% faster. * Feb 19, 2016: Handle small payloads faster in level 1-3. * Feb 19, 2016: Added faster level 2 + 3 compression modes. -* Feb 19, 2016: [Rebalanced compression levels](https://blog.klauspost.com/rebalancing-deflate-compression-levels/), so there is a more even progresssion in terms of compression. New default level is 5. +* Feb 19, 2016: [Rebalanced compression levels](https://blog.klauspost.com/rebalancing-deflate-compression-levels/), so there is a more even progression in terms of compression. New default level is 5. * Feb 14, 2016: Snappy: Merge upstream changes. * Feb 14, 2016: Snappy: Fix aggressive skipping. * Feb 14, 2016: Snappy: Update benchmark. diff --git a/vendor/github.com/klauspost/compress/flate/deflate.go b/vendor/github.com/klauspost/compress/flate/deflate.go index 66d1657d2c..af53fb860c 100644 --- a/vendor/github.com/klauspost/compress/flate/deflate.go +++ b/vendor/github.com/klauspost/compress/flate/deflate.go @@ -861,7 +861,7 @@ func (d *compressor) reset(w io.Writer) { } switch d.compressionLevel.chain { case 0: - // level was NoCompression or ConstantCompresssion. + // level was NoCompression or ConstantCompression. d.windowEnd = 0 default: s := d.state diff --git a/vendor/github.com/klauspost/compress/flate/inflate.go b/vendor/github.com/klauspost/compress/flate/inflate.go index 2f410d64f5..0d7b437f1c 100644 --- a/vendor/github.com/klauspost/compress/flate/inflate.go +++ b/vendor/github.com/klauspost/compress/flate/inflate.go @@ -298,6 +298,14 @@ const ( huffmanGenericReader ) +// flushMode tells decompressor when to return data +type flushMode uint8 + +const ( + syncFlush flushMode = iota // return data after sync flush block + partialFlush // return data after each block +) + // Decompress state. type decompressor struct { // Input source. @@ -332,6 +340,8 @@ type decompressor struct { nb uint final bool + + flushMode flushMode } func (f *decompressor) nextBlock() { @@ -618,7 +628,10 @@ func (f *decompressor) dataBlock() { } if n == 0 { - f.toRead = f.dict.readFlush() + if f.flushMode == syncFlush { + f.toRead = f.dict.readFlush() + } + f.finishBlock() return } @@ -657,8 +670,12 @@ func (f *decompressor) finishBlock() { if f.dict.availRead() > 0 { f.toRead = f.dict.readFlush() } + f.err = io.EOF + } else if f.flushMode == partialFlush && f.dict.availRead() > 0 { + f.toRead = f.dict.readFlush() } + f.step = nextBlock } @@ -789,15 +806,25 @@ func (f *decompressor) Reset(r io.Reader, dict []byte) error { return nil } -// NewReader returns a new ReadCloser that can be used -// to read the uncompressed version of r. -// If r does not also implement io.ByteReader, -// the decompressor may read more data than necessary from r. -// It is the caller's responsibility to call Close on the ReadCloser -// when finished reading. -// -// The ReadCloser returned by NewReader also implements Resetter. -func NewReader(r io.Reader) io.ReadCloser { +type ReaderOpt func(*decompressor) + +// WithPartialBlock tells decompressor to return after each block, +// so it can read data written with partial flush +func WithPartialBlock() ReaderOpt { + return func(f *decompressor) { + f.flushMode = partialFlush + } +} + +// WithDict initializes the reader with a preset dictionary +func WithDict(dict []byte) ReaderOpt { + return func(f *decompressor) { + f.dict.init(maxMatchOffset, dict) + } +} + +// NewReaderOpts returns new reader with provided options +func NewReaderOpts(r io.Reader, opts ...ReaderOpt) io.ReadCloser { fixedHuffmanDecoderInit() var f decompressor @@ -806,9 +833,26 @@ func NewReader(r io.Reader) io.ReadCloser { f.codebits = new([numCodes]int) f.step = nextBlock f.dict.init(maxMatchOffset, nil) + + for _, opt := range opts { + opt(&f) + } + return &f } +// NewReader returns a new ReadCloser that can be used +// to read the uncompressed version of r. +// If r does not also implement io.ByteReader, +// the decompressor may read more data than necessary from r. +// It is the caller's responsibility to call Close on the ReadCloser +// when finished reading. +// +// The ReadCloser returned by NewReader also implements Resetter. +func NewReader(r io.Reader) io.ReadCloser { + return NewReaderOpts(r) +} + // NewReaderDict is like NewReader but initializes the reader // with a preset dictionary. The returned Reader behaves as if // the uncompressed data stream started with the given dictionary, @@ -817,13 +861,5 @@ func NewReader(r io.Reader) io.ReadCloser { // // The ReadCloser returned by NewReader also implements Resetter. func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser { - fixedHuffmanDecoderInit() - - var f decompressor - f.r = makeReader(r) - f.bits = new([maxNumLit + maxNumDist]int) - f.codebits = new([numCodes]int) - f.step = nextBlock - f.dict.init(maxMatchOffset, dict) - return &f + return NewReaderOpts(r, WithDict(dict)) } diff --git a/vendor/github.com/klauspost/compress/fse/decompress.go b/vendor/github.com/klauspost/compress/fse/decompress.go index cc05d0f7ea..0c7dd4ffef 100644 --- a/vendor/github.com/klauspost/compress/fse/decompress.go +++ b/vendor/github.com/klauspost/compress/fse/decompress.go @@ -15,7 +15,7 @@ const ( // It is possible, but by no way guaranteed that corrupt data will // return an error. // It is up to the caller to verify integrity of the returned data. -// Use a predefined Scrach to set maximum acceptable output size. +// Use a predefined Scratch to set maximum acceptable output size. func Decompress(b []byte, s *Scratch) ([]byte, error) { s, err := s.prepare(b) if err != nil { diff --git a/vendor/github.com/klauspost/compress/huff0/decompress.go b/vendor/github.com/klauspost/compress/huff0/decompress.go index 54bd08b25c..0f56b02d74 100644 --- a/vendor/github.com/klauspost/compress/huff0/decompress.go +++ b/vendor/github.com/klauspost/compress/huff0/decompress.go @@ -1136,7 +1136,7 @@ func (s *Scratch) matches(ct cTable, w io.Writer) { errs++ } if errs > 0 { - fmt.Fprintf(w, "%d errros in base, stopping\n", errs) + fmt.Fprintf(w, "%d errors in base, stopping\n", errs) continue } // Ensure that all combinations are covered. @@ -1152,7 +1152,7 @@ func (s *Scratch) matches(ct cTable, w io.Writer) { errs++ } if errs > 20 { - fmt.Fprintf(w, "%d errros, stopping\n", errs) + fmt.Fprintf(w, "%d errors, stopping\n", errs) break } } diff --git a/vendor/github.com/klauspost/compress/s2/encode.go b/vendor/github.com/klauspost/compress/s2/encode.go index 0c9088adfe..20b802270a 100644 --- a/vendor/github.com/klauspost/compress/s2/encode.go +++ b/vendor/github.com/klauspost/compress/s2/encode.go @@ -9,6 +9,9 @@ import ( "encoding/binary" "math" "math/bits" + "sync" + + "github.com/klauspost/compress/internal/race" ) // Encode returns the encoded form of src. The returned slice may be a sub- @@ -52,6 +55,8 @@ func Encode(dst, src []byte) []byte { return dst[:d] } +var estblockPool [2]sync.Pool + // EstimateBlockSize will perform a very fast compression // without outputting the result and return the compressed output size. // The function returns -1 if no improvement could be achieved. @@ -61,9 +66,25 @@ func EstimateBlockSize(src []byte) (d int) { return -1 } if len(src) <= 1024 { - d = calcBlockSizeSmall(src) + const sz, pool = 2048, 0 + tmp, ok := estblockPool[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer estblockPool[pool].Put(tmp) + + d = calcBlockSizeSmall(src, tmp) } else { - d = calcBlockSize(src) + const sz, pool = 32768, 1 + tmp, ok := estblockPool[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer estblockPool[pool].Put(tmp) + + d = calcBlockSize(src, tmp) } if d == 0 { diff --git a/vendor/github.com/klauspost/compress/s2/encode_amd64.go b/vendor/github.com/klauspost/compress/s2/encode_amd64.go index 4f45206a4e..7aadd255fe 100644 --- a/vendor/github.com/klauspost/compress/s2/encode_amd64.go +++ b/vendor/github.com/klauspost/compress/s2/encode_amd64.go @@ -3,10 +3,16 @@ package s2 -import "github.com/klauspost/compress/internal/race" +import ( + "sync" + + "github.com/klauspost/compress/internal/race" +) const hasAmd64Asm = true +var encPools [4]sync.Pool + // encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It // assumes that the varint-encoded length of the decompressed bytes has already // been written. @@ -29,23 +35,60 @@ func encodeBlock(dst, src []byte) (d int) { ) if len(src) >= 4<<20 { - return encodeBlockAsm(dst, src) + const sz, pool = 65536, 0 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeBlockAsm(dst, src, tmp) } if len(src) >= limit12B { - return encodeBlockAsm4MB(dst, src) + const sz, pool = 65536, 0 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeBlockAsm4MB(dst, src, tmp) } if len(src) >= limit10B { - return encodeBlockAsm12B(dst, src) + const sz, pool = 16384, 1 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeBlockAsm12B(dst, src, tmp) } if len(src) >= limit8B { - return encodeBlockAsm10B(dst, src) + const sz, pool = 4096, 2 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeBlockAsm10B(dst, src, tmp) } if len(src) < minNonLiteralBlockSize { return 0 } - return encodeBlockAsm8B(dst, src) + const sz, pool = 1024, 3 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeBlockAsm8B(dst, src, tmp) } +var encBetterPools [5]sync.Pool + // encodeBlockBetter encodes a non-empty src to a guaranteed-large-enough dst. It // assumes that the varint-encoded length of the decompressed bytes has already // been written. @@ -68,21 +111,59 @@ func encodeBlockBetter(dst, src []byte) (d int) { ) if len(src) > 4<<20 { - return encodeBetterBlockAsm(dst, src) + const sz, pool = 589824, 0 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeBetterBlockAsm(dst, src, tmp) } if len(src) >= limit12B { - return encodeBetterBlockAsm4MB(dst, src) + const sz, pool = 589824, 0 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + + return encodeBetterBlockAsm4MB(dst, src, tmp) } if len(src) >= limit10B { - return encodeBetterBlockAsm12B(dst, src) + const sz, pool = 81920, 0 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + + return encodeBetterBlockAsm12B(dst, src, tmp) } if len(src) >= limit8B { - return encodeBetterBlockAsm10B(dst, src) + const sz, pool = 20480, 1 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeBetterBlockAsm10B(dst, src, tmp) } if len(src) < minNonLiteralBlockSize { return 0 } - return encodeBetterBlockAsm8B(dst, src) + + const sz, pool = 5120, 2 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeBetterBlockAsm8B(dst, src, tmp) } // encodeBlockSnappy encodes a non-empty src to a guaranteed-large-enough dst. It @@ -105,22 +186,57 @@ func encodeBlockSnappy(dst, src []byte) (d int) { // Use 8 bit table when less than... limit8B = 512 ) - if len(src) >= 64<<10 { - return encodeSnappyBlockAsm(dst, src) + if len(src) > 65536 { + const sz, pool = 65536, 0 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeSnappyBlockAsm(dst, src, tmp) } if len(src) >= limit12B { - return encodeSnappyBlockAsm64K(dst, src) + const sz, pool = 65536, 0 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeSnappyBlockAsm64K(dst, src, tmp) } if len(src) >= limit10B { - return encodeSnappyBlockAsm12B(dst, src) + const sz, pool = 16384, 1 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeSnappyBlockAsm12B(dst, src, tmp) } if len(src) >= limit8B { - return encodeSnappyBlockAsm10B(dst, src) + const sz, pool = 4096, 2 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeSnappyBlockAsm10B(dst, src, tmp) } if len(src) < minNonLiteralBlockSize { return 0 } - return encodeSnappyBlockAsm8B(dst, src) + const sz, pool = 1024, 3 + tmp, ok := encPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encPools[pool].Put(tmp) + return encodeSnappyBlockAsm8B(dst, src, tmp) } // encodeBlockSnappy encodes a non-empty src to a guaranteed-large-enough dst. It @@ -143,20 +259,59 @@ func encodeBlockBetterSnappy(dst, src []byte) (d int) { // Use 8 bit table when less than... limit8B = 512 ) - if len(src) >= 64<<10 { - return encodeSnappyBetterBlockAsm(dst, src) + if len(src) > 65536 { + const sz, pool = 589824, 0 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeSnappyBetterBlockAsm(dst, src, tmp) } + if len(src) >= limit12B { - return encodeSnappyBetterBlockAsm64K(dst, src) + const sz, pool = 294912, 4 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + + return encodeSnappyBetterBlockAsm64K(dst, src, tmp) } if len(src) >= limit10B { - return encodeSnappyBetterBlockAsm12B(dst, src) + const sz, pool = 81920, 0 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + + return encodeSnappyBetterBlockAsm12B(dst, src, tmp) } if len(src) >= limit8B { - return encodeSnappyBetterBlockAsm10B(dst, src) + const sz, pool = 20480, 1 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeSnappyBetterBlockAsm10B(dst, src, tmp) } if len(src) < minNonLiteralBlockSize { return 0 } - return encodeSnappyBetterBlockAsm8B(dst, src) + + const sz, pool = 5120, 2 + tmp, ok := encBetterPools[pool].Get().(*[sz]byte) + if !ok { + tmp = &[sz]byte{} + } + race.WriteSlice(tmp[:]) + defer encBetterPools[pool].Put(tmp) + return encodeSnappyBetterBlockAsm8B(dst, src, tmp) } diff --git a/vendor/github.com/klauspost/compress/s2/encode_go.go b/vendor/github.com/klauspost/compress/s2/encode_go.go index 6b393c34d3..dd1c973ca5 100644 --- a/vendor/github.com/klauspost/compress/s2/encode_go.go +++ b/vendor/github.com/klauspost/compress/s2/encode_go.go @@ -317,7 +317,7 @@ func matchLen(a []byte, b []byte) int { } // input must be > inputMargin -func calcBlockSize(src []byte) (d int) { +func calcBlockSize(src []byte, _ *[32768]byte) (d int) { // Initialize the hash table. const ( tableBits = 13 @@ -503,7 +503,7 @@ emitRemainder: } // length must be > inputMargin. -func calcBlockSizeSmall(src []byte) (d int) { +func calcBlockSizeSmall(src []byte, _ *[2048]byte) (d int) { // Initialize the hash table. const ( tableBits = 9 diff --git a/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go b/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go index 297e41501b..f43aa81543 100644 --- a/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go +++ b/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go @@ -11,154 +11,154 @@ func _dummy_() // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeBlockAsm(dst []byte, src []byte) int +func encodeBlockAsm(dst []byte, src []byte, tmp *[65536]byte) int // encodeBlockAsm4MB encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 4194304 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeBlockAsm4MB(dst []byte, src []byte) int +func encodeBlockAsm4MB(dst []byte, src []byte, tmp *[65536]byte) int // encodeBlockAsm12B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 16383 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeBlockAsm12B(dst []byte, src []byte) int +func encodeBlockAsm12B(dst []byte, src []byte, tmp *[16384]byte) int // encodeBlockAsm10B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 4095 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeBlockAsm10B(dst []byte, src []byte) int +func encodeBlockAsm10B(dst []byte, src []byte, tmp *[4096]byte) int // encodeBlockAsm8B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 511 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeBlockAsm8B(dst []byte, src []byte) int +func encodeBlockAsm8B(dst []byte, src []byte, tmp *[1024]byte) int // encodeBetterBlockAsm encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 4294967295 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeBetterBlockAsm(dst []byte, src []byte) int +func encodeBetterBlockAsm(dst []byte, src []byte, tmp *[589824]byte) int // encodeBetterBlockAsm4MB encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 4194304 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeBetterBlockAsm4MB(dst []byte, src []byte) int +func encodeBetterBlockAsm4MB(dst []byte, src []byte, tmp *[589824]byte) int // encodeBetterBlockAsm12B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 16383 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeBetterBlockAsm12B(dst []byte, src []byte) int +func encodeBetterBlockAsm12B(dst []byte, src []byte, tmp *[81920]byte) int // encodeBetterBlockAsm10B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 4095 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeBetterBlockAsm10B(dst []byte, src []byte) int +func encodeBetterBlockAsm10B(dst []byte, src []byte, tmp *[20480]byte) int // encodeBetterBlockAsm8B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 511 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeBetterBlockAsm8B(dst []byte, src []byte) int +func encodeBetterBlockAsm8B(dst []byte, src []byte, tmp *[5120]byte) int // encodeSnappyBlockAsm encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 4294967295 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeSnappyBlockAsm(dst []byte, src []byte) int +func encodeSnappyBlockAsm(dst []byte, src []byte, tmp *[65536]byte) int // encodeSnappyBlockAsm64K encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 65535 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeSnappyBlockAsm64K(dst []byte, src []byte) int +func encodeSnappyBlockAsm64K(dst []byte, src []byte, tmp *[65536]byte) int // encodeSnappyBlockAsm12B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 16383 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeSnappyBlockAsm12B(dst []byte, src []byte) int +func encodeSnappyBlockAsm12B(dst []byte, src []byte, tmp *[16384]byte) int // encodeSnappyBlockAsm10B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 4095 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeSnappyBlockAsm10B(dst []byte, src []byte) int +func encodeSnappyBlockAsm10B(dst []byte, src []byte, tmp *[4096]byte) int // encodeSnappyBlockAsm8B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 511 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeSnappyBlockAsm8B(dst []byte, src []byte) int +func encodeSnappyBlockAsm8B(dst []byte, src []byte, tmp *[1024]byte) int // encodeSnappyBetterBlockAsm encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 4294967295 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeSnappyBetterBlockAsm(dst []byte, src []byte) int +func encodeSnappyBetterBlockAsm(dst []byte, src []byte, tmp *[589824]byte) int // encodeSnappyBetterBlockAsm64K encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 65535 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeSnappyBetterBlockAsm64K(dst []byte, src []byte) int +func encodeSnappyBetterBlockAsm64K(dst []byte, src []byte, tmp *[294912]byte) int // encodeSnappyBetterBlockAsm12B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 16383 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeSnappyBetterBlockAsm12B(dst []byte, src []byte) int +func encodeSnappyBetterBlockAsm12B(dst []byte, src []byte, tmp *[81920]byte) int // encodeSnappyBetterBlockAsm10B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 4095 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeSnappyBetterBlockAsm10B(dst []byte, src []byte) int +func encodeSnappyBetterBlockAsm10B(dst []byte, src []byte, tmp *[20480]byte) int // encodeSnappyBetterBlockAsm8B encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 511 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func encodeSnappyBetterBlockAsm8B(dst []byte, src []byte) int +func encodeSnappyBetterBlockAsm8B(dst []byte, src []byte, tmp *[5120]byte) int // calcBlockSize encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 4294967295 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func calcBlockSize(src []byte) int +func calcBlockSize(src []byte, tmp *[32768]byte) int // calcBlockSizeSmall encodes a non-empty src to a guaranteed-large-enough dst. // Maximum input 1024 bytes. // It assumes that the varint-encoded length of the decompressed bytes has already been written. // //go:noescape -func calcBlockSizeSmall(src []byte) int +func calcBlockSizeSmall(src []byte, tmp *[2048]byte) int // emitLiteral writes a literal chunk and returns the number of bytes written. // diff --git a/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s b/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s index 2ff5b33401..df9be687be 100644 --- a/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s +++ b/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s @@ -13,1270 +13,1271 @@ TEXT ·_dummy_(SB), $0 #endif RET -// func encodeBlockAsm(dst []byte, src []byte) int +// func encodeBlockAsm(dst []byte, src []byte, tmp *[65536]byte) int // Requires: BMI, SSE2 -TEXT ·encodeBlockAsm(SB), $65560-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000200, CX - LEAQ 24(SP), DX +TEXT ·encodeBlockAsm(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000200, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeBlockAsm: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeBlockAsm MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX search_loop_encodeBlockAsm: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x06, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeBlockAsm - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x10, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x32, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 + SHLQ $0x10, R11 + IMULQ R9, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 JNE no_repeat_found_encodeBlockAsm - LEAL 1(CX), SI - MOVL 12(SP), DI - MOVL SI, BX - SUBL 16(SP), BX + LEAL 1(DX), DI + MOVL 12(SP), R8 + MOVL DI, SI + SUBL 16(SP), SI JZ repeat_extend_back_end_encodeBlockAsm repeat_extend_back_loop_encodeBlockAsm: - CMPL SI, DI + CMPL DI, R8 JBE repeat_extend_back_end_encodeBlockAsm - MOVB -1(DX)(BX*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(SI*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_encodeBlockAsm - LEAL -1(SI), SI - DECL BX + LEAL -1(DI), DI + DECL SI JNZ repeat_extend_back_loop_encodeBlockAsm repeat_extend_back_end_encodeBlockAsm: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 5(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 5(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_encodeBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET repeat_dst_size_check_encodeBlockAsm: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_encodeBlockAsm - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_encodeBlockAsm - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_encodeBlockAsm - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB three_bytes_repeat_emit_encodeBlockAsm - CMPL BX, $0x01000000 + CMPL SI, $0x01000000 JB four_bytes_repeat_emit_encodeBlockAsm - MOVB $0xfc, (AX) - MOVL BX, 1(AX) - ADDQ $0x05, AX + MOVB $0xfc, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX JMP memmove_long_repeat_emit_encodeBlockAsm four_bytes_repeat_emit_encodeBlockAsm: - MOVL BX, R10 - SHRL $0x10, R10 - MOVB $0xf8, (AX) - MOVW BX, 1(AX) - MOVB R10, 3(AX) - ADDQ $0x04, AX + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX JMP memmove_long_repeat_emit_encodeBlockAsm three_bytes_repeat_emit_encodeBlockAsm: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_repeat_emit_encodeBlockAsm two_bytes_repeat_emit_encodeBlockAsm: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_encodeBlockAsm JMP memmove_long_repeat_emit_encodeBlockAsm one_byte_repeat_emit_encodeBlockAsm: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_repeat_emit_encodeBlockAsm: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_17through32 JMP emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_33through64 emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8: - MOVQ (R9), R10 - MOVQ R10, (AX) + MOVQ (R10), R11 + MOVQ R11, (CX) JMP memmove_end_copy_repeat_emit_encodeBlockAsm emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_repeat_emit_encodeBlockAsm emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_repeat_emit_encodeBlockAsm emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_repeat_emit_encodeBlockAsm: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_repeat_emit_encodeBlockAsm memmove_long_repeat_emit_encodeBlockAsm: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R11 - SHRQ $0x05, R11 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R12 - SUBQ R10, R12 - DECQ R11 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R12 + SHRQ $0x05, R12 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 JA emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_forward_sse_loop_32 - LEAQ -32(R9)(R12*1), R10 - LEAQ -32(AX)(R12*1), R13 + LEAQ -32(R10)(R13*1), R11 + LEAQ -32(CX)(R13*1), R14 emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R13) - MOVOA X5, 16(R13) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 ADDQ $0x20, R13 - ADDQ $0x20, R10 - ADDQ $0x20, R12 - DECQ R11 + DECQ R12 JNA emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_big_loop_back emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_forward_sse_loop_32: - MOVOU -32(R9)(R12*1), X4 - MOVOU -16(R9)(R12*1), X5 - MOVOA X4, -32(AX)(R12*1) - MOVOA X5, -16(AX)(R12*1) - ADDQ $0x20, R12 - CMPQ R8, R12 + MOVOU -32(R10)(R13*1), X4 + MOVOU -16(R10)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R9, R13 JAE emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_repeat_emit_encodeBlockAsm: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+32(FP), R8 - SUBL CX, R8 - LEAQ (DX)(CX*1), R9 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R9 + SUBL DX, R9 + LEAQ (BX)(DX*1), R10 + LEAQ (BX)(SI*1), SI // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_repeat_extend_encodeBlockAsm: - CMPL R8, $0x10 + CMPL R9, $0x10 JB matchlen_match8_repeat_extend_encodeBlockAsm - MOVQ (R9)(R11*1), R10 - MOVQ 8(R9)(R11*1), R12 - XORQ (BX)(R11*1), R10 + MOVQ (R10)(R12*1), R11 + MOVQ 8(R10)(R12*1), R13 + XORQ (SI)(R12*1), R11 JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm - XORQ 8(BX)(R11*1), R12 + XORQ 8(SI)(R12*1), R13 JNZ matchlen_bsf_16repeat_extend_encodeBlockAsm - LEAL -16(R8), R8 - LEAL 16(R11), R11 + LEAL -16(R9), R9 + LEAL 16(R12), R12 JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm matchlen_bsf_16repeat_extend_encodeBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP repeat_extend_forward_end_encodeBlockAsm matchlen_match8_repeat_extend_encodeBlockAsm: - CMPL R8, $0x08 + CMPL R9, $0x08 JB matchlen_match4_repeat_extend_encodeBlockAsm - MOVQ (R9)(R11*1), R10 - XORQ (BX)(R11*1), R10 + MOVQ (R10)(R12*1), R11 + XORQ (SI)(R12*1), R11 JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm - LEAL -8(R8), R8 - LEAL 8(R11), R11 + LEAL -8(R9), R9 + LEAL 8(R12), R12 JMP matchlen_match4_repeat_extend_encodeBlockAsm matchlen_bsf_8_repeat_extend_encodeBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP repeat_extend_forward_end_encodeBlockAsm matchlen_match4_repeat_extend_encodeBlockAsm: - CMPL R8, $0x04 + CMPL R9, $0x04 JB matchlen_match2_repeat_extend_encodeBlockAsm - MOVL (R9)(R11*1), R10 - CMPL (BX)(R11*1), R10 + MOVL (R10)(R12*1), R11 + CMPL (SI)(R12*1), R11 JNE matchlen_match2_repeat_extend_encodeBlockAsm - LEAL -4(R8), R8 - LEAL 4(R11), R11 + LEAL -4(R9), R9 + LEAL 4(R12), R12 matchlen_match2_repeat_extend_encodeBlockAsm: - CMPL R8, $0x01 + CMPL R9, $0x01 JE matchlen_match1_repeat_extend_encodeBlockAsm JB repeat_extend_forward_end_encodeBlockAsm - MOVW (R9)(R11*1), R10 - CMPW (BX)(R11*1), R10 + MOVW (R10)(R12*1), R11 + CMPW (SI)(R12*1), R11 JNE matchlen_match1_repeat_extend_encodeBlockAsm - LEAL 2(R11), R11 - SUBL $0x02, R8 + LEAL 2(R12), R12 + SUBL $0x02, R9 JZ repeat_extend_forward_end_encodeBlockAsm matchlen_match1_repeat_extend_encodeBlockAsm: - MOVB (R9)(R11*1), R10 - CMPB (BX)(R11*1), R10 + MOVB (R10)(R12*1), R11 + CMPB (SI)(R12*1), R11 JNE repeat_extend_forward_end_encodeBlockAsm - LEAL 1(R11), R11 + LEAL 1(R12), R12 repeat_extend_forward_end_encodeBlockAsm: - ADDL R11, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI - TESTL DI, DI + ADDL R12, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + TESTL R8, R8 JZ repeat_as_copy_encodeBlockAsm // emitRepeat emit_repeat_again_match_repeat_encodeBlockAsm: - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_match_repeat_encodeBlockAsm - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_match_repeat_encodeBlockAsm - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_match_repeat_encodeBlockAsm cant_repeat_two_offset_match_repeat_encodeBlockAsm: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_match_repeat_encodeBlockAsm - CMPL BX, $0x00010100 + CMPL SI, $0x00010100 JB repeat_four_match_repeat_encodeBlockAsm - CMPL BX, $0x0100ffff + CMPL SI, $0x0100ffff JB repeat_five_match_repeat_encodeBlockAsm - LEAL -16842747(BX), BX - MOVL $0xfffb001d, (AX) - MOVB $0xff, 4(AX) - ADDQ $0x05, AX + LEAL -16842747(SI), SI + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX JMP emit_repeat_again_match_repeat_encodeBlockAsm repeat_five_match_repeat_encodeBlockAsm: - LEAL -65536(BX), BX - MOVL BX, SI - MOVW $0x001d, (AX) - MOVW BX, 2(AX) - SARL $0x10, SI - MOVB SI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX JMP repeat_end_emit_encodeBlockAsm repeat_four_match_repeat_encodeBlockAsm: - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm repeat_three_match_repeat_encodeBlockAsm: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm repeat_two_match_repeat_encodeBlockAsm: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm repeat_two_offset_match_repeat_encodeBlockAsm: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm repeat_as_copy_encodeBlockAsm: // emitCopy - CMPL SI, $0x00010000 + CMPL DI, $0x00010000 JB two_byte_offset_repeat_as_copy_encodeBlockAsm - CMPL BX, $0x40 + CMPL SI, $0x40 JBE four_bytes_remain_repeat_as_copy_encodeBlockAsm - MOVB $0xff, (AX) - MOVL SI, 1(AX) - LEAL -64(BX), BX - ADDQ $0x05, AX - CMPL BX, $0x04 + MOVB $0xff, (CX) + MOVL DI, 1(CX) + LEAL -64(SI), SI + ADDQ $0x05, CX + CMPL SI, $0x04 JB four_bytes_remain_repeat_as_copy_encodeBlockAsm // emitRepeat emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy: - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy - CMPL BX, $0x00010100 + CMPL SI, $0x00010100 JB repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy - CMPL BX, $0x0100ffff + CMPL SI, $0x0100ffff JB repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy - LEAL -16842747(BX), BX - MOVL $0xfffb001d, (AX) - MOVB $0xff, 4(AX) - ADDQ $0x05, AX + LEAL -16842747(SI), SI + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX JMP emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy: - LEAL -65536(BX), BX - MOVL BX, SI - MOVW $0x001d, (AX) - MOVW BX, 2(AX) - SARL $0x10, SI - MOVB SI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX JMP repeat_end_emit_encodeBlockAsm repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy: - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm four_bytes_remain_repeat_as_copy_encodeBlockAsm: - TESTL BX, BX + TESTL SI, SI JZ repeat_end_emit_encodeBlockAsm - XORL DI, DI - LEAL -1(DI)(BX*4), BX - MOVB BL, (AX) - MOVL SI, 1(AX) - ADDQ $0x05, AX + XORL R8, R8 + LEAL -1(R8)(SI*4), SI + MOVB SI, (CX) + MOVL DI, 1(CX) + ADDQ $0x05, CX JMP repeat_end_emit_encodeBlockAsm two_byte_offset_repeat_as_copy_encodeBlockAsm: - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_encodeBlockAsm - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE long_offset_short_repeat_as_copy_encodeBlockAsm - MOVL $0x00000001, DI - LEAL 16(DI), DI - MOVB SI, 1(AX) - MOVL SI, R8 - SHRL $0x08, R8 - SHLL $0x05, R8 - ORL R8, DI - MOVB DI, (AX) - ADDQ $0x02, AX - SUBL $0x08, BX + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB DI, 1(CX) + MOVL DI, R9 + SHRL $0x08, R9 + SHLL $0x05, R9 + ORL R9, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + SUBL $0x08, SI // emitRepeat - LEAL -4(BX), BX + LEAL -4(SI), SI JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b - CMPL BX, $0x00010100 + CMPL SI, $0x00010100 JB repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b - CMPL BX, $0x0100ffff + CMPL SI, $0x0100ffff JB repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b - LEAL -16842747(BX), BX - MOVL $0xfffb001d, (AX) - MOVB $0xff, 4(AX) - ADDQ $0x05, AX + LEAL -16842747(SI), SI + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX JMP emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: - LEAL -65536(BX), BX - MOVL BX, SI - MOVW $0x001d, (AX) - MOVW BX, 2(AX) - SARL $0x10, SI - MOVB SI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX JMP repeat_end_emit_encodeBlockAsm repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm long_offset_short_repeat_as_copy_encodeBlockAsm: - MOVB $0xee, (AX) - MOVW SI, 1(AX) - LEAL -60(BX), BX - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX // emitRepeat emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short: - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short - CMPL BX, $0x00010100 + CMPL SI, $0x00010100 JB repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short - CMPL BX, $0x0100ffff + CMPL SI, $0x0100ffff JB repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short - LEAL -16842747(BX), BX - MOVL $0xfffb001d, (AX) - MOVB $0xff, 4(AX) - ADDQ $0x05, AX + LEAL -16842747(SI), SI + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX JMP emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short: - LEAL -65536(BX), BX - MOVL BX, SI - MOVW $0x001d, (AX) - MOVW BX, 2(AX) - SARL $0x10, SI - MOVB SI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX JMP repeat_end_emit_encodeBlockAsm repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short: - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm two_byte_offset_short_repeat_as_copy_encodeBlockAsm: - MOVL BX, DI - SHLL $0x02, DI - CMPL BX, $0x0c + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_encodeBlockAsm - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE emit_copy_three_repeat_as_copy_encodeBlockAsm - LEAL -15(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm emit_copy_three_repeat_as_copy_encodeBlockAsm: - LEAL -2(DI), DI - MOVB DI, (AX) - MOVW SI, 1(AX) - ADDQ $0x03, AX + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX repeat_end_emit_encodeBlockAsm: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_encodeBlockAsm no_repeat_found_encodeBlockAsm: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeBlockAsm - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_encodeBlockAsm - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_encodeBlockAsm - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeBlockAsm candidate3_match_encodeBlockAsm: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_encodeBlockAsm candidate2_match_encodeBlockAsm: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_encodeBlockAsm: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeBlockAsm match_extend_back_loop_encodeBlockAsm: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeBlockAsm - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeBlockAsm - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeBlockAsm JMP match_extend_back_loop_encodeBlockAsm match_extend_back_end_encodeBlockAsm: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 5(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 5(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeBlockAsm: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_encodeBlockAsm - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), DI - CMPL DI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c JB one_byte_match_emit_encodeBlockAsm - CMPL DI, $0x00000100 + CMPL R8, $0x00000100 JB two_bytes_match_emit_encodeBlockAsm - CMPL DI, $0x00010000 + CMPL R8, $0x00010000 JB three_bytes_match_emit_encodeBlockAsm - CMPL DI, $0x01000000 + CMPL R8, $0x01000000 JB four_bytes_match_emit_encodeBlockAsm - MOVB $0xfc, (AX) - MOVL DI, 1(AX) - ADDQ $0x05, AX + MOVB $0xfc, (CX) + MOVL R8, 1(CX) + ADDQ $0x05, CX JMP memmove_long_match_emit_encodeBlockAsm four_bytes_match_emit_encodeBlockAsm: - MOVL DI, R9 - SHRL $0x10, R9 - MOVB $0xf8, (AX) - MOVW DI, 1(AX) - MOVB R9, 3(AX) - ADDQ $0x04, AX + MOVL R8, R10 + SHRL $0x10, R10 + MOVB $0xf8, (CX) + MOVW R8, 1(CX) + MOVB R10, 3(CX) + ADDQ $0x04, CX JMP memmove_long_match_emit_encodeBlockAsm three_bytes_match_emit_encodeBlockAsm: - MOVB $0xf4, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeBlockAsm two_bytes_match_emit_encodeBlockAsm: - MOVB $0xf0, (AX) - MOVB DI, 1(AX) - ADDQ $0x02, AX - CMPL DI, $0x40 + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 JB memmove_match_emit_encodeBlockAsm JMP memmove_long_match_emit_encodeBlockAsm one_byte_match_emit_encodeBlockAsm: - SHLB $0x02, DI - MOVB DI, (AX) - ADDQ $0x01, AX + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeBlockAsm: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_33through64 emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8: - MOVQ (SI), R9 - MOVQ R9, (AX) + MOVQ (DI), R10 + MOVQ R10, (CX) JMP memmove_end_copy_match_emit_encodeBlockAsm emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8through16: - MOVQ (SI), R9 - MOVQ -8(SI)(R8*1), SI - MOVQ R9, (AX) - MOVQ SI, -8(AX)(R8*1) + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBlockAsm emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_17through32: - MOVOU (SI), X0 - MOVOU -16(SI)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBlockAsm emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_33through64: - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeBlockAsm: - MOVQ DI, AX + MOVQ R8, CX JMP emit_literal_done_match_emit_encodeBlockAsm memmove_long_match_emit_encodeBlockAsm: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveLong - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVQ R8, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_forward_sse_loop_32 - LEAQ -32(SI)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_big_loop_back emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_forward_sse_loop_32: - MOVOU -32(SI)(R11*1), X4 - MOVOU -16(SI)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ R8, R11 + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 JAE emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ DI, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX emit_literal_done_match_emit_encodeBlockAsm: match_nolit_loop_encodeBlockAsm: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_encodeBlockAsm: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_encodeBlockAsm - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_encodeBlockAsm - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_encodeBlockAsm matchlen_bsf_16match_nolit_encodeBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_encodeBlockAsm matchlen_match8_match_nolit_encodeBlockAsm: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_encodeBlockAsm - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_encodeBlockAsm matchlen_bsf_8_match_nolit_encodeBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_encodeBlockAsm matchlen_match4_match_nolit_encodeBlockAsm: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_encodeBlockAsm - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_encodeBlockAsm - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_encodeBlockAsm: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_encodeBlockAsm JB match_nolit_end_encodeBlockAsm - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_encodeBlockAsm - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_encodeBlockAsm matchlen_match1_match_nolit_encodeBlockAsm: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_encodeBlockAsm - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_encodeBlockAsm: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB two_byte_offset_match_nolit_encodeBlockAsm - CMPL R9, $0x40 + CMPL R10, $0x40 JBE four_bytes_remain_match_nolit_encodeBlockAsm - MOVB $0xff, (AX) - MOVL BX, 1(AX) - LEAL -64(R9), R9 - ADDQ $0x05, AX - CMPL R9, $0x04 + MOVB $0xff, (CX) + MOVL SI, 1(CX) + LEAL -64(R10), R10 + ADDQ $0x05, CX + CMPL R10, $0x04 JB four_bytes_remain_match_nolit_encodeBlockAsm // emitRepeat emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy: - MOVL R9, SI - LEAL -4(R9), R9 - CMPL SI, $0x08 + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm_emit_copy - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JB repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm_emit_copy - CMPL R9, $0x00010100 + CMPL R10, $0x00010100 JB repeat_four_match_nolit_encodeBlockAsm_emit_copy - CMPL R9, $0x0100ffff + CMPL R10, $0x0100ffff JB repeat_five_match_nolit_encodeBlockAsm_emit_copy - LEAL -16842747(R9), R9 - MOVL $0xfffb001d, (AX) - MOVB $0xff, 4(AX) - ADDQ $0x05, AX + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX JMP emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy repeat_five_match_nolit_encodeBlockAsm_emit_copy: - LEAL -65536(R9), R9 - MOVL R9, BX - MOVW $0x001d, (AX) - MOVW R9, 2(AX) - SARL $0x10, BX - MOVB BL, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_four_match_nolit_encodeBlockAsm_emit_copy: - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_three_match_nolit_encodeBlockAsm_emit_copy: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_two_match_nolit_encodeBlockAsm_emit_copy: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy: - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm four_bytes_remain_match_nolit_encodeBlockAsm: - TESTL R9, R9 + TESTL R10, R10 JZ match_nolit_emitcopy_end_encodeBlockAsm - XORL SI, SI - LEAL -1(SI)(R9*4), R9 - MOVB R9, (AX) - MOVL BX, 1(AX) - ADDQ $0x05, AX + XORL DI, DI + LEAL -1(DI)(R10*4), R10 + MOVB R10, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBlockAsm two_byte_offset_match_nolit_encodeBlockAsm: - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_encodeBlockAsm - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE long_offset_short_match_nolit_encodeBlockAsm - MOVL $0x00000001, SI - LEAL 16(SI), SI - MOVB BL, 1(AX) - MOVL BX, DI - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, SI - MOVB SI, (AX) - ADDQ $0x02, AX - SUBL $0x08, R9 + MOVL $0x00000001, DI + LEAL 16(DI), DI + MOVB SI, 1(CX) + MOVL SI, R8 + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, DI + MOVB DI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R10 // emitRepeat - LEAL -4(R9), R9 + LEAL -4(R10), R10 JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short_2b: - MOVL R9, SI - LEAL -4(R9), R9 - CMPL SI, $0x08 + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm_emit_copy_short_2b - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JB repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm_emit_copy_short_2b - CMPL R9, $0x00010100 + CMPL R10, $0x00010100 JB repeat_four_match_nolit_encodeBlockAsm_emit_copy_short_2b - CMPL R9, $0x0100ffff + CMPL R10, $0x0100ffff JB repeat_five_match_nolit_encodeBlockAsm_emit_copy_short_2b - LEAL -16842747(R9), R9 - MOVL $0xfffb001d, (AX) - MOVB $0xff, 4(AX) - ADDQ $0x05, AX + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX JMP emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short_2b repeat_five_match_nolit_encodeBlockAsm_emit_copy_short_2b: - LEAL -65536(R9), R9 - MOVL R9, BX - MOVW $0x001d, (AX) - MOVW R9, 2(AX) - SARL $0x10, BX - MOVB BL, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_four_match_nolit_encodeBlockAsm_emit_copy_short_2b: - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_three_match_nolit_encodeBlockAsm_emit_copy_short_2b: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_two_match_nolit_encodeBlockAsm_emit_copy_short_2b: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b: - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm long_offset_short_match_nolit_encodeBlockAsm: - MOVB $0xee, (AX) - MOVW BX, 1(AX) - LEAL -60(R9), R9 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX // emitRepeat emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short: - MOVL R9, SI - LEAL -4(R9), R9 - CMPL SI, $0x08 + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm_emit_copy_short - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JB repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm_emit_copy_short - CMPL R9, $0x00010100 + CMPL R10, $0x00010100 JB repeat_four_match_nolit_encodeBlockAsm_emit_copy_short - CMPL R9, $0x0100ffff + CMPL R10, $0x0100ffff JB repeat_five_match_nolit_encodeBlockAsm_emit_copy_short - LEAL -16842747(R9), R9 - MOVL $0xfffb001d, (AX) - MOVB $0xff, 4(AX) - ADDQ $0x05, AX + LEAL -16842747(R10), R10 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX JMP emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short repeat_five_match_nolit_encodeBlockAsm_emit_copy_short: - LEAL -65536(R9), R9 - MOVL R9, BX - MOVW $0x001d, (AX) - MOVW R9, 2(AX) - SARL $0x10, BX - MOVB BL, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_four_match_nolit_encodeBlockAsm_emit_copy_short: - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_three_match_nolit_encodeBlockAsm_emit_copy_short: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_two_match_nolit_encodeBlockAsm_emit_copy_short: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short: - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm two_byte_offset_short_match_nolit_encodeBlockAsm: - MOVL R9, SI - SHLL $0x02, SI - CMPL R9, $0x0c + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_encodeBlockAsm - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE emit_copy_three_match_nolit_encodeBlockAsm - LEAL -15(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm emit_copy_three_match_nolit_encodeBlockAsm: - LEAL -2(SI), SI - MOVB SI, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeBlockAsm: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeBlockAsm - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeBlockAsm: - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x10, DI - IMULQ R8, DI - SHRQ $0x32, DI - SHLQ $0x10, BX - IMULQ R8, BX - SHRQ $0x32, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x10, R8 + IMULQ R9, R8 + SHRQ $0x32, R8 + SHLQ $0x10, SI + IMULQ R9, SI + SHRQ $0x32, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_encodeBlockAsm - INCL CX + INCL DX JMP search_loop_encodeBlockAsm emit_remainder_encodeBlockAsm: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 5(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 5(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeBlockAsm: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeBlockAsm - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeBlockAsm @@ -1286,41 +1287,41 @@ emit_remainder_ok_encodeBlockAsm: JB three_bytes_emit_remainder_encodeBlockAsm CMPL DX, $0x01000000 JB four_bytes_emit_remainder_encodeBlockAsm - MOVB $0xfc, (AX) - MOVL DX, 1(AX) - ADDQ $0x05, AX + MOVB $0xfc, (CX) + MOVL DX, 1(CX) + ADDQ $0x05, CX JMP memmove_long_emit_remainder_encodeBlockAsm four_bytes_emit_remainder_encodeBlockAsm: MOVL DX, BX SHRL $0x10, BX - MOVB $0xf8, (AX) - MOVW DX, 1(AX) - MOVB BL, 3(AX) - ADDQ $0x04, AX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX JMP memmove_long_emit_remainder_encodeBlockAsm three_bytes_emit_remainder_encodeBlockAsm: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeBlockAsm two_bytes_emit_remainder_encodeBlockAsm: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeBlockAsm JMP memmove_long_emit_remainder_encodeBlockAsm one_byte_emit_remainder_encodeBlockAsm: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeBlockAsm: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -1336,73 +1337,73 @@ memmove_emit_remainder_encodeBlockAsm: JMP emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeBlockAsm emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeBlockAsm: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeBlockAsm memmove_long_emit_remainder_encodeBlockAsm: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_big_loop_back: MOVOU (SI), X4 @@ -1416,1199 +1417,1200 @@ emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeBlockAsm: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeBlockAsm4MB(dst []byte, src []byte) int +// func encodeBlockAsm4MB(dst []byte, src []byte, tmp *[65536]byte) int // Requires: BMI, SSE2 -TEXT ·encodeBlockAsm4MB(SB), $65560-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000200, CX - LEAQ 24(SP), DX +TEXT ·encodeBlockAsm4MB(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000200, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeBlockAsm4MB: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeBlockAsm4MB MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX search_loop_encodeBlockAsm4MB: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x06, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeBlockAsm4MB - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x10, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x32, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 + SHLQ $0x10, R11 + IMULQ R9, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 JNE no_repeat_found_encodeBlockAsm4MB - LEAL 1(CX), SI - MOVL 12(SP), DI - MOVL SI, BX - SUBL 16(SP), BX + LEAL 1(DX), DI + MOVL 12(SP), R8 + MOVL DI, SI + SUBL 16(SP), SI JZ repeat_extend_back_end_encodeBlockAsm4MB repeat_extend_back_loop_encodeBlockAsm4MB: - CMPL SI, DI + CMPL DI, R8 JBE repeat_extend_back_end_encodeBlockAsm4MB - MOVB -1(DX)(BX*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(SI*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_encodeBlockAsm4MB - LEAL -1(SI), SI - DECL BX + LEAL -1(DI), DI + DECL SI JNZ repeat_extend_back_loop_encodeBlockAsm4MB repeat_extend_back_end_encodeBlockAsm4MB: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 4(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 4(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_encodeBlockAsm4MB - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET repeat_dst_size_check_encodeBlockAsm4MB: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_encodeBlockAsm4MB - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_encodeBlockAsm4MB - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_encodeBlockAsm4MB - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB three_bytes_repeat_emit_encodeBlockAsm4MB - MOVL BX, R10 - SHRL $0x10, R10 - MOVB $0xf8, (AX) - MOVW BX, 1(AX) - MOVB R10, 3(AX) - ADDQ $0x04, AX + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX JMP memmove_long_repeat_emit_encodeBlockAsm4MB three_bytes_repeat_emit_encodeBlockAsm4MB: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_repeat_emit_encodeBlockAsm4MB two_bytes_repeat_emit_encodeBlockAsm4MB: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_encodeBlockAsm4MB JMP memmove_long_repeat_emit_encodeBlockAsm4MB one_byte_repeat_emit_encodeBlockAsm4MB: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_repeat_emit_encodeBlockAsm4MB: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_17through32 JMP emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_33through64 emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8: - MOVQ (R9), R10 - MOVQ R10, (AX) + MOVQ (R10), R11 + MOVQ R11, (CX) JMP memmove_end_copy_repeat_emit_encodeBlockAsm4MB emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_repeat_emit_encodeBlockAsm4MB emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_repeat_emit_encodeBlockAsm4MB emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_repeat_emit_encodeBlockAsm4MB: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_repeat_emit_encodeBlockAsm4MB memmove_long_repeat_emit_encodeBlockAsm4MB: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R11 - SHRQ $0x05, R11 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R12 - SUBQ R10, R12 - DECQ R11 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R12 + SHRQ $0x05, R12 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 JA emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32 - LEAQ -32(R9)(R12*1), R10 - LEAQ -32(AX)(R12*1), R13 + LEAQ -32(R10)(R13*1), R11 + LEAQ -32(CX)(R13*1), R14 emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R13) - MOVOA X5, 16(R13) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 ADDQ $0x20, R13 - ADDQ $0x20, R10 - ADDQ $0x20, R12 - DECQ R11 + DECQ R12 JNA emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_big_loop_back emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32: - MOVOU -32(R9)(R12*1), X4 - MOVOU -16(R9)(R12*1), X5 - MOVOA X4, -32(AX)(R12*1) - MOVOA X5, -16(AX)(R12*1) - ADDQ $0x20, R12 - CMPQ R8, R12 + MOVOU -32(R10)(R13*1), X4 + MOVOU -16(R10)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R9, R13 JAE emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_repeat_emit_encodeBlockAsm4MB: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+32(FP), R8 - SUBL CX, R8 - LEAQ (DX)(CX*1), R9 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R9 + SUBL DX, R9 + LEAQ (BX)(DX*1), R10 + LEAQ (BX)(SI*1), SI // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_repeat_extend_encodeBlockAsm4MB: - CMPL R8, $0x10 + CMPL R9, $0x10 JB matchlen_match8_repeat_extend_encodeBlockAsm4MB - MOVQ (R9)(R11*1), R10 - MOVQ 8(R9)(R11*1), R12 - XORQ (BX)(R11*1), R10 + MOVQ (R10)(R12*1), R11 + MOVQ 8(R10)(R12*1), R13 + XORQ (SI)(R12*1), R11 JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm4MB - XORQ 8(BX)(R11*1), R12 + XORQ 8(SI)(R12*1), R13 JNZ matchlen_bsf_16repeat_extend_encodeBlockAsm4MB - LEAL -16(R8), R8 - LEAL 16(R11), R11 + LEAL -16(R9), R9 + LEAL 16(R12), R12 JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm4MB matchlen_bsf_16repeat_extend_encodeBlockAsm4MB: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP repeat_extend_forward_end_encodeBlockAsm4MB matchlen_match8_repeat_extend_encodeBlockAsm4MB: - CMPL R8, $0x08 + CMPL R9, $0x08 JB matchlen_match4_repeat_extend_encodeBlockAsm4MB - MOVQ (R9)(R11*1), R10 - XORQ (BX)(R11*1), R10 + MOVQ (R10)(R12*1), R11 + XORQ (SI)(R12*1), R11 JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm4MB - LEAL -8(R8), R8 - LEAL 8(R11), R11 + LEAL -8(R9), R9 + LEAL 8(R12), R12 JMP matchlen_match4_repeat_extend_encodeBlockAsm4MB matchlen_bsf_8_repeat_extend_encodeBlockAsm4MB: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP repeat_extend_forward_end_encodeBlockAsm4MB matchlen_match4_repeat_extend_encodeBlockAsm4MB: - CMPL R8, $0x04 + CMPL R9, $0x04 JB matchlen_match2_repeat_extend_encodeBlockAsm4MB - MOVL (R9)(R11*1), R10 - CMPL (BX)(R11*1), R10 + MOVL (R10)(R12*1), R11 + CMPL (SI)(R12*1), R11 JNE matchlen_match2_repeat_extend_encodeBlockAsm4MB - LEAL -4(R8), R8 - LEAL 4(R11), R11 + LEAL -4(R9), R9 + LEAL 4(R12), R12 matchlen_match2_repeat_extend_encodeBlockAsm4MB: - CMPL R8, $0x01 + CMPL R9, $0x01 JE matchlen_match1_repeat_extend_encodeBlockAsm4MB JB repeat_extend_forward_end_encodeBlockAsm4MB - MOVW (R9)(R11*1), R10 - CMPW (BX)(R11*1), R10 + MOVW (R10)(R12*1), R11 + CMPW (SI)(R12*1), R11 JNE matchlen_match1_repeat_extend_encodeBlockAsm4MB - LEAL 2(R11), R11 - SUBL $0x02, R8 + LEAL 2(R12), R12 + SUBL $0x02, R9 JZ repeat_extend_forward_end_encodeBlockAsm4MB matchlen_match1_repeat_extend_encodeBlockAsm4MB: - MOVB (R9)(R11*1), R10 - CMPB (BX)(R11*1), R10 + MOVB (R10)(R12*1), R11 + CMPB (SI)(R12*1), R11 JNE repeat_extend_forward_end_encodeBlockAsm4MB - LEAL 1(R11), R11 + LEAL 1(R12), R12 repeat_extend_forward_end_encodeBlockAsm4MB: - ADDL R11, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI - TESTL DI, DI + ADDL R12, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + TESTL R8, R8 JZ repeat_as_copy_encodeBlockAsm4MB // emitRepeat - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_match_repeat_encodeBlockAsm4MB - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_match_repeat_encodeBlockAsm4MB - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_match_repeat_encodeBlockAsm4MB cant_repeat_two_offset_match_repeat_encodeBlockAsm4MB: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_match_repeat_encodeBlockAsm4MB - CMPL BX, $0x00010100 + CMPL SI, $0x00010100 JB repeat_four_match_repeat_encodeBlockAsm4MB - LEAL -65536(BX), BX - MOVL BX, SI - MOVW $0x001d, (AX) - MOVW BX, 2(AX) - SARL $0x10, SI - MOVB SI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_four_match_repeat_encodeBlockAsm4MB: - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_three_match_repeat_encodeBlockAsm4MB: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_two_match_repeat_encodeBlockAsm4MB: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_two_offset_match_repeat_encodeBlockAsm4MB: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_as_copy_encodeBlockAsm4MB: // emitCopy - CMPL SI, $0x00010000 + CMPL DI, $0x00010000 JB two_byte_offset_repeat_as_copy_encodeBlockAsm4MB - CMPL BX, $0x40 + CMPL SI, $0x40 JBE four_bytes_remain_repeat_as_copy_encodeBlockAsm4MB - MOVB $0xff, (AX) - MOVL SI, 1(AX) - LEAL -64(BX), BX - ADDQ $0x05, AX - CMPL BX, $0x04 + MOVB $0xff, (CX) + MOVL DI, 1(CX) + LEAL -64(SI), SI + ADDQ $0x05, CX + CMPL SI, $0x04 JB four_bytes_remain_repeat_as_copy_encodeBlockAsm4MB // emitRepeat - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy - CMPL BX, $0x00010100 + CMPL SI, $0x00010100 JB repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy - LEAL -65536(BX), BX - MOVL BX, SI - MOVW $0x001d, (AX) - MOVW BX, 2(AX) - SARL $0x10, SI - MOVB SI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy: - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm4MB four_bytes_remain_repeat_as_copy_encodeBlockAsm4MB: - TESTL BX, BX + TESTL SI, SI JZ repeat_end_emit_encodeBlockAsm4MB - XORL DI, DI - LEAL -1(DI)(BX*4), BX - MOVB BL, (AX) - MOVL SI, 1(AX) - ADDQ $0x05, AX + XORL R8, R8 + LEAL -1(R8)(SI*4), SI + MOVB SI, (CX) + MOVL DI, 1(CX) + ADDQ $0x05, CX JMP repeat_end_emit_encodeBlockAsm4MB two_byte_offset_repeat_as_copy_encodeBlockAsm4MB: - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_encodeBlockAsm4MB - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE long_offset_short_repeat_as_copy_encodeBlockAsm4MB - MOVL $0x00000001, DI - LEAL 16(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX - SUBL $0x08, BX + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + SUBL $0x08, SI // emitRepeat - LEAL -4(BX), BX + LEAL -4(SI), SI JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b - CMPL BX, $0x00010100 + CMPL SI, $0x00010100 JB repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b - LEAL -65536(BX), BX - MOVL BX, SI - MOVW $0x001d, (AX) - MOVW BX, 2(AX) - SARL $0x10, SI - MOVB SI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm4MB long_offset_short_repeat_as_copy_encodeBlockAsm4MB: - MOVB $0xee, (AX) - MOVW SI, 1(AX) - LEAL -60(BX), BX - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX // emitRepeat - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short - CMPL BX, $0x00010100 + CMPL SI, $0x00010100 JB repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short - LEAL -65536(BX), BX - MOVL BX, SI - MOVW $0x001d, (AX) - MOVW BX, 2(AX) - SARL $0x10, SI - MOVB SI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(SI), SI + MOVL SI, DI + MOVW $0x001d, (CX) + MOVW SI, 2(CX) + SARL $0x10, DI + MOVB DI, 4(CX) + ADDQ $0x05, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm4MB repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm4MB two_byte_offset_short_repeat_as_copy_encodeBlockAsm4MB: - MOVL BX, DI - SHLL $0x02, DI - CMPL BX, $0x0c + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_encodeBlockAsm4MB - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE emit_copy_three_repeat_as_copy_encodeBlockAsm4MB - LEAL -15(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm4MB emit_copy_three_repeat_as_copy_encodeBlockAsm4MB: - LEAL -2(DI), DI - MOVB DI, (AX) - MOVW SI, 1(AX) - ADDQ $0x03, AX + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX repeat_end_emit_encodeBlockAsm4MB: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_encodeBlockAsm4MB no_repeat_found_encodeBlockAsm4MB: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeBlockAsm4MB - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_encodeBlockAsm4MB - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_encodeBlockAsm4MB - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeBlockAsm4MB candidate3_match_encodeBlockAsm4MB: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_encodeBlockAsm4MB candidate2_match_encodeBlockAsm4MB: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_encodeBlockAsm4MB: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeBlockAsm4MB match_extend_back_loop_encodeBlockAsm4MB: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeBlockAsm4MB - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeBlockAsm4MB - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeBlockAsm4MB JMP match_extend_back_loop_encodeBlockAsm4MB match_extend_back_end_encodeBlockAsm4MB: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 4(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 4(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeBlockAsm4MB - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeBlockAsm4MB: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_encodeBlockAsm4MB - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), DI - CMPL DI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c JB one_byte_match_emit_encodeBlockAsm4MB - CMPL DI, $0x00000100 + CMPL R8, $0x00000100 JB two_bytes_match_emit_encodeBlockAsm4MB - CMPL DI, $0x00010000 + CMPL R8, $0x00010000 JB three_bytes_match_emit_encodeBlockAsm4MB - MOVL DI, R9 - SHRL $0x10, R9 - MOVB $0xf8, (AX) - MOVW DI, 1(AX) - MOVB R9, 3(AX) - ADDQ $0x04, AX + MOVL R8, R10 + SHRL $0x10, R10 + MOVB $0xf8, (CX) + MOVW R8, 1(CX) + MOVB R10, 3(CX) + ADDQ $0x04, CX JMP memmove_long_match_emit_encodeBlockAsm4MB three_bytes_match_emit_encodeBlockAsm4MB: - MOVB $0xf4, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeBlockAsm4MB two_bytes_match_emit_encodeBlockAsm4MB: - MOVB $0xf0, (AX) - MOVB DI, 1(AX) - ADDQ $0x02, AX - CMPL DI, $0x40 + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 JB memmove_match_emit_encodeBlockAsm4MB JMP memmove_long_match_emit_encodeBlockAsm4MB one_byte_match_emit_encodeBlockAsm4MB: - SHLB $0x02, DI - MOVB DI, (AX) - ADDQ $0x01, AX + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeBlockAsm4MB: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_33through64 emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8: - MOVQ (SI), R9 - MOVQ R9, (AX) + MOVQ (DI), R10 + MOVQ R10, (CX) JMP memmove_end_copy_match_emit_encodeBlockAsm4MB emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8through16: - MOVQ (SI), R9 - MOVQ -8(SI)(R8*1), SI - MOVQ R9, (AX) - MOVQ SI, -8(AX)(R8*1) + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBlockAsm4MB emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_17through32: - MOVOU (SI), X0 - MOVOU -16(SI)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBlockAsm4MB emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_33through64: - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeBlockAsm4MB: - MOVQ DI, AX + MOVQ R8, CX JMP emit_literal_done_match_emit_encodeBlockAsm4MB memmove_long_match_emit_encodeBlockAsm4MB: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveLong - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVQ R8, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32 - LEAQ -32(SI)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_big_loop_back emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32: - MOVOU -32(SI)(R11*1), X4 - MOVOU -16(SI)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ R8, R11 + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 JAE emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ DI, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX emit_literal_done_match_emit_encodeBlockAsm4MB: match_nolit_loop_encodeBlockAsm4MB: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_encodeBlockAsm4MB: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_encodeBlockAsm4MB - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm4MB - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_encodeBlockAsm4MB - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_encodeBlockAsm4MB matchlen_bsf_16match_nolit_encodeBlockAsm4MB: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_encodeBlockAsm4MB matchlen_match8_match_nolit_encodeBlockAsm4MB: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_encodeBlockAsm4MB - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm4MB - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_encodeBlockAsm4MB matchlen_bsf_8_match_nolit_encodeBlockAsm4MB: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_encodeBlockAsm4MB matchlen_match4_match_nolit_encodeBlockAsm4MB: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_encodeBlockAsm4MB - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_encodeBlockAsm4MB - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_encodeBlockAsm4MB: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_encodeBlockAsm4MB JB match_nolit_end_encodeBlockAsm4MB - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_encodeBlockAsm4MB - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_encodeBlockAsm4MB matchlen_match1_match_nolit_encodeBlockAsm4MB: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_encodeBlockAsm4MB - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_encodeBlockAsm4MB: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB two_byte_offset_match_nolit_encodeBlockAsm4MB - CMPL R9, $0x40 + CMPL R10, $0x40 JBE four_bytes_remain_match_nolit_encodeBlockAsm4MB - MOVB $0xff, (AX) - MOVL BX, 1(AX) - LEAL -64(R9), R9 - ADDQ $0x05, AX - CMPL R9, $0x04 + MOVB $0xff, (CX) + MOVL SI, 1(CX) + LEAL -64(R10), R10 + ADDQ $0x05, CX + CMPL R10, $0x04 JB four_bytes_remain_match_nolit_encodeBlockAsm4MB // emitRepeat - MOVL R9, SI - LEAL -4(R9), R9 - CMPL SI, $0x08 + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JB repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy - CMPL R9, $0x00010100 + CMPL R10, $0x00010100 JB repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy - LEAL -65536(R9), R9 - MOVL R9, BX - MOVW $0x001d, (AX) - MOVW R9, 2(AX) - SARL $0x10, BX - MOVB BL, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy: - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy: - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB four_bytes_remain_match_nolit_encodeBlockAsm4MB: - TESTL R9, R9 + TESTL R10, R10 JZ match_nolit_emitcopy_end_encodeBlockAsm4MB - XORL SI, SI - LEAL -1(SI)(R9*4), R9 - MOVB R9, (AX) - MOVL BX, 1(AX) - ADDQ $0x05, AX + XORL DI, DI + LEAL -1(DI)(R10*4), R10 + MOVB R10, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB two_byte_offset_match_nolit_encodeBlockAsm4MB: - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_encodeBlockAsm4MB - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE long_offset_short_match_nolit_encodeBlockAsm4MB - MOVL $0x00000001, SI - LEAL 16(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX - SUBL $0x08, R9 - + MOVL $0x00000001, DI + LEAL 16(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R10 + // emitRepeat - LEAL -4(R9), R9 + LEAL -4(R10), R10 JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b - MOVL R9, SI - LEAL -4(R9), R9 - CMPL SI, $0x08 + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JB repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b - CMPL R9, $0x00010100 + CMPL R10, $0x00010100 JB repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b - LEAL -65536(R9), R9 - MOVL R9, BX - MOVW $0x001d, (AX) - MOVW R9, 2(AX) - SARL $0x10, BX - MOVB BL, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB long_offset_short_match_nolit_encodeBlockAsm4MB: - MOVB $0xee, (AX) - MOVW BX, 1(AX) - LEAL -60(R9), R9 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX // emitRepeat - MOVL R9, SI - LEAL -4(R9), R9 - CMPL SI, $0x08 + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JB repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short - CMPL R9, $0x00010100 + CMPL R10, $0x00010100 JB repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short - LEAL -65536(R9), R9 - MOVL R9, BX - MOVW $0x001d, (AX) - MOVW R9, 2(AX) - SARL $0x10, BX - MOVB BL, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R10), R10 + MOVL R10, SI + MOVW $0x001d, (CX) + MOVW R10, 2(CX) + SARL $0x10, SI + MOVB SI, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short: - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short: - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB two_byte_offset_short_match_nolit_encodeBlockAsm4MB: - MOVL R9, SI - SHLL $0x02, SI - CMPL R9, $0x0c + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_encodeBlockAsm4MB - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE emit_copy_three_match_nolit_encodeBlockAsm4MB - LEAL -15(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm4MB emit_copy_three_match_nolit_encodeBlockAsm4MB: - LEAL -2(SI), SI - MOVB SI, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeBlockAsm4MB: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeBlockAsm4MB - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeBlockAsm4MB - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeBlockAsm4MB: - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x10, DI - IMULQ R8, DI - SHRQ $0x32, DI - SHLQ $0x10, BX - IMULQ R8, BX - SHRQ $0x32, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x10, R8 + IMULQ R9, R8 + SHRQ $0x32, R8 + SHLQ $0x10, SI + IMULQ R9, SI + SHRQ $0x32, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_encodeBlockAsm4MB - INCL CX + INCL DX JMP search_loop_encodeBlockAsm4MB emit_remainder_encodeBlockAsm4MB: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 4(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 4(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeBlockAsm4MB - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeBlockAsm4MB: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeBlockAsm4MB - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeBlockAsm4MB @@ -2618,33 +2620,33 @@ emit_remainder_ok_encodeBlockAsm4MB: JB three_bytes_emit_remainder_encodeBlockAsm4MB MOVL DX, BX SHRL $0x10, BX - MOVB $0xf8, (AX) - MOVW DX, 1(AX) - MOVB BL, 3(AX) - ADDQ $0x04, AX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX JMP memmove_long_emit_remainder_encodeBlockAsm4MB three_bytes_emit_remainder_encodeBlockAsm4MB: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeBlockAsm4MB two_bytes_emit_remainder_encodeBlockAsm4MB: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeBlockAsm4MB JMP memmove_long_emit_remainder_encodeBlockAsm4MB one_byte_emit_remainder_encodeBlockAsm4MB: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeBlockAsm4MB: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -2660,73 +2662,73 @@ memmove_emit_remainder_encodeBlockAsm4MB: JMP emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeBlockAsm4MB: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeBlockAsm4MB memmove_long_emit_remainder_encodeBlockAsm4MB: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_big_loop_back: MOVOU (SI), X4 @@ -2740,967 +2742,968 @@ emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeBlockAsm4MB: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeBlockAsm12B(dst []byte, src []byte) int +// func encodeBlockAsm12B(dst []byte, src []byte, tmp *[16384]byte) int // Requires: BMI, SSE2 -TEXT ·encodeBlockAsm12B(SB), $16408-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000080, CX - LEAQ 24(SP), DX +TEXT ·encodeBlockAsm12B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000080, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeBlockAsm12B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeBlockAsm12B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX search_loop_encodeBlockAsm12B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x05, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeBlockAsm12B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x000000cf1bbcdcbb, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x18, R9 - IMULQ R8, R9 - SHRQ $0x34, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x000000cf1bbcdcbb, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x18, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x34, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x18, R9 - IMULQ R8, R9 - SHRQ $0x34, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 + SHLQ $0x18, R11 + IMULQ R9, R11 + SHRQ $0x34, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x18, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 JNE no_repeat_found_encodeBlockAsm12B - LEAL 1(CX), SI - MOVL 12(SP), DI - MOVL SI, BX - SUBL 16(SP), BX + LEAL 1(DX), DI + MOVL 12(SP), R8 + MOVL DI, SI + SUBL 16(SP), SI JZ repeat_extend_back_end_encodeBlockAsm12B repeat_extend_back_loop_encodeBlockAsm12B: - CMPL SI, DI + CMPL DI, R8 JBE repeat_extend_back_end_encodeBlockAsm12B - MOVB -1(DX)(BX*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(SI*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_encodeBlockAsm12B - LEAL -1(SI), SI - DECL BX + LEAL -1(DI), DI + DECL SI JNZ repeat_extend_back_loop_encodeBlockAsm12B repeat_extend_back_end_encodeBlockAsm12B: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 3(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_encodeBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET repeat_dst_size_check_encodeBlockAsm12B: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_encodeBlockAsm12B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_encodeBlockAsm12B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_encodeBlockAsm12B JB three_bytes_repeat_emit_encodeBlockAsm12B three_bytes_repeat_emit_encodeBlockAsm12B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_repeat_emit_encodeBlockAsm12B two_bytes_repeat_emit_encodeBlockAsm12B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_encodeBlockAsm12B JMP memmove_long_repeat_emit_encodeBlockAsm12B one_byte_repeat_emit_encodeBlockAsm12B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_repeat_emit_encodeBlockAsm12B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_17through32 JMP emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_33through64 emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8: - MOVQ (R9), R10 - MOVQ R10, (AX) + MOVQ (R10), R11 + MOVQ R11, (CX) JMP memmove_end_copy_repeat_emit_encodeBlockAsm12B emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_repeat_emit_encodeBlockAsm12B emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_repeat_emit_encodeBlockAsm12B emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_repeat_emit_encodeBlockAsm12B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_repeat_emit_encodeBlockAsm12B memmove_long_repeat_emit_encodeBlockAsm12B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R11 - SHRQ $0x05, R11 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R12 - SUBQ R10, R12 - DECQ R11 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R12 + SHRQ $0x05, R12 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 JA emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_forward_sse_loop_32 - LEAQ -32(R9)(R12*1), R10 - LEAQ -32(AX)(R12*1), R13 + LEAQ -32(R10)(R13*1), R11 + LEAQ -32(CX)(R13*1), R14 emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R13) - MOVOA X5, 16(R13) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 ADDQ $0x20, R13 - ADDQ $0x20, R10 - ADDQ $0x20, R12 - DECQ R11 + DECQ R12 JNA emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_big_loop_back emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_forward_sse_loop_32: - MOVOU -32(R9)(R12*1), X4 - MOVOU -16(R9)(R12*1), X5 - MOVOA X4, -32(AX)(R12*1) - MOVOA X5, -16(AX)(R12*1) - ADDQ $0x20, R12 - CMPQ R8, R12 + MOVOU -32(R10)(R13*1), X4 + MOVOU -16(R10)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R9, R13 JAE emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_repeat_emit_encodeBlockAsm12B: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+32(FP), R8 - SUBL CX, R8 - LEAQ (DX)(CX*1), R9 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R9 + SUBL DX, R9 + LEAQ (BX)(DX*1), R10 + LEAQ (BX)(SI*1), SI // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_repeat_extend_encodeBlockAsm12B: - CMPL R8, $0x10 + CMPL R9, $0x10 JB matchlen_match8_repeat_extend_encodeBlockAsm12B - MOVQ (R9)(R11*1), R10 - MOVQ 8(R9)(R11*1), R12 - XORQ (BX)(R11*1), R10 + MOVQ (R10)(R12*1), R11 + MOVQ 8(R10)(R12*1), R13 + XORQ (SI)(R12*1), R11 JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm12B - XORQ 8(BX)(R11*1), R12 + XORQ 8(SI)(R12*1), R13 JNZ matchlen_bsf_16repeat_extend_encodeBlockAsm12B - LEAL -16(R8), R8 - LEAL 16(R11), R11 + LEAL -16(R9), R9 + LEAL 16(R12), R12 JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm12B matchlen_bsf_16repeat_extend_encodeBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP repeat_extend_forward_end_encodeBlockAsm12B matchlen_match8_repeat_extend_encodeBlockAsm12B: - CMPL R8, $0x08 + CMPL R9, $0x08 JB matchlen_match4_repeat_extend_encodeBlockAsm12B - MOVQ (R9)(R11*1), R10 - XORQ (BX)(R11*1), R10 + MOVQ (R10)(R12*1), R11 + XORQ (SI)(R12*1), R11 JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm12B - LEAL -8(R8), R8 - LEAL 8(R11), R11 + LEAL -8(R9), R9 + LEAL 8(R12), R12 JMP matchlen_match4_repeat_extend_encodeBlockAsm12B matchlen_bsf_8_repeat_extend_encodeBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP repeat_extend_forward_end_encodeBlockAsm12B matchlen_match4_repeat_extend_encodeBlockAsm12B: - CMPL R8, $0x04 + CMPL R9, $0x04 JB matchlen_match2_repeat_extend_encodeBlockAsm12B - MOVL (R9)(R11*1), R10 - CMPL (BX)(R11*1), R10 + MOVL (R10)(R12*1), R11 + CMPL (SI)(R12*1), R11 JNE matchlen_match2_repeat_extend_encodeBlockAsm12B - LEAL -4(R8), R8 - LEAL 4(R11), R11 + LEAL -4(R9), R9 + LEAL 4(R12), R12 matchlen_match2_repeat_extend_encodeBlockAsm12B: - CMPL R8, $0x01 + CMPL R9, $0x01 JE matchlen_match1_repeat_extend_encodeBlockAsm12B JB repeat_extend_forward_end_encodeBlockAsm12B - MOVW (R9)(R11*1), R10 - CMPW (BX)(R11*1), R10 + MOVW (R10)(R12*1), R11 + CMPW (SI)(R12*1), R11 JNE matchlen_match1_repeat_extend_encodeBlockAsm12B - LEAL 2(R11), R11 - SUBL $0x02, R8 + LEAL 2(R12), R12 + SUBL $0x02, R9 JZ repeat_extend_forward_end_encodeBlockAsm12B matchlen_match1_repeat_extend_encodeBlockAsm12B: - MOVB (R9)(R11*1), R10 - CMPB (BX)(R11*1), R10 + MOVB (R10)(R12*1), R11 + CMPB (SI)(R12*1), R11 JNE repeat_extend_forward_end_encodeBlockAsm12B - LEAL 1(R11), R11 + LEAL 1(R12), R12 repeat_extend_forward_end_encodeBlockAsm12B: - ADDL R11, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI - TESTL DI, DI + ADDL R12, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + TESTL R8, R8 JZ repeat_as_copy_encodeBlockAsm12B // emitRepeat - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_match_repeat_encodeBlockAsm12B - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_match_repeat_encodeBlockAsm12B - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_match_repeat_encodeBlockAsm12B cant_repeat_two_offset_match_repeat_encodeBlockAsm12B: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_match_repeat_encodeBlockAsm12B - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm12B repeat_three_match_repeat_encodeBlockAsm12B: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm12B repeat_two_match_repeat_encodeBlockAsm12B: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm12B repeat_two_offset_match_repeat_encodeBlockAsm12B: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm12B repeat_as_copy_encodeBlockAsm12B: // emitCopy - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_encodeBlockAsm12B - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE long_offset_short_repeat_as_copy_encodeBlockAsm12B - MOVL $0x00000001, DI - LEAL 16(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX - SUBL $0x08, BX + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + SUBL $0x08, SI // emitRepeat - LEAL -4(BX), BX + LEAL -4(SI), SI JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm12B repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm12B repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm12B repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm12B long_offset_short_repeat_as_copy_encodeBlockAsm12B: - MOVB $0xee, (AX) - MOVW SI, 1(AX) - LEAL -60(BX), BX - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX // emitRepeat - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm12B repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm12B repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm12B repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm12B two_byte_offset_short_repeat_as_copy_encodeBlockAsm12B: - MOVL BX, DI - SHLL $0x02, DI - CMPL BX, $0x0c + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_encodeBlockAsm12B - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE emit_copy_three_repeat_as_copy_encodeBlockAsm12B - LEAL -15(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm12B emit_copy_three_repeat_as_copy_encodeBlockAsm12B: - LEAL -2(DI), DI - MOVB DI, (AX) - MOVW SI, 1(AX) - ADDQ $0x03, AX + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX repeat_end_emit_encodeBlockAsm12B: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_encodeBlockAsm12B no_repeat_found_encodeBlockAsm12B: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeBlockAsm12B - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_encodeBlockAsm12B - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_encodeBlockAsm12B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeBlockAsm12B candidate3_match_encodeBlockAsm12B: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_encodeBlockAsm12B candidate2_match_encodeBlockAsm12B: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_encodeBlockAsm12B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeBlockAsm12B match_extend_back_loop_encodeBlockAsm12B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeBlockAsm12B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeBlockAsm12B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeBlockAsm12B JMP match_extend_back_loop_encodeBlockAsm12B match_extend_back_end_encodeBlockAsm12B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeBlockAsm12B: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_encodeBlockAsm12B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), DI - CMPL DI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c JB one_byte_match_emit_encodeBlockAsm12B - CMPL DI, $0x00000100 + CMPL R8, $0x00000100 JB two_bytes_match_emit_encodeBlockAsm12B JB three_bytes_match_emit_encodeBlockAsm12B three_bytes_match_emit_encodeBlockAsm12B: - MOVB $0xf4, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeBlockAsm12B two_bytes_match_emit_encodeBlockAsm12B: - MOVB $0xf0, (AX) - MOVB DI, 1(AX) - ADDQ $0x02, AX - CMPL DI, $0x40 + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 JB memmove_match_emit_encodeBlockAsm12B JMP memmove_long_match_emit_encodeBlockAsm12B one_byte_match_emit_encodeBlockAsm12B: - SHLB $0x02, DI - MOVB DI, (AX) - ADDQ $0x01, AX + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeBlockAsm12B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8: - MOVQ (SI), R9 - MOVQ R9, (AX) + MOVQ (DI), R10 + MOVQ R10, (CX) JMP memmove_end_copy_match_emit_encodeBlockAsm12B emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8through16: - MOVQ (SI), R9 - MOVQ -8(SI)(R8*1), SI - MOVQ R9, (AX) - MOVQ SI, -8(AX)(R8*1) + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBlockAsm12B emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_17through32: - MOVOU (SI), X0 - MOVOU -16(SI)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBlockAsm12B emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_33through64: - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeBlockAsm12B: - MOVQ DI, AX + MOVQ R8, CX JMP emit_literal_done_match_emit_encodeBlockAsm12B memmove_long_match_emit_encodeBlockAsm12B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveLong - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVQ R8, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_forward_sse_loop_32 - LEAQ -32(SI)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_forward_sse_loop_32: - MOVOU -32(SI)(R11*1), X4 - MOVOU -16(SI)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ R8, R11 + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 JAE emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ DI, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX emit_literal_done_match_emit_encodeBlockAsm12B: match_nolit_loop_encodeBlockAsm12B: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_encodeBlockAsm12B: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_encodeBlockAsm12B - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm12B - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_encodeBlockAsm12B - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_encodeBlockAsm12B matchlen_bsf_16match_nolit_encodeBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_encodeBlockAsm12B matchlen_match8_match_nolit_encodeBlockAsm12B: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_encodeBlockAsm12B - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm12B - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_encodeBlockAsm12B matchlen_bsf_8_match_nolit_encodeBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_encodeBlockAsm12B matchlen_match4_match_nolit_encodeBlockAsm12B: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_encodeBlockAsm12B - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_encodeBlockAsm12B - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_encodeBlockAsm12B: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_encodeBlockAsm12B JB match_nolit_end_encodeBlockAsm12B - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_encodeBlockAsm12B - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_encodeBlockAsm12B matchlen_match1_match_nolit_encodeBlockAsm12B: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_encodeBlockAsm12B - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_encodeBlockAsm12B: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_encodeBlockAsm12B - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE long_offset_short_match_nolit_encodeBlockAsm12B - MOVL $0x00000001, SI - LEAL 16(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX - SUBL $0x08, R9 + MOVL $0x00000001, DI + LEAL 16(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R10 // emitRepeat - LEAL -4(R9), R9 + LEAL -4(R10), R10 JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b - MOVL R9, SI - LEAL -4(R9), R9 - CMPL SI, $0x08 + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short_2b - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JB repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short_2b - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm12B repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm12B repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm12B repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm12B long_offset_short_match_nolit_encodeBlockAsm12B: - MOVB $0xee, (AX) - MOVW BX, 1(AX) - LEAL -60(R9), R9 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX // emitRepeat - MOVL R9, SI - LEAL -4(R9), R9 - CMPL SI, $0x08 + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JB repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm12B repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm12B repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm12B repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short: - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX - JMP match_nolit_emitcopy_end_encodeBlockAsm12B - + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + two_byte_offset_short_match_nolit_encodeBlockAsm12B: - MOVL R9, SI - SHLL $0x02, SI - CMPL R9, $0x0c + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_encodeBlockAsm12B - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE emit_copy_three_match_nolit_encodeBlockAsm12B - LEAL -15(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm12B emit_copy_three_match_nolit_encodeBlockAsm12B: - LEAL -2(SI), SI - MOVB SI, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeBlockAsm12B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeBlockAsm12B - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeBlockAsm12B: - MOVQ $0x000000cf1bbcdcbb, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x18, DI - IMULQ R8, DI - SHRQ $0x34, DI - SHLQ $0x18, BX - IMULQ R8, BX - SHRQ $0x34, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x000000cf1bbcdcbb, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x18, R8 + IMULQ R9, R8 + SHRQ $0x34, R8 + SHLQ $0x18, SI + IMULQ R9, SI + SHRQ $0x34, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_encodeBlockAsm12B - INCL CX + INCL DX JMP search_loop_encodeBlockAsm12B emit_remainder_encodeBlockAsm12B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeBlockAsm12B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeBlockAsm12B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeBlockAsm12B @@ -3709,26 +3712,26 @@ emit_remainder_ok_encodeBlockAsm12B: JB three_bytes_emit_remainder_encodeBlockAsm12B three_bytes_emit_remainder_encodeBlockAsm12B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeBlockAsm12B two_bytes_emit_remainder_encodeBlockAsm12B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeBlockAsm12B JMP memmove_long_emit_remainder_encodeBlockAsm12B one_byte_emit_remainder_encodeBlockAsm12B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeBlockAsm12B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -3744,73 +3747,73 @@ memmove_emit_remainder_encodeBlockAsm12B: JMP emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeBlockAsm12B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeBlockAsm12B memmove_long_emit_remainder_encodeBlockAsm12B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_big_loop_back: MOVOU (SI), X4 @@ -3824,967 +3827,968 @@ emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeBlockAsm12B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeBlockAsm10B(dst []byte, src []byte) int +// func encodeBlockAsm10B(dst []byte, src []byte, tmp *[4096]byte) int // Requires: BMI, SSE2 -TEXT ·encodeBlockAsm10B(SB), $4120-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000020, CX - LEAQ 24(SP), DX +TEXT ·encodeBlockAsm10B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000020, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeBlockAsm10B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeBlockAsm10B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX search_loop_encodeBlockAsm10B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x05, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeBlockAsm10B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x9e3779b1, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x20, R9 - IMULQ R8, R9 - SHRQ $0x36, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x9e3779b1, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x20, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x36, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x20, R9 - IMULQ R8, R9 - SHRQ $0x36, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 + SHLQ $0x20, R11 + IMULQ R9, R11 + SHRQ $0x36, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 JNE no_repeat_found_encodeBlockAsm10B - LEAL 1(CX), SI - MOVL 12(SP), DI - MOVL SI, BX - SUBL 16(SP), BX + LEAL 1(DX), DI + MOVL 12(SP), R8 + MOVL DI, SI + SUBL 16(SP), SI JZ repeat_extend_back_end_encodeBlockAsm10B repeat_extend_back_loop_encodeBlockAsm10B: - CMPL SI, DI + CMPL DI, R8 JBE repeat_extend_back_end_encodeBlockAsm10B - MOVB -1(DX)(BX*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(SI*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_encodeBlockAsm10B - LEAL -1(SI), SI - DECL BX + LEAL -1(DI), DI + DECL SI JNZ repeat_extend_back_loop_encodeBlockAsm10B repeat_extend_back_end_encodeBlockAsm10B: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 3(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_encodeBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET repeat_dst_size_check_encodeBlockAsm10B: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_encodeBlockAsm10B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_encodeBlockAsm10B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_encodeBlockAsm10B JB three_bytes_repeat_emit_encodeBlockAsm10B three_bytes_repeat_emit_encodeBlockAsm10B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_repeat_emit_encodeBlockAsm10B two_bytes_repeat_emit_encodeBlockAsm10B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_encodeBlockAsm10B JMP memmove_long_repeat_emit_encodeBlockAsm10B one_byte_repeat_emit_encodeBlockAsm10B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_repeat_emit_encodeBlockAsm10B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_17through32 JMP emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_33through64 emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8: - MOVQ (R9), R10 - MOVQ R10, (AX) + MOVQ (R10), R11 + MOVQ R11, (CX) JMP memmove_end_copy_repeat_emit_encodeBlockAsm10B emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_repeat_emit_encodeBlockAsm10B emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_repeat_emit_encodeBlockAsm10B emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_repeat_emit_encodeBlockAsm10B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_repeat_emit_encodeBlockAsm10B memmove_long_repeat_emit_encodeBlockAsm10B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R11 - SHRQ $0x05, R11 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R12 - SUBQ R10, R12 - DECQ R11 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R12 + SHRQ $0x05, R12 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 JA emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_forward_sse_loop_32 - LEAQ -32(R9)(R12*1), R10 - LEAQ -32(AX)(R12*1), R13 + LEAQ -32(R10)(R13*1), R11 + LEAQ -32(CX)(R13*1), R14 emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R13) - MOVOA X5, 16(R13) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 ADDQ $0x20, R13 - ADDQ $0x20, R10 - ADDQ $0x20, R12 - DECQ R11 + DECQ R12 JNA emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_big_loop_back emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_forward_sse_loop_32: - MOVOU -32(R9)(R12*1), X4 - MOVOU -16(R9)(R12*1), X5 - MOVOA X4, -32(AX)(R12*1) - MOVOA X5, -16(AX)(R12*1) - ADDQ $0x20, R12 - CMPQ R8, R12 + MOVOU -32(R10)(R13*1), X4 + MOVOU -16(R10)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R9, R13 JAE emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_repeat_emit_encodeBlockAsm10B: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+32(FP), R8 - SUBL CX, R8 - LEAQ (DX)(CX*1), R9 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R9 + SUBL DX, R9 + LEAQ (BX)(DX*1), R10 + LEAQ (BX)(SI*1), SI // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_repeat_extend_encodeBlockAsm10B: - CMPL R8, $0x10 + CMPL R9, $0x10 JB matchlen_match8_repeat_extend_encodeBlockAsm10B - MOVQ (R9)(R11*1), R10 - MOVQ 8(R9)(R11*1), R12 - XORQ (BX)(R11*1), R10 + MOVQ (R10)(R12*1), R11 + MOVQ 8(R10)(R12*1), R13 + XORQ (SI)(R12*1), R11 JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm10B - XORQ 8(BX)(R11*1), R12 + XORQ 8(SI)(R12*1), R13 JNZ matchlen_bsf_16repeat_extend_encodeBlockAsm10B - LEAL -16(R8), R8 - LEAL 16(R11), R11 + LEAL -16(R9), R9 + LEAL 16(R12), R12 JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm10B matchlen_bsf_16repeat_extend_encodeBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP repeat_extend_forward_end_encodeBlockAsm10B matchlen_match8_repeat_extend_encodeBlockAsm10B: - CMPL R8, $0x08 + CMPL R9, $0x08 JB matchlen_match4_repeat_extend_encodeBlockAsm10B - MOVQ (R9)(R11*1), R10 - XORQ (BX)(R11*1), R10 + MOVQ (R10)(R12*1), R11 + XORQ (SI)(R12*1), R11 JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm10B - LEAL -8(R8), R8 - LEAL 8(R11), R11 + LEAL -8(R9), R9 + LEAL 8(R12), R12 JMP matchlen_match4_repeat_extend_encodeBlockAsm10B matchlen_bsf_8_repeat_extend_encodeBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP repeat_extend_forward_end_encodeBlockAsm10B matchlen_match4_repeat_extend_encodeBlockAsm10B: - CMPL R8, $0x04 + CMPL R9, $0x04 JB matchlen_match2_repeat_extend_encodeBlockAsm10B - MOVL (R9)(R11*1), R10 - CMPL (BX)(R11*1), R10 + MOVL (R10)(R12*1), R11 + CMPL (SI)(R12*1), R11 JNE matchlen_match2_repeat_extend_encodeBlockAsm10B - LEAL -4(R8), R8 - LEAL 4(R11), R11 + LEAL -4(R9), R9 + LEAL 4(R12), R12 matchlen_match2_repeat_extend_encodeBlockAsm10B: - CMPL R8, $0x01 + CMPL R9, $0x01 JE matchlen_match1_repeat_extend_encodeBlockAsm10B JB repeat_extend_forward_end_encodeBlockAsm10B - MOVW (R9)(R11*1), R10 - CMPW (BX)(R11*1), R10 + MOVW (R10)(R12*1), R11 + CMPW (SI)(R12*1), R11 JNE matchlen_match1_repeat_extend_encodeBlockAsm10B - LEAL 2(R11), R11 - SUBL $0x02, R8 + LEAL 2(R12), R12 + SUBL $0x02, R9 JZ repeat_extend_forward_end_encodeBlockAsm10B matchlen_match1_repeat_extend_encodeBlockAsm10B: - MOVB (R9)(R11*1), R10 - CMPB (BX)(R11*1), R10 + MOVB (R10)(R12*1), R11 + CMPB (SI)(R12*1), R11 JNE repeat_extend_forward_end_encodeBlockAsm10B - LEAL 1(R11), R11 + LEAL 1(R12), R12 repeat_extend_forward_end_encodeBlockAsm10B: - ADDL R11, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI - TESTL DI, DI + ADDL R12, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + TESTL R8, R8 JZ repeat_as_copy_encodeBlockAsm10B // emitRepeat - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_match_repeat_encodeBlockAsm10B - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_match_repeat_encodeBlockAsm10B - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_match_repeat_encodeBlockAsm10B cant_repeat_two_offset_match_repeat_encodeBlockAsm10B: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_match_repeat_encodeBlockAsm10B - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm10B repeat_three_match_repeat_encodeBlockAsm10B: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm10B repeat_two_match_repeat_encodeBlockAsm10B: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm10B repeat_two_offset_match_repeat_encodeBlockAsm10B: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm10B repeat_as_copy_encodeBlockAsm10B: // emitCopy - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_encodeBlockAsm10B - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE long_offset_short_repeat_as_copy_encodeBlockAsm10B - MOVL $0x00000001, DI - LEAL 16(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX - SUBL $0x08, BX + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + SUBL $0x08, SI // emitRepeat - LEAL -4(BX), BX + LEAL -4(SI), SI JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm10B repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm10B repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm10B repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm10B long_offset_short_repeat_as_copy_encodeBlockAsm10B: - MOVB $0xee, (AX) - MOVW SI, 1(AX) - LEAL -60(BX), BX - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX // emitRepeat - MOVL BX, DI - LEAL -4(BX), BX - CMPL DI, $0x08 + MOVL SI, R8 + LEAL -4(SI), SI + CMPL R8, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short - CMPL DI, $0x0c + CMPL R8, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JB repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm10B repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm10B repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm10B repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm10B two_byte_offset_short_repeat_as_copy_encodeBlockAsm10B: - MOVL BX, DI - SHLL $0x02, DI - CMPL BX, $0x0c + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_encodeBlockAsm10B - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE emit_copy_three_repeat_as_copy_encodeBlockAsm10B - LEAL -15(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm10B emit_copy_three_repeat_as_copy_encodeBlockAsm10B: - LEAL -2(DI), DI - MOVB DI, (AX) - MOVW SI, 1(AX) - ADDQ $0x03, AX + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX repeat_end_emit_encodeBlockAsm10B: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_encodeBlockAsm10B no_repeat_found_encodeBlockAsm10B: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeBlockAsm10B - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_encodeBlockAsm10B - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_encodeBlockAsm10B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeBlockAsm10B candidate3_match_encodeBlockAsm10B: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_encodeBlockAsm10B candidate2_match_encodeBlockAsm10B: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_encodeBlockAsm10B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeBlockAsm10B match_extend_back_loop_encodeBlockAsm10B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeBlockAsm10B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeBlockAsm10B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeBlockAsm10B JMP match_extend_back_loop_encodeBlockAsm10B match_extend_back_end_encodeBlockAsm10B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeBlockAsm10B: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_encodeBlockAsm10B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), DI - CMPL DI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c JB one_byte_match_emit_encodeBlockAsm10B - CMPL DI, $0x00000100 + CMPL R8, $0x00000100 JB two_bytes_match_emit_encodeBlockAsm10B JB three_bytes_match_emit_encodeBlockAsm10B three_bytes_match_emit_encodeBlockAsm10B: - MOVB $0xf4, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeBlockAsm10B two_bytes_match_emit_encodeBlockAsm10B: - MOVB $0xf0, (AX) - MOVB DI, 1(AX) - ADDQ $0x02, AX - CMPL DI, $0x40 + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 JB memmove_match_emit_encodeBlockAsm10B JMP memmove_long_match_emit_encodeBlockAsm10B one_byte_match_emit_encodeBlockAsm10B: - SHLB $0x02, DI - MOVB DI, (AX) - ADDQ $0x01, AX + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeBlockAsm10B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8: - MOVQ (SI), R9 - MOVQ R9, (AX) + MOVQ (DI), R10 + MOVQ R10, (CX) JMP memmove_end_copy_match_emit_encodeBlockAsm10B emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8through16: - MOVQ (SI), R9 - MOVQ -8(SI)(R8*1), SI - MOVQ R9, (AX) - MOVQ SI, -8(AX)(R8*1) + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBlockAsm10B emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_17through32: - MOVOU (SI), X0 - MOVOU -16(SI)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBlockAsm10B emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_33through64: - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeBlockAsm10B: - MOVQ DI, AX + MOVQ R8, CX JMP emit_literal_done_match_emit_encodeBlockAsm10B memmove_long_match_emit_encodeBlockAsm10B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveLong - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVQ R8, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_forward_sse_loop_32 - LEAQ -32(SI)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_forward_sse_loop_32: - MOVOU -32(SI)(R11*1), X4 - MOVOU -16(SI)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ R8, R11 + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 JAE emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ DI, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX emit_literal_done_match_emit_encodeBlockAsm10B: match_nolit_loop_encodeBlockAsm10B: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_encodeBlockAsm10B: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_encodeBlockAsm10B - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm10B - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_encodeBlockAsm10B - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_encodeBlockAsm10B matchlen_bsf_16match_nolit_encodeBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_encodeBlockAsm10B matchlen_match8_match_nolit_encodeBlockAsm10B: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_encodeBlockAsm10B - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm10B - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_encodeBlockAsm10B matchlen_bsf_8_match_nolit_encodeBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_encodeBlockAsm10B matchlen_match4_match_nolit_encodeBlockAsm10B: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_encodeBlockAsm10B - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_encodeBlockAsm10B - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_encodeBlockAsm10B: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_encodeBlockAsm10B JB match_nolit_end_encodeBlockAsm10B - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_encodeBlockAsm10B - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_encodeBlockAsm10B matchlen_match1_match_nolit_encodeBlockAsm10B: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_encodeBlockAsm10B - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_encodeBlockAsm10B: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_encodeBlockAsm10B - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE long_offset_short_match_nolit_encodeBlockAsm10B - MOVL $0x00000001, SI - LEAL 16(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX - SUBL $0x08, R9 + MOVL $0x00000001, DI + LEAL 16(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R10 // emitRepeat - LEAL -4(R9), R9 + LEAL -4(R10), R10 JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b - MOVL R9, SI - LEAL -4(R9), R9 - CMPL SI, $0x08 + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short_2b - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JB repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short_2b - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm10B repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm10B repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm10B repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm10B long_offset_short_match_nolit_encodeBlockAsm10B: - MOVB $0xee, (AX) - MOVW BX, 1(AX) - LEAL -60(R9), R9 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX // emitRepeat - MOVL R9, SI - LEAL -4(R9), R9 - CMPL SI, $0x08 + MOVL R10, DI + LEAL -4(R10), R10 + CMPL DI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JB repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm10B repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm10B repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm10B repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short: - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm10B two_byte_offset_short_match_nolit_encodeBlockAsm10B: - MOVL R9, SI - SHLL $0x02, SI - CMPL R9, $0x0c + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_encodeBlockAsm10B - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE emit_copy_three_match_nolit_encodeBlockAsm10B - LEAL -15(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm10B emit_copy_three_match_nolit_encodeBlockAsm10B: - LEAL -2(SI), SI - MOVB SI, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeBlockAsm10B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeBlockAsm10B - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeBlockAsm10B: - MOVQ $0x9e3779b1, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x20, DI - IMULQ R8, DI - SHRQ $0x36, DI - SHLQ $0x20, BX - IMULQ R8, BX - SHRQ $0x36, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x9e3779b1, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x20, R8 + IMULQ R9, R8 + SHRQ $0x36, R8 + SHLQ $0x20, SI + IMULQ R9, SI + SHRQ $0x36, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_encodeBlockAsm10B - INCL CX + INCL DX JMP search_loop_encodeBlockAsm10B emit_remainder_encodeBlockAsm10B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeBlockAsm10B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeBlockAsm10B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeBlockAsm10B @@ -4793,26 +4797,26 @@ emit_remainder_ok_encodeBlockAsm10B: JB three_bytes_emit_remainder_encodeBlockAsm10B three_bytes_emit_remainder_encodeBlockAsm10B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeBlockAsm10B two_bytes_emit_remainder_encodeBlockAsm10B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeBlockAsm10B JMP memmove_long_emit_remainder_encodeBlockAsm10B one_byte_emit_remainder_encodeBlockAsm10B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeBlockAsm10B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -4828,73 +4832,73 @@ memmove_emit_remainder_encodeBlockAsm10B: JMP emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeBlockAsm10B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeBlockAsm10B memmove_long_emit_remainder_encodeBlockAsm10B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_big_loop_back: MOVOU (SI), X4 @@ -4908,943 +4912,944 @@ emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeBlockAsm10B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeBlockAsm8B(dst []byte, src []byte) int +// func encodeBlockAsm8B(dst []byte, src []byte, tmp *[1024]byte) int // Requires: BMI, SSE2 -TEXT ·encodeBlockAsm8B(SB), $1048-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000008, CX - LEAQ 24(SP), DX +TEXT ·encodeBlockAsm8B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000008, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeBlockAsm8B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeBlockAsm8B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX search_loop_encodeBlockAsm8B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x04, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x04, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeBlockAsm8B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x9e3779b1, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x20, R9 - IMULQ R8, R9 - SHRQ $0x38, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x9e3779b1, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x20, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x38, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x20, R9 - IMULQ R8, R9 - SHRQ $0x38, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 - JNE no_repeat_found_encodeBlockAsm8B - LEAL 1(CX), SI - MOVL 12(SP), DI - MOVL SI, BX - SUBL 16(SP), BX + SHLQ $0x20, R11 + IMULQ R9, R11 + SHRQ $0x38, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x38, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 + JNE no_repeat_found_encodeBlockAsm8B + LEAL 1(DX), DI + MOVL 12(SP), R8 + MOVL DI, SI + SUBL 16(SP), SI JZ repeat_extend_back_end_encodeBlockAsm8B repeat_extend_back_loop_encodeBlockAsm8B: - CMPL SI, DI + CMPL DI, R8 JBE repeat_extend_back_end_encodeBlockAsm8B - MOVB -1(DX)(BX*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(SI*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_encodeBlockAsm8B - LEAL -1(SI), SI - DECL BX + LEAL -1(DI), DI + DECL SI JNZ repeat_extend_back_loop_encodeBlockAsm8B repeat_extend_back_end_encodeBlockAsm8B: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 3(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_encodeBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET repeat_dst_size_check_encodeBlockAsm8B: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_encodeBlockAsm8B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_encodeBlockAsm8B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_encodeBlockAsm8B JB three_bytes_repeat_emit_encodeBlockAsm8B three_bytes_repeat_emit_encodeBlockAsm8B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_repeat_emit_encodeBlockAsm8B two_bytes_repeat_emit_encodeBlockAsm8B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_encodeBlockAsm8B JMP memmove_long_repeat_emit_encodeBlockAsm8B one_byte_repeat_emit_encodeBlockAsm8B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_repeat_emit_encodeBlockAsm8B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_17through32 JMP emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_33through64 emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8: - MOVQ (R9), R10 - MOVQ R10, (AX) + MOVQ (R10), R11 + MOVQ R11, (CX) JMP memmove_end_copy_repeat_emit_encodeBlockAsm8B emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_repeat_emit_encodeBlockAsm8B emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_repeat_emit_encodeBlockAsm8B emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_repeat_emit_encodeBlockAsm8B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_repeat_emit_encodeBlockAsm8B memmove_long_repeat_emit_encodeBlockAsm8B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R11 - SHRQ $0x05, R11 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R12 - SUBQ R10, R12 - DECQ R11 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R12 + SHRQ $0x05, R12 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R13 + SUBQ R11, R13 + DECQ R12 JA emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_forward_sse_loop_32 - LEAQ -32(R9)(R12*1), R10 - LEAQ -32(AX)(R12*1), R13 + LEAQ -32(R10)(R13*1), R11 + LEAQ -32(CX)(R13*1), R14 emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R13) - MOVOA X5, 16(R13) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R11 ADDQ $0x20, R13 - ADDQ $0x20, R10 - ADDQ $0x20, R12 - DECQ R11 + DECQ R12 JNA emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_big_loop_back emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_forward_sse_loop_32: - MOVOU -32(R9)(R12*1), X4 - MOVOU -16(R9)(R12*1), X5 - MOVOA X4, -32(AX)(R12*1) - MOVOA X5, -16(AX)(R12*1) - ADDQ $0x20, R12 - CMPQ R8, R12 + MOVOU -32(R10)(R13*1), X4 + MOVOU -16(R10)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R9, R13 JAE emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_repeat_emit_encodeBlockAsm8B: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+32(FP), R8 - SUBL CX, R8 - LEAQ (DX)(CX*1), R9 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R9 + SUBL DX, R9 + LEAQ (BX)(DX*1), R10 + LEAQ (BX)(SI*1), SI // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_repeat_extend_encodeBlockAsm8B: - CMPL R8, $0x10 + CMPL R9, $0x10 JB matchlen_match8_repeat_extend_encodeBlockAsm8B - MOVQ (R9)(R11*1), R10 - MOVQ 8(R9)(R11*1), R12 - XORQ (BX)(R11*1), R10 + MOVQ (R10)(R12*1), R11 + MOVQ 8(R10)(R12*1), R13 + XORQ (SI)(R12*1), R11 JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm8B - XORQ 8(BX)(R11*1), R12 + XORQ 8(SI)(R12*1), R13 JNZ matchlen_bsf_16repeat_extend_encodeBlockAsm8B - LEAL -16(R8), R8 - LEAL 16(R11), R11 + LEAL -16(R9), R9 + LEAL 16(R12), R12 JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm8B matchlen_bsf_16repeat_extend_encodeBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP repeat_extend_forward_end_encodeBlockAsm8B matchlen_match8_repeat_extend_encodeBlockAsm8B: - CMPL R8, $0x08 + CMPL R9, $0x08 JB matchlen_match4_repeat_extend_encodeBlockAsm8B - MOVQ (R9)(R11*1), R10 - XORQ (BX)(R11*1), R10 + MOVQ (R10)(R12*1), R11 + XORQ (SI)(R12*1), R11 JNZ matchlen_bsf_8_repeat_extend_encodeBlockAsm8B - LEAL -8(R8), R8 - LEAL 8(R11), R11 + LEAL -8(R9), R9 + LEAL 8(R12), R12 JMP matchlen_match4_repeat_extend_encodeBlockAsm8B matchlen_bsf_8_repeat_extend_encodeBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP repeat_extend_forward_end_encodeBlockAsm8B matchlen_match4_repeat_extend_encodeBlockAsm8B: - CMPL R8, $0x04 + CMPL R9, $0x04 JB matchlen_match2_repeat_extend_encodeBlockAsm8B - MOVL (R9)(R11*1), R10 - CMPL (BX)(R11*1), R10 + MOVL (R10)(R12*1), R11 + CMPL (SI)(R12*1), R11 JNE matchlen_match2_repeat_extend_encodeBlockAsm8B - LEAL -4(R8), R8 - LEAL 4(R11), R11 + LEAL -4(R9), R9 + LEAL 4(R12), R12 matchlen_match2_repeat_extend_encodeBlockAsm8B: - CMPL R8, $0x01 + CMPL R9, $0x01 JE matchlen_match1_repeat_extend_encodeBlockAsm8B JB repeat_extend_forward_end_encodeBlockAsm8B - MOVW (R9)(R11*1), R10 - CMPW (BX)(R11*1), R10 + MOVW (R10)(R12*1), R11 + CMPW (SI)(R12*1), R11 JNE matchlen_match1_repeat_extend_encodeBlockAsm8B - LEAL 2(R11), R11 - SUBL $0x02, R8 + LEAL 2(R12), R12 + SUBL $0x02, R9 JZ repeat_extend_forward_end_encodeBlockAsm8B matchlen_match1_repeat_extend_encodeBlockAsm8B: - MOVB (R9)(R11*1), R10 - CMPB (BX)(R11*1), R10 + MOVB (R10)(R12*1), R11 + CMPB (SI)(R12*1), R11 JNE repeat_extend_forward_end_encodeBlockAsm8B - LEAL 1(R11), R11 + LEAL 1(R12), R12 repeat_extend_forward_end_encodeBlockAsm8B: - ADDL R11, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI - TESTL DI, DI + ADDL R12, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI + TESTL R8, R8 JZ repeat_as_copy_encodeBlockAsm8B // emitRepeat - MOVL BX, SI - LEAL -4(BX), BX - CMPL SI, $0x08 + MOVL SI, DI + LEAL -4(SI), SI + CMPL DI, $0x08 JBE repeat_two_match_repeat_encodeBlockAsm8B - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_match_repeat_encodeBlockAsm8B cant_repeat_two_offset_match_repeat_encodeBlockAsm8B: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_match_repeat_encodeBlockAsm8B - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm8B repeat_three_match_repeat_encodeBlockAsm8B: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm8B repeat_two_match_repeat_encodeBlockAsm8B: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm8B - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm8B repeat_as_copy_encodeBlockAsm8B: // emitCopy - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_encodeBlockAsm8B - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE long_offset_short_repeat_as_copy_encodeBlockAsm8B - MOVL $0x00000001, DI - LEAL 16(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX - SUBL $0x08, BX + MOVL $0x00000001, R8 + LEAL 16(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX + SUBL $0x08, SI // emitRepeat - LEAL -4(BX), BX + LEAL -4(SI), SI JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b - MOVL BX, SI - LEAL -4(BX), BX - CMPL SI, $0x08 + MOVL SI, DI + LEAL -4(SI), SI + CMPL DI, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm8B repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm8B repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm8B - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm8B long_offset_short_repeat_as_copy_encodeBlockAsm8B: - MOVB $0xee, (AX) - MOVW SI, 1(AX) - LEAL -60(BX), BX - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX // emitRepeat - MOVL BX, SI - LEAL -4(BX), BX - CMPL SI, $0x08 + MOVL SI, DI + LEAL -4(SI), SI + CMPL DI, $0x08 JBE repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short - CMPL SI, $0x0c + CMPL DI, $0x0c JAE cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short: - CMPL BX, $0x00000104 + CMPL SI, $0x00000104 JB repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short - LEAL -256(BX), BX - MOVW $0x0019, (AX) - MOVW BX, 2(AX) - ADDQ $0x04, AX + LEAL -256(SI), SI + MOVW $0x0019, (CX) + MOVW SI, 2(CX) + ADDQ $0x04, CX JMP repeat_end_emit_encodeBlockAsm8B repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short: - LEAL -4(BX), BX - MOVW $0x0015, (AX) - MOVB BL, 2(AX) - ADDQ $0x03, AX + LEAL -4(SI), SI + MOVW $0x0015, (CX) + MOVB SI, 2(CX) + ADDQ $0x03, CX JMP repeat_end_emit_encodeBlockAsm8B repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short: - SHLL $0x02, BX - ORL $0x01, BX - MOVW BX, (AX) - ADDQ $0x02, AX + SHLL $0x02, SI + ORL $0x01, SI + MOVW SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm8B - XORQ DI, DI - LEAL 1(DI)(BX*4), BX - MOVB SI, 1(AX) - SARL $0x08, SI - SHLL $0x05, SI - ORL SI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + XORQ R8, R8 + LEAL 1(R8)(SI*4), SI + MOVB DI, 1(CX) + SARL $0x08, DI + SHLL $0x05, DI + ORL DI, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm8B two_byte_offset_short_repeat_as_copy_encodeBlockAsm8B: - MOVL BX, DI - SHLL $0x02, DI - CMPL BX, $0x0c + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_encodeBlockAsm8B - LEAL -15(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeBlockAsm8B emit_copy_three_repeat_as_copy_encodeBlockAsm8B: - LEAL -2(DI), DI - MOVB DI, (AX) - MOVW SI, 1(AX) - ADDQ $0x03, AX + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX repeat_end_emit_encodeBlockAsm8B: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_encodeBlockAsm8B no_repeat_found_encodeBlockAsm8B: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeBlockAsm8B - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_encodeBlockAsm8B - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_encodeBlockAsm8B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeBlockAsm8B candidate3_match_encodeBlockAsm8B: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_encodeBlockAsm8B candidate2_match_encodeBlockAsm8B: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_encodeBlockAsm8B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeBlockAsm8B match_extend_back_loop_encodeBlockAsm8B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeBlockAsm8B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeBlockAsm8B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeBlockAsm8B JMP match_extend_back_loop_encodeBlockAsm8B match_extend_back_end_encodeBlockAsm8B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeBlockAsm8B: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_encodeBlockAsm8B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), DI - CMPL DI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c JB one_byte_match_emit_encodeBlockAsm8B - CMPL DI, $0x00000100 + CMPL R8, $0x00000100 JB two_bytes_match_emit_encodeBlockAsm8B JB three_bytes_match_emit_encodeBlockAsm8B three_bytes_match_emit_encodeBlockAsm8B: - MOVB $0xf4, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeBlockAsm8B two_bytes_match_emit_encodeBlockAsm8B: - MOVB $0xf0, (AX) - MOVB DI, 1(AX) - ADDQ $0x02, AX - CMPL DI, $0x40 + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 JB memmove_match_emit_encodeBlockAsm8B JMP memmove_long_match_emit_encodeBlockAsm8B one_byte_match_emit_encodeBlockAsm8B: - SHLB $0x02, DI - MOVB DI, (AX) - ADDQ $0x01, AX + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeBlockAsm8B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8: - MOVQ (SI), R9 - MOVQ R9, (AX) + MOVQ (DI), R10 + MOVQ R10, (CX) JMP memmove_end_copy_match_emit_encodeBlockAsm8B emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8through16: - MOVQ (SI), R9 - MOVQ -8(SI)(R8*1), SI - MOVQ R9, (AX) - MOVQ SI, -8(AX)(R8*1) + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBlockAsm8B emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_17through32: - MOVOU (SI), X0 - MOVOU -16(SI)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBlockAsm8B emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_33through64: - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeBlockAsm8B: - MOVQ DI, AX + MOVQ R8, CX JMP emit_literal_done_match_emit_encodeBlockAsm8B memmove_long_match_emit_encodeBlockAsm8B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveLong - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVQ R8, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_forward_sse_loop_32 - LEAQ -32(SI)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) - ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 + ADDQ $0x20, R12 + DECQ R11 JNA emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_forward_sse_loop_32: - MOVOU -32(SI)(R11*1), X4 - MOVOU -16(SI)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ R8, R11 + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 JAE emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ DI, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX emit_literal_done_match_emit_encodeBlockAsm8B: match_nolit_loop_encodeBlockAsm8B: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_encodeBlockAsm8B: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_encodeBlockAsm8B - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm8B - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_encodeBlockAsm8B - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_encodeBlockAsm8B matchlen_bsf_16match_nolit_encodeBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_encodeBlockAsm8B matchlen_match8_match_nolit_encodeBlockAsm8B: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_encodeBlockAsm8B - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeBlockAsm8B - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_encodeBlockAsm8B matchlen_bsf_8_match_nolit_encodeBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_encodeBlockAsm8B matchlen_match4_match_nolit_encodeBlockAsm8B: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_encodeBlockAsm8B - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_encodeBlockAsm8B - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_encodeBlockAsm8B: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_encodeBlockAsm8B JB match_nolit_end_encodeBlockAsm8B - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_encodeBlockAsm8B - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_encodeBlockAsm8B matchlen_match1_match_nolit_encodeBlockAsm8B: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_encodeBlockAsm8B - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_encodeBlockAsm8B: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_encodeBlockAsm8B - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE long_offset_short_match_nolit_encodeBlockAsm8B - MOVL $0x00000001, SI - LEAL 16(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX - SUBL $0x08, R9 + MOVL $0x00000001, DI + LEAL 16(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R10 // emitRepeat - LEAL -4(R9), R9 + LEAL -4(R10), R10 JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short_2b - MOVL R9, BX - LEAL -4(R9), R9 - CMPL BX, $0x08 + MOVL R10, SI + LEAL -4(R10), R10 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short_2b - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short_2b cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short_2b: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short_2b - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm8B repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short_2b: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm8B repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short_2b: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm8B - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm8B long_offset_short_match_nolit_encodeBlockAsm8B: - MOVB $0xee, (AX) - MOVW BX, 1(AX) - LEAL -60(R9), R9 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX // emitRepeat - MOVL R9, BX - LEAL -4(R9), R9 - CMPL BX, $0x08 + MOVL R10, SI + LEAL -4(R10), R10 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short: - CMPL R9, $0x00000104 + CMPL R10, $0x00000104 JB repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short - LEAL -256(R9), R9 - MOVW $0x0019, (AX) - MOVW R9, 2(AX) - ADDQ $0x04, AX + LEAL -256(R10), R10 + MOVW $0x0019, (CX) + MOVW R10, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBlockAsm8B repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short: - LEAL -4(R9), R9 - MOVW $0x0015, (AX) - MOVB R9, 2(AX) - ADDQ $0x03, AX + LEAL -4(R10), R10 + MOVW $0x0015, (CX) + MOVB R10, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBlockAsm8B repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short: - SHLL $0x02, R9 - ORL $0x01, R9 - MOVW R9, (AX) - ADDQ $0x02, AX + SHLL $0x02, R10 + ORL $0x01, R10 + MOVW R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm8B - XORQ SI, SI - LEAL 1(SI)(R9*4), R9 - MOVB BL, 1(AX) - SARL $0x08, BX - SHLL $0x05, BX - ORL BX, R9 - MOVB R9, (AX) - ADDQ $0x02, AX + XORQ DI, DI + LEAL 1(DI)(R10*4), R10 + MOVB SI, 1(CX) + SARL $0x08, SI + SHLL $0x05, SI + ORL SI, R10 + MOVB R10, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm8B two_byte_offset_short_match_nolit_encodeBlockAsm8B: - MOVL R9, SI - SHLL $0x02, SI - CMPL R9, $0x0c + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_encodeBlockAsm8B - LEAL -15(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBlockAsm8B emit_copy_three_match_nolit_encodeBlockAsm8B: - LEAL -2(SI), SI - MOVB SI, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeBlockAsm8B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeBlockAsm8B - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeBlockAsm8B: - MOVQ $0x9e3779b1, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x20, DI - IMULQ R8, DI - SHRQ $0x38, DI - SHLQ $0x20, BX - IMULQ R8, BX - SHRQ $0x38, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x9e3779b1, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x20, R8 + IMULQ R9, R8 + SHRQ $0x38, R8 + SHLQ $0x20, SI + IMULQ R9, SI + SHRQ $0x38, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_encodeBlockAsm8B - INCL CX + INCL DX JMP search_loop_encodeBlockAsm8B emit_remainder_encodeBlockAsm8B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeBlockAsm8B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeBlockAsm8B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeBlockAsm8B @@ -5853,26 +5858,26 @@ emit_remainder_ok_encodeBlockAsm8B: JB three_bytes_emit_remainder_encodeBlockAsm8B three_bytes_emit_remainder_encodeBlockAsm8B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeBlockAsm8B two_bytes_emit_remainder_encodeBlockAsm8B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeBlockAsm8B JMP memmove_long_emit_remainder_encodeBlockAsm8B one_byte_emit_remainder_encodeBlockAsm8B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeBlockAsm8B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -5888,73 +5893,73 @@ memmove_emit_remainder_encodeBlockAsm8B: JMP emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeBlockAsm8B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeBlockAsm8B memmove_long_emit_remainder_encodeBlockAsm8B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_big_loop_back: MOVOU (SI), X4 @@ -5968,961 +5973,962 @@ emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeBlockAsm8B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeBetterBlockAsm(dst []byte, src []byte) int +// func encodeBetterBlockAsm(dst []byte, src []byte, tmp *[589824]byte) int // Requires: BMI, SSE2 -TEXT ·encodeBetterBlockAsm(SB), $589848-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00001200, CX - LEAQ 24(SP), DX +TEXT ·encodeBetterBlockAsm(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00001200, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeBetterBlockAsm: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeBetterBlockAsm MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -6(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX + MOVQ src_len+32(FP), DX + LEAQ -6(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX MOVL $0x00000000, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_base+24(FP), BX search_loop_encodeBetterBlockAsm: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x07, BX - CMPL BX, $0x63 + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x07, SI + CMPL SI, $0x63 JBE check_maxskip_ok_encodeBetterBlockAsm - LEAL 100(CX), BX + LEAL 100(DX), SI JMP check_maxskip_cont_encodeBetterBlockAsm check_maxskip_ok_encodeBetterBlockAsm: - LEAL 1(CX)(BX*1), BX + LEAL 1(DX)(SI*1), SI check_maxskip_cont_encodeBetterBlockAsm: - CMPL BX, 8(SP) + CMPL SI, 8(SP) JAE emit_remainder_encodeBetterBlockAsm - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x00cf1bbcdcbfa563, R8 - MOVQ $0x9e3779b1, BX - MOVQ SI, R9 - MOVQ SI, R10 - SHLQ $0x08, R9 - IMULQ R8, R9 - SHRQ $0x2f, R9 - SHLQ $0x20, R10 - IMULQ BX, R10 - SHRQ $0x32, R10 - MOVL 24(SP)(R9*4), BX - MOVL 524312(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - MOVL CX, 524312(SP)(R10*4) - MOVQ (DX)(BX*1), R9 - MOVQ (DX)(DI*1), R10 - CMPQ R9, SI + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x00cf1bbcdcbfa563, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL 524288(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 524288(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI JEQ candidate_match_encodeBetterBlockAsm - CMPQ R10, SI + CMPQ R11, DI JNE no_short_found_encodeBetterBlockAsm - MOVL DI, BX + MOVL R8, SI JMP candidate_match_encodeBetterBlockAsm no_short_found_encodeBetterBlockAsm: - CMPL R9, SI + CMPL R10, DI JEQ candidate_match_encodeBetterBlockAsm - CMPL R10, SI + CMPL R11, DI JEQ candidateS_match_encodeBetterBlockAsm - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeBetterBlockAsm candidateS_match_encodeBetterBlockAsm: - SHRQ $0x08, SI - MOVQ SI, R9 - SHLQ $0x08, R9 - IMULQ R8, R9 - SHRQ $0x2f, R9 - MOVL 24(SP)(R9*4), BX - INCL CX - MOVL CX, 24(SP)(R9*4) - CMPL (DX)(BX*1), SI + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeBetterBlockAsm - DECL CX - MOVL DI, BX + DECL DX + MOVL R8, SI candidate_match_encodeBetterBlockAsm: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeBetterBlockAsm match_extend_back_loop_encodeBetterBlockAsm: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeBetterBlockAsm - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeBetterBlockAsm - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeBetterBlockAsm JMP match_extend_back_loop_encodeBetterBlockAsm match_extend_back_end_encodeBetterBlockAsm: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 5(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 5(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeBetterBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeBetterBlockAsm: - MOVL CX, SI - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), R9 + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_match_nolit_encodeBetterBlockAsm: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_match_nolit_encodeBetterBlockAsm - MOVQ (R8)(R11*1), R10 - MOVQ 8(R8)(R11*1), R12 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm - XORQ 8(R9)(R11*1), R12 + XORQ 8(R10)(R12*1), R13 JNZ matchlen_bsf_16match_nolit_encodeBetterBlockAsm - LEAL -16(DI), DI - LEAL 16(R11), R11 + LEAL -16(R8), R8 + LEAL 16(R12), R12 JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm matchlen_bsf_16match_nolit_encodeBetterBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP match_nolit_end_encodeBetterBlockAsm matchlen_match8_match_nolit_encodeBetterBlockAsm: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_match_nolit_encodeBetterBlockAsm - MOVQ (R8)(R11*1), R10 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm - LEAL -8(DI), DI - LEAL 8(R11), R11 + LEAL -8(R8), R8 + LEAL 8(R12), R12 JMP matchlen_match4_match_nolit_encodeBetterBlockAsm matchlen_bsf_8_match_nolit_encodeBetterBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP match_nolit_end_encodeBetterBlockAsm matchlen_match4_match_nolit_encodeBetterBlockAsm: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_match_nolit_encodeBetterBlockAsm - MOVL (R8)(R11*1), R10 - CMPL (R9)(R11*1), R10 + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 JNE matchlen_match2_match_nolit_encodeBetterBlockAsm - LEAL -4(DI), DI - LEAL 4(R11), R11 + LEAL -4(R8), R8 + LEAL 4(R12), R12 matchlen_match2_match_nolit_encodeBetterBlockAsm: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_match_nolit_encodeBetterBlockAsm JB match_nolit_end_encodeBetterBlockAsm - MOVW (R8)(R11*1), R10 - CMPW (R9)(R11*1), R10 + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 JNE matchlen_match1_match_nolit_encodeBetterBlockAsm - LEAL 2(R11), R11 - SUBL $0x02, DI + LEAL 2(R12), R12 + SUBL $0x02, R8 JZ match_nolit_end_encodeBetterBlockAsm matchlen_match1_match_nolit_encodeBetterBlockAsm: - MOVB (R8)(R11*1), R10 - CMPB (R9)(R11*1), R10 + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 JNE match_nolit_end_encodeBetterBlockAsm - LEAL 1(R11), R11 + LEAL 1(R12), R12 match_nolit_end_encodeBetterBlockAsm: - MOVL CX, DI - SUBL BX, DI + MOVL DX, R8 + SUBL SI, R8 // Check if repeat - CMPL 16(SP), DI + CMPL 16(SP), R8 JEQ match_is_repeat_encodeBetterBlockAsm - CMPL R11, $0x01 + CMPL R12, $0x01 JA match_length_ok_encodeBetterBlockAsm - CMPL DI, $0x0000ffff + CMPL R8, $0x0000ffff JBE match_length_ok_encodeBetterBlockAsm - MOVL 20(SP), CX - INCL CX + MOVL 20(SP), DX + INCL DX JMP search_loop_encodeBetterBlockAsm match_length_ok_encodeBetterBlockAsm: - MOVL DI, 16(SP) - MOVL 12(SP), BX - CMPL BX, SI + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_encodeBetterBlockAsm - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_encodeBetterBlockAsm - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_encodeBetterBlockAsm - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB three_bytes_match_emit_encodeBetterBlockAsm - CMPL BX, $0x01000000 + CMPL SI, $0x01000000 JB four_bytes_match_emit_encodeBetterBlockAsm - MOVB $0xfc, (AX) - MOVL BX, 1(AX) - ADDQ $0x05, AX + MOVB $0xfc, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX JMP memmove_long_match_emit_encodeBetterBlockAsm four_bytes_match_emit_encodeBetterBlockAsm: - MOVL BX, R10 - SHRL $0x10, R10 - MOVB $0xf8, (AX) - MOVW BX, 1(AX) - MOVB R10, 3(AX) - ADDQ $0x04, AX + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX JMP memmove_long_match_emit_encodeBetterBlockAsm three_bytes_match_emit_encodeBetterBlockAsm: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeBetterBlockAsm two_bytes_match_emit_encodeBetterBlockAsm: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_encodeBetterBlockAsm JMP memmove_long_match_emit_encodeBetterBlockAsm one_byte_match_emit_encodeBetterBlockAsm: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeBetterBlockAsm: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x04 + CMPQ R9, $0x04 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4 - CMPQ R8, $0x08 + CMPQ R9, $0x08 JB emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4through7 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_33through64 emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4: - MOVL (R9), R10 - MOVL R10, (AX) + MOVL (R10), R11 + MOVL R11, (CX) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4through7: - MOVL (R9), R10 - MOVL -4(R9)(R8*1), R9 - MOVL R10, (AX) - MOVL R9, -4(AX)(R8*1) + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeBetterBlockAsm: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_encodeBetterBlockAsm memmove_long_match_emit_encodeBetterBlockAsm: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_big_loop_back emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_encodeBetterBlockAsm: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitCopy - CMPL DI, $0x00010000 + CMPL R8, $0x00010000 JB two_byte_offset_match_nolit_encodeBetterBlockAsm - CMPL R11, $0x40 + CMPL R12, $0x40 JBE four_bytes_remain_match_nolit_encodeBetterBlockAsm - MOVB $0xff, (AX) - MOVL DI, 1(AX) - LEAL -64(R11), R11 - ADDQ $0x05, AX - CMPL R11, $0x04 + MOVB $0xff, (CX) + MOVL R8, 1(CX) + LEAL -64(R12), R12 + ADDQ $0x05, CX + CMPL R12, $0x04 JB four_bytes_remain_match_nolit_encodeBetterBlockAsm // emitRepeat emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy: - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy - CMPL R11, $0x00010100 + CMPL R12, $0x00010100 JB repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy - CMPL R11, $0x0100ffff + CMPL R12, $0x0100ffff JB repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy - LEAL -16842747(R11), R11 - MOVL $0xfffb001d, (AX) - MOVB $0xff, 4(AX) - ADDQ $0x05, AX + LEAL -16842747(R12), R12 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX JMP emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy: - LEAL -65536(R11), R11 - MOVL R11, DI - MOVW $0x001d, (AX) - MOVW R11, 2(AX) - SARL $0x10, DI - MOVB DI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy: - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm four_bytes_remain_match_nolit_encodeBetterBlockAsm: - TESTL R11, R11 + TESTL R12, R12 JZ match_nolit_emitcopy_end_encodeBetterBlockAsm - XORL BX, BX - LEAL -1(BX)(R11*4), R11 - MOVB R11, (AX) - MOVL DI, 1(AX) - ADDQ $0x05, AX + XORL SI, SI + LEAL -1(SI)(R12*4), R12 + MOVB R12, (CX) + MOVL R8, 1(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm two_byte_offset_match_nolit_encodeBetterBlockAsm: - CMPL R11, $0x40 + CMPL R12, $0x40 JBE two_byte_offset_short_match_nolit_encodeBetterBlockAsm - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE long_offset_short_match_nolit_encodeBetterBlockAsm - MOVL $0x00000001, BX - LEAL 16(BX), BX - MOVB DI, 1(AX) - MOVL DI, R8 - SHRL $0x08, R8 - SHLL $0x05, R8 - ORL R8, BX - MOVB BL, (AX) - ADDQ $0x02, AX - SUBL $0x08, R11 + MOVL $0x00000001, SI + LEAL 16(SI), SI + MOVB R8, 1(CX) + MOVL R8, R9 + SHRL $0x08, R9 + SHLL $0x05, R9 + ORL R9, SI + MOVB SI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R12 // emitRepeat - LEAL -4(R11), R11 + LEAL -4(R12), R12 JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b - CMPL R11, $0x00010100 + CMPL R12, $0x00010100 JB repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b - CMPL R11, $0x0100ffff + CMPL R12, $0x0100ffff JB repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b - LEAL -16842747(R11), R11 - MOVL $0xfffb001d, (AX) - MOVB $0xff, 4(AX) - ADDQ $0x05, AX + LEAL -16842747(R12), R12 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX JMP emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: - LEAL -65536(R11), R11 - MOVL R11, DI - MOVW $0x001d, (AX) - MOVW R11, 2(AX) - SARL $0x10, DI - MOVB DI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm long_offset_short_match_nolit_encodeBetterBlockAsm: - MOVB $0xee, (AX) - MOVW DI, 1(AX) - LEAL -60(R11), R11 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX // emitRepeat emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short: - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short - CMPL R11, $0x00010100 + CMPL R12, $0x00010100 JB repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short - CMPL R11, $0x0100ffff + CMPL R12, $0x0100ffff JB repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short - LEAL -16842747(R11), R11 - MOVL $0xfffb001d, (AX) - MOVB $0xff, 4(AX) - ADDQ $0x05, AX + LEAL -16842747(R12), R12 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX JMP emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short: - LEAL -65536(R11), R11 - MOVL R11, DI - MOVW $0x001d, (AX) - MOVW R11, 2(AX) - SARL $0x10, DI - MOVB DI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short: - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm two_byte_offset_short_match_nolit_encodeBetterBlockAsm: - MOVL R11, BX - SHLL $0x02, BX - CMPL R11, $0x0c + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c JAE emit_copy_three_match_nolit_encodeBetterBlockAsm - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE emit_copy_three_match_nolit_encodeBetterBlockAsm - LEAL -15(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm emit_copy_three_match_nolit_encodeBetterBlockAsm: - LEAL -2(BX), BX - MOVB BL, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm match_is_repeat_encodeBetterBlockAsm: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_repeat_encodeBetterBlockAsm - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_repeat_encodeBetterBlockAsm - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB three_bytes_match_emit_repeat_encodeBetterBlockAsm - CMPL BX, $0x01000000 + CMPL SI, $0x01000000 JB four_bytes_match_emit_repeat_encodeBetterBlockAsm - MOVB $0xfc, (AX) - MOVL BX, 1(AX) - ADDQ $0x05, AX + MOVB $0xfc, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm four_bytes_match_emit_repeat_encodeBetterBlockAsm: - MOVL BX, R10 - SHRL $0x10, R10 - MOVB $0xf8, (AX) - MOVW BX, 1(AX) - MOVB R10, 3(AX) - ADDQ $0x04, AX + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm three_bytes_match_emit_repeat_encodeBetterBlockAsm: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm two_bytes_match_emit_repeat_encodeBetterBlockAsm: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_repeat_encodeBetterBlockAsm JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm one_byte_match_emit_repeat_encodeBetterBlockAsm: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_repeat_encodeBetterBlockAsm: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x04 + CMPQ R9, $0x04 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4 - CMPQ R8, $0x08 + CMPQ R9, $0x08 JB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4through7 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_17through32 JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_33through64 emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4: - MOVL (R9), R10 - MOVL R10, (AX) + MOVL (R10), R11 + MOVL R11, (CX) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4through7: - MOVL (R9), R10 - MOVL -4(R9)(R8*1), R9 - MOVL R10, (AX) - MOVL R9, -4(AX)(R8*1) + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm memmove_long_match_emit_repeat_encodeBetterBlockAsm: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_big_loop_back emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_repeat_encodeBetterBlockAsm: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitRepeat emit_repeat_again_match_nolit_repeat_encodeBetterBlockAsm: - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_repeat_encodeBetterBlockAsm - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_repeat_encodeBetterBlockAsm - CMPL R11, $0x00010100 + CMPL R12, $0x00010100 JB repeat_four_match_nolit_repeat_encodeBetterBlockAsm - CMPL R11, $0x0100ffff + CMPL R12, $0x0100ffff JB repeat_five_match_nolit_repeat_encodeBetterBlockAsm - LEAL -16842747(R11), R11 - MOVL $0xfffb001d, (AX) - MOVB $0xff, 4(AX) - ADDQ $0x05, AX + LEAL -16842747(R12), R12 + MOVL $0xfffb001d, (CX) + MOVB $0xff, 4(CX) + ADDQ $0x05, CX JMP emit_repeat_again_match_nolit_repeat_encodeBetterBlockAsm repeat_five_match_nolit_repeat_encodeBetterBlockAsm: - LEAL -65536(R11), R11 - MOVL R11, DI - MOVW $0x001d, (AX) - MOVW R11, 2(AX) - SARL $0x10, DI - MOVB DI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_four_match_nolit_repeat_encodeBetterBlockAsm: - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_three_match_nolit_repeat_encodeBetterBlockAsm: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_two_match_nolit_repeat_encodeBetterBlockAsm: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX match_nolit_emitcopy_end_encodeBetterBlockAsm: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeBetterBlockAsm - CMPQ AX, (SP) - JB match_nolit_dst_ok_encodeBetterBlockAsm - MOVQ $0x00000000, ret+48(FP) - RET - -match_nolit_dst_ok_encodeBetterBlockAsm: - MOVQ $0x00cf1bbcdcbfa563, BX - MOVQ $0x9e3779b1, DI - LEAQ 1(SI), SI - LEAQ -2(CX), R8 - MOVQ (DX)(SI*1), R9 - MOVQ 1(DX)(SI*1), R10 - MOVQ (DX)(R8*1), R11 - MOVQ 1(DX)(R8*1), R12 - SHLQ $0x08, R9 - IMULQ BX, R9 - SHRQ $0x2f, R9 - SHLQ $0x20, R10 - IMULQ DI, R10 - SHRQ $0x32, R10 - SHLQ $0x08, R11 - IMULQ BX, R11 - SHRQ $0x2f, R11 - SHLQ $0x20, R12 - IMULQ DI, R12 - SHRQ $0x32, R12 - LEAQ 1(SI), DI - LEAQ 1(R8), R13 - MOVL SI, 24(SP)(R9*4) - MOVL R8, 24(SP)(R11*4) - MOVL DI, 524312(SP)(R10*4) - MOVL R13, 524312(SP)(R12*4) - LEAQ 1(R8)(SI*1), DI - SHRQ $0x01, DI - ADDQ $0x01, SI - SUBQ $0x01, R8 + CMPQ CX, (SP) + JB match_nolit_dst_ok_encodeBetterBlockAsm + MOVQ $0x00000000, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBetterBlockAsm: + MOVQ $0x00cf1bbcdcbfa563, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x32, R11 + SHLQ $0x08, R12 + IMULQ SI, R12 + SHRQ $0x2f, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x32, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 524288(AX)(R11*4) + MOVL R14, 524288(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 index_loop_encodeBetterBlockAsm: - CMPQ DI, R8 + CMPQ R8, R9 JAE search_loop_encodeBetterBlockAsm - MOVQ (DX)(SI*1), R9 - MOVQ (DX)(DI*1), R10 - SHLQ $0x08, R9 - IMULQ BX, R9 - SHRQ $0x2f, R9 + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 SHLQ $0x08, R10 - IMULQ BX, R10 + IMULQ SI, R10 SHRQ $0x2f, R10 - MOVL SI, 24(SP)(R9*4) - MOVL DI, 24(SP)(R10*4) - ADDQ $0x02, SI + SHLQ $0x08, R11 + IMULQ SI, R11 + SHRQ $0x2f, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) ADDQ $0x02, DI + ADDQ $0x02, R8 JMP index_loop_encodeBetterBlockAsm emit_remainder_encodeBetterBlockAsm: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 5(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 5(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeBetterBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeBetterBlockAsm: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeBetterBlockAsm @@ -6932,41 +6938,41 @@ emit_remainder_ok_encodeBetterBlockAsm: JB three_bytes_emit_remainder_encodeBetterBlockAsm CMPL DX, $0x01000000 JB four_bytes_emit_remainder_encodeBetterBlockAsm - MOVB $0xfc, (AX) - MOVL DX, 1(AX) - ADDQ $0x05, AX + MOVB $0xfc, (CX) + MOVL DX, 1(CX) + ADDQ $0x05, CX JMP memmove_long_emit_remainder_encodeBetterBlockAsm four_bytes_emit_remainder_encodeBetterBlockAsm: MOVL DX, BX SHRL $0x10, BX - MOVB $0xf8, (AX) - MOVW DX, 1(AX) - MOVB BL, 3(AX) - ADDQ $0x04, AX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX JMP memmove_long_emit_remainder_encodeBetterBlockAsm three_bytes_emit_remainder_encodeBetterBlockAsm: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeBetterBlockAsm two_bytes_emit_remainder_encodeBetterBlockAsm: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeBetterBlockAsm JMP memmove_long_emit_remainder_encodeBetterBlockAsm one_byte_emit_remainder_encodeBetterBlockAsm: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeBetterBlockAsm: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -6982,73 +6988,73 @@ memmove_emit_remainder_encodeBetterBlockAsm: JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeBetterBlockAsm: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm memmove_long_emit_remainder_encodeBetterBlockAsm: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_big_loop_back: MOVOU (SI), X4 @@ -7062,903 +7068,904 @@ emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeBetterBlockAsm: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeBetterBlockAsm4MB(dst []byte, src []byte) int +// func encodeBetterBlockAsm4MB(dst []byte, src []byte, tmp *[589824]byte) int // Requires: BMI, SSE2 -TEXT ·encodeBetterBlockAsm4MB(SB), $589848-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00001200, CX - LEAQ 24(SP), DX +TEXT ·encodeBetterBlockAsm4MB(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00001200, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeBetterBlockAsm4MB: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeBetterBlockAsm4MB MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -6(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX + MOVQ src_len+32(FP), DX + LEAQ -6(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX MOVL $0x00000000, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_base+24(FP), BX search_loop_encodeBetterBlockAsm4MB: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x07, BX - CMPL BX, $0x63 + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x07, SI + CMPL SI, $0x63 JBE check_maxskip_ok_encodeBetterBlockAsm4MB - LEAL 100(CX), BX + LEAL 100(DX), SI JMP check_maxskip_cont_encodeBetterBlockAsm4MB check_maxskip_ok_encodeBetterBlockAsm4MB: - LEAL 1(CX)(BX*1), BX + LEAL 1(DX)(SI*1), SI check_maxskip_cont_encodeBetterBlockAsm4MB: - CMPL BX, 8(SP) + CMPL SI, 8(SP) JAE emit_remainder_encodeBetterBlockAsm4MB - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x00cf1bbcdcbfa563, R8 - MOVQ $0x9e3779b1, BX - MOVQ SI, R9 - MOVQ SI, R10 - SHLQ $0x08, R9 - IMULQ R8, R9 - SHRQ $0x2f, R9 - SHLQ $0x20, R10 - IMULQ BX, R10 - SHRQ $0x32, R10 - MOVL 24(SP)(R9*4), BX - MOVL 524312(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - MOVL CX, 524312(SP)(R10*4) - MOVQ (DX)(BX*1), R9 - MOVQ (DX)(DI*1), R10 - CMPQ R9, SI + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x00cf1bbcdcbfa563, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL 524288(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 524288(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI JEQ candidate_match_encodeBetterBlockAsm4MB - CMPQ R10, SI + CMPQ R11, DI JNE no_short_found_encodeBetterBlockAsm4MB - MOVL DI, BX + MOVL R8, SI JMP candidate_match_encodeBetterBlockAsm4MB no_short_found_encodeBetterBlockAsm4MB: - CMPL R9, SI + CMPL R10, DI JEQ candidate_match_encodeBetterBlockAsm4MB - CMPL R10, SI + CMPL R11, DI JEQ candidateS_match_encodeBetterBlockAsm4MB - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeBetterBlockAsm4MB candidateS_match_encodeBetterBlockAsm4MB: - SHRQ $0x08, SI - MOVQ SI, R9 - SHLQ $0x08, R9 - IMULQ R8, R9 - SHRQ $0x2f, R9 - MOVL 24(SP)(R9*4), BX - INCL CX - MOVL CX, 24(SP)(R9*4) - CMPL (DX)(BX*1), SI + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeBetterBlockAsm4MB - DECL CX - MOVL DI, BX + DECL DX + MOVL R8, SI candidate_match_encodeBetterBlockAsm4MB: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeBetterBlockAsm4MB match_extend_back_loop_encodeBetterBlockAsm4MB: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeBetterBlockAsm4MB - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeBetterBlockAsm4MB - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeBetterBlockAsm4MB JMP match_extend_back_loop_encodeBetterBlockAsm4MB match_extend_back_end_encodeBetterBlockAsm4MB: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 4(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 4(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeBetterBlockAsm4MB - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeBetterBlockAsm4MB: - MOVL CX, SI - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), R9 + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_match_nolit_encodeBetterBlockAsm4MB: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_match_nolit_encodeBetterBlockAsm4MB - MOVQ (R8)(R11*1), R10 - MOVQ 8(R8)(R11*1), R12 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm4MB - XORQ 8(R9)(R11*1), R12 + XORQ 8(R10)(R12*1), R13 JNZ matchlen_bsf_16match_nolit_encodeBetterBlockAsm4MB - LEAL -16(DI), DI - LEAL 16(R11), R11 + LEAL -16(R8), R8 + LEAL 16(R12), R12 JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm4MB matchlen_bsf_16match_nolit_encodeBetterBlockAsm4MB: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP match_nolit_end_encodeBetterBlockAsm4MB matchlen_match8_match_nolit_encodeBetterBlockAsm4MB: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_match_nolit_encodeBetterBlockAsm4MB - MOVQ (R8)(R11*1), R10 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm4MB - LEAL -8(DI), DI - LEAL 8(R11), R11 + LEAL -8(R8), R8 + LEAL 8(R12), R12 JMP matchlen_match4_match_nolit_encodeBetterBlockAsm4MB matchlen_bsf_8_match_nolit_encodeBetterBlockAsm4MB: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP match_nolit_end_encodeBetterBlockAsm4MB matchlen_match4_match_nolit_encodeBetterBlockAsm4MB: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_match_nolit_encodeBetterBlockAsm4MB - MOVL (R8)(R11*1), R10 - CMPL (R9)(R11*1), R10 + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 JNE matchlen_match2_match_nolit_encodeBetterBlockAsm4MB - LEAL -4(DI), DI - LEAL 4(R11), R11 + LEAL -4(R8), R8 + LEAL 4(R12), R12 matchlen_match2_match_nolit_encodeBetterBlockAsm4MB: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_match_nolit_encodeBetterBlockAsm4MB JB match_nolit_end_encodeBetterBlockAsm4MB - MOVW (R8)(R11*1), R10 - CMPW (R9)(R11*1), R10 + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 JNE matchlen_match1_match_nolit_encodeBetterBlockAsm4MB - LEAL 2(R11), R11 - SUBL $0x02, DI + LEAL 2(R12), R12 + SUBL $0x02, R8 JZ match_nolit_end_encodeBetterBlockAsm4MB matchlen_match1_match_nolit_encodeBetterBlockAsm4MB: - MOVB (R8)(R11*1), R10 - CMPB (R9)(R11*1), R10 + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 JNE match_nolit_end_encodeBetterBlockAsm4MB - LEAL 1(R11), R11 + LEAL 1(R12), R12 match_nolit_end_encodeBetterBlockAsm4MB: - MOVL CX, DI - SUBL BX, DI + MOVL DX, R8 + SUBL SI, R8 // Check if repeat - CMPL 16(SP), DI + CMPL 16(SP), R8 JEQ match_is_repeat_encodeBetterBlockAsm4MB - CMPL R11, $0x01 + CMPL R12, $0x01 JA match_length_ok_encodeBetterBlockAsm4MB - CMPL DI, $0x0000ffff + CMPL R8, $0x0000ffff JBE match_length_ok_encodeBetterBlockAsm4MB - MOVL 20(SP), CX - INCL CX + MOVL 20(SP), DX + INCL DX JMP search_loop_encodeBetterBlockAsm4MB match_length_ok_encodeBetterBlockAsm4MB: - MOVL DI, 16(SP) - MOVL 12(SP), BX - CMPL BX, SI + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_encodeBetterBlockAsm4MB - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_encodeBetterBlockAsm4MB - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_encodeBetterBlockAsm4MB - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB three_bytes_match_emit_encodeBetterBlockAsm4MB - MOVL BX, R10 - SHRL $0x10, R10 - MOVB $0xf8, (AX) - MOVW BX, 1(AX) - MOVB R10, 3(AX) - ADDQ $0x04, AX + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX JMP memmove_long_match_emit_encodeBetterBlockAsm4MB three_bytes_match_emit_encodeBetterBlockAsm4MB: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeBetterBlockAsm4MB two_bytes_match_emit_encodeBetterBlockAsm4MB: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_encodeBetterBlockAsm4MB JMP memmove_long_match_emit_encodeBetterBlockAsm4MB one_byte_match_emit_encodeBetterBlockAsm4MB: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeBetterBlockAsm4MB: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x04 + CMPQ R9, $0x04 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4 - CMPQ R8, $0x08 + CMPQ R9, $0x08 JB emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4through7 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_33through64 emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4: - MOVL (R9), R10 - MOVL R10, (AX) + MOVL (R10), R11 + MOVL R11, (CX) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4through7: - MOVL (R9), R10 - MOVL -4(R9)(R8*1), R9 - MOVL R10, (AX) - MOVL R9, -4(AX)(R8*1) + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeBetterBlockAsm4MB: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_encodeBetterBlockAsm4MB memmove_long_match_emit_encodeBetterBlockAsm4MB: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_big_loop_back emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_encodeBetterBlockAsm4MB: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitCopy - CMPL DI, $0x00010000 + CMPL R8, $0x00010000 JB two_byte_offset_match_nolit_encodeBetterBlockAsm4MB - CMPL R11, $0x40 + CMPL R12, $0x40 JBE four_bytes_remain_match_nolit_encodeBetterBlockAsm4MB - MOVB $0xff, (AX) - MOVL DI, 1(AX) - LEAL -64(R11), R11 - ADDQ $0x05, AX - CMPL R11, $0x04 + MOVB $0xff, (CX) + MOVL R8, 1(CX) + LEAL -64(R12), R12 + ADDQ $0x05, CX + CMPL R12, $0x04 JB four_bytes_remain_match_nolit_encodeBetterBlockAsm4MB // emitRepeat - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy - CMPL R11, $0x00010100 + CMPL R12, $0x00010100 JB repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy - LEAL -65536(R11), R11 - MOVL R11, DI - MOVW $0x001d, (AX) - MOVW R11, 2(AX) - SARL $0x10, DI - MOVB DI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy: - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB four_bytes_remain_match_nolit_encodeBetterBlockAsm4MB: - TESTL R11, R11 + TESTL R12, R12 JZ match_nolit_emitcopy_end_encodeBetterBlockAsm4MB - XORL BX, BX - LEAL -1(BX)(R11*4), R11 - MOVB R11, (AX) - MOVL DI, 1(AX) - ADDQ $0x05, AX + XORL SI, SI + LEAL -1(SI)(R12*4), R12 + MOVB R12, (CX) + MOVL R8, 1(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB two_byte_offset_match_nolit_encodeBetterBlockAsm4MB: - CMPL R11, $0x40 + CMPL R12, $0x40 JBE two_byte_offset_short_match_nolit_encodeBetterBlockAsm4MB - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE long_offset_short_match_nolit_encodeBetterBlockAsm4MB - MOVL $0x00000001, BX - LEAL 16(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX - SUBL $0x08, R11 + MOVL $0x00000001, SI + LEAL 16(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R12 // emitRepeat - LEAL -4(R11), R11 + LEAL -4(R12), R12 JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b - CMPL R11, $0x00010100 + CMPL R12, $0x00010100 JB repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b - LEAL -65536(R11), R11 - MOVL R11, DI - MOVW $0x001d, (AX) - MOVW R11, 2(AX) - SARL $0x10, DI - MOVB DI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB long_offset_short_match_nolit_encodeBetterBlockAsm4MB: - MOVB $0xee, (AX) - MOVW DI, 1(AX) - LEAL -60(R11), R11 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX // emitRepeat - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short - CMPL R11, $0x00010100 + CMPL R12, $0x00010100 JB repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short - LEAL -65536(R11), R11 - MOVL R11, DI - MOVW $0x001d, (AX) - MOVW R11, 2(AX) - SARL $0x10, DI - MOVB DI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB two_byte_offset_short_match_nolit_encodeBetterBlockAsm4MB: - MOVL R11, BX - SHLL $0x02, BX - CMPL R11, $0x0c + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c JAE emit_copy_three_match_nolit_encodeBetterBlockAsm4MB - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE emit_copy_three_match_nolit_encodeBetterBlockAsm4MB - LEAL -15(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB emit_copy_three_match_nolit_encodeBetterBlockAsm4MB: - LEAL -2(BX), BX - MOVB BL, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB match_is_repeat_encodeBetterBlockAsm4MB: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm4MB - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_repeat_encodeBetterBlockAsm4MB - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_repeat_encodeBetterBlockAsm4MB - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB three_bytes_match_emit_repeat_encodeBetterBlockAsm4MB - MOVL BX, R10 - SHRL $0x10, R10 - MOVB $0xf8, (AX) - MOVW BX, 1(AX) - MOVB R10, 3(AX) - ADDQ $0x04, AX + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB three_bytes_match_emit_repeat_encodeBetterBlockAsm4MB: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB two_bytes_match_emit_repeat_encodeBetterBlockAsm4MB: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_repeat_encodeBetterBlockAsm4MB JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB one_byte_match_emit_repeat_encodeBetterBlockAsm4MB: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_repeat_encodeBetterBlockAsm4MB: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x04 + CMPQ R9, $0x04 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4 - CMPQ R8, $0x08 + CMPQ R9, $0x08 JB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4through7 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_17through32 JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_33through64 emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4: - MOVL (R9), R10 - MOVL R10, (AX) + MOVL (R10), R11 + MOVL R11, (CX) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4through7: - MOVL (R9), R10 - MOVL -4(R9)(R8*1), R9 - MOVL R10, (AX) - MOVL R9, -4(AX)(R8*1) + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm4MB memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_big_loop_back emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_repeat_encodeBetterBlockAsm4MB: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitRepeat - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_repeat_encodeBetterBlockAsm4MB - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_repeat_encodeBetterBlockAsm4MB - CMPL R11, $0x00010100 + CMPL R12, $0x00010100 JB repeat_four_match_nolit_repeat_encodeBetterBlockAsm4MB - LEAL -65536(R11), R11 - MOVL R11, DI - MOVW $0x001d, (AX) - MOVW R11, 2(AX) - SARL $0x10, DI - MOVB DI, 4(AX) - ADDQ $0x05, AX + LEAL -65536(R12), R12 + MOVL R12, R8 + MOVW $0x001d, (CX) + MOVW R12, 2(CX) + SARL $0x10, R8 + MOVB R8, 4(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_four_match_nolit_repeat_encodeBetterBlockAsm4MB: - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_three_match_nolit_repeat_encodeBetterBlockAsm4MB: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_two_match_nolit_repeat_encodeBetterBlockAsm4MB: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX match_nolit_emitcopy_end_encodeBetterBlockAsm4MB: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeBetterBlockAsm4MB - CMPQ AX, (SP) + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeBetterBlockAsm4MB - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeBetterBlockAsm4MB: - MOVQ $0x00cf1bbcdcbfa563, BX - MOVQ $0x9e3779b1, DI - LEAQ 1(SI), SI - LEAQ -2(CX), R8 - MOVQ (DX)(SI*1), R9 - MOVQ 1(DX)(SI*1), R10 - MOVQ (DX)(R8*1), R11 - MOVQ 1(DX)(R8*1), R12 - SHLQ $0x08, R9 - IMULQ BX, R9 - SHRQ $0x2f, R9 - SHLQ $0x20, R10 - IMULQ DI, R10 - SHRQ $0x32, R10 - SHLQ $0x08, R11 - IMULQ BX, R11 - SHRQ $0x2f, R11 - SHLQ $0x20, R12 - IMULQ DI, R12 - SHRQ $0x32, R12 - LEAQ 1(SI), DI - LEAQ 1(R8), R13 - MOVL SI, 24(SP)(R9*4) - MOVL R8, 24(SP)(R11*4) - MOVL DI, 524312(SP)(R10*4) - MOVL R13, 524312(SP)(R12*4) - LEAQ 1(R8)(SI*1), DI - SHRQ $0x01, DI - ADDQ $0x01, SI - SUBQ $0x01, R8 + MOVQ $0x00cf1bbcdcbfa563, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x32, R11 + SHLQ $0x08, R12 + IMULQ SI, R12 + SHRQ $0x2f, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x32, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 524288(AX)(R11*4) + MOVL R14, 524288(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 index_loop_encodeBetterBlockAsm4MB: - CMPQ DI, R8 + CMPQ R8, R9 JAE search_loop_encodeBetterBlockAsm4MB - MOVQ (DX)(SI*1), R9 - MOVQ (DX)(DI*1), R10 - SHLQ $0x08, R9 - IMULQ BX, R9 - SHRQ $0x2f, R9 + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 SHLQ $0x08, R10 - IMULQ BX, R10 + IMULQ SI, R10 SHRQ $0x2f, R10 - MOVL SI, 24(SP)(R9*4) - MOVL DI, 24(SP)(R10*4) - ADDQ $0x02, SI + SHLQ $0x08, R11 + IMULQ SI, R11 + SHRQ $0x2f, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) ADDQ $0x02, DI + ADDQ $0x02, R8 JMP index_loop_encodeBetterBlockAsm4MB emit_remainder_encodeBetterBlockAsm4MB: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 4(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 4(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeBetterBlockAsm4MB - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeBetterBlockAsm4MB: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm4MB - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeBetterBlockAsm4MB @@ -7968,33 +7975,33 @@ emit_remainder_ok_encodeBetterBlockAsm4MB: JB three_bytes_emit_remainder_encodeBetterBlockAsm4MB MOVL DX, BX SHRL $0x10, BX - MOVB $0xf8, (AX) - MOVW DX, 1(AX) - MOVB BL, 3(AX) - ADDQ $0x04, AX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX JMP memmove_long_emit_remainder_encodeBetterBlockAsm4MB three_bytes_emit_remainder_encodeBetterBlockAsm4MB: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeBetterBlockAsm4MB two_bytes_emit_remainder_encodeBetterBlockAsm4MB: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeBetterBlockAsm4MB JMP memmove_long_emit_remainder_encodeBetterBlockAsm4MB one_byte_emit_remainder_encodeBetterBlockAsm4MB: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeBetterBlockAsm4MB: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -8010,73 +8017,73 @@ memmove_emit_remainder_encodeBetterBlockAsm4MB: JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm4MB memmove_long_emit_remainder_encodeBetterBlockAsm4MB: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_big_loop_back: MOVOU (SI), X4 @@ -8090,756 +8097,757 @@ emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeBetterBlockAsm4MB: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeBetterBlockAsm12B(dst []byte, src []byte) int +// func encodeBetterBlockAsm12B(dst []byte, src []byte, tmp *[81920]byte) int // Requires: BMI, SSE2 -TEXT ·encodeBetterBlockAsm12B(SB), $81944-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000280, CX - LEAQ 24(SP), DX +TEXT ·encodeBetterBlockAsm12B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000280, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeBetterBlockAsm12B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeBetterBlockAsm12B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -6(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX + MOVQ src_len+32(FP), DX + LEAQ -6(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX MOVL $0x00000000, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_base+24(FP), BX search_loop_encodeBetterBlockAsm12B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x06, BX - LEAL 1(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeBetterBlockAsm12B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ $0x9e3779b1, BX - MOVQ SI, R9 - MOVQ SI, R10 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 - SHLQ $0x20, R10 - IMULQ BX, R10 - SHRQ $0x34, R10 - MOVL 24(SP)(R9*4), BX - MOVL 65560(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - MOVL CX, 65560(SP)(R10*4) - MOVQ (DX)(BX*1), R9 - MOVQ (DX)(DI*1), R10 - CMPQ R9, SI + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x34, R11 + MOVL (AX)(R10*4), SI + MOVL 65536(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 65536(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI JEQ candidate_match_encodeBetterBlockAsm12B - CMPQ R10, SI + CMPQ R11, DI JNE no_short_found_encodeBetterBlockAsm12B - MOVL DI, BX + MOVL R8, SI JMP candidate_match_encodeBetterBlockAsm12B no_short_found_encodeBetterBlockAsm12B: - CMPL R9, SI + CMPL R10, DI JEQ candidate_match_encodeBetterBlockAsm12B - CMPL R10, SI + CMPL R11, DI JEQ candidateS_match_encodeBetterBlockAsm12B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeBetterBlockAsm12B candidateS_match_encodeBetterBlockAsm12B: - SHRQ $0x08, SI - MOVQ SI, R9 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 - MOVL 24(SP)(R9*4), BX - INCL CX - MOVL CX, 24(SP)(R9*4) - CMPL (DX)(BX*1), SI + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeBetterBlockAsm12B - DECL CX - MOVL DI, BX + DECL DX + MOVL R8, SI candidate_match_encodeBetterBlockAsm12B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeBetterBlockAsm12B match_extend_back_loop_encodeBetterBlockAsm12B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeBetterBlockAsm12B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeBetterBlockAsm12B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeBetterBlockAsm12B JMP match_extend_back_loop_encodeBetterBlockAsm12B match_extend_back_end_encodeBetterBlockAsm12B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeBetterBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeBetterBlockAsm12B: - MOVL CX, SI - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), R9 + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_match_nolit_encodeBetterBlockAsm12B: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_match_nolit_encodeBetterBlockAsm12B - MOVQ (R8)(R11*1), R10 - MOVQ 8(R8)(R11*1), R12 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm12B - XORQ 8(R9)(R11*1), R12 + XORQ 8(R10)(R12*1), R13 JNZ matchlen_bsf_16match_nolit_encodeBetterBlockAsm12B - LEAL -16(DI), DI - LEAL 16(R11), R11 + LEAL -16(R8), R8 + LEAL 16(R12), R12 JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm12B matchlen_bsf_16match_nolit_encodeBetterBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP match_nolit_end_encodeBetterBlockAsm12B matchlen_match8_match_nolit_encodeBetterBlockAsm12B: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_match_nolit_encodeBetterBlockAsm12B - MOVQ (R8)(R11*1), R10 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm12B - LEAL -8(DI), DI - LEAL 8(R11), R11 + LEAL -8(R8), R8 + LEAL 8(R12), R12 JMP matchlen_match4_match_nolit_encodeBetterBlockAsm12B matchlen_bsf_8_match_nolit_encodeBetterBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP match_nolit_end_encodeBetterBlockAsm12B matchlen_match4_match_nolit_encodeBetterBlockAsm12B: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_match_nolit_encodeBetterBlockAsm12B - MOVL (R8)(R11*1), R10 - CMPL (R9)(R11*1), R10 + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 JNE matchlen_match2_match_nolit_encodeBetterBlockAsm12B - LEAL -4(DI), DI - LEAL 4(R11), R11 + LEAL -4(R8), R8 + LEAL 4(R12), R12 matchlen_match2_match_nolit_encodeBetterBlockAsm12B: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_match_nolit_encodeBetterBlockAsm12B JB match_nolit_end_encodeBetterBlockAsm12B - MOVW (R8)(R11*1), R10 - CMPW (R9)(R11*1), R10 + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 JNE matchlen_match1_match_nolit_encodeBetterBlockAsm12B - LEAL 2(R11), R11 - SUBL $0x02, DI + LEAL 2(R12), R12 + SUBL $0x02, R8 JZ match_nolit_end_encodeBetterBlockAsm12B matchlen_match1_match_nolit_encodeBetterBlockAsm12B: - MOVB (R8)(R11*1), R10 - CMPB (R9)(R11*1), R10 + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 JNE match_nolit_end_encodeBetterBlockAsm12B - LEAL 1(R11), R11 + LEAL 1(R12), R12 match_nolit_end_encodeBetterBlockAsm12B: - MOVL CX, DI - SUBL BX, DI + MOVL DX, R8 + SUBL SI, R8 // Check if repeat - CMPL 16(SP), DI + CMPL 16(SP), R8 JEQ match_is_repeat_encodeBetterBlockAsm12B - MOVL DI, 16(SP) - MOVL 12(SP), BX - CMPL BX, SI + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_encodeBetterBlockAsm12B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_encodeBetterBlockAsm12B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_encodeBetterBlockAsm12B JB three_bytes_match_emit_encodeBetterBlockAsm12B three_bytes_match_emit_encodeBetterBlockAsm12B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeBetterBlockAsm12B two_bytes_match_emit_encodeBetterBlockAsm12B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_encodeBetterBlockAsm12B JMP memmove_long_match_emit_encodeBetterBlockAsm12B one_byte_match_emit_encodeBetterBlockAsm12B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeBetterBlockAsm12B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x04 + CMPQ R9, $0x04 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4 - CMPQ R8, $0x08 + CMPQ R9, $0x08 JB emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4through7 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4: - MOVL (R9), R10 - MOVL R10, (AX) + MOVL (R10), R11 + MOVL R11, (CX) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4through7: - MOVL (R9), R10 - MOVL -4(R9)(R8*1), R9 - MOVL R10, (AX) - MOVL R9, -4(AX)(R8*1) + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeBetterBlockAsm12B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_encodeBetterBlockAsm12B memmove_long_match_emit_encodeBetterBlockAsm12B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_encodeBetterBlockAsm12B: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitCopy - CMPL R11, $0x40 + CMPL R12, $0x40 JBE two_byte_offset_short_match_nolit_encodeBetterBlockAsm12B - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE long_offset_short_match_nolit_encodeBetterBlockAsm12B - MOVL $0x00000001, BX - LEAL 16(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX - SUBL $0x08, R11 + MOVL $0x00000001, SI + LEAL 16(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R12 // emitRepeat - LEAL -4(R11), R11 + LEAL -4(R12), R12 JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B long_offset_short_match_nolit_encodeBetterBlockAsm12B: - MOVB $0xee, (AX) - MOVW DI, 1(AX) - LEAL -60(R11), R11 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX // emitRepeat - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B two_byte_offset_short_match_nolit_encodeBetterBlockAsm12B: - MOVL R11, BX - SHLL $0x02, BX - CMPL R11, $0x0c + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c JAE emit_copy_three_match_nolit_encodeBetterBlockAsm12B - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE emit_copy_three_match_nolit_encodeBetterBlockAsm12B - LEAL -15(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B emit_copy_three_match_nolit_encodeBetterBlockAsm12B: - LEAL -2(BX), BX - MOVB BL, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B match_is_repeat_encodeBetterBlockAsm12B: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm12B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_repeat_encodeBetterBlockAsm12B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_repeat_encodeBetterBlockAsm12B JB three_bytes_match_emit_repeat_encodeBetterBlockAsm12B three_bytes_match_emit_repeat_encodeBetterBlockAsm12B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm12B two_bytes_match_emit_repeat_encodeBetterBlockAsm12B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_repeat_encodeBetterBlockAsm12B JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm12B one_byte_match_emit_repeat_encodeBetterBlockAsm12B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_repeat_encodeBetterBlockAsm12B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x04 + CMPQ R9, $0x04 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4 - CMPQ R8, $0x08 + CMPQ R9, $0x08 JB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4through7 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_33through64 emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4: - MOVL (R9), R10 - MOVL R10, (AX) + MOVL (R10), R11 + MOVL R11, (CX) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4through7: - MOVL (R9), R10 - MOVL -4(R9)(R8*1), R9 - MOVL R10, (AX) - MOVL R9, -4(AX)(R8*1) + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm12B memmove_long_match_emit_repeat_encodeBetterBlockAsm12B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_big_loop_back emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_repeat_encodeBetterBlockAsm12B: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitRepeat - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_repeat_encodeBetterBlockAsm12B - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_repeat_encodeBetterBlockAsm12B - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B repeat_three_match_nolit_repeat_encodeBetterBlockAsm12B: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B repeat_two_match_nolit_repeat_encodeBetterBlockAsm12B: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX match_nolit_emitcopy_end_encodeBetterBlockAsm12B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeBetterBlockAsm12B - CMPQ AX, (SP) + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeBetterBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeBetterBlockAsm12B: - MOVQ $0x0000cf1bbcdcbf9b, BX - MOVQ $0x9e3779b1, DI - LEAQ 1(SI), SI - LEAQ -2(CX), R8 - MOVQ (DX)(SI*1), R9 - MOVQ 1(DX)(SI*1), R10 - MOVQ (DX)(R8*1), R11 - MOVQ 1(DX)(R8*1), R12 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x32, R9 - SHLQ $0x20, R10 - IMULQ DI, R10 - SHRQ $0x34, R10 - SHLQ $0x10, R11 - IMULQ BX, R11 - SHRQ $0x32, R11 - SHLQ $0x20, R12 - IMULQ DI, R12 - SHRQ $0x34, R12 - LEAQ 1(SI), DI - LEAQ 1(R8), R13 - MOVL SI, 24(SP)(R9*4) - MOVL R8, 24(SP)(R11*4) - MOVL DI, 65560(SP)(R10*4) - MOVL R13, 65560(SP)(R12*4) - LEAQ 1(R8)(SI*1), DI - SHRQ $0x01, DI - ADDQ $0x01, SI - SUBQ $0x01, R8 + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x32, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x34, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x32, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x34, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 65536(AX)(R11*4) + MOVL R14, 65536(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 index_loop_encodeBetterBlockAsm12B: - CMPQ DI, R8 + CMPQ R8, R9 JAE search_loop_encodeBetterBlockAsm12B - MOVQ (DX)(SI*1), R9 - MOVQ (DX)(DI*1), R10 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x32, R9 + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 SHLQ $0x10, R10 - IMULQ BX, R10 + IMULQ SI, R10 SHRQ $0x32, R10 - MOVL SI, 24(SP)(R9*4) - MOVL DI, 24(SP)(R10*4) - ADDQ $0x02, SI + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x32, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) ADDQ $0x02, DI + ADDQ $0x02, R8 JMP index_loop_encodeBetterBlockAsm12B emit_remainder_encodeBetterBlockAsm12B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeBetterBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeBetterBlockAsm12B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm12B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeBetterBlockAsm12B @@ -8848,26 +8856,26 @@ emit_remainder_ok_encodeBetterBlockAsm12B: JB three_bytes_emit_remainder_encodeBetterBlockAsm12B three_bytes_emit_remainder_encodeBetterBlockAsm12B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeBetterBlockAsm12B two_bytes_emit_remainder_encodeBetterBlockAsm12B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeBetterBlockAsm12B JMP memmove_long_emit_remainder_encodeBetterBlockAsm12B one_byte_emit_remainder_encodeBetterBlockAsm12B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeBetterBlockAsm12B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -8883,73 +8891,73 @@ memmove_emit_remainder_encodeBetterBlockAsm12B: JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm12B memmove_long_emit_remainder_encodeBetterBlockAsm12B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_big_loop_back: MOVOU (SI), X4 @@ -8963,756 +8971,757 @@ emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 - JAE emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + JAE emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_forward_sse_loop_32 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeBetterBlockAsm12B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeBetterBlockAsm10B(dst []byte, src []byte) int +// func encodeBetterBlockAsm10B(dst []byte, src []byte, tmp *[20480]byte) int // Requires: BMI, SSE2 -TEXT ·encodeBetterBlockAsm10B(SB), $20504-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x000000a0, CX - LEAQ 24(SP), DX +TEXT ·encodeBetterBlockAsm10B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x000000a0, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeBetterBlockAsm10B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeBetterBlockAsm10B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -6(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX + MOVQ src_len+32(FP), DX + LEAQ -6(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX MOVL $0x00000000, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_base+24(FP), BX search_loop_encodeBetterBlockAsm10B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x05, BX - LEAL 1(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeBetterBlockAsm10B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ $0x9e3779b1, BX - MOVQ SI, R9 - MOVQ SI, R10 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x34, R9 - SHLQ $0x20, R10 - IMULQ BX, R10 - SHRQ $0x36, R10 - MOVL 24(SP)(R9*4), BX - MOVL 16408(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - MOVL CX, 16408(SP)(R10*4) - MOVQ (DX)(BX*1), R9 - MOVQ (DX)(DI*1), R10 - CMPQ R9, SI + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x36, R11 + MOVL (AX)(R10*4), SI + MOVL 16384(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 16384(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI JEQ candidate_match_encodeBetterBlockAsm10B - CMPQ R10, SI + CMPQ R11, DI JNE no_short_found_encodeBetterBlockAsm10B - MOVL DI, BX + MOVL R8, SI JMP candidate_match_encodeBetterBlockAsm10B no_short_found_encodeBetterBlockAsm10B: - CMPL R9, SI + CMPL R10, DI JEQ candidate_match_encodeBetterBlockAsm10B - CMPL R10, SI + CMPL R11, DI JEQ candidateS_match_encodeBetterBlockAsm10B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeBetterBlockAsm10B candidateS_match_encodeBetterBlockAsm10B: - SHRQ $0x08, SI - MOVQ SI, R9 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x34, R9 - MOVL 24(SP)(R9*4), BX - INCL CX - MOVL CX, 24(SP)(R9*4) - CMPL (DX)(BX*1), SI + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeBetterBlockAsm10B - DECL CX - MOVL DI, BX + DECL DX + MOVL R8, SI candidate_match_encodeBetterBlockAsm10B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeBetterBlockAsm10B match_extend_back_loop_encodeBetterBlockAsm10B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeBetterBlockAsm10B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeBetterBlockAsm10B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeBetterBlockAsm10B JMP match_extend_back_loop_encodeBetterBlockAsm10B match_extend_back_end_encodeBetterBlockAsm10B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeBetterBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeBetterBlockAsm10B: - MOVL CX, SI - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), R9 + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_match_nolit_encodeBetterBlockAsm10B: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_match_nolit_encodeBetterBlockAsm10B - MOVQ (R8)(R11*1), R10 - MOVQ 8(R8)(R11*1), R12 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm10B - XORQ 8(R9)(R11*1), R12 + XORQ 8(R10)(R12*1), R13 JNZ matchlen_bsf_16match_nolit_encodeBetterBlockAsm10B - LEAL -16(DI), DI - LEAL 16(R11), R11 + LEAL -16(R8), R8 + LEAL 16(R12), R12 JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm10B matchlen_bsf_16match_nolit_encodeBetterBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP match_nolit_end_encodeBetterBlockAsm10B matchlen_match8_match_nolit_encodeBetterBlockAsm10B: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_match_nolit_encodeBetterBlockAsm10B - MOVQ (R8)(R11*1), R10 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm10B - LEAL -8(DI), DI - LEAL 8(R11), R11 + LEAL -8(R8), R8 + LEAL 8(R12), R12 JMP matchlen_match4_match_nolit_encodeBetterBlockAsm10B matchlen_bsf_8_match_nolit_encodeBetterBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP match_nolit_end_encodeBetterBlockAsm10B matchlen_match4_match_nolit_encodeBetterBlockAsm10B: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_match_nolit_encodeBetterBlockAsm10B - MOVL (R8)(R11*1), R10 - CMPL (R9)(R11*1), R10 + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 JNE matchlen_match2_match_nolit_encodeBetterBlockAsm10B - LEAL -4(DI), DI - LEAL 4(R11), R11 + LEAL -4(R8), R8 + LEAL 4(R12), R12 matchlen_match2_match_nolit_encodeBetterBlockAsm10B: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_match_nolit_encodeBetterBlockAsm10B JB match_nolit_end_encodeBetterBlockAsm10B - MOVW (R8)(R11*1), R10 - CMPW (R9)(R11*1), R10 + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 JNE matchlen_match1_match_nolit_encodeBetterBlockAsm10B - LEAL 2(R11), R11 - SUBL $0x02, DI + LEAL 2(R12), R12 + SUBL $0x02, R8 JZ match_nolit_end_encodeBetterBlockAsm10B matchlen_match1_match_nolit_encodeBetterBlockAsm10B: - MOVB (R8)(R11*1), R10 - CMPB (R9)(R11*1), R10 + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 JNE match_nolit_end_encodeBetterBlockAsm10B - LEAL 1(R11), R11 + LEAL 1(R12), R12 match_nolit_end_encodeBetterBlockAsm10B: - MOVL CX, DI - SUBL BX, DI + MOVL DX, R8 + SUBL SI, R8 // Check if repeat - CMPL 16(SP), DI + CMPL 16(SP), R8 JEQ match_is_repeat_encodeBetterBlockAsm10B - MOVL DI, 16(SP) - MOVL 12(SP), BX - CMPL BX, SI + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_encodeBetterBlockAsm10B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_encodeBetterBlockAsm10B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_encodeBetterBlockAsm10B JB three_bytes_match_emit_encodeBetterBlockAsm10B three_bytes_match_emit_encodeBetterBlockAsm10B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeBetterBlockAsm10B two_bytes_match_emit_encodeBetterBlockAsm10B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_encodeBetterBlockAsm10B JMP memmove_long_match_emit_encodeBetterBlockAsm10B one_byte_match_emit_encodeBetterBlockAsm10B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeBetterBlockAsm10B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x04 + CMPQ R9, $0x04 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4 - CMPQ R8, $0x08 + CMPQ R9, $0x08 JB emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4through7 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4: - MOVL (R9), R10 - MOVL R10, (AX) + MOVL (R10), R11 + MOVL R11, (CX) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4through7: - MOVL (R9), R10 - MOVL -4(R9)(R8*1), R9 - MOVL R10, (AX) - MOVL R9, -4(AX)(R8*1) + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeBetterBlockAsm10B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_encodeBetterBlockAsm10B memmove_long_match_emit_encodeBetterBlockAsm10B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_encodeBetterBlockAsm10B: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitCopy - CMPL R11, $0x40 + CMPL R12, $0x40 JBE two_byte_offset_short_match_nolit_encodeBetterBlockAsm10B - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE long_offset_short_match_nolit_encodeBetterBlockAsm10B - MOVL $0x00000001, BX - LEAL 16(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX - SUBL $0x08, R11 + MOVL $0x00000001, SI + LEAL 16(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R12 // emitRepeat - LEAL -4(R11), R11 + LEAL -4(R12), R12 JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B long_offset_short_match_nolit_encodeBetterBlockAsm10B: - MOVB $0xee, (AX) - MOVW DI, 1(AX) - LEAL -60(R11), R11 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX // emitRepeat - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B two_byte_offset_short_match_nolit_encodeBetterBlockAsm10B: - MOVL R11, BX - SHLL $0x02, BX - CMPL R11, $0x0c + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c JAE emit_copy_three_match_nolit_encodeBetterBlockAsm10B - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE emit_copy_three_match_nolit_encodeBetterBlockAsm10B - LEAL -15(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B emit_copy_three_match_nolit_encodeBetterBlockAsm10B: - LEAL -2(BX), BX - MOVB BL, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B match_is_repeat_encodeBetterBlockAsm10B: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm10B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_repeat_encodeBetterBlockAsm10B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_repeat_encodeBetterBlockAsm10B JB three_bytes_match_emit_repeat_encodeBetterBlockAsm10B three_bytes_match_emit_repeat_encodeBetterBlockAsm10B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm10B two_bytes_match_emit_repeat_encodeBetterBlockAsm10B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_repeat_encodeBetterBlockAsm10B JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm10B one_byte_match_emit_repeat_encodeBetterBlockAsm10B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_repeat_encodeBetterBlockAsm10B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x04 + CMPQ R9, $0x04 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4 - CMPQ R8, $0x08 + CMPQ R9, $0x08 JB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4through7 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_33through64 emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4: - MOVL (R9), R10 - MOVL R10, (AX) + MOVL (R10), R11 + MOVL R11, (CX) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4through7: - MOVL (R9), R10 - MOVL -4(R9)(R8*1), R9 - MOVL R10, (AX) - MOVL R9, -4(AX)(R8*1) + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm10B memmove_long_match_emit_repeat_encodeBetterBlockAsm10B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_big_loop_back emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_repeat_encodeBetterBlockAsm10B: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitRepeat - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_repeat_encodeBetterBlockAsm10B - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JB repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_repeat_encodeBetterBlockAsm10B - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B repeat_three_match_nolit_repeat_encodeBetterBlockAsm10B: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B repeat_two_match_nolit_repeat_encodeBetterBlockAsm10B: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B: - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX match_nolit_emitcopy_end_encodeBetterBlockAsm10B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeBetterBlockAsm10B - CMPQ AX, (SP) + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeBetterBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeBetterBlockAsm10B: - MOVQ $0x0000cf1bbcdcbf9b, BX - MOVQ $0x9e3779b1, DI - LEAQ 1(SI), SI - LEAQ -2(CX), R8 - MOVQ (DX)(SI*1), R9 - MOVQ 1(DX)(SI*1), R10 - MOVQ (DX)(R8*1), R11 - MOVQ 1(DX)(R8*1), R12 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x34, R9 - SHLQ $0x20, R10 - IMULQ DI, R10 - SHRQ $0x36, R10 - SHLQ $0x10, R11 - IMULQ BX, R11 - SHRQ $0x34, R11 - SHLQ $0x20, R12 - IMULQ DI, R12 - SHRQ $0x36, R12 - LEAQ 1(SI), DI - LEAQ 1(R8), R13 - MOVL SI, 24(SP)(R9*4) - MOVL R8, 24(SP)(R11*4) - MOVL DI, 16408(SP)(R10*4) - MOVL R13, 16408(SP)(R12*4) - LEAQ 1(R8)(SI*1), DI - SHRQ $0x01, DI - ADDQ $0x01, SI - SUBQ $0x01, R8 + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x34, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x36, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x34, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x36, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 16384(AX)(R11*4) + MOVL R14, 16384(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 index_loop_encodeBetterBlockAsm10B: - CMPQ DI, R8 + CMPQ R8, R9 JAE search_loop_encodeBetterBlockAsm10B - MOVQ (DX)(SI*1), R9 - MOVQ (DX)(DI*1), R10 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x34, R9 + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 SHLQ $0x10, R10 - IMULQ BX, R10 + IMULQ SI, R10 SHRQ $0x34, R10 - MOVL SI, 24(SP)(R9*4) - MOVL DI, 24(SP)(R10*4) - ADDQ $0x02, SI + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x34, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) ADDQ $0x02, DI + ADDQ $0x02, R8 JMP index_loop_encodeBetterBlockAsm10B emit_remainder_encodeBetterBlockAsm10B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeBetterBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeBetterBlockAsm10B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm10B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeBetterBlockAsm10B @@ -9721,26 +9730,26 @@ emit_remainder_ok_encodeBetterBlockAsm10B: JB three_bytes_emit_remainder_encodeBetterBlockAsm10B three_bytes_emit_remainder_encodeBetterBlockAsm10B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeBetterBlockAsm10B two_bytes_emit_remainder_encodeBetterBlockAsm10B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeBetterBlockAsm10B JMP memmove_long_emit_remainder_encodeBetterBlockAsm10B one_byte_emit_remainder_encodeBetterBlockAsm10B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeBetterBlockAsm10B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -9756,73 +9765,73 @@ memmove_emit_remainder_encodeBetterBlockAsm10B: JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm10B memmove_long_emit_remainder_encodeBetterBlockAsm10B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_big_loop_back: MOVOU (SI), X4 @@ -9836,742 +9845,743 @@ emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeBetterBlockAsm10B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeBetterBlockAsm8B(dst []byte, src []byte) int +// func encodeBetterBlockAsm8B(dst []byte, src []byte, tmp *[5120]byte) int // Requires: BMI, SSE2 -TEXT ·encodeBetterBlockAsm8B(SB), $5144-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000028, CX - LEAQ 24(SP), DX +TEXT ·encodeBetterBlockAsm8B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000028, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeBetterBlockAsm8B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeBetterBlockAsm8B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -6(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX + MOVQ src_len+32(FP), DX + LEAQ -6(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX MOVL $0x00000000, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_base+24(FP), BX search_loop_encodeBetterBlockAsm8B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x04, BX - LEAL 1(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x04, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeBetterBlockAsm8B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ $0x9e3779b1, BX - MOVQ SI, R9 - MOVQ SI, R10 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x36, R9 - SHLQ $0x20, R10 - IMULQ BX, R10 - SHRQ $0x38, R10 - MOVL 24(SP)(R9*4), BX - MOVL 4120(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - MOVL CX, 4120(SP)(R10*4) - MOVQ (DX)(BX*1), R9 - MOVQ (DX)(DI*1), R10 - CMPQ R9, SI + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x38, R11 + MOVL (AX)(R10*4), SI + MOVL 4096(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 4096(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI JEQ candidate_match_encodeBetterBlockAsm8B - CMPQ R10, SI + CMPQ R11, DI JNE no_short_found_encodeBetterBlockAsm8B - MOVL DI, BX + MOVL R8, SI JMP candidate_match_encodeBetterBlockAsm8B no_short_found_encodeBetterBlockAsm8B: - CMPL R9, SI + CMPL R10, DI JEQ candidate_match_encodeBetterBlockAsm8B - CMPL R10, SI + CMPL R11, DI JEQ candidateS_match_encodeBetterBlockAsm8B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeBetterBlockAsm8B candidateS_match_encodeBetterBlockAsm8B: - SHRQ $0x08, SI - MOVQ SI, R9 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x36, R9 - MOVL 24(SP)(R9*4), BX - INCL CX - MOVL CX, 24(SP)(R9*4) - CMPL (DX)(BX*1), SI + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeBetterBlockAsm8B - DECL CX - MOVL DI, BX + DECL DX + MOVL R8, SI candidate_match_encodeBetterBlockAsm8B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeBetterBlockAsm8B match_extend_back_loop_encodeBetterBlockAsm8B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeBetterBlockAsm8B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeBetterBlockAsm8B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeBetterBlockAsm8B JMP match_extend_back_loop_encodeBetterBlockAsm8B match_extend_back_end_encodeBetterBlockAsm8B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeBetterBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeBetterBlockAsm8B: - MOVL CX, SI - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), R9 + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_match_nolit_encodeBetterBlockAsm8B: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_match_nolit_encodeBetterBlockAsm8B - MOVQ (R8)(R11*1), R10 - MOVQ 8(R8)(R11*1), R12 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm8B - XORQ 8(R9)(R11*1), R12 + XORQ 8(R10)(R12*1), R13 JNZ matchlen_bsf_16match_nolit_encodeBetterBlockAsm8B - LEAL -16(DI), DI - LEAL 16(R11), R11 + LEAL -16(R8), R8 + LEAL 16(R12), R12 JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm8B matchlen_bsf_16match_nolit_encodeBetterBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP match_nolit_end_encodeBetterBlockAsm8B matchlen_match8_match_nolit_encodeBetterBlockAsm8B: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_match_nolit_encodeBetterBlockAsm8B - MOVQ (R8)(R11*1), R10 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeBetterBlockAsm8B - LEAL -8(DI), DI - LEAL 8(R11), R11 + LEAL -8(R8), R8 + LEAL 8(R12), R12 JMP matchlen_match4_match_nolit_encodeBetterBlockAsm8B matchlen_bsf_8_match_nolit_encodeBetterBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP match_nolit_end_encodeBetterBlockAsm8B matchlen_match4_match_nolit_encodeBetterBlockAsm8B: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_match_nolit_encodeBetterBlockAsm8B - MOVL (R8)(R11*1), R10 - CMPL (R9)(R11*1), R10 + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 JNE matchlen_match2_match_nolit_encodeBetterBlockAsm8B - LEAL -4(DI), DI - LEAL 4(R11), R11 + LEAL -4(R8), R8 + LEAL 4(R12), R12 matchlen_match2_match_nolit_encodeBetterBlockAsm8B: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_match_nolit_encodeBetterBlockAsm8B JB match_nolit_end_encodeBetterBlockAsm8B - MOVW (R8)(R11*1), R10 - CMPW (R9)(R11*1), R10 + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 JNE matchlen_match1_match_nolit_encodeBetterBlockAsm8B - LEAL 2(R11), R11 - SUBL $0x02, DI + LEAL 2(R12), R12 + SUBL $0x02, R8 JZ match_nolit_end_encodeBetterBlockAsm8B matchlen_match1_match_nolit_encodeBetterBlockAsm8B: - MOVB (R8)(R11*1), R10 - CMPB (R9)(R11*1), R10 + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 JNE match_nolit_end_encodeBetterBlockAsm8B - LEAL 1(R11), R11 + LEAL 1(R12), R12 match_nolit_end_encodeBetterBlockAsm8B: - MOVL CX, DI - SUBL BX, DI + MOVL DX, R8 + SUBL SI, R8 // Check if repeat - CMPL 16(SP), DI + CMPL 16(SP), R8 JEQ match_is_repeat_encodeBetterBlockAsm8B - MOVL DI, 16(SP) - MOVL 12(SP), BX - CMPL BX, SI + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_encodeBetterBlockAsm8B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_encodeBetterBlockAsm8B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_encodeBetterBlockAsm8B JB three_bytes_match_emit_encodeBetterBlockAsm8B three_bytes_match_emit_encodeBetterBlockAsm8B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeBetterBlockAsm8B two_bytes_match_emit_encodeBetterBlockAsm8B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_encodeBetterBlockAsm8B JMP memmove_long_match_emit_encodeBetterBlockAsm8B one_byte_match_emit_encodeBetterBlockAsm8B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeBetterBlockAsm8B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x04 + CMPQ R9, $0x04 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4 - CMPQ R8, $0x08 + CMPQ R9, $0x08 JB emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4through7 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4: - MOVL (R9), R10 - MOVL R10, (AX) + MOVL (R10), R11 + MOVL R11, (CX) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4through7: - MOVL (R9), R10 - MOVL -4(R9)(R8*1), R9 - MOVL R10, (AX) - MOVL R9, -4(AX)(R8*1) + MOVL (R10), R11 + MOVL -4(R10)(R9*1), R10 + MOVL R11, (CX) + MOVL R10, -4(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeBetterBlockAsm8B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_encodeBetterBlockAsm8B memmove_long_match_emit_encodeBetterBlockAsm8B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_encodeBetterBlockAsm8B: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitCopy - CMPL R11, $0x40 + CMPL R12, $0x40 JBE two_byte_offset_short_match_nolit_encodeBetterBlockAsm8B - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE long_offset_short_match_nolit_encodeBetterBlockAsm8B - MOVL $0x00000001, BX - LEAL 16(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX - SUBL $0x08, R11 + MOVL $0x00000001, SI + LEAL 16(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX + SUBL $0x08, R12 // emitRepeat - LEAL -4(R11), R11 + LEAL -4(R12), R12 JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B long_offset_short_match_nolit_encodeBetterBlockAsm8B: - MOVB $0xee, (AX) - MOVW DI, 1(AX) - LEAL -60(R11), R11 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX // emitRepeat - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B -repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX - JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX +repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short: + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B two_byte_offset_short_match_nolit_encodeBetterBlockAsm8B: - MOVL R11, BX - SHLL $0x02, BX - CMPL R11, $0x0c + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c JAE emit_copy_three_match_nolit_encodeBetterBlockAsm8B - LEAL -15(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B emit_copy_three_match_nolit_encodeBetterBlockAsm8B: - LEAL -2(BX), BX - MOVB BL, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B match_is_repeat_encodeBetterBlockAsm8B: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm8B - MOVL SI, DI - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R8 - SUBL BX, DI - LEAL -1(DI), BX - CMPL BX, $0x3c + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c JB one_byte_match_emit_repeat_encodeBetterBlockAsm8B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_repeat_encodeBetterBlockAsm8B JB three_bytes_match_emit_repeat_encodeBetterBlockAsm8B three_bytes_match_emit_repeat_encodeBetterBlockAsm8B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm8B two_bytes_match_emit_repeat_encodeBetterBlockAsm8B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_repeat_encodeBetterBlockAsm8B JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm8B one_byte_match_emit_repeat_encodeBetterBlockAsm8B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_repeat_encodeBetterBlockAsm8B: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveShort - CMPQ DI, $0x04 + CMPQ R8, $0x04 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4 - CMPQ DI, $0x08 + CMPQ R8, $0x08 JB emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4through7 - CMPQ DI, $0x10 + CMPQ R8, $0x10 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_8through16 - CMPQ DI, $0x20 + CMPQ R8, $0x20 JBE emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_33through64 emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4: - MOVL (R8), R9 - MOVL R9, (AX) + MOVL (R9), R10 + MOVL R10, (CX) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4through7: - MOVL (R8), R9 - MOVL -4(R8)(DI*1), R8 - MOVL R9, (AX) - MOVL R8, -4(AX)(DI*1) + MOVL (R9), R10 + MOVL -4(R9)(R8*1), R9 + MOVL R10, (CX) + MOVL R9, -4(CX)(R8*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_8through16: - MOVQ (R8), R9 - MOVQ -8(R8)(DI*1), R8 - MOVQ R9, (AX) - MOVQ R8, -8(AX)(DI*1) + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_17through32: - MOVOU (R8), X0 - MOVOU -16(R8)(DI*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_33through64: - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm8B memmove_long_match_emit_repeat_encodeBetterBlockAsm8B: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveLong - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVQ DI, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R12 - SUBQ R9, R12 - DECQ R10 + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R13 + SUBQ R10, R13 + DECQ R11 JA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 - LEAQ -32(R8)(R12*1), R9 - LEAQ -32(AX)(R12*1), R13 + LEAQ -32(R9)(R13*1), R10 + LEAQ -32(CX)(R13*1), R14 emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R13) - MOVOA X5, 16(R13) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R14) + MOVOA X5, 16(R14) + ADDQ $0x20, R14 + ADDQ $0x20, R10 ADDQ $0x20, R13 - ADDQ $0x20, R9 - ADDQ $0x20, R12 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_big_loop_back emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_forward_sse_loop_32: - MOVOU -32(R8)(R12*1), X4 - MOVOU -16(R8)(R12*1), X5 - MOVOA X4, -32(AX)(R12*1) - MOVOA X5, -16(AX)(R12*1) - ADDQ $0x20, R12 - CMPQ DI, R12 + MOVOU -32(R9)(R13*1), X4 + MOVOU -16(R9)(R13*1), X5 + MOVOA X4, -32(CX)(R13*1) + MOVOA X5, -16(CX)(R13*1) + ADDQ $0x20, R13 + CMPQ R8, R13 JAE emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX emit_literal_done_match_emit_repeat_encodeBetterBlockAsm8B: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitRepeat - MOVL R11, BX - LEAL -4(R11), R11 - CMPL BX, $0x08 + MOVL R12, SI + LEAL -4(R12), R12 + CMPL SI, $0x08 JBE repeat_two_match_nolit_repeat_encodeBetterBlockAsm8B - CMPL BX, $0x0c + CMPL SI, $0x0c JAE cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm8B cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm8B: - CMPL R11, $0x00000104 + CMPL R12, $0x00000104 JB repeat_three_match_nolit_repeat_encodeBetterBlockAsm8B - LEAL -256(R11), R11 - MOVW $0x0019, (AX) - MOVW R11, 2(AX) - ADDQ $0x04, AX + LEAL -256(R12), R12 + MOVW $0x0019, (CX) + MOVW R12, 2(CX) + ADDQ $0x04, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B repeat_three_match_nolit_repeat_encodeBetterBlockAsm8B: - LEAL -4(R11), R11 - MOVW $0x0015, (AX) - MOVB R11, 2(AX) - ADDQ $0x03, AX + LEAL -4(R12), R12 + MOVW $0x0015, (CX) + MOVB R12, 2(CX) + ADDQ $0x03, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B repeat_two_match_nolit_repeat_encodeBetterBlockAsm8B: - SHLL $0x02, R11 - ORL $0x01, R11 - MOVW R11, (AX) - ADDQ $0x02, AX + SHLL $0x02, R12 + ORL $0x01, R12 + MOVW R12, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B - XORQ BX, BX - LEAL 1(BX)(R11*4), R11 - MOVB DI, 1(AX) - SARL $0x08, DI - SHLL $0x05, DI - ORL DI, R11 - MOVB R11, (AX) - ADDQ $0x02, AX + XORQ SI, SI + LEAL 1(SI)(R12*4), R12 + MOVB R8, 1(CX) + SARL $0x08, R8 + SHLL $0x05, R8 + ORL R8, R12 + MOVB R12, (CX) + ADDQ $0x02, CX match_nolit_emitcopy_end_encodeBetterBlockAsm8B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeBetterBlockAsm8B - CMPQ AX, (SP) + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeBetterBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeBetterBlockAsm8B: - MOVQ $0x0000cf1bbcdcbf9b, BX - MOVQ $0x9e3779b1, DI - LEAQ 1(SI), SI - LEAQ -2(CX), R8 - MOVQ (DX)(SI*1), R9 - MOVQ 1(DX)(SI*1), R10 - MOVQ (DX)(R8*1), R11 - MOVQ 1(DX)(R8*1), R12 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x36, R9 - SHLQ $0x20, R10 - IMULQ DI, R10 - SHRQ $0x38, R10 - SHLQ $0x10, R11 - IMULQ BX, R11 - SHRQ $0x36, R11 - SHLQ $0x20, R12 - IMULQ DI, R12 - SHRQ $0x38, R12 - LEAQ 1(SI), DI - LEAQ 1(R8), R13 - MOVL SI, 24(SP)(R9*4) - MOVL R8, 24(SP)(R11*4) - MOVL DI, 4120(SP)(R10*4) - MOVL R13, 4120(SP)(R12*4) - LEAQ 1(R8)(SI*1), DI - SHRQ $0x01, DI - ADDQ $0x01, SI - SUBQ $0x01, R8 + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x36, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x38, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x36, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x38, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 4096(AX)(R11*4) + MOVL R14, 4096(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 index_loop_encodeBetterBlockAsm8B: - CMPQ DI, R8 + CMPQ R8, R9 JAE search_loop_encodeBetterBlockAsm8B - MOVQ (DX)(SI*1), R9 - MOVQ (DX)(DI*1), R10 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x36, R9 + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 SHLQ $0x10, R10 - IMULQ BX, R10 + IMULQ SI, R10 SHRQ $0x36, R10 - MOVL SI, 24(SP)(R9*4) - MOVL DI, 24(SP)(R10*4) - ADDQ $0x02, SI + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x36, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) ADDQ $0x02, DI + ADDQ $0x02, R8 JMP index_loop_encodeBetterBlockAsm8B emit_remainder_encodeBetterBlockAsm8B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeBetterBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeBetterBlockAsm8B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm8B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeBetterBlockAsm8B @@ -10580,26 +10590,26 @@ emit_remainder_ok_encodeBetterBlockAsm8B: JB three_bytes_emit_remainder_encodeBetterBlockAsm8B three_bytes_emit_remainder_encodeBetterBlockAsm8B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeBetterBlockAsm8B two_bytes_emit_remainder_encodeBetterBlockAsm8B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeBetterBlockAsm8B JMP memmove_long_emit_remainder_encodeBetterBlockAsm8B one_byte_emit_remainder_encodeBetterBlockAsm8B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeBetterBlockAsm8B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -10615,73 +10625,73 @@ memmove_emit_remainder_encodeBetterBlockAsm8B: JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm8B memmove_long_emit_remainder_encodeBetterBlockAsm8B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_big_loop_back: MOVOU (SI), X4 @@ -10695,798 +10705,799 @@ emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeBetterBlockAsm8B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeSnappyBlockAsm(dst []byte, src []byte) int +// func encodeSnappyBlockAsm(dst []byte, src []byte, tmp *[65536]byte) int // Requires: BMI, SSE2 -TEXT ·encodeSnappyBlockAsm(SB), $65560-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000200, CX - LEAQ 24(SP), DX +TEXT ·encodeSnappyBlockAsm(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000200, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeSnappyBlockAsm: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeSnappyBlockAsm MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX search_loop_encodeSnappyBlockAsm: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x06, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeSnappyBlockAsm - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x10, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x32, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 + SHLQ $0x10, R11 + IMULQ R9, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 JNE no_repeat_found_encodeSnappyBlockAsm - LEAL 1(CX), SI - MOVL 12(SP), BX - MOVL SI, DI - SUBL 16(SP), DI + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 JZ repeat_extend_back_end_encodeSnappyBlockAsm repeat_extend_back_loop_encodeSnappyBlockAsm: - CMPL SI, BX + CMPL DI, SI JBE repeat_extend_back_end_encodeSnappyBlockAsm - MOVB -1(DX)(DI*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_encodeSnappyBlockAsm - LEAL -1(SI), SI - DECL DI + LEAL -1(DI), DI + DECL R8 JNZ repeat_extend_back_loop_encodeSnappyBlockAsm repeat_extend_back_end_encodeSnappyBlockAsm: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 5(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 5(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_encodeSnappyBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET repeat_dst_size_check_encodeSnappyBlockAsm: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm - MOVL SI, DI - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R8 - SUBL BX, DI - LEAL -1(DI), BX - CMPL BX, $0x3c + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_encodeSnappyBlockAsm - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_encodeSnappyBlockAsm - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB three_bytes_repeat_emit_encodeSnappyBlockAsm - CMPL BX, $0x01000000 + CMPL SI, $0x01000000 JB four_bytes_repeat_emit_encodeSnappyBlockAsm - MOVB $0xfc, (AX) - MOVL BX, 1(AX) - ADDQ $0x05, AX + MOVB $0xfc, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX JMP memmove_long_repeat_emit_encodeSnappyBlockAsm four_bytes_repeat_emit_encodeSnappyBlockAsm: - MOVL BX, R9 - SHRL $0x10, R9 - MOVB $0xf8, (AX) - MOVW BX, 1(AX) - MOVB R9, 3(AX) - ADDQ $0x04, AX + MOVL SI, R10 + SHRL $0x10, R10 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R10, 3(CX) + ADDQ $0x04, CX JMP memmove_long_repeat_emit_encodeSnappyBlockAsm three_bytes_repeat_emit_encodeSnappyBlockAsm: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_repeat_emit_encodeSnappyBlockAsm two_bytes_repeat_emit_encodeSnappyBlockAsm: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_encodeSnappyBlockAsm JMP memmove_long_repeat_emit_encodeSnappyBlockAsm one_byte_repeat_emit_encodeSnappyBlockAsm: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_repeat_emit_encodeSnappyBlockAsm: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveShort - CMPQ DI, $0x08 + CMPQ R8, $0x08 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8 - CMPQ DI, $0x10 + CMPQ R8, $0x10 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8through16 - CMPQ DI, $0x20 + CMPQ R8, $0x20 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_17through32 JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_33through64 emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8: - MOVQ (R8), R9 - MOVQ R9, (AX) + MOVQ (R9), R10 + MOVQ R10, (CX) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8through16: - MOVQ (R8), R9 - MOVQ -8(R8)(DI*1), R8 - MOVQ R9, (AX) - MOVQ R8, -8(AX)(DI*1) + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_17through32: - MOVOU (R8), X0 - MOVOU -16(R8)(DI*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_33through64: - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) memmove_end_copy_repeat_emit_encodeSnappyBlockAsm: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm memmove_long_repeat_emit_encodeSnappyBlockAsm: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveLong - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVQ DI, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32 - LEAQ -32(R8)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(R9)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_big_loop_back emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32: - MOVOU -32(R8)(R11*1), X4 - MOVOU -16(R8)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ DI, R11 + MOVOU -32(R9)(R12*1), X4 + MOVOU -16(R9)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R8, R12 JAE emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX emit_literal_done_repeat_emit_encodeSnappyBlockAsm: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI // matchLen - XORL R10, R10 + XORL R11, R11 matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_repeat_extend_encodeSnappyBlockAsm - MOVQ (R8)(R10*1), R9 - MOVQ 8(R8)(R10*1), R11 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm - XORQ 8(BX)(R10*1), R11 + XORQ 8(SI)(R11*1), R12 JNZ matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm - LEAL -16(DI), DI - LEAL 16(R10), R10 + LEAL -16(R8), R8 + LEAL 16(R11), R11 JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R11, R11 + TZCNTQ R12, R12 #else - BSFQ R11, R11 + BSFQ R12, R12 #endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 JMP repeat_extend_forward_end_encodeSnappyBlockAsm matchlen_match8_repeat_extend_encodeSnappyBlockAsm: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_repeat_extend_encodeSnappyBlockAsm - MOVQ (R8)(R10*1), R9 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm - LEAL -8(DI), DI - LEAL 8(R10), R10 + LEAL -8(R8), R8 + LEAL 8(R11), R11 JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R9, R9 + TZCNTQ R10, R10 #else - BSFQ R9, R9 + BSFQ R10, R10 #endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 JMP repeat_extend_forward_end_encodeSnappyBlockAsm matchlen_match4_repeat_extend_encodeSnappyBlockAsm: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_repeat_extend_encodeSnappyBlockAsm - MOVL (R8)(R10*1), R9 - CMPL (BX)(R10*1), R9 + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 JNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm - LEAL -4(DI), DI - LEAL 4(R10), R10 + LEAL -4(R8), R8 + LEAL 4(R11), R11 matchlen_match2_repeat_extend_encodeSnappyBlockAsm: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_repeat_extend_encodeSnappyBlockAsm JB repeat_extend_forward_end_encodeSnappyBlockAsm - MOVW (R8)(R10*1), R9 - CMPW (BX)(R10*1), R9 + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 JNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm - LEAL 2(R10), R10 - SUBL $0x02, DI + LEAL 2(R11), R11 + SUBL $0x02, R8 JZ repeat_extend_forward_end_encodeSnappyBlockAsm matchlen_match1_repeat_extend_encodeSnappyBlockAsm: - MOVB (R8)(R10*1), R9 - CMPB (BX)(R10*1), R9 + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 JNE repeat_extend_forward_end_encodeSnappyBlockAsm - LEAL 1(R10), R10 + LEAL 1(R11), R11 repeat_extend_forward_end_encodeSnappyBlockAsm: - ADDL R10, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI // emitCopy - CMPL SI, $0x00010000 + CMPL DI, $0x00010000 JB two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm four_bytes_loop_back_repeat_as_copy_encodeSnappyBlockAsm: - CMPL BX, $0x40 + CMPL SI, $0x40 JBE four_bytes_remain_repeat_as_copy_encodeSnappyBlockAsm - MOVB $0xff, (AX) - MOVL SI, 1(AX) - LEAL -64(BX), BX - ADDQ $0x05, AX - CMPL BX, $0x04 + MOVB $0xff, (CX) + MOVL DI, 1(CX) + LEAL -64(SI), SI + ADDQ $0x05, CX + CMPL SI, $0x04 JB four_bytes_remain_repeat_as_copy_encodeSnappyBlockAsm JMP four_bytes_loop_back_repeat_as_copy_encodeSnappyBlockAsm four_bytes_remain_repeat_as_copy_encodeSnappyBlockAsm: - TESTL BX, BX + TESTL SI, SI JZ repeat_end_emit_encodeSnappyBlockAsm - XORL DI, DI - LEAL -1(DI)(BX*4), BX - MOVB BL, (AX) - MOVL SI, 1(AX) - ADDQ $0x05, AX + XORL R8, R8 + LEAL -1(R8)(SI*4), SI + MOVB SI, (CX) + MOVL DI, 1(CX) + ADDQ $0x05, CX JMP repeat_end_emit_encodeSnappyBlockAsm two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm: - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm - MOVB $0xee, (AX) - MOVW SI, 1(AX) - LEAL -60(BX), BX - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm: - MOVL BX, DI - SHLL $0x02, DI - CMPL BX, $0x0c + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm - LEAL -15(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeSnappyBlockAsm emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm: - LEAL -2(DI), DI - MOVB DI, (AX) - MOVW SI, 1(AX) - ADDQ $0x03, AX + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX repeat_end_emit_encodeSnappyBlockAsm: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_encodeSnappyBlockAsm no_repeat_found_encodeSnappyBlockAsm: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeSnappyBlockAsm - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_encodeSnappyBlockAsm - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_encodeSnappyBlockAsm - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeSnappyBlockAsm candidate3_match_encodeSnappyBlockAsm: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_encodeSnappyBlockAsm candidate2_match_encodeSnappyBlockAsm: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_encodeSnappyBlockAsm: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeSnappyBlockAsm match_extend_back_loop_encodeSnappyBlockAsm: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeSnappyBlockAsm - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeSnappyBlockAsm - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeSnappyBlockAsm JMP match_extend_back_loop_encodeSnappyBlockAsm match_extend_back_end_encodeSnappyBlockAsm: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 5(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 5(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeSnappyBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeSnappyBlockAsm: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_encodeSnappyBlockAsm - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), DI - CMPL DI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c JB one_byte_match_emit_encodeSnappyBlockAsm - CMPL DI, $0x00000100 + CMPL R8, $0x00000100 JB two_bytes_match_emit_encodeSnappyBlockAsm - CMPL DI, $0x00010000 + CMPL R8, $0x00010000 JB three_bytes_match_emit_encodeSnappyBlockAsm - CMPL DI, $0x01000000 + CMPL R8, $0x01000000 JB four_bytes_match_emit_encodeSnappyBlockAsm - MOVB $0xfc, (AX) - MOVL DI, 1(AX) - ADDQ $0x05, AX + MOVB $0xfc, (CX) + MOVL R8, 1(CX) + ADDQ $0x05, CX JMP memmove_long_match_emit_encodeSnappyBlockAsm four_bytes_match_emit_encodeSnappyBlockAsm: - MOVL DI, R9 - SHRL $0x10, R9 - MOVB $0xf8, (AX) - MOVW DI, 1(AX) - MOVB R9, 3(AX) - ADDQ $0x04, AX + MOVL R8, R10 + SHRL $0x10, R10 + MOVB $0xf8, (CX) + MOVW R8, 1(CX) + MOVB R10, 3(CX) + ADDQ $0x04, CX JMP memmove_long_match_emit_encodeSnappyBlockAsm three_bytes_match_emit_encodeSnappyBlockAsm: - MOVB $0xf4, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeSnappyBlockAsm two_bytes_match_emit_encodeSnappyBlockAsm: - MOVB $0xf0, (AX) - MOVB DI, 1(AX) - ADDQ $0x02, AX - CMPL DI, $0x40 + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 JB memmove_match_emit_encodeSnappyBlockAsm JMP memmove_long_match_emit_encodeSnappyBlockAsm one_byte_match_emit_encodeSnappyBlockAsm: - SHLB $0x02, DI - MOVB DI, (AX) - ADDQ $0x01, AX + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeSnappyBlockAsm: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_33through64 emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8: - MOVQ (SI), R9 - MOVQ R9, (AX) + MOVQ (DI), R10 + MOVQ R10, (CX) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8through16: - MOVQ (SI), R9 - MOVQ -8(SI)(R8*1), SI - MOVQ R9, (AX) - MOVQ SI, -8(AX)(R8*1) + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_17through32: - MOVOU (SI), X0 - MOVOU -16(SI)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_33through64: - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeSnappyBlockAsm: - MOVQ DI, AX + MOVQ R8, CX JMP emit_literal_done_match_emit_encodeSnappyBlockAsm memmove_long_match_emit_encodeSnappyBlockAsm: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveLong - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVQ R8, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32 - LEAQ -32(SI)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_big_loop_back emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32: - MOVOU -32(SI)(R11*1), X4 - MOVOU -16(SI)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ R8, R11 + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 JAE emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ DI, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX emit_literal_done_match_emit_encodeSnappyBlockAsm: match_nolit_loop_encodeSnappyBlockAsm: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_encodeSnappyBlockAsm - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_encodeSnappyBlockAsm - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm matchlen_bsf_16match_nolit_encodeSnappyBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_encodeSnappyBlockAsm matchlen_match8_match_nolit_encodeSnappyBlockAsm: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_encodeSnappyBlockAsm - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_encodeSnappyBlockAsm matchlen_match4_match_nolit_encodeSnappyBlockAsm: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_encodeSnappyBlockAsm - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_encodeSnappyBlockAsm - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_encodeSnappyBlockAsm: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_encodeSnappyBlockAsm JB match_nolit_end_encodeSnappyBlockAsm - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_encodeSnappyBlockAsm - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_encodeSnappyBlockAsm matchlen_match1_match_nolit_encodeSnappyBlockAsm: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_encodeSnappyBlockAsm - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_encodeSnappyBlockAsm: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB two_byte_offset_match_nolit_encodeSnappyBlockAsm four_bytes_loop_back_match_nolit_encodeSnappyBlockAsm: - CMPL R9, $0x40 + CMPL R10, $0x40 JBE four_bytes_remain_match_nolit_encodeSnappyBlockAsm - MOVB $0xff, (AX) - MOVL BX, 1(AX) - LEAL -64(R9), R9 - ADDQ $0x05, AX - CMPL R9, $0x04 + MOVB $0xff, (CX) + MOVL SI, 1(CX) + LEAL -64(R10), R10 + ADDQ $0x05, CX + CMPL R10, $0x04 JB four_bytes_remain_match_nolit_encodeSnappyBlockAsm JMP four_bytes_loop_back_match_nolit_encodeSnappyBlockAsm four_bytes_remain_match_nolit_encodeSnappyBlockAsm: - TESTL R9, R9 + TESTL R10, R10 JZ match_nolit_emitcopy_end_encodeSnappyBlockAsm - XORL SI, SI - LEAL -1(SI)(R9*4), R9 - MOVB R9, (AX) - MOVL BX, 1(AX) - ADDQ $0x05, AX + XORL DI, DI + LEAL -1(DI)(R10*4), R10 + MOVB R10, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm two_byte_offset_match_nolit_encodeSnappyBlockAsm: - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_encodeSnappyBlockAsm - MOVB $0xee, (AX) - MOVW BX, 1(AX) - LEAL -60(R9), R9 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm two_byte_offset_short_match_nolit_encodeSnappyBlockAsm: - MOVL R9, SI - SHLL $0x02, SI - CMPL R9, $0x0c + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm - LEAL -15(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm emit_copy_three_match_nolit_encodeSnappyBlockAsm: - LEAL -2(SI), SI - MOVB SI, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeSnappyBlockAsm: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeSnappyBlockAsm - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeSnappyBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeSnappyBlockAsm: - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x10, DI - IMULQ R8, DI - SHRQ $0x32, DI - SHLQ $0x10, BX - IMULQ R8, BX - SHRQ $0x32, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x10, R8 + IMULQ R9, R8 + SHRQ $0x32, R8 + SHLQ $0x10, SI + IMULQ R9, SI + SHRQ $0x32, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_encodeSnappyBlockAsm - INCL CX + INCL DX JMP search_loop_encodeSnappyBlockAsm emit_remainder_encodeSnappyBlockAsm: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 5(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 5(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeSnappyBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeSnappyBlockAsm: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeSnappyBlockAsm @@ -11496,41 +11507,41 @@ emit_remainder_ok_encodeSnappyBlockAsm: JB three_bytes_emit_remainder_encodeSnappyBlockAsm CMPL DX, $0x01000000 JB four_bytes_emit_remainder_encodeSnappyBlockAsm - MOVB $0xfc, (AX) - MOVL DX, 1(AX) - ADDQ $0x05, AX + MOVB $0xfc, (CX) + MOVL DX, 1(CX) + ADDQ $0x05, CX JMP memmove_long_emit_remainder_encodeSnappyBlockAsm four_bytes_emit_remainder_encodeSnappyBlockAsm: MOVL DX, BX SHRL $0x10, BX - MOVB $0xf8, (AX) - MOVW DX, 1(AX) - MOVB BL, 3(AX) - ADDQ $0x04, AX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX JMP memmove_long_emit_remainder_encodeSnappyBlockAsm three_bytes_emit_remainder_encodeSnappyBlockAsm: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeSnappyBlockAsm two_bytes_emit_remainder_encodeSnappyBlockAsm: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeSnappyBlockAsm JMP memmove_long_emit_remainder_encodeSnappyBlockAsm one_byte_emit_remainder_encodeSnappyBlockAsm: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeSnappyBlockAsm: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -11546,73 +11557,73 @@ memmove_emit_remainder_encodeSnappyBlockAsm: JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeSnappyBlockAsm: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm memmove_long_emit_remainder_encodeSnappyBlockAsm: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_big_loop_back: MOVOU (SI), X4 @@ -11626,718 +11637,719 @@ emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeSnappyBlockAsm: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeSnappyBlockAsm64K(dst []byte, src []byte) int +// func encodeSnappyBlockAsm64K(dst []byte, src []byte, tmp *[65536]byte) int // Requires: BMI, SSE2 -TEXT ·encodeSnappyBlockAsm64K(SB), $65560-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000200, CX - LEAQ 24(SP), DX +TEXT ·encodeSnappyBlockAsm64K(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000200, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeSnappyBlockAsm64K: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeSnappyBlockAsm64K MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX search_loop_encodeSnappyBlockAsm64K: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x06, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeSnappyBlockAsm64K - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x10, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x32, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 + SHLQ $0x10, R11 + IMULQ R9, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 JNE no_repeat_found_encodeSnappyBlockAsm64K - LEAL 1(CX), SI - MOVL 12(SP), BX - MOVL SI, DI - SUBL 16(SP), DI + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 JZ repeat_extend_back_end_encodeSnappyBlockAsm64K repeat_extend_back_loop_encodeSnappyBlockAsm64K: - CMPL SI, BX + CMPL DI, SI JBE repeat_extend_back_end_encodeSnappyBlockAsm64K - MOVB -1(DX)(DI*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_encodeSnappyBlockAsm64K - LEAL -1(SI), SI - DECL DI + LEAL -1(DI), DI + DECL R8 JNZ repeat_extend_back_loop_encodeSnappyBlockAsm64K repeat_extend_back_end_encodeSnappyBlockAsm64K: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 3(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_encodeSnappyBlockAsm64K - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET repeat_dst_size_check_encodeSnappyBlockAsm64K: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K - MOVL SI, DI - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R8 - SUBL BX, DI - LEAL -1(DI), BX - CMPL BX, $0x3c + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_encodeSnappyBlockAsm64K - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_encodeSnappyBlockAsm64K JB three_bytes_repeat_emit_encodeSnappyBlockAsm64K three_bytes_repeat_emit_encodeSnappyBlockAsm64K: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_repeat_emit_encodeSnappyBlockAsm64K two_bytes_repeat_emit_encodeSnappyBlockAsm64K: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_encodeSnappyBlockAsm64K JMP memmove_long_repeat_emit_encodeSnappyBlockAsm64K one_byte_repeat_emit_encodeSnappyBlockAsm64K: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_repeat_emit_encodeSnappyBlockAsm64K: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveShort - CMPQ DI, $0x08 + CMPQ R8, $0x08 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8 - CMPQ DI, $0x10 + CMPQ R8, $0x10 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8through16 - CMPQ DI, $0x20 + CMPQ R8, $0x20 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_17through32 JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_33through64 emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8: - MOVQ (R8), R9 - MOVQ R9, (AX) + MOVQ (R9), R10 + MOVQ R10, (CX) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8through16: - MOVQ (R8), R9 - MOVQ -8(R8)(DI*1), R8 - MOVQ R9, (AX) - MOVQ R8, -8(AX)(DI*1) + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_17through32: - MOVOU (R8), X0 - MOVOU -16(R8)(DI*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_33through64: - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K memmove_long_repeat_emit_encodeSnappyBlockAsm64K: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveLong - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVQ DI, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 - LEAQ -32(R8)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(R9)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_big_loop_back emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32: - MOVOU -32(R8)(R11*1), X4 - MOVOU -16(R8)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ DI, R11 + MOVOU -32(R9)(R12*1), X4 + MOVOU -16(R9)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R8, R12 JAE emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI // matchLen - XORL R10, R10 + XORL R11, R11 matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm64K: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_repeat_extend_encodeSnappyBlockAsm64K - MOVQ (R8)(R10*1), R9 - MOVQ 8(R8)(R10*1), R11 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm64K - XORQ 8(BX)(R10*1), R11 + XORQ 8(SI)(R11*1), R12 JNZ matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm64K - LEAL -16(DI), DI - LEAL 16(R10), R10 + LEAL -16(R8), R8 + LEAL 16(R11), R11 JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm64K matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm64K: #ifdef GOAMD64_v3 - TZCNTQ R11, R11 + TZCNTQ R12, R12 #else - BSFQ R11, R11 + BSFQ R12, R12 #endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 JMP repeat_extend_forward_end_encodeSnappyBlockAsm64K matchlen_match8_repeat_extend_encodeSnappyBlockAsm64K: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_repeat_extend_encodeSnappyBlockAsm64K - MOVQ (R8)(R10*1), R9 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm64K - LEAL -8(DI), DI - LEAL 8(R10), R10 + LEAL -8(R8), R8 + LEAL 8(R11), R11 JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm64K matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm64K: #ifdef GOAMD64_v3 - TZCNTQ R9, R9 + TZCNTQ R10, R10 #else - BSFQ R9, R9 + BSFQ R10, R10 #endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 JMP repeat_extend_forward_end_encodeSnappyBlockAsm64K matchlen_match4_repeat_extend_encodeSnappyBlockAsm64K: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_repeat_extend_encodeSnappyBlockAsm64K - MOVL (R8)(R10*1), R9 - CMPL (BX)(R10*1), R9 + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 JNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm64K - LEAL -4(DI), DI - LEAL 4(R10), R10 + LEAL -4(R8), R8 + LEAL 4(R11), R11 matchlen_match2_repeat_extend_encodeSnappyBlockAsm64K: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_repeat_extend_encodeSnappyBlockAsm64K JB repeat_extend_forward_end_encodeSnappyBlockAsm64K - MOVW (R8)(R10*1), R9 - CMPW (BX)(R10*1), R9 + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 JNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm64K - LEAL 2(R10), R10 - SUBL $0x02, DI + LEAL 2(R11), R11 + SUBL $0x02, R8 JZ repeat_extend_forward_end_encodeSnappyBlockAsm64K matchlen_match1_repeat_extend_encodeSnappyBlockAsm64K: - MOVB (R8)(R10*1), R9 - CMPB (BX)(R10*1), R9 + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 JNE repeat_extend_forward_end_encodeSnappyBlockAsm64K - LEAL 1(R10), R10 + LEAL 1(R11), R11 repeat_extend_forward_end_encodeSnappyBlockAsm64K: - ADDL R10, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI // emitCopy two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm64K: - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm64K - MOVB $0xee, (AX) - MOVW SI, 1(AX) - LEAL -60(BX), BX - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm64K two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm64K: - MOVL BX, DI - SHLL $0x02, DI - CMPL BX, $0x0c + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm64K - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm64K - LEAL -15(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeSnappyBlockAsm64K emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm64K: - LEAL -2(DI), DI - MOVB DI, (AX) - MOVW SI, 1(AX) - ADDQ $0x03, AX + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX repeat_end_emit_encodeSnappyBlockAsm64K: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_encodeSnappyBlockAsm64K no_repeat_found_encodeSnappyBlockAsm64K: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeSnappyBlockAsm64K - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_encodeSnappyBlockAsm64K - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_encodeSnappyBlockAsm64K - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeSnappyBlockAsm64K candidate3_match_encodeSnappyBlockAsm64K: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_encodeSnappyBlockAsm64K candidate2_match_encodeSnappyBlockAsm64K: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_encodeSnappyBlockAsm64K: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeSnappyBlockAsm64K match_extend_back_loop_encodeSnappyBlockAsm64K: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeSnappyBlockAsm64K - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeSnappyBlockAsm64K - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeSnappyBlockAsm64K JMP match_extend_back_loop_encodeSnappyBlockAsm64K match_extend_back_end_encodeSnappyBlockAsm64K: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeSnappyBlockAsm64K - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeSnappyBlockAsm64K: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_encodeSnappyBlockAsm64K - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), DI - CMPL DI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c JB one_byte_match_emit_encodeSnappyBlockAsm64K - CMPL DI, $0x00000100 + CMPL R8, $0x00000100 JB two_bytes_match_emit_encodeSnappyBlockAsm64K JB three_bytes_match_emit_encodeSnappyBlockAsm64K three_bytes_match_emit_encodeSnappyBlockAsm64K: - MOVB $0xf4, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeSnappyBlockAsm64K two_bytes_match_emit_encodeSnappyBlockAsm64K: - MOVB $0xf0, (AX) - MOVB DI, 1(AX) - ADDQ $0x02, AX - CMPL DI, $0x40 + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 JB memmove_match_emit_encodeSnappyBlockAsm64K JMP memmove_long_match_emit_encodeSnappyBlockAsm64K one_byte_match_emit_encodeSnappyBlockAsm64K: - SHLB $0x02, DI - MOVB DI, (AX) - ADDQ $0x01, AX + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeSnappyBlockAsm64K: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_33through64 emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8: - MOVQ (SI), R9 - MOVQ R9, (AX) + MOVQ (DI), R10 + MOVQ R10, (CX) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm64K emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8through16: - MOVQ (SI), R9 - MOVQ -8(SI)(R8*1), SI - MOVQ R9, (AX) - MOVQ SI, -8(AX)(R8*1) + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm64K emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_17through32: - MOVOU (SI), X0 - MOVOU -16(SI)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm64K emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_33through64: - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeSnappyBlockAsm64K: - MOVQ DI, AX + MOVQ R8, CX JMP emit_literal_done_match_emit_encodeSnappyBlockAsm64K memmove_long_match_emit_encodeSnappyBlockAsm64K: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveLong - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVQ R8, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 - LEAQ -32(SI)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_big_loop_back emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32: - MOVOU -32(SI)(R11*1), X4 - MOVOU -16(SI)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ R8, R11 + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 JAE emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ DI, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX emit_literal_done_match_emit_encodeSnappyBlockAsm64K: match_nolit_loop_encodeSnappyBlockAsm64K: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm64K: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_encodeSnappyBlockAsm64K - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm64K - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_encodeSnappyBlockAsm64K - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm64K matchlen_bsf_16match_nolit_encodeSnappyBlockAsm64K: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_encodeSnappyBlockAsm64K matchlen_match8_match_nolit_encodeSnappyBlockAsm64K: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_encodeSnappyBlockAsm64K - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm64K - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm64K matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm64K: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_encodeSnappyBlockAsm64K matchlen_match4_match_nolit_encodeSnappyBlockAsm64K: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_encodeSnappyBlockAsm64K - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_encodeSnappyBlockAsm64K - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_encodeSnappyBlockAsm64K: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_encodeSnappyBlockAsm64K JB match_nolit_end_encodeSnappyBlockAsm64K - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_encodeSnappyBlockAsm64K - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_encodeSnappyBlockAsm64K matchlen_match1_match_nolit_encodeSnappyBlockAsm64K: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_encodeSnappyBlockAsm64K - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_encodeSnappyBlockAsm64K: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy two_byte_offset_match_nolit_encodeSnappyBlockAsm64K: - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_encodeSnappyBlockAsm64K - MOVB $0xee, (AX) - MOVW BX, 1(AX) - LEAL -60(R9), R9 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm64K two_byte_offset_short_match_nolit_encodeSnappyBlockAsm64K: - MOVL R9, SI - SHLL $0x02, SI - CMPL R9, $0x0c + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm64K - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm64K - LEAL -15(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm64K emit_copy_three_match_nolit_encodeSnappyBlockAsm64K: - LEAL -2(SI), SI - MOVB SI, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeSnappyBlockAsm64K: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeSnappyBlockAsm64K - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeSnappyBlockAsm64K - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeSnappyBlockAsm64K: - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x10, DI - IMULQ R8, DI - SHRQ $0x32, DI - SHLQ $0x10, BX - IMULQ R8, BX - SHRQ $0x32, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x10, R8 + IMULQ R9, R8 + SHRQ $0x32, R8 + SHLQ $0x10, SI + IMULQ R9, SI + SHRQ $0x32, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_encodeSnappyBlockAsm64K - INCL CX + INCL DX JMP search_loop_encodeSnappyBlockAsm64K emit_remainder_encodeSnappyBlockAsm64K: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeSnappyBlockAsm64K - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeSnappyBlockAsm64K: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm64K - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeSnappyBlockAsm64K @@ -12346,26 +12358,26 @@ emit_remainder_ok_encodeSnappyBlockAsm64K: JB three_bytes_emit_remainder_encodeSnappyBlockAsm64K three_bytes_emit_remainder_encodeSnappyBlockAsm64K: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeSnappyBlockAsm64K two_bytes_emit_remainder_encodeSnappyBlockAsm64K: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeSnappyBlockAsm64K JMP memmove_long_emit_remainder_encodeSnappyBlockAsm64K one_byte_emit_remainder_encodeSnappyBlockAsm64K: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeSnappyBlockAsm64K: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -12381,73 +12393,73 @@ memmove_emit_remainder_encodeSnappyBlockAsm64K: JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K -emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_4through7: + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm64K memmove_long_emit_remainder_encodeSnappyBlockAsm64K: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_big_loop_back: MOVOU (SI), X4 @@ -12461,718 +12473,719 @@ emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeSnappyBlockAsm64K: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeSnappyBlockAsm12B(dst []byte, src []byte) int +// func encodeSnappyBlockAsm12B(dst []byte, src []byte, tmp *[16384]byte) int // Requires: BMI, SSE2 -TEXT ·encodeSnappyBlockAsm12B(SB), $16408-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000080, CX - LEAQ 24(SP), DX +TEXT ·encodeSnappyBlockAsm12B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000080, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeSnappyBlockAsm12B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeSnappyBlockAsm12B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX search_loop_encodeSnappyBlockAsm12B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x05, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeSnappyBlockAsm12B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x000000cf1bbcdcbb, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x18, R9 - IMULQ R8, R9 - SHRQ $0x34, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x000000cf1bbcdcbb, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x18, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x34, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x18, R9 - IMULQ R8, R9 - SHRQ $0x34, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 + SHLQ $0x18, R11 + IMULQ R9, R11 + SHRQ $0x34, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x18, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 JNE no_repeat_found_encodeSnappyBlockAsm12B - LEAL 1(CX), SI - MOVL 12(SP), BX - MOVL SI, DI - SUBL 16(SP), DI + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 JZ repeat_extend_back_end_encodeSnappyBlockAsm12B repeat_extend_back_loop_encodeSnappyBlockAsm12B: - CMPL SI, BX + CMPL DI, SI JBE repeat_extend_back_end_encodeSnappyBlockAsm12B - MOVB -1(DX)(DI*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_encodeSnappyBlockAsm12B - LEAL -1(SI), SI - DECL DI + LEAL -1(DI), DI + DECL R8 JNZ repeat_extend_back_loop_encodeSnappyBlockAsm12B repeat_extend_back_end_encodeSnappyBlockAsm12B: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 3(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_encodeSnappyBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET repeat_dst_size_check_encodeSnappyBlockAsm12B: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B - MOVL SI, DI - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R8 - SUBL BX, DI - LEAL -1(DI), BX - CMPL BX, $0x3c + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_encodeSnappyBlockAsm12B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_encodeSnappyBlockAsm12B JB three_bytes_repeat_emit_encodeSnappyBlockAsm12B three_bytes_repeat_emit_encodeSnappyBlockAsm12B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_repeat_emit_encodeSnappyBlockAsm12B two_bytes_repeat_emit_encodeSnappyBlockAsm12B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_encodeSnappyBlockAsm12B JMP memmove_long_repeat_emit_encodeSnappyBlockAsm12B one_byte_repeat_emit_encodeSnappyBlockAsm12B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_repeat_emit_encodeSnappyBlockAsm12B: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveShort - CMPQ DI, $0x08 + CMPQ R8, $0x08 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8 - CMPQ DI, $0x10 + CMPQ R8, $0x10 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8through16 - CMPQ DI, $0x20 + CMPQ R8, $0x20 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_17through32 JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_33through64 emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8: - MOVQ (R8), R9 - MOVQ R9, (AX) + MOVQ (R9), R10 + MOVQ R10, (CX) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8through16: - MOVQ (R8), R9 - MOVQ -8(R8)(DI*1), R8 - MOVQ R9, (AX) - MOVQ R8, -8(AX)(DI*1) + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_17through32: - MOVOU (R8), X0 - MOVOU -16(R8)(DI*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_33through64: - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B memmove_long_repeat_emit_encodeSnappyBlockAsm12B: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveLong - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVQ DI, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 - LEAQ -32(R8)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(R9)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_big_loop_back emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32: - MOVOU -32(R8)(R11*1), X4 - MOVOU -16(R8)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ DI, R11 + MOVOU -32(R9)(R12*1), X4 + MOVOU -16(R9)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R8, R12 JAE emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI // matchLen - XORL R10, R10 + XORL R11, R11 matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm12B: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_repeat_extend_encodeSnappyBlockAsm12B - MOVQ (R8)(R10*1), R9 - MOVQ 8(R8)(R10*1), R11 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm12B - XORQ 8(BX)(R10*1), R11 + XORQ 8(SI)(R11*1), R12 JNZ matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm12B - LEAL -16(DI), DI - LEAL 16(R10), R10 + LEAL -16(R8), R8 + LEAL 16(R11), R11 JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm12B matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R11, R11 + TZCNTQ R12, R12 #else - BSFQ R11, R11 + BSFQ R12, R12 #endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 JMP repeat_extend_forward_end_encodeSnappyBlockAsm12B matchlen_match8_repeat_extend_encodeSnappyBlockAsm12B: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_repeat_extend_encodeSnappyBlockAsm12B - MOVQ (R8)(R10*1), R9 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm12B - LEAL -8(DI), DI - LEAL 8(R10), R10 + LEAL -8(R8), R8 + LEAL 8(R11), R11 JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm12B matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R9, R9 + TZCNTQ R10, R10 #else - BSFQ R9, R9 + BSFQ R10, R10 #endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 JMP repeat_extend_forward_end_encodeSnappyBlockAsm12B matchlen_match4_repeat_extend_encodeSnappyBlockAsm12B: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_repeat_extend_encodeSnappyBlockAsm12B - MOVL (R8)(R10*1), R9 - CMPL (BX)(R10*1), R9 + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 JNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm12B - LEAL -4(DI), DI - LEAL 4(R10), R10 + LEAL -4(R8), R8 + LEAL 4(R11), R11 matchlen_match2_repeat_extend_encodeSnappyBlockAsm12B: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_repeat_extend_encodeSnappyBlockAsm12B JB repeat_extend_forward_end_encodeSnappyBlockAsm12B - MOVW (R8)(R10*1), R9 - CMPW (BX)(R10*1), R9 + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 JNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm12B - LEAL 2(R10), R10 - SUBL $0x02, DI + LEAL 2(R11), R11 + SUBL $0x02, R8 JZ repeat_extend_forward_end_encodeSnappyBlockAsm12B matchlen_match1_repeat_extend_encodeSnappyBlockAsm12B: - MOVB (R8)(R10*1), R9 - CMPB (BX)(R10*1), R9 + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 JNE repeat_extend_forward_end_encodeSnappyBlockAsm12B - LEAL 1(R10), R10 + LEAL 1(R11), R11 repeat_extend_forward_end_encodeSnappyBlockAsm12B: - ADDL R10, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI // emitCopy two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm12B: - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm12B - MOVB $0xee, (AX) - MOVW SI, 1(AX) - LEAL -60(BX), BX - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm12B two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm12B: - MOVL BX, DI - SHLL $0x02, DI - CMPL BX, $0x0c + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm12B - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm12B - LEAL -15(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeSnappyBlockAsm12B emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm12B: - LEAL -2(DI), DI - MOVB DI, (AX) - MOVW SI, 1(AX) - ADDQ $0x03, AX + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX repeat_end_emit_encodeSnappyBlockAsm12B: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_encodeSnappyBlockAsm12B no_repeat_found_encodeSnappyBlockAsm12B: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeSnappyBlockAsm12B - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_encodeSnappyBlockAsm12B - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_encodeSnappyBlockAsm12B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeSnappyBlockAsm12B candidate3_match_encodeSnappyBlockAsm12B: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_encodeSnappyBlockAsm12B candidate2_match_encodeSnappyBlockAsm12B: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_encodeSnappyBlockAsm12B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeSnappyBlockAsm12B match_extend_back_loop_encodeSnappyBlockAsm12B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeSnappyBlockAsm12B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeSnappyBlockAsm12B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeSnappyBlockAsm12B JMP match_extend_back_loop_encodeSnappyBlockAsm12B match_extend_back_end_encodeSnappyBlockAsm12B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeSnappyBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeSnappyBlockAsm12B: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_encodeSnappyBlockAsm12B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), DI - CMPL DI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c JB one_byte_match_emit_encodeSnappyBlockAsm12B - CMPL DI, $0x00000100 + CMPL R8, $0x00000100 JB two_bytes_match_emit_encodeSnappyBlockAsm12B JB three_bytes_match_emit_encodeSnappyBlockAsm12B three_bytes_match_emit_encodeSnappyBlockAsm12B: - MOVB $0xf4, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeSnappyBlockAsm12B two_bytes_match_emit_encodeSnappyBlockAsm12B: - MOVB $0xf0, (AX) - MOVB DI, 1(AX) - ADDQ $0x02, AX - CMPL DI, $0x40 + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 JB memmove_match_emit_encodeSnappyBlockAsm12B JMP memmove_long_match_emit_encodeSnappyBlockAsm12B one_byte_match_emit_encodeSnappyBlockAsm12B: - SHLB $0x02, DI - MOVB DI, (AX) - ADDQ $0x01, AX + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeSnappyBlockAsm12B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8: - MOVQ (SI), R9 - MOVQ R9, (AX) + MOVQ (DI), R10 + MOVQ R10, (CX) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm12B emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8through16: - MOVQ (SI), R9 - MOVQ -8(SI)(R8*1), SI - MOVQ R9, (AX) - MOVQ SI, -8(AX)(R8*1) + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm12B emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_17through32: - MOVOU (SI), X0 - MOVOU -16(SI)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm12B emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_33through64: - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeSnappyBlockAsm12B: - MOVQ DI, AX + MOVQ R8, CX JMP emit_literal_done_match_emit_encodeSnappyBlockAsm12B memmove_long_match_emit_encodeSnappyBlockAsm12B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveLong - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVQ R8, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 - LEAQ -32(SI)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32: - MOVOU -32(SI)(R11*1), X4 - MOVOU -16(SI)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ R8, R11 + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 JAE emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ DI, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX emit_literal_done_match_emit_encodeSnappyBlockAsm12B: match_nolit_loop_encodeSnappyBlockAsm12B: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm12B: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_encodeSnappyBlockAsm12B - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm12B - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_encodeSnappyBlockAsm12B - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm12B matchlen_bsf_16match_nolit_encodeSnappyBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_encodeSnappyBlockAsm12B matchlen_match8_match_nolit_encodeSnappyBlockAsm12B: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_encodeSnappyBlockAsm12B - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm12B - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm12B matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_encodeSnappyBlockAsm12B matchlen_match4_match_nolit_encodeSnappyBlockAsm12B: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_encodeSnappyBlockAsm12B - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_encodeSnappyBlockAsm12B - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_encodeSnappyBlockAsm12B: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_encodeSnappyBlockAsm12B JB match_nolit_end_encodeSnappyBlockAsm12B - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_encodeSnappyBlockAsm12B - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_encodeSnappyBlockAsm12B matchlen_match1_match_nolit_encodeSnappyBlockAsm12B: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_encodeSnappyBlockAsm12B - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_encodeSnappyBlockAsm12B: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy two_byte_offset_match_nolit_encodeSnappyBlockAsm12B: - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_encodeSnappyBlockAsm12B - MOVB $0xee, (AX) - MOVW BX, 1(AX) - LEAL -60(R9), R9 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm12B two_byte_offset_short_match_nolit_encodeSnappyBlockAsm12B: - MOVL R9, SI - SHLL $0x02, SI - CMPL R9, $0x0c + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm12B - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm12B - LEAL -15(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm12B emit_copy_three_match_nolit_encodeSnappyBlockAsm12B: - LEAL -2(SI), SI - MOVB SI, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeSnappyBlockAsm12B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeSnappyBlockAsm12B - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeSnappyBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeSnappyBlockAsm12B: - MOVQ $0x000000cf1bbcdcbb, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x18, DI - IMULQ R8, DI - SHRQ $0x34, DI - SHLQ $0x18, BX - IMULQ R8, BX - SHRQ $0x34, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x000000cf1bbcdcbb, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x18, R8 + IMULQ R9, R8 + SHRQ $0x34, R8 + SHLQ $0x18, SI + IMULQ R9, SI + SHRQ $0x34, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_encodeSnappyBlockAsm12B - INCL CX + INCL DX JMP search_loop_encodeSnappyBlockAsm12B emit_remainder_encodeSnappyBlockAsm12B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeSnappyBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeSnappyBlockAsm12B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm12B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeSnappyBlockAsm12B @@ -13181,26 +13194,26 @@ emit_remainder_ok_encodeSnappyBlockAsm12B: JB three_bytes_emit_remainder_encodeSnappyBlockAsm12B three_bytes_emit_remainder_encodeSnappyBlockAsm12B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeSnappyBlockAsm12B two_bytes_emit_remainder_encodeSnappyBlockAsm12B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeSnappyBlockAsm12B JMP memmove_long_emit_remainder_encodeSnappyBlockAsm12B one_byte_emit_remainder_encodeSnappyBlockAsm12B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeSnappyBlockAsm12B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -13216,73 +13229,73 @@ memmove_emit_remainder_encodeSnappyBlockAsm12B: JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm12B memmove_long_emit_remainder_encodeSnappyBlockAsm12B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_big_loop_back: MOVOU (SI), X4 @@ -13296,718 +13309,719 @@ emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeSnappyBlockAsm12B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeSnappyBlockAsm10B(dst []byte, src []byte) int +// func encodeSnappyBlockAsm10B(dst []byte, src []byte, tmp *[4096]byte) int // Requires: BMI, SSE2 -TEXT ·encodeSnappyBlockAsm10B(SB), $4120-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000020, CX - LEAQ 24(SP), DX +TEXT ·encodeSnappyBlockAsm10B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000020, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeSnappyBlockAsm10B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeSnappyBlockAsm10B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX search_loop_encodeSnappyBlockAsm10B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x05, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeSnappyBlockAsm10B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x9e3779b1, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x20, R9 - IMULQ R8, R9 - SHRQ $0x36, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x9e3779b1, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x20, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x36, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x20, R9 - IMULQ R8, R9 - SHRQ $0x36, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 + SHLQ $0x20, R11 + IMULQ R9, R11 + SHRQ $0x36, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 JNE no_repeat_found_encodeSnappyBlockAsm10B - LEAL 1(CX), SI - MOVL 12(SP), BX - MOVL SI, DI - SUBL 16(SP), DI + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 JZ repeat_extend_back_end_encodeSnappyBlockAsm10B repeat_extend_back_loop_encodeSnappyBlockAsm10B: - CMPL SI, BX + CMPL DI, SI JBE repeat_extend_back_end_encodeSnappyBlockAsm10B - MOVB -1(DX)(DI*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_encodeSnappyBlockAsm10B - LEAL -1(SI), SI - DECL DI + LEAL -1(DI), DI + DECL R8 JNZ repeat_extend_back_loop_encodeSnappyBlockAsm10B repeat_extend_back_end_encodeSnappyBlockAsm10B: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 3(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_encodeSnappyBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET repeat_dst_size_check_encodeSnappyBlockAsm10B: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B - MOVL SI, DI - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R8 - SUBL BX, DI - LEAL -1(DI), BX - CMPL BX, $0x3c + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_encodeSnappyBlockAsm10B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_encodeSnappyBlockAsm10B JB three_bytes_repeat_emit_encodeSnappyBlockAsm10B three_bytes_repeat_emit_encodeSnappyBlockAsm10B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_repeat_emit_encodeSnappyBlockAsm10B two_bytes_repeat_emit_encodeSnappyBlockAsm10B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_encodeSnappyBlockAsm10B JMP memmove_long_repeat_emit_encodeSnappyBlockAsm10B one_byte_repeat_emit_encodeSnappyBlockAsm10B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_repeat_emit_encodeSnappyBlockAsm10B: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveShort - CMPQ DI, $0x08 + CMPQ R8, $0x08 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8 - CMPQ DI, $0x10 + CMPQ R8, $0x10 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8through16 - CMPQ DI, $0x20 + CMPQ R8, $0x20 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_17through32 JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_33through64 emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8: - MOVQ (R8), R9 - MOVQ R9, (AX) + MOVQ (R9), R10 + MOVQ R10, (CX) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8through16: - MOVQ (R8), R9 - MOVQ -8(R8)(DI*1), R8 - MOVQ R9, (AX) - MOVQ R8, -8(AX)(DI*1) + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_17through32: - MOVOU (R8), X0 - MOVOU -16(R8)(DI*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_33through64: - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B memmove_long_repeat_emit_encodeSnappyBlockAsm10B: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveLong - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVQ DI, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 - LEAQ -32(R8)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(R9)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_big_loop_back emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32: - MOVOU -32(R8)(R11*1), X4 - MOVOU -16(R8)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ DI, R11 + MOVOU -32(R9)(R12*1), X4 + MOVOU -16(R9)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R8, R12 JAE emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI // matchLen - XORL R10, R10 + XORL R11, R11 matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm10B: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_repeat_extend_encodeSnappyBlockAsm10B - MOVQ (R8)(R10*1), R9 - MOVQ 8(R8)(R10*1), R11 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm10B - XORQ 8(BX)(R10*1), R11 + XORQ 8(SI)(R11*1), R12 JNZ matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm10B - LEAL -16(DI), DI - LEAL 16(R10), R10 + LEAL -16(R8), R8 + LEAL 16(R11), R11 JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm10B matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R11, R11 + TZCNTQ R12, R12 #else - BSFQ R11, R11 + BSFQ R12, R12 #endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 JMP repeat_extend_forward_end_encodeSnappyBlockAsm10B matchlen_match8_repeat_extend_encodeSnappyBlockAsm10B: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_repeat_extend_encodeSnappyBlockAsm10B - MOVQ (R8)(R10*1), R9 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm10B - LEAL -8(DI), DI - LEAL 8(R10), R10 + LEAL -8(R8), R8 + LEAL 8(R11), R11 JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm10B matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R9, R9 + TZCNTQ R10, R10 #else - BSFQ R9, R9 + BSFQ R10, R10 #endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 JMP repeat_extend_forward_end_encodeSnappyBlockAsm10B matchlen_match4_repeat_extend_encodeSnappyBlockAsm10B: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_repeat_extend_encodeSnappyBlockAsm10B - MOVL (R8)(R10*1), R9 - CMPL (BX)(R10*1), R9 + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 JNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm10B - LEAL -4(DI), DI - LEAL 4(R10), R10 + LEAL -4(R8), R8 + LEAL 4(R11), R11 matchlen_match2_repeat_extend_encodeSnappyBlockAsm10B: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_repeat_extend_encodeSnappyBlockAsm10B JB repeat_extend_forward_end_encodeSnappyBlockAsm10B - MOVW (R8)(R10*1), R9 - CMPW (BX)(R10*1), R9 + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 JNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm10B - LEAL 2(R10), R10 - SUBL $0x02, DI + LEAL 2(R11), R11 + SUBL $0x02, R8 JZ repeat_extend_forward_end_encodeSnappyBlockAsm10B matchlen_match1_repeat_extend_encodeSnappyBlockAsm10B: - MOVB (R8)(R10*1), R9 - CMPB (BX)(R10*1), R9 + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 JNE repeat_extend_forward_end_encodeSnappyBlockAsm10B - LEAL 1(R10), R10 + LEAL 1(R11), R11 repeat_extend_forward_end_encodeSnappyBlockAsm10B: - ADDL R10, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI // emitCopy two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm10B: - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm10B - MOVB $0xee, (AX) - MOVW SI, 1(AX) - LEAL -60(BX), BX - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm10B two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm10B: - MOVL BX, DI - SHLL $0x02, DI - CMPL BX, $0x0c + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm10B - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm10B - LEAL -15(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeSnappyBlockAsm10B emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm10B: - LEAL -2(DI), DI - MOVB DI, (AX) - MOVW SI, 1(AX) - ADDQ $0x03, AX + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX repeat_end_emit_encodeSnappyBlockAsm10B: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_encodeSnappyBlockAsm10B no_repeat_found_encodeSnappyBlockAsm10B: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeSnappyBlockAsm10B - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_encodeSnappyBlockAsm10B - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_encodeSnappyBlockAsm10B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeSnappyBlockAsm10B candidate3_match_encodeSnappyBlockAsm10B: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_encodeSnappyBlockAsm10B candidate2_match_encodeSnappyBlockAsm10B: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_encodeSnappyBlockAsm10B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeSnappyBlockAsm10B match_extend_back_loop_encodeSnappyBlockAsm10B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeSnappyBlockAsm10B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeSnappyBlockAsm10B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeSnappyBlockAsm10B JMP match_extend_back_loop_encodeSnappyBlockAsm10B match_extend_back_end_encodeSnappyBlockAsm10B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeSnappyBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeSnappyBlockAsm10B: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_encodeSnappyBlockAsm10B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), DI - CMPL DI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c JB one_byte_match_emit_encodeSnappyBlockAsm10B - CMPL DI, $0x00000100 + CMPL R8, $0x00000100 JB two_bytes_match_emit_encodeSnappyBlockAsm10B JB three_bytes_match_emit_encodeSnappyBlockAsm10B three_bytes_match_emit_encodeSnappyBlockAsm10B: - MOVB $0xf4, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeSnappyBlockAsm10B two_bytes_match_emit_encodeSnappyBlockAsm10B: - MOVB $0xf0, (AX) - MOVB DI, 1(AX) - ADDQ $0x02, AX - CMPL DI, $0x40 + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 JB memmove_match_emit_encodeSnappyBlockAsm10B JMP memmove_long_match_emit_encodeSnappyBlockAsm10B one_byte_match_emit_encodeSnappyBlockAsm10B: - SHLB $0x02, DI - MOVB DI, (AX) - ADDQ $0x01, AX + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeSnappyBlockAsm10B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8: - MOVQ (SI), R9 - MOVQ R9, (AX) + MOVQ (DI), R10 + MOVQ R10, (CX) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm10B emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8through16: - MOVQ (SI), R9 - MOVQ -8(SI)(R8*1), SI - MOVQ R9, (AX) - MOVQ SI, -8(AX)(R8*1) + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm10B emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_17through32: - MOVOU (SI), X0 - MOVOU -16(SI)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm10B emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_33through64: - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeSnappyBlockAsm10B: - MOVQ DI, AX + MOVQ R8, CX JMP emit_literal_done_match_emit_encodeSnappyBlockAsm10B memmove_long_match_emit_encodeSnappyBlockAsm10B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveLong - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVQ R8, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 - LEAQ -32(SI)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32: - MOVOU -32(SI)(R11*1), X4 - MOVOU -16(SI)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ R8, R11 + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 JAE emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ DI, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX emit_literal_done_match_emit_encodeSnappyBlockAsm10B: match_nolit_loop_encodeSnappyBlockAsm10B: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm10B: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_encodeSnappyBlockAsm10B - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm10B - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_encodeSnappyBlockAsm10B - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm10B matchlen_bsf_16match_nolit_encodeSnappyBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_encodeSnappyBlockAsm10B matchlen_match8_match_nolit_encodeSnappyBlockAsm10B: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_encodeSnappyBlockAsm10B - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm10B - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm10B matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_encodeSnappyBlockAsm10B matchlen_match4_match_nolit_encodeSnappyBlockAsm10B: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_encodeSnappyBlockAsm10B - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_encodeSnappyBlockAsm10B - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_encodeSnappyBlockAsm10B: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_encodeSnappyBlockAsm10B JB match_nolit_end_encodeSnappyBlockAsm10B - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_encodeSnappyBlockAsm10B - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_encodeSnappyBlockAsm10B matchlen_match1_match_nolit_encodeSnappyBlockAsm10B: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_encodeSnappyBlockAsm10B - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_encodeSnappyBlockAsm10B: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy two_byte_offset_match_nolit_encodeSnappyBlockAsm10B: - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_encodeSnappyBlockAsm10B - MOVB $0xee, (AX) - MOVW BX, 1(AX) - LEAL -60(R9), R9 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm10B two_byte_offset_short_match_nolit_encodeSnappyBlockAsm10B: - MOVL R9, SI - SHLL $0x02, SI - CMPL R9, $0x0c + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm10B - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm10B - LEAL -15(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm10B emit_copy_three_match_nolit_encodeSnappyBlockAsm10B: - LEAL -2(SI), SI - MOVB SI, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeSnappyBlockAsm10B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeSnappyBlockAsm10B - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeSnappyBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeSnappyBlockAsm10B: - MOVQ $0x9e3779b1, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x20, DI - IMULQ R8, DI - SHRQ $0x36, DI - SHLQ $0x20, BX - IMULQ R8, BX - SHRQ $0x36, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x9e3779b1, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x20, R8 + IMULQ R9, R8 + SHRQ $0x36, R8 + SHLQ $0x20, SI + IMULQ R9, SI + SHRQ $0x36, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_encodeSnappyBlockAsm10B - INCL CX + INCL DX JMP search_loop_encodeSnappyBlockAsm10B emit_remainder_encodeSnappyBlockAsm10B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeSnappyBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeSnappyBlockAsm10B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm10B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeSnappyBlockAsm10B @@ -14016,26 +14030,26 @@ emit_remainder_ok_encodeSnappyBlockAsm10B: JB three_bytes_emit_remainder_encodeSnappyBlockAsm10B three_bytes_emit_remainder_encodeSnappyBlockAsm10B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeSnappyBlockAsm10B two_bytes_emit_remainder_encodeSnappyBlockAsm10B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeSnappyBlockAsm10B JMP memmove_long_emit_remainder_encodeSnappyBlockAsm10B one_byte_emit_remainder_encodeSnappyBlockAsm10B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeSnappyBlockAsm10B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -14051,73 +14065,73 @@ memmove_emit_remainder_encodeSnappyBlockAsm10B: JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm10B memmove_long_emit_remainder_encodeSnappyBlockAsm10B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_big_loop_back: MOVOU (SI), X4 @@ -14131,714 +14145,715 @@ emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeSnappyBlockAsm10B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeSnappyBlockAsm8B(dst []byte, src []byte) int +// func encodeSnappyBlockAsm8B(dst []byte, src []byte, tmp *[1024]byte) int // Requires: BMI, SSE2 -TEXT ·encodeSnappyBlockAsm8B(SB), $1048-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000008, CX - LEAQ 24(SP), DX +TEXT ·encodeSnappyBlockAsm8B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000008, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeSnappyBlockAsm8B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeSnappyBlockAsm8B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+24(FP), BX search_loop_encodeSnappyBlockAsm8B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x04, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x04, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeSnappyBlockAsm8B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x9e3779b1, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x20, R9 - IMULQ R8, R9 - SHRQ $0x38, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x9e3779b1, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x20, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x38, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x20, R9 - IMULQ R8, R9 - SHRQ $0x38, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 + SHLQ $0x20, R11 + IMULQ R9, R11 + SHRQ $0x38, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x38, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 JNE no_repeat_found_encodeSnappyBlockAsm8B - LEAL 1(CX), SI - MOVL 12(SP), BX - MOVL SI, DI - SUBL 16(SP), DI + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 JZ repeat_extend_back_end_encodeSnappyBlockAsm8B repeat_extend_back_loop_encodeSnappyBlockAsm8B: - CMPL SI, BX + CMPL DI, SI JBE repeat_extend_back_end_encodeSnappyBlockAsm8B - MOVB -1(DX)(DI*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_encodeSnappyBlockAsm8B - LEAL -1(SI), SI - DECL DI + LEAL -1(DI), DI + DECL R8 JNZ repeat_extend_back_loop_encodeSnappyBlockAsm8B repeat_extend_back_end_encodeSnappyBlockAsm8B: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 3(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_encodeSnappyBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET repeat_dst_size_check_encodeSnappyBlockAsm8B: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B - MOVL SI, DI - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R8 - SUBL BX, DI - LEAL -1(DI), BX - CMPL BX, $0x3c + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_encodeSnappyBlockAsm8B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_encodeSnappyBlockAsm8B JB three_bytes_repeat_emit_encodeSnappyBlockAsm8B three_bytes_repeat_emit_encodeSnappyBlockAsm8B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_repeat_emit_encodeSnappyBlockAsm8B two_bytes_repeat_emit_encodeSnappyBlockAsm8B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_encodeSnappyBlockAsm8B JMP memmove_long_repeat_emit_encodeSnappyBlockAsm8B one_byte_repeat_emit_encodeSnappyBlockAsm8B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_repeat_emit_encodeSnappyBlockAsm8B: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveShort - CMPQ DI, $0x08 + CMPQ R8, $0x08 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8 - CMPQ DI, $0x10 + CMPQ R8, $0x10 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8through16 - CMPQ DI, $0x20 + CMPQ R8, $0x20 JBE emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_17through32 JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_33through64 emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8: - MOVQ (R8), R9 - MOVQ R9, (AX) + MOVQ (R9), R10 + MOVQ R10, (CX) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8through16: - MOVQ (R8), R9 - MOVQ -8(R8)(DI*1), R8 - MOVQ R9, (AX) - MOVQ R8, -8(AX)(DI*1) + MOVQ (R9), R10 + MOVQ -8(R9)(R8*1), R9 + MOVQ R10, (CX) + MOVQ R9, -8(CX)(R8*1) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_17through32: - MOVOU (R8), X0 - MOVOU -16(R8)(DI*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU -16(R9)(R8*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R8*1) JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_33through64: - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B memmove_long_repeat_emit_encodeSnappyBlockAsm8B: - LEAQ (AX)(DI*1), BX + LEAQ (CX)(R8*1), SI // genMemMoveLong - MOVOU (R8), X0 - MOVOU 16(R8), X1 - MOVOU -32(R8)(DI*1), X2 - MOVOU -16(R8)(DI*1), X3 - MOVQ DI, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (R9), X0 + MOVOU 16(R9), X1 + MOVOU -32(R9)(R8*1), X2 + MOVOU -16(R9)(R8*1), X3 + MOVQ R8, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 - LEAQ -32(R8)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(R9)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_big_loop_back emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32: - MOVOU -32(R8)(R11*1), X4 - MOVOU -16(R8)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ DI, R11 + MOVOU -32(R9)(R12*1), X4 + MOVOU -16(R9)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R8, R12 JAE emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(DI*1) - MOVOU X3, -16(AX)(DI*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R8*1) + MOVOU X3, -16(CX)(R8*1) + MOVQ SI, CX emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI // matchLen - XORL R10, R10 + XORL R11, R11 matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm8B: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_repeat_extend_encodeSnappyBlockAsm8B - MOVQ (R8)(R10*1), R9 - MOVQ 8(R8)(R10*1), R11 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm8B - XORQ 8(BX)(R10*1), R11 + XORQ 8(SI)(R11*1), R12 JNZ matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm8B - LEAL -16(DI), DI - LEAL 16(R10), R10 + LEAL -16(R8), R8 + LEAL 16(R11), R11 JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm8B matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R11, R11 + TZCNTQ R12, R12 #else - BSFQ R11, R11 + BSFQ R12, R12 #endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 JMP repeat_extend_forward_end_encodeSnappyBlockAsm8B matchlen_match8_repeat_extend_encodeSnappyBlockAsm8B: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_repeat_extend_encodeSnappyBlockAsm8B - MOVQ (R8)(R10*1), R9 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm8B - LEAL -8(DI), DI - LEAL 8(R10), R10 + LEAL -8(R8), R8 + LEAL 8(R11), R11 JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm8B matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R9, R9 + TZCNTQ R10, R10 #else - BSFQ R9, R9 + BSFQ R10, R10 #endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 JMP repeat_extend_forward_end_encodeSnappyBlockAsm8B matchlen_match4_repeat_extend_encodeSnappyBlockAsm8B: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_repeat_extend_encodeSnappyBlockAsm8B - MOVL (R8)(R10*1), R9 - CMPL (BX)(R10*1), R9 + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 JNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm8B - LEAL -4(DI), DI - LEAL 4(R10), R10 + LEAL -4(R8), R8 + LEAL 4(R11), R11 matchlen_match2_repeat_extend_encodeSnappyBlockAsm8B: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_repeat_extend_encodeSnappyBlockAsm8B JB repeat_extend_forward_end_encodeSnappyBlockAsm8B - MOVW (R8)(R10*1), R9 - CMPW (BX)(R10*1), R9 + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 JNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm8B - LEAL 2(R10), R10 - SUBL $0x02, DI + LEAL 2(R11), R11 + SUBL $0x02, R8 JZ repeat_extend_forward_end_encodeSnappyBlockAsm8B matchlen_match1_repeat_extend_encodeSnappyBlockAsm8B: - MOVB (R8)(R10*1), R9 - CMPB (BX)(R10*1), R9 + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 JNE repeat_extend_forward_end_encodeSnappyBlockAsm8B - LEAL 1(R10), R10 + LEAL 1(R11), R11 repeat_extend_forward_end_encodeSnappyBlockAsm8B: - ADDL R10, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI // emitCopy two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm8B: - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm8B - MOVB $0xee, (AX) - MOVW SI, 1(AX) - LEAL -60(BX), BX - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW DI, 1(CX) + LEAL -60(SI), SI + ADDQ $0x03, CX JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm8B two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm8B: - MOVL BX, DI - SHLL $0x02, DI - CMPL BX, $0x0c + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm8B - LEAL -15(DI), DI - MOVB SI, 1(AX) - SHRL $0x08, SI - SHLL $0x05, SI - ORL SI, DI - MOVB DI, (AX) - ADDQ $0x02, AX + LEAL -15(R8), R8 + MOVB DI, 1(CX) + SHRL $0x08, DI + SHLL $0x05, DI + ORL DI, R8 + MOVB R8, (CX) + ADDQ $0x02, CX JMP repeat_end_emit_encodeSnappyBlockAsm8B emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm8B: - LEAL -2(DI), DI - MOVB DI, (AX) - MOVW SI, 1(AX) - ADDQ $0x03, AX + LEAL -2(R8), R8 + MOVB R8, (CX) + MOVW DI, 1(CX) + ADDQ $0x03, CX repeat_end_emit_encodeSnappyBlockAsm8B: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_encodeSnappyBlockAsm8B no_repeat_found_encodeSnappyBlockAsm8B: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeSnappyBlockAsm8B - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_encodeSnappyBlockAsm8B - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_encodeSnappyBlockAsm8B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeSnappyBlockAsm8B candidate3_match_encodeSnappyBlockAsm8B: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_encodeSnappyBlockAsm8B candidate2_match_encodeSnappyBlockAsm8B: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_encodeSnappyBlockAsm8B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeSnappyBlockAsm8B match_extend_back_loop_encodeSnappyBlockAsm8B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeSnappyBlockAsm8B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeSnappyBlockAsm8B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeSnappyBlockAsm8B JMP match_extend_back_loop_encodeSnappyBlockAsm8B match_extend_back_end_encodeSnappyBlockAsm8B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeSnappyBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeSnappyBlockAsm8B: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_encodeSnappyBlockAsm8B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), DI - CMPL DI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), R8 + CMPL R8, $0x3c JB one_byte_match_emit_encodeSnappyBlockAsm8B - CMPL DI, $0x00000100 + CMPL R8, $0x00000100 JB two_bytes_match_emit_encodeSnappyBlockAsm8B JB three_bytes_match_emit_encodeSnappyBlockAsm8B three_bytes_match_emit_encodeSnappyBlockAsm8B: - MOVB $0xf4, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeSnappyBlockAsm8B two_bytes_match_emit_encodeSnappyBlockAsm8B: - MOVB $0xf0, (AX) - MOVB DI, 1(AX) - ADDQ $0x02, AX - CMPL DI, $0x40 + MOVB $0xf0, (CX) + MOVB R8, 1(CX) + ADDQ $0x02, CX + CMPL R8, $0x40 JB memmove_match_emit_encodeSnappyBlockAsm8B JMP memmove_long_match_emit_encodeSnappyBlockAsm8B one_byte_match_emit_encodeSnappyBlockAsm8B: - SHLB $0x02, DI - MOVB DI, (AX) - ADDQ $0x01, AX + SHLB $0x02, R8 + MOVB R8, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeSnappyBlockAsm8B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8: - MOVQ (SI), R9 - MOVQ R9, (AX) + MOVQ (DI), R10 + MOVQ R10, (CX) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm8B emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8through16: - MOVQ (SI), R9 - MOVQ -8(SI)(R8*1), SI - MOVQ R9, (AX) - MOVQ SI, -8(AX)(R8*1) + MOVQ (DI), R10 + MOVQ -8(DI)(R9*1), DI + MOVQ R10, (CX) + MOVQ DI, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm8B emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_17through32: - MOVOU (SI), X0 - MOVOU -16(SI)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU -16(DI)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm8B emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_33through64: - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeSnappyBlockAsm8B: - MOVQ DI, AX + MOVQ R8, CX JMP emit_literal_done_match_emit_encodeSnappyBlockAsm8B memmove_long_match_emit_encodeSnappyBlockAsm8B: - LEAQ (AX)(R8*1), DI + LEAQ (CX)(R9*1), R8 // genMemMoveLong - MOVOU (SI), X0 - MOVOU 16(SI), X1 - MOVOU -32(SI)(R8*1), X2 - MOVOU -16(SI)(R8*1), X3 - MOVQ R8, R10 - SHRQ $0x05, R10 - MOVQ AX, R9 - ANDL $0x0000001f, R9 - MOVQ $0x00000040, R11 - SUBQ R9, R11 - DECQ R10 + MOVOU (DI), X0 + MOVOU 16(DI), X1 + MOVOU -32(DI)(R9*1), X2 + MOVOU -16(DI)(R9*1), X3 + MOVQ R9, R11 + SHRQ $0x05, R11 + MOVQ CX, R10 + ANDL $0x0000001f, R10 + MOVQ $0x00000040, R12 + SUBQ R10, R12 + DECQ R11 JA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 - LEAQ -32(SI)(R11*1), R9 - LEAQ -32(AX)(R11*1), R12 + LEAQ -32(DI)(R12*1), R10 + LEAQ -32(CX)(R12*1), R13 emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_big_loop_back: - MOVOU (R9), X4 - MOVOU 16(R9), X5 - MOVOA X4, (R12) - MOVOA X5, 16(R12) + MOVOU (R10), X4 + MOVOU 16(R10), X5 + MOVOA X4, (R13) + MOVOA X5, 16(R13) + ADDQ $0x20, R13 + ADDQ $0x20, R10 ADDQ $0x20, R12 - ADDQ $0x20, R9 - ADDQ $0x20, R11 - DECQ R10 + DECQ R11 JNA emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32: - MOVOU -32(SI)(R11*1), X4 - MOVOU -16(SI)(R11*1), X5 - MOVOA X4, -32(AX)(R11*1) - MOVOA X5, -16(AX)(R11*1) - ADDQ $0x20, R11 - CMPQ R8, R11 + MOVOU -32(DI)(R12*1), X4 + MOVOU -16(DI)(R12*1), X5 + MOVOA X4, -32(CX)(R12*1) + MOVOA X5, -16(CX)(R12*1) + ADDQ $0x20, R12 + CMPQ R9, R12 JAE emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ DI, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ R8, CX emit_literal_done_match_emit_encodeSnappyBlockAsm8B: match_nolit_loop_encodeSnappyBlockAsm8B: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm8B: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_encodeSnappyBlockAsm8B - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm8B - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_encodeSnappyBlockAsm8B - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm8B matchlen_bsf_16match_nolit_encodeSnappyBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_encodeSnappyBlockAsm8B matchlen_match8_match_nolit_encodeSnappyBlockAsm8B: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_encodeSnappyBlockAsm8B - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm8B - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm8B matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_encodeSnappyBlockAsm8B matchlen_match4_match_nolit_encodeSnappyBlockAsm8B: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_encodeSnappyBlockAsm8B - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_encodeSnappyBlockAsm8B - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_encodeSnappyBlockAsm8B: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_encodeSnappyBlockAsm8B JB match_nolit_end_encodeSnappyBlockAsm8B - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_encodeSnappyBlockAsm8B - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_encodeSnappyBlockAsm8B matchlen_match1_match_nolit_encodeSnappyBlockAsm8B: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_encodeSnappyBlockAsm8B - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_encodeSnappyBlockAsm8B: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy two_byte_offset_match_nolit_encodeSnappyBlockAsm8B: - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_encodeSnappyBlockAsm8B - MOVB $0xee, (AX) - MOVW BX, 1(AX) - LEAL -60(R9), R9 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW SI, 1(CX) + LEAL -60(R10), R10 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm8B two_byte_offset_short_match_nolit_encodeSnappyBlockAsm8B: - MOVL R9, SI - SHLL $0x02, SI - CMPL R9, $0x0c + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_encodeSnappyBlockAsm8B - LEAL -15(SI), SI - MOVB BL, 1(AX) - SHRL $0x08, BX - SHLL $0x05, BX - ORL BX, SI - MOVB SI, (AX) - ADDQ $0x02, AX + LEAL -15(DI), DI + MOVB SI, 1(CX) + SHRL $0x08, SI + SHLL $0x05, SI + ORL SI, DI + MOVB DI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm8B emit_copy_three_match_nolit_encodeSnappyBlockAsm8B: - LEAL -2(SI), SI - MOVB SI, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + LEAL -2(DI), DI + MOVB DI, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeSnappyBlockAsm8B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeSnappyBlockAsm8B - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeSnappyBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeSnappyBlockAsm8B: - MOVQ $0x9e3779b1, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x20, DI - IMULQ R8, DI - SHRQ $0x38, DI - SHLQ $0x20, BX - IMULQ R8, BX - SHRQ $0x38, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x9e3779b1, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x20, R8 + IMULQ R9, R8 + SHRQ $0x38, R8 + SHLQ $0x20, SI + IMULQ R9, SI + SHRQ $0x38, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_encodeSnappyBlockAsm8B - INCL CX + INCL DX JMP search_loop_encodeSnappyBlockAsm8B emit_remainder_encodeSnappyBlockAsm8B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeSnappyBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeSnappyBlockAsm8B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm8B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeSnappyBlockAsm8B @@ -14847,26 +14862,26 @@ emit_remainder_ok_encodeSnappyBlockAsm8B: JB three_bytes_emit_remainder_encodeSnappyBlockAsm8B three_bytes_emit_remainder_encodeSnappyBlockAsm8B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeSnappyBlockAsm8B two_bytes_emit_remainder_encodeSnappyBlockAsm8B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeSnappyBlockAsm8B JMP memmove_long_emit_remainder_encodeSnappyBlockAsm8B one_byte_emit_remainder_encodeSnappyBlockAsm8B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeSnappyBlockAsm8B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -14882,73 +14897,73 @@ memmove_emit_remainder_encodeSnappyBlockAsm8B: JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm8B memmove_long_emit_remainder_encodeSnappyBlockAsm8B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_big_loop_back: MOVOU (SI), X4 @@ -14962,520 +14977,521 @@ emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_big_loop_back: JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeSnappyBlockAsm8B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeSnappyBetterBlockAsm(dst []byte, src []byte) int +// func encodeSnappyBetterBlockAsm(dst []byte, src []byte, tmp *[589824]byte) int // Requires: BMI, SSE2 -TEXT ·encodeSnappyBetterBlockAsm(SB), $589848-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00001200, CX - LEAQ 24(SP), DX +TEXT ·encodeSnappyBetterBlockAsm(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00001200, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeSnappyBetterBlockAsm: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeSnappyBetterBlockAsm MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX MOVL $0x00000000, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_base+24(FP), BX search_loop_encodeSnappyBetterBlockAsm: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x07, BX - CMPL BX, $0x63 + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x07, SI + CMPL SI, $0x63 JBE check_maxskip_ok_encodeSnappyBetterBlockAsm - LEAL 100(CX), BX + LEAL 100(DX), SI JMP check_maxskip_cont_encodeSnappyBetterBlockAsm check_maxskip_ok_encodeSnappyBetterBlockAsm: - LEAL 1(CX)(BX*1), BX + LEAL 1(DX)(SI*1), SI check_maxskip_cont_encodeSnappyBetterBlockAsm: - CMPL BX, 8(SP) + CMPL SI, 8(SP) JAE emit_remainder_encodeSnappyBetterBlockAsm - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x00cf1bbcdcbfa563, R8 - MOVQ $0x9e3779b1, BX - MOVQ SI, R9 - MOVQ SI, R10 - SHLQ $0x08, R9 - IMULQ R8, R9 - SHRQ $0x2f, R9 - SHLQ $0x20, R10 - IMULQ BX, R10 - SHRQ $0x32, R10 - MOVL 24(SP)(R9*4), BX - MOVL 524312(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - MOVL CX, 524312(SP)(R10*4) - MOVQ (DX)(BX*1), R9 - MOVQ (DX)(DI*1), R10 - CMPQ R9, SI + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x00cf1bbcdcbfa563, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x32, R11 + MOVL (AX)(R10*4), SI + MOVL 524288(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 524288(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI JEQ candidate_match_encodeSnappyBetterBlockAsm - CMPQ R10, SI + CMPQ R11, DI JNE no_short_found_encodeSnappyBetterBlockAsm - MOVL DI, BX + MOVL R8, SI JMP candidate_match_encodeSnappyBetterBlockAsm no_short_found_encodeSnappyBetterBlockAsm: - CMPL R9, SI + CMPL R10, DI JEQ candidate_match_encodeSnappyBetterBlockAsm - CMPL R10, SI + CMPL R11, DI JEQ candidateS_match_encodeSnappyBetterBlockAsm - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeSnappyBetterBlockAsm candidateS_match_encodeSnappyBetterBlockAsm: - SHRQ $0x08, SI - MOVQ SI, R9 - SHLQ $0x08, R9 - IMULQ R8, R9 - SHRQ $0x2f, R9 - MOVL 24(SP)(R9*4), BX - INCL CX - MOVL CX, 24(SP)(R9*4) - CMPL (DX)(BX*1), SI + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x2f, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeSnappyBetterBlockAsm - DECL CX - MOVL DI, BX + DECL DX + MOVL R8, SI candidate_match_encodeSnappyBetterBlockAsm: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeSnappyBetterBlockAsm match_extend_back_loop_encodeSnappyBetterBlockAsm: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeSnappyBetterBlockAsm - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeSnappyBetterBlockAsm - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeSnappyBetterBlockAsm JMP match_extend_back_loop_encodeSnappyBetterBlockAsm match_extend_back_end_encodeSnappyBetterBlockAsm: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 5(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 5(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeSnappyBetterBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeSnappyBetterBlockAsm: - MOVL CX, SI - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), R9 + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm - MOVQ (R8)(R11*1), R10 - MOVQ 8(R8)(R11*1), R12 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm - XORQ 8(R9)(R11*1), R12 + XORQ 8(R10)(R12*1), R13 JNZ matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm - LEAL -16(DI), DI - LEAL 16(R11), R11 + LEAL -16(R8), R8 + LEAL 16(R12), R12 JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP match_nolit_end_encodeSnappyBetterBlockAsm matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm - MOVQ (R8)(R11*1), R10 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm - LEAL -8(DI), DI - LEAL 8(R11), R11 + LEAL -8(R8), R8 + LEAL 8(R12), R12 JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP match_nolit_end_encodeSnappyBetterBlockAsm matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm - MOVL (R8)(R11*1), R10 - CMPL (R9)(R11*1), R10 + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 JNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm - LEAL -4(DI), DI - LEAL 4(R11), R11 + LEAL -4(R8), R8 + LEAL 4(R12), R12 matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm JB match_nolit_end_encodeSnappyBetterBlockAsm - MOVW (R8)(R11*1), R10 - CMPW (R9)(R11*1), R10 + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 JNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm - LEAL 2(R11), R11 - SUBL $0x02, DI + LEAL 2(R12), R12 + SUBL $0x02, R8 JZ match_nolit_end_encodeSnappyBetterBlockAsm matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm: - MOVB (R8)(R11*1), R10 - CMPB (R9)(R11*1), R10 + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 JNE match_nolit_end_encodeSnappyBetterBlockAsm - LEAL 1(R11), R11 + LEAL 1(R12), R12 match_nolit_end_encodeSnappyBetterBlockAsm: - MOVL CX, DI - SUBL BX, DI + MOVL DX, R8 + SUBL SI, R8 // Check if repeat - CMPL R11, $0x01 + CMPL R12, $0x01 JA match_length_ok_encodeSnappyBetterBlockAsm - CMPL DI, $0x0000ffff + CMPL R8, $0x0000ffff JBE match_length_ok_encodeSnappyBetterBlockAsm - MOVL 20(SP), CX - INCL CX + MOVL 20(SP), DX + INCL DX JMP search_loop_encodeSnappyBetterBlockAsm match_length_ok_encodeSnappyBetterBlockAsm: - MOVL DI, 16(SP) - MOVL 12(SP), BX - CMPL BX, SI + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_encodeSnappyBetterBlockAsm - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_encodeSnappyBetterBlockAsm - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB three_bytes_match_emit_encodeSnappyBetterBlockAsm - CMPL BX, $0x01000000 + CMPL SI, $0x01000000 JB four_bytes_match_emit_encodeSnappyBetterBlockAsm - MOVB $0xfc, (AX) - MOVL BX, 1(AX) - ADDQ $0x05, AX + MOVB $0xfc, (CX) + MOVL SI, 1(CX) + ADDQ $0x05, CX JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm four_bytes_match_emit_encodeSnappyBetterBlockAsm: - MOVL BX, R10 - SHRL $0x10, R10 - MOVB $0xf8, (AX) - MOVW BX, 1(AX) - MOVB R10, 3(AX) - ADDQ $0x04, AX + MOVL SI, R11 + SHRL $0x10, R11 + MOVB $0xf8, (CX) + MOVW SI, 1(CX) + MOVB R11, 3(CX) + ADDQ $0x04, CX JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm three_bytes_match_emit_encodeSnappyBetterBlockAsm: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm two_bytes_match_emit_encodeSnappyBetterBlockAsm: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_encodeSnappyBetterBlockAsm JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm one_byte_match_emit_encodeSnappyBetterBlockAsm: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeSnappyBetterBlockAsm: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_33through64 emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8: - MOVQ (R9), R10 - MOVQ R10, (AX) + MOVQ (R10), R11 + MOVQ R11, (CX) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm memmove_long_match_emit_encodeSnappyBetterBlockAsm: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_big_loop_back emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_encodeSnappyBetterBlockAsm: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitCopy - CMPL DI, $0x00010000 + CMPL R8, $0x00010000 JB two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm four_bytes_loop_back_match_nolit_encodeSnappyBetterBlockAsm: - CMPL R11, $0x40 + CMPL R12, $0x40 JBE four_bytes_remain_match_nolit_encodeSnappyBetterBlockAsm - MOVB $0xff, (AX) - MOVL DI, 1(AX) - LEAL -64(R11), R11 - ADDQ $0x05, AX - CMPL R11, $0x04 + MOVB $0xff, (CX) + MOVL R8, 1(CX) + LEAL -64(R12), R12 + ADDQ $0x05, CX + CMPL R12, $0x04 JB four_bytes_remain_match_nolit_encodeSnappyBetterBlockAsm JMP four_bytes_loop_back_match_nolit_encodeSnappyBetterBlockAsm four_bytes_remain_match_nolit_encodeSnappyBetterBlockAsm: - TESTL R11, R11 + TESTL R12, R12 JZ match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm - XORL BX, BX - LEAL -1(BX)(R11*4), R11 - MOVB R11, (AX) - MOVL DI, 1(AX) - ADDQ $0x05, AX + XORL SI, SI + LEAL -1(SI)(R12*4), R12 + MOVB R12, (CX) + MOVL R8, 1(CX) + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm: - CMPL R11, $0x40 + CMPL R12, $0x40 JBE two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm - MOVB $0xee, (AX) - MOVW DI, 1(AX) - LEAL -60(R11), R11 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm: - MOVL R11, BX - SHLL $0x02, BX - CMPL R11, $0x0c + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm - LEAL -15(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm: - LEAL -2(BX), BX - MOVB BL, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeSnappyBetterBlockAsm - CMPQ AX, (SP) + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeSnappyBetterBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeSnappyBetterBlockAsm: - MOVQ $0x00cf1bbcdcbfa563, BX - MOVQ $0x9e3779b1, DI - LEAQ 1(SI), SI - LEAQ -2(CX), R8 - MOVQ (DX)(SI*1), R9 - MOVQ 1(DX)(SI*1), R10 - MOVQ (DX)(R8*1), R11 - MOVQ 1(DX)(R8*1), R12 - SHLQ $0x08, R9 - IMULQ BX, R9 - SHRQ $0x2f, R9 - SHLQ $0x20, R10 - IMULQ DI, R10 - SHRQ $0x32, R10 - SHLQ $0x08, R11 - IMULQ BX, R11 - SHRQ $0x2f, R11 - SHLQ $0x20, R12 - IMULQ DI, R12 - SHRQ $0x32, R12 - LEAQ 1(SI), DI - LEAQ 1(R8), R13 - MOVL SI, 24(SP)(R9*4) - MOVL R8, 24(SP)(R11*4) - MOVL DI, 524312(SP)(R10*4) - MOVL R13, 524312(SP)(R12*4) - LEAQ 1(R8)(SI*1), DI - SHRQ $0x01, DI - ADDQ $0x01, SI - SUBQ $0x01, R8 + MOVQ $0x00cf1bbcdcbfa563, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x2f, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x32, R11 + SHLQ $0x08, R12 + IMULQ SI, R12 + SHRQ $0x2f, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x32, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 524288(AX)(R11*4) + MOVL R14, 524288(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 index_loop_encodeSnappyBetterBlockAsm: - CMPQ DI, R8 + CMPQ R8, R9 JAE search_loop_encodeSnappyBetterBlockAsm - MOVQ (DX)(SI*1), R9 - MOVQ (DX)(DI*1), R10 - SHLQ $0x08, R9 - IMULQ BX, R9 - SHRQ $0x2f, R9 + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 SHLQ $0x08, R10 - IMULQ BX, R10 + IMULQ SI, R10 SHRQ $0x2f, R10 - MOVL SI, 24(SP)(R9*4) - MOVL DI, 24(SP)(R10*4) - ADDQ $0x02, SI + SHLQ $0x08, R11 + IMULQ SI, R11 + SHRQ $0x2f, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) ADDQ $0x02, DI + ADDQ $0x02, R8 JMP index_loop_encodeSnappyBetterBlockAsm emit_remainder_encodeSnappyBetterBlockAsm: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 5(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 5(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeSnappyBetterBlockAsm - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeSnappyBetterBlockAsm: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeSnappyBetterBlockAsm @@ -15485,41 +15501,41 @@ emit_remainder_ok_encodeSnappyBetterBlockAsm: JB three_bytes_emit_remainder_encodeSnappyBetterBlockAsm CMPL DX, $0x01000000 JB four_bytes_emit_remainder_encodeSnappyBetterBlockAsm - MOVB $0xfc, (AX) - MOVL DX, 1(AX) - ADDQ $0x05, AX + MOVB $0xfc, (CX) + MOVL DX, 1(CX) + ADDQ $0x05, CX JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm four_bytes_emit_remainder_encodeSnappyBetterBlockAsm: MOVL DX, BX SHRL $0x10, BX - MOVB $0xf8, (AX) - MOVW DX, 1(AX) - MOVB BL, 3(AX) - ADDQ $0x04, AX + MOVB $0xf8, (CX) + MOVW DX, 1(CX) + MOVB BL, 3(CX) + ADDQ $0x04, CX JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm three_bytes_emit_remainder_encodeSnappyBetterBlockAsm: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm two_bytes_emit_remainder_encodeSnappyBetterBlockAsm: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeSnappyBetterBlockAsm JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm one_byte_emit_remainder_encodeSnappyBetterBlockAsm: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeSnappyBetterBlockAsm: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -15535,73 +15551,73 @@ memmove_emit_remainder_encodeSnappyBetterBlockAsm: JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm memmove_long_emit_remainder_encodeSnappyBetterBlockAsm: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_big_loop_back: MOVOU (SI), X4 @@ -15615,463 +15631,464 @@ emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_big_loop_ba JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeSnappyBetterBlockAsm64K(dst []byte, src []byte) int +// func encodeSnappyBetterBlockAsm64K(dst []byte, src []byte, tmp *[294912]byte) int // Requires: BMI, SSE2 -TEXT ·encodeSnappyBetterBlockAsm64K(SB), $327704-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000a00, CX - LEAQ 24(SP), DX +TEXT ·encodeSnappyBetterBlockAsm64K(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000900, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeSnappyBetterBlockAsm64K: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeSnappyBetterBlockAsm64K MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX MOVL $0x00000000, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_base+24(FP), BX search_loop_encodeSnappyBetterBlockAsm64K: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x07, BX - LEAL 1(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x07, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeSnappyBetterBlockAsm64K - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x00cf1bbcdcbfa563, R8 - MOVQ $0x9e3779b1, BX - MOVQ SI, R9 - MOVQ SI, R10 - SHLQ $0x08, R9 - IMULQ R8, R9 - SHRQ $0x30, R9 - SHLQ $0x20, R10 - IMULQ BX, R10 - SHRQ $0x32, R10 - MOVL 24(SP)(R9*4), BX - MOVL 262168(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - MOVL CX, 262168(SP)(R10*4) - MOVQ (DX)(BX*1), R9 - MOVQ (DX)(DI*1), R10 - CMPQ R9, SI + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x00cf1bbcdcbfa563, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x30, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x33, R11 + MOVL (AX)(R10*4), SI + MOVL 262144(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 262144(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI JEQ candidate_match_encodeSnappyBetterBlockAsm64K - CMPQ R10, SI + CMPQ R11, DI JNE no_short_found_encodeSnappyBetterBlockAsm64K - MOVL DI, BX + MOVL R8, SI JMP candidate_match_encodeSnappyBetterBlockAsm64K no_short_found_encodeSnappyBetterBlockAsm64K: - CMPL R9, SI + CMPL R10, DI JEQ candidate_match_encodeSnappyBetterBlockAsm64K - CMPL R10, SI + CMPL R11, DI JEQ candidateS_match_encodeSnappyBetterBlockAsm64K - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeSnappyBetterBlockAsm64K candidateS_match_encodeSnappyBetterBlockAsm64K: - SHRQ $0x08, SI - MOVQ SI, R9 - SHLQ $0x08, R9 - IMULQ R8, R9 - SHRQ $0x30, R9 - MOVL 24(SP)(R9*4), BX - INCL CX - MOVL CX, 24(SP)(R9*4) - CMPL (DX)(BX*1), SI + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x08, R10 + IMULQ R9, R10 + SHRQ $0x30, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeSnappyBetterBlockAsm64K - DECL CX - MOVL DI, BX + DECL DX + MOVL R8, SI candidate_match_encodeSnappyBetterBlockAsm64K: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeSnappyBetterBlockAsm64K match_extend_back_loop_encodeSnappyBetterBlockAsm64K: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeSnappyBetterBlockAsm64K - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeSnappyBetterBlockAsm64K - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeSnappyBetterBlockAsm64K JMP match_extend_back_loop_encodeSnappyBetterBlockAsm64K match_extend_back_end_encodeSnappyBetterBlockAsm64K: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeSnappyBetterBlockAsm64K - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeSnappyBetterBlockAsm64K: - MOVL CX, SI - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), R9 + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm64K: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm64K - MOVQ (R8)(R11*1), R10 - MOVQ 8(R8)(R11*1), R12 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm64K - XORQ 8(R9)(R11*1), R12 + XORQ 8(R10)(R12*1), R13 JNZ matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm64K - LEAL -16(DI), DI - LEAL 16(R11), R11 + LEAL -16(R8), R8 + LEAL 16(R12), R12 JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm64K matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm64K: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP match_nolit_end_encodeSnappyBetterBlockAsm64K matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm64K: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm64K - MOVQ (R8)(R11*1), R10 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm64K - LEAL -8(DI), DI - LEAL 8(R11), R11 + LEAL -8(R8), R8 + LEAL 8(R12), R12 JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm64K matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm64K: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP match_nolit_end_encodeSnappyBetterBlockAsm64K matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm64K: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm64K - MOVL (R8)(R11*1), R10 - CMPL (R9)(R11*1), R10 + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 JNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm64K - LEAL -4(DI), DI - LEAL 4(R11), R11 + LEAL -4(R8), R8 + LEAL 4(R12), R12 matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm64K: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm64K JB match_nolit_end_encodeSnappyBetterBlockAsm64K - MOVW (R8)(R11*1), R10 - CMPW (R9)(R11*1), R10 + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 JNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm64K - LEAL 2(R11), R11 - SUBL $0x02, DI + LEAL 2(R12), R12 + SUBL $0x02, R8 JZ match_nolit_end_encodeSnappyBetterBlockAsm64K matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm64K: - MOVB (R8)(R11*1), R10 - CMPB (R9)(R11*1), R10 + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 JNE match_nolit_end_encodeSnappyBetterBlockAsm64K - LEAL 1(R11), R11 + LEAL 1(R12), R12 match_nolit_end_encodeSnappyBetterBlockAsm64K: - MOVL CX, DI - SUBL BX, DI + MOVL DX, R8 + SUBL SI, R8 // Check if repeat - MOVL DI, 16(SP) - MOVL 12(SP), BX - CMPL BX, SI + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm64K - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_encodeSnappyBetterBlockAsm64K - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_encodeSnappyBetterBlockAsm64K JB three_bytes_match_emit_encodeSnappyBetterBlockAsm64K three_bytes_match_emit_encodeSnappyBetterBlockAsm64K: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm64K two_bytes_match_emit_encodeSnappyBetterBlockAsm64K: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_encodeSnappyBetterBlockAsm64K JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm64K one_byte_match_emit_encodeSnappyBetterBlockAsm64K: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeSnappyBetterBlockAsm64K: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_33through64 emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8: - MOVQ (R9), R10 - MOVQ R10, (AX) + MOVQ (R10), R11 + MOVQ R11, (CX) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm64K memmove_long_match_emit_encodeSnappyBetterBlockAsm64K: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_big_loop_back - -emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32: + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_encodeSnappyBetterBlockAsm64K: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitCopy two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm64K: - CMPL R11, $0x40 + CMPL R12, $0x40 JBE two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm64K - MOVB $0xee, (AX) - MOVW DI, 1(AX) - LEAL -60(R11), R11 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm64K two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm64K: - MOVL R11, BX - SHLL $0x02, BX - CMPL R11, $0x0c + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm64K - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm64K - LEAL -15(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm64K emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm64K: - LEAL -2(BX), BX - MOVB BL, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm64K: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeSnappyBetterBlockAsm64K - CMPQ AX, (SP) + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeSnappyBetterBlockAsm64K - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeSnappyBetterBlockAsm64K: - MOVQ $0x00cf1bbcdcbfa563, BX - MOVQ $0x9e3779b1, DI - LEAQ 1(SI), SI - LEAQ -2(CX), R8 - MOVQ (DX)(SI*1), R9 - MOVQ 1(DX)(SI*1), R10 - MOVQ (DX)(R8*1), R11 - MOVQ 1(DX)(R8*1), R12 - SHLQ $0x08, R9 - IMULQ BX, R9 - SHRQ $0x30, R9 - SHLQ $0x20, R10 - IMULQ DI, R10 - SHRQ $0x32, R10 - SHLQ $0x08, R11 - IMULQ BX, R11 - SHRQ $0x30, R11 - SHLQ $0x20, R12 - IMULQ DI, R12 - SHRQ $0x32, R12 - LEAQ 1(SI), DI - LEAQ 1(R8), R13 - MOVL SI, 24(SP)(R9*4) - MOVL R8, 24(SP)(R11*4) - MOVL DI, 262168(SP)(R10*4) - MOVL R13, 262168(SP)(R12*4) - LEAQ 1(R8)(SI*1), DI - SHRQ $0x01, DI - ADDQ $0x01, SI - SUBQ $0x01, R8 + MOVQ $0x00cf1bbcdcbfa563, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x08, R10 + IMULQ SI, R10 + SHRQ $0x30, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x33, R11 + SHLQ $0x08, R12 + IMULQ SI, R12 + SHRQ $0x30, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x33, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 262144(AX)(R11*4) + MOVL R14, 262144(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 index_loop_encodeSnappyBetterBlockAsm64K: - CMPQ DI, R8 + CMPQ R8, R9 JAE search_loop_encodeSnappyBetterBlockAsm64K - MOVQ (DX)(SI*1), R9 - MOVQ (DX)(DI*1), R10 - SHLQ $0x08, R9 - IMULQ BX, R9 - SHRQ $0x30, R9 + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 SHLQ $0x08, R10 - IMULQ BX, R10 + IMULQ SI, R10 SHRQ $0x30, R10 - MOVL SI, 24(SP)(R9*4) - MOVL DI, 24(SP)(R10*4) - ADDQ $0x02, SI + SHLQ $0x08, R11 + IMULQ SI, R11 + SHRQ $0x30, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) ADDQ $0x02, DI + ADDQ $0x02, R8 JMP index_loop_encodeSnappyBetterBlockAsm64K emit_remainder_encodeSnappyBetterBlockAsm64K: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeSnappyBetterBlockAsm64K - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeSnappyBetterBlockAsm64K: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm64K - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeSnappyBetterBlockAsm64K @@ -16080,26 +16097,26 @@ emit_remainder_ok_encodeSnappyBetterBlockAsm64K: JB three_bytes_emit_remainder_encodeSnappyBetterBlockAsm64K three_bytes_emit_remainder_encodeSnappyBetterBlockAsm64K: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64K two_bytes_emit_remainder_encodeSnappyBetterBlockAsm64K: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeSnappyBetterBlockAsm64K JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64K one_byte_emit_remainder_encodeSnappyBetterBlockAsm64K: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeSnappyBetterBlockAsm64K: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -16115,73 +16132,73 @@ memmove_emit_remainder_encodeSnappyBetterBlockAsm64K: JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm64K memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64K: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_big_loop_back: MOVOU (SI), X4 @@ -16195,463 +16212,464 @@ emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_big_loop JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm64K: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeSnappyBetterBlockAsm12B(dst []byte, src []byte) int +// func encodeSnappyBetterBlockAsm12B(dst []byte, src []byte, tmp *[81920]byte) int // Requires: BMI, SSE2 -TEXT ·encodeSnappyBetterBlockAsm12B(SB), $81944-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000280, CX - LEAQ 24(SP), DX +TEXT ·encodeSnappyBetterBlockAsm12B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000280, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeSnappyBetterBlockAsm12B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeSnappyBetterBlockAsm12B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX MOVL $0x00000000, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_base+24(FP), BX search_loop_encodeSnappyBetterBlockAsm12B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x06, BX - LEAL 1(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x06, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeSnappyBetterBlockAsm12B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ $0x9e3779b1, BX - MOVQ SI, R9 - MOVQ SI, R10 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 - SHLQ $0x20, R10 - IMULQ BX, R10 - SHRQ $0x34, R10 - MOVL 24(SP)(R9*4), BX - MOVL 65560(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - MOVL CX, 65560(SP)(R10*4) - MOVQ (DX)(BX*1), R9 - MOVQ (DX)(DI*1), R10 - CMPQ R9, SI + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x34, R11 + MOVL (AX)(R10*4), SI + MOVL 65536(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 65536(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI JEQ candidate_match_encodeSnappyBetterBlockAsm12B - CMPQ R10, SI + CMPQ R11, DI JNE no_short_found_encodeSnappyBetterBlockAsm12B - MOVL DI, BX + MOVL R8, SI JMP candidate_match_encodeSnappyBetterBlockAsm12B no_short_found_encodeSnappyBetterBlockAsm12B: - CMPL R9, SI + CMPL R10, DI JEQ candidate_match_encodeSnappyBetterBlockAsm12B - CMPL R10, SI + CMPL R11, DI JEQ candidateS_match_encodeSnappyBetterBlockAsm12B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeSnappyBetterBlockAsm12B candidateS_match_encodeSnappyBetterBlockAsm12B: - SHRQ $0x08, SI - MOVQ SI, R9 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x32, R9 - MOVL 24(SP)(R9*4), BX - INCL CX - MOVL CX, 24(SP)(R9*4) - CMPL (DX)(BX*1), SI + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x32, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeSnappyBetterBlockAsm12B - DECL CX - MOVL DI, BX + DECL DX + MOVL R8, SI candidate_match_encodeSnappyBetterBlockAsm12B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeSnappyBetterBlockAsm12B match_extend_back_loop_encodeSnappyBetterBlockAsm12B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeSnappyBetterBlockAsm12B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeSnappyBetterBlockAsm12B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeSnappyBetterBlockAsm12B JMP match_extend_back_loop_encodeSnappyBetterBlockAsm12B match_extend_back_end_encodeSnappyBetterBlockAsm12B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeSnappyBetterBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeSnappyBetterBlockAsm12B: - MOVL CX, SI - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), R9 + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm12B: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm12B - MOVQ (R8)(R11*1), R10 - MOVQ 8(R8)(R11*1), R12 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm12B - XORQ 8(R9)(R11*1), R12 + XORQ 8(R10)(R12*1), R13 JNZ matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm12B - LEAL -16(DI), DI - LEAL 16(R11), R11 + LEAL -16(R8), R8 + LEAL 16(R12), R12 JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm12B matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP match_nolit_end_encodeSnappyBetterBlockAsm12B matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm12B: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm12B - MOVQ (R8)(R11*1), R10 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm12B - LEAL -8(DI), DI - LEAL 8(R11), R11 + LEAL -8(R8), R8 + LEAL 8(R12), R12 JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm12B matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm12B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP match_nolit_end_encodeSnappyBetterBlockAsm12B matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm12B: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm12B - MOVL (R8)(R11*1), R10 - CMPL (R9)(R11*1), R10 + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 JNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm12B - LEAL -4(DI), DI - LEAL 4(R11), R11 + LEAL -4(R8), R8 + LEAL 4(R12), R12 matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm12B: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm12B JB match_nolit_end_encodeSnappyBetterBlockAsm12B - MOVW (R8)(R11*1), R10 - CMPW (R9)(R11*1), R10 + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 JNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm12B - LEAL 2(R11), R11 - SUBL $0x02, DI + LEAL 2(R12), R12 + SUBL $0x02, R8 JZ match_nolit_end_encodeSnappyBetterBlockAsm12B matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm12B: - MOVB (R8)(R11*1), R10 - CMPB (R9)(R11*1), R10 + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 JNE match_nolit_end_encodeSnappyBetterBlockAsm12B - LEAL 1(R11), R11 + LEAL 1(R12), R12 match_nolit_end_encodeSnappyBetterBlockAsm12B: - MOVL CX, DI - SUBL BX, DI + MOVL DX, R8 + SUBL SI, R8 // Check if repeat - MOVL DI, 16(SP) - MOVL 12(SP), BX - CMPL BX, SI + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm12B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_encodeSnappyBetterBlockAsm12B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_encodeSnappyBetterBlockAsm12B JB three_bytes_match_emit_encodeSnappyBetterBlockAsm12B three_bytes_match_emit_encodeSnappyBetterBlockAsm12B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm12B two_bytes_match_emit_encodeSnappyBetterBlockAsm12B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_encodeSnappyBetterBlockAsm12B JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm12B one_byte_match_emit_encodeSnappyBetterBlockAsm12B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeSnappyBetterBlockAsm12B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8: - MOVQ (R9), R10 - MOVQ R10, (AX) + MOVQ (R10), R11 + MOVQ R11, (CX) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm12B memmove_long_match_emit_encodeSnappyBetterBlockAsm12B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_encodeSnappyBetterBlockAsm12B: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitCopy two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm12B: - CMPL R11, $0x40 + CMPL R12, $0x40 JBE two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm12B - MOVB $0xee, (AX) - MOVW DI, 1(AX) - LEAL -60(R11), R11 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm12B two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm12B: - MOVL R11, BX - SHLL $0x02, BX - CMPL R11, $0x0c + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm12B - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm12B - LEAL -15(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm12B emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm12B: - LEAL -2(BX), BX - MOVB BL, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm12B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeSnappyBetterBlockAsm12B - CMPQ AX, (SP) + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeSnappyBetterBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeSnappyBetterBlockAsm12B: - MOVQ $0x0000cf1bbcdcbf9b, BX - MOVQ $0x9e3779b1, DI - LEAQ 1(SI), SI - LEAQ -2(CX), R8 - MOVQ (DX)(SI*1), R9 - MOVQ 1(DX)(SI*1), R10 - MOVQ (DX)(R8*1), R11 - MOVQ 1(DX)(R8*1), R12 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x32, R9 - SHLQ $0x20, R10 - IMULQ DI, R10 - SHRQ $0x34, R10 - SHLQ $0x10, R11 - IMULQ BX, R11 - SHRQ $0x32, R11 - SHLQ $0x20, R12 - IMULQ DI, R12 - SHRQ $0x34, R12 - LEAQ 1(SI), DI - LEAQ 1(R8), R13 - MOVL SI, 24(SP)(R9*4) - MOVL R8, 24(SP)(R11*4) - MOVL DI, 65560(SP)(R10*4) - MOVL R13, 65560(SP)(R12*4) - LEAQ 1(R8)(SI*1), DI - SHRQ $0x01, DI - ADDQ $0x01, SI - SUBQ $0x01, R8 + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x32, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x34, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x32, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x34, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 65536(AX)(R11*4) + MOVL R14, 65536(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 index_loop_encodeSnappyBetterBlockAsm12B: - CMPQ DI, R8 + CMPQ R8, R9 JAE search_loop_encodeSnappyBetterBlockAsm12B - MOVQ (DX)(SI*1), R9 - MOVQ (DX)(DI*1), R10 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x32, R9 + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 SHLQ $0x10, R10 - IMULQ BX, R10 + IMULQ SI, R10 SHRQ $0x32, R10 - MOVL SI, 24(SP)(R9*4) - MOVL DI, 24(SP)(R10*4) - ADDQ $0x02, SI + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x32, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) ADDQ $0x02, DI + ADDQ $0x02, R8 JMP index_loop_encodeSnappyBetterBlockAsm12B emit_remainder_encodeSnappyBetterBlockAsm12B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeSnappyBetterBlockAsm12B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeSnappyBetterBlockAsm12B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm12B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeSnappyBetterBlockAsm12B @@ -16660,26 +16678,26 @@ emit_remainder_ok_encodeSnappyBetterBlockAsm12B: JB three_bytes_emit_remainder_encodeSnappyBetterBlockAsm12B three_bytes_emit_remainder_encodeSnappyBetterBlockAsm12B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12B two_bytes_emit_remainder_encodeSnappyBetterBlockAsm12B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeSnappyBetterBlockAsm12B JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12B one_byte_emit_remainder_encodeSnappyBetterBlockAsm12B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeSnappyBetterBlockAsm12B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -16695,73 +16713,73 @@ memmove_emit_remainder_encodeSnappyBetterBlockAsm12B: JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) - JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B - -emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_33through64: + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm12B memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_big_loop_back: MOVOU (SI), X4 @@ -16775,463 +16793,464 @@ emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_big_loop JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm12B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeSnappyBetterBlockAsm10B(dst []byte, src []byte) int +// func encodeSnappyBetterBlockAsm10B(dst []byte, src []byte, tmp *[20480]byte) int // Requires: BMI, SSE2 -TEXT ·encodeSnappyBetterBlockAsm10B(SB), $20504-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x000000a0, CX - LEAQ 24(SP), DX +TEXT ·encodeSnappyBetterBlockAsm10B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x000000a0, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeSnappyBetterBlockAsm10B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeSnappyBetterBlockAsm10B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX MOVL $0x00000000, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_base+24(FP), BX search_loop_encodeSnappyBetterBlockAsm10B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x05, BX - LEAL 1(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeSnappyBetterBlockAsm10B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ $0x9e3779b1, BX - MOVQ SI, R9 - MOVQ SI, R10 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x34, R9 - SHLQ $0x20, R10 - IMULQ BX, R10 - SHRQ $0x36, R10 - MOVL 24(SP)(R9*4), BX - MOVL 16408(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - MOVL CX, 16408(SP)(R10*4) - MOVQ (DX)(BX*1), R9 - MOVQ (DX)(DI*1), R10 - CMPQ R9, SI + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x36, R11 + MOVL (AX)(R10*4), SI + MOVL 16384(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 16384(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI JEQ candidate_match_encodeSnappyBetterBlockAsm10B - CMPQ R10, SI + CMPQ R11, DI JNE no_short_found_encodeSnappyBetterBlockAsm10B - MOVL DI, BX + MOVL R8, SI JMP candidate_match_encodeSnappyBetterBlockAsm10B no_short_found_encodeSnappyBetterBlockAsm10B: - CMPL R9, SI + CMPL R10, DI JEQ candidate_match_encodeSnappyBetterBlockAsm10B - CMPL R10, SI + CMPL R11, DI JEQ candidateS_match_encodeSnappyBetterBlockAsm10B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeSnappyBetterBlockAsm10B candidateS_match_encodeSnappyBetterBlockAsm10B: - SHRQ $0x08, SI - MOVQ SI, R9 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x34, R9 - MOVL 24(SP)(R9*4), BX - INCL CX - MOVL CX, 24(SP)(R9*4) - CMPL (DX)(BX*1), SI + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x34, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeSnappyBetterBlockAsm10B - DECL CX - MOVL DI, BX + DECL DX + MOVL R8, SI candidate_match_encodeSnappyBetterBlockAsm10B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeSnappyBetterBlockAsm10B match_extend_back_loop_encodeSnappyBetterBlockAsm10B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeSnappyBetterBlockAsm10B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeSnappyBetterBlockAsm10B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeSnappyBetterBlockAsm10B JMP match_extend_back_loop_encodeSnappyBetterBlockAsm10B match_extend_back_end_encodeSnappyBetterBlockAsm10B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeSnappyBetterBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeSnappyBetterBlockAsm10B: - MOVL CX, SI - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), R9 + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm10B: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm10B - MOVQ (R8)(R11*1), R10 - MOVQ 8(R8)(R11*1), R12 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm10B - XORQ 8(R9)(R11*1), R12 + XORQ 8(R10)(R12*1), R13 JNZ matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm10B - LEAL -16(DI), DI - LEAL 16(R11), R11 + LEAL -16(R8), R8 + LEAL 16(R12), R12 JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm10B matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP match_nolit_end_encodeSnappyBetterBlockAsm10B matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm10B: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm10B - MOVQ (R8)(R11*1), R10 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm10B - LEAL -8(DI), DI - LEAL 8(R11), R11 + LEAL -8(R8), R8 + LEAL 8(R12), R12 JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm10B matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm10B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP match_nolit_end_encodeSnappyBetterBlockAsm10B matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm10B: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm10B - MOVL (R8)(R11*1), R10 - CMPL (R9)(R11*1), R10 + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 JNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm10B - LEAL -4(DI), DI - LEAL 4(R11), R11 + LEAL -4(R8), R8 + LEAL 4(R12), R12 matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm10B: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm10B JB match_nolit_end_encodeSnappyBetterBlockAsm10B - MOVW (R8)(R11*1), R10 - CMPW (R9)(R11*1), R10 + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 JNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm10B - LEAL 2(R11), R11 - SUBL $0x02, DI + LEAL 2(R12), R12 + SUBL $0x02, R8 JZ match_nolit_end_encodeSnappyBetterBlockAsm10B matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm10B: - MOVB (R8)(R11*1), R10 - CMPB (R9)(R11*1), R10 + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 JNE match_nolit_end_encodeSnappyBetterBlockAsm10B - LEAL 1(R11), R11 + LEAL 1(R12), R12 match_nolit_end_encodeSnappyBetterBlockAsm10B: - MOVL CX, DI - SUBL BX, DI + MOVL DX, R8 + SUBL SI, R8 // Check if repeat - MOVL DI, 16(SP) - MOVL 12(SP), BX - CMPL BX, SI + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm10B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_encodeSnappyBetterBlockAsm10B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_encodeSnappyBetterBlockAsm10B JB three_bytes_match_emit_encodeSnappyBetterBlockAsm10B three_bytes_match_emit_encodeSnappyBetterBlockAsm10B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm10B two_bytes_match_emit_encodeSnappyBetterBlockAsm10B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_encodeSnappyBetterBlockAsm10B JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm10B one_byte_match_emit_encodeSnappyBetterBlockAsm10B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeSnappyBetterBlockAsm10B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8: - MOVQ (R9), R10 - MOVQ R10, (AX) + MOVQ (R10), R11 + MOVQ R11, (CX) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm10B memmove_long_match_emit_encodeSnappyBetterBlockAsm10B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_encodeSnappyBetterBlockAsm10B: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitCopy two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm10B: - CMPL R11, $0x40 + CMPL R12, $0x40 JBE two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm10B - MOVB $0xee, (AX) - MOVW DI, 1(AX) - LEAL -60(R11), R11 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm10B two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm10B: - MOVL R11, BX - SHLL $0x02, BX - CMPL R11, $0x0c + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm10B - CMPL DI, $0x00000800 + CMPL R8, $0x00000800 JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm10B - LEAL -15(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm10B emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm10B: - LEAL -2(BX), BX - MOVB BL, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm10B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeSnappyBetterBlockAsm10B - CMPQ AX, (SP) + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeSnappyBetterBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeSnappyBetterBlockAsm10B: - MOVQ $0x0000cf1bbcdcbf9b, BX - MOVQ $0x9e3779b1, DI - LEAQ 1(SI), SI - LEAQ -2(CX), R8 - MOVQ (DX)(SI*1), R9 - MOVQ 1(DX)(SI*1), R10 - MOVQ (DX)(R8*1), R11 - MOVQ 1(DX)(R8*1), R12 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x34, R9 - SHLQ $0x20, R10 - IMULQ DI, R10 - SHRQ $0x36, R10 - SHLQ $0x10, R11 - IMULQ BX, R11 - SHRQ $0x34, R11 - SHLQ $0x20, R12 - IMULQ DI, R12 - SHRQ $0x36, R12 - LEAQ 1(SI), DI - LEAQ 1(R8), R13 - MOVL SI, 24(SP)(R9*4) - MOVL R8, 24(SP)(R11*4) - MOVL DI, 16408(SP)(R10*4) - MOVL R13, 16408(SP)(R12*4) - LEAQ 1(R8)(SI*1), DI - SHRQ $0x01, DI - ADDQ $0x01, SI - SUBQ $0x01, R8 + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x34, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x36, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x34, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x36, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 16384(AX)(R11*4) + MOVL R14, 16384(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 index_loop_encodeSnappyBetterBlockAsm10B: - CMPQ DI, R8 + CMPQ R8, R9 JAE search_loop_encodeSnappyBetterBlockAsm10B - MOVQ (DX)(SI*1), R9 - MOVQ (DX)(DI*1), R10 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x34, R9 + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 SHLQ $0x10, R10 - IMULQ BX, R10 + IMULQ SI, R10 SHRQ $0x34, R10 - MOVL SI, 24(SP)(R9*4) - MOVL DI, 24(SP)(R10*4) - ADDQ $0x02, SI + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x34, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) ADDQ $0x02, DI + ADDQ $0x02, R8 JMP index_loop_encodeSnappyBetterBlockAsm10B emit_remainder_encodeSnappyBetterBlockAsm10B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeSnappyBetterBlockAsm10B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeSnappyBetterBlockAsm10B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm10B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeSnappyBetterBlockAsm10B @@ -17240,26 +17259,26 @@ emit_remainder_ok_encodeSnappyBetterBlockAsm10B: JB three_bytes_emit_remainder_encodeSnappyBetterBlockAsm10B three_bytes_emit_remainder_encodeSnappyBetterBlockAsm10B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10B two_bytes_emit_remainder_encodeSnappyBetterBlockAsm10B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeSnappyBetterBlockAsm10B JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10B one_byte_emit_remainder_encodeSnappyBetterBlockAsm10B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeSnappyBetterBlockAsm10B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -17275,73 +17294,73 @@ memmove_emit_remainder_encodeSnappyBetterBlockAsm10B: JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm10B memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_big_loop_back: MOVOU (SI), X4 @@ -17355,461 +17374,462 @@ emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_big_loop JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm10B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func encodeSnappyBetterBlockAsm8B(dst []byte, src []byte) int +// func encodeSnappyBetterBlockAsm8B(dst []byte, src []byte, tmp *[5120]byte) int // Requires: BMI, SSE2 -TEXT ·encodeSnappyBetterBlockAsm8B(SB), $5144-56 - MOVQ dst_base+0(FP), AX - MOVQ $0x00000028, CX - LEAQ 24(SP), DX +TEXT ·encodeSnappyBetterBlockAsm8B(SB), $24-64 + MOVQ tmp+48(FP), AX + MOVQ dst_base+0(FP), CX + MOVQ $0x00000028, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_encodeSnappyBetterBlockAsm8B: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_encodeSnappyBetterBlockAsm8B MOVL $0x00000000, 12(SP) - MOVQ src_len+32(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX + MOVQ src_len+32(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX MOVL $0x00000000, 16(SP) - MOVQ src_base+24(FP), DX + MOVQ src_base+24(FP), BX search_loop_encodeSnappyBetterBlockAsm8B: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x04, BX - LEAL 1(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x04, SI + LEAL 1(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_encodeSnappyBetterBlockAsm8B - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ $0x9e3779b1, BX - MOVQ SI, R9 - MOVQ SI, R10 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x36, R9 - SHLQ $0x20, R10 - IMULQ BX, R10 - SHRQ $0x38, R10 - MOVL 24(SP)(R9*4), BX - MOVL 4120(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - MOVL CX, 4120(SP)(R10*4) - MOVQ (DX)(BX*1), R9 - MOVQ (DX)(DI*1), R10 - CMPQ R9, SI + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ $0x9e3779b1, SI + MOVQ DI, R10 + MOVQ DI, R11 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + SHLQ $0x20, R11 + IMULQ SI, R11 + SHRQ $0x38, R11 + MOVL (AX)(R10*4), SI + MOVL 4096(AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + MOVL DX, 4096(AX)(R11*4) + MOVQ (BX)(SI*1), R10 + MOVQ (BX)(R8*1), R11 + CMPQ R10, DI JEQ candidate_match_encodeSnappyBetterBlockAsm8B - CMPQ R10, SI + CMPQ R11, DI JNE no_short_found_encodeSnappyBetterBlockAsm8B - MOVL DI, BX + MOVL R8, SI JMP candidate_match_encodeSnappyBetterBlockAsm8B no_short_found_encodeSnappyBetterBlockAsm8B: - CMPL R9, SI + CMPL R10, DI JEQ candidate_match_encodeSnappyBetterBlockAsm8B - CMPL R10, SI + CMPL R11, DI JEQ candidateS_match_encodeSnappyBetterBlockAsm8B - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_encodeSnappyBetterBlockAsm8B candidateS_match_encodeSnappyBetterBlockAsm8B: - SHRQ $0x08, SI - MOVQ SI, R9 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x36, R9 - MOVL 24(SP)(R9*4), BX - INCL CX - MOVL CX, 24(SP)(R9*4) - CMPL (DX)(BX*1), SI + SHRQ $0x08, DI + MOVQ DI, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x36, R10 + MOVL (AX)(R10*4), SI + INCL DX + MOVL DX, (AX)(R10*4) + CMPL (BX)(SI*1), DI JEQ candidate_match_encodeSnappyBetterBlockAsm8B - DECL CX - MOVL DI, BX + DECL DX + MOVL R8, SI candidate_match_encodeSnappyBetterBlockAsm8B: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_encodeSnappyBetterBlockAsm8B match_extend_back_loop_encodeSnappyBetterBlockAsm8B: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_encodeSnappyBetterBlockAsm8B - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_encodeSnappyBetterBlockAsm8B - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_encodeSnappyBetterBlockAsm8B JMP match_extend_back_loop_encodeSnappyBetterBlockAsm8B match_extend_back_end_encodeSnappyBetterBlockAsm8B: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_encodeSnappyBetterBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_dst_size_check_encodeSnappyBetterBlockAsm8B: - MOVL CX, SI - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+32(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), R9 + MOVL DX, DI + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+32(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), R10 // matchLen - XORL R11, R11 + XORL R12, R12 matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm8B: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm8B - MOVQ (R8)(R11*1), R10 - MOVQ 8(R8)(R11*1), R12 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + MOVQ 8(R9)(R12*1), R13 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm8B - XORQ 8(R9)(R11*1), R12 + XORQ 8(R10)(R12*1), R13 JNZ matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm8B - LEAL -16(DI), DI - LEAL 16(R11), R11 + LEAL -16(R8), R8 + LEAL 16(R12), R12 JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm8B matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R12, R12 + TZCNTQ R13, R13 #else - BSFQ R12, R12 + BSFQ R13, R13 #endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 JMP match_nolit_end_encodeSnappyBetterBlockAsm8B matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm8B: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm8B - MOVQ (R8)(R11*1), R10 - XORQ (R9)(R11*1), R10 + MOVQ (R9)(R12*1), R11 + XORQ (R10)(R12*1), R11 JNZ matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm8B - LEAL -8(DI), DI - LEAL 8(R11), R11 + LEAL -8(R8), R8 + LEAL 8(R12), R12 JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm8B matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm8B: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 JMP match_nolit_end_encodeSnappyBetterBlockAsm8B matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm8B: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm8B - MOVL (R8)(R11*1), R10 - CMPL (R9)(R11*1), R10 - JNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm8B - LEAL -4(DI), DI - LEAL 4(R11), R11 + MOVL (R9)(R12*1), R11 + CMPL (R10)(R12*1), R11 + JNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm8B + LEAL -4(R8), R8 + LEAL 4(R12), R12 matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm8B: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm8B JB match_nolit_end_encodeSnappyBetterBlockAsm8B - MOVW (R8)(R11*1), R10 - CMPW (R9)(R11*1), R10 + MOVW (R9)(R12*1), R11 + CMPW (R10)(R12*1), R11 JNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm8B - LEAL 2(R11), R11 - SUBL $0x02, DI + LEAL 2(R12), R12 + SUBL $0x02, R8 JZ match_nolit_end_encodeSnappyBetterBlockAsm8B matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm8B: - MOVB (R8)(R11*1), R10 - CMPB (R9)(R11*1), R10 + MOVB (R9)(R12*1), R11 + CMPB (R10)(R12*1), R11 JNE match_nolit_end_encodeSnappyBetterBlockAsm8B - LEAL 1(R11), R11 + LEAL 1(R12), R12 match_nolit_end_encodeSnappyBetterBlockAsm8B: - MOVL CX, DI - SUBL BX, DI + MOVL DX, R8 + SUBL SI, R8 // Check if repeat - MOVL DI, 16(SP) - MOVL 12(SP), BX - CMPL BX, SI + MOVL R8, 16(SP) + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm8B - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R9 - SUBL BX, R8 - LEAL -1(R8), BX - CMPL BX, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R10 + SUBL SI, R9 + LEAL -1(R9), SI + CMPL SI, $0x3c JB one_byte_match_emit_encodeSnappyBetterBlockAsm8B - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_match_emit_encodeSnappyBetterBlockAsm8B JB three_bytes_match_emit_encodeSnappyBetterBlockAsm8B three_bytes_match_emit_encodeSnappyBetterBlockAsm8B: - MOVB $0xf4, (AX) - MOVW BX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW SI, 1(CX) + ADDQ $0x03, CX JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm8B two_bytes_match_emit_encodeSnappyBetterBlockAsm8B: - MOVB $0xf0, (AX) - MOVB BL, 1(AX) - ADDQ $0x02, AX - CMPL BX, $0x40 + MOVB $0xf0, (CX) + MOVB SI, 1(CX) + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_match_emit_encodeSnappyBetterBlockAsm8B JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm8B one_byte_match_emit_encodeSnappyBetterBlockAsm8B: - SHLB $0x02, BL - MOVB BL, (AX) - ADDQ $0x01, AX + SHLB $0x02, SI + MOVB SI, (CX) + ADDQ $0x01, CX memmove_match_emit_encodeSnappyBetterBlockAsm8B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveShort - CMPQ R8, $0x08 + CMPQ R9, $0x08 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8 - CMPQ R8, $0x10 + CMPQ R9, $0x10 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8through16 - CMPQ R8, $0x20 + CMPQ R9, $0x20 JBE emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_17through32 JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_33through64 emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8: - MOVQ (R9), R10 - MOVQ R10, (AX) + MOVQ (R10), R11 + MOVQ R11, (CX) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8through16: - MOVQ (R9), R10 - MOVQ -8(R9)(R8*1), R9 - MOVQ R10, (AX) - MOVQ R9, -8(AX)(R8*1) + MOVQ (R10), R11 + MOVQ -8(R10)(R9*1), R10 + MOVQ R11, (CX) + MOVQ R10, -8(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_17through32: - MOVOU (R9), X0 - MOVOU -16(R9)(R8*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU -16(R10)(R9*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(R9*1) JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_33through64: - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B: - MOVQ BX, AX + MOVQ SI, CX JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm8B memmove_long_match_emit_encodeSnappyBetterBlockAsm8B: - LEAQ (AX)(R8*1), BX + LEAQ (CX)(R9*1), SI // genMemMoveLong - MOVOU (R9), X0 - MOVOU 16(R9), X1 - MOVOU -32(R9)(R8*1), X2 - MOVOU -16(R9)(R8*1), X3 - MOVQ R8, R12 - SHRQ $0x05, R12 - MOVQ AX, R10 - ANDL $0x0000001f, R10 - MOVQ $0x00000040, R13 - SUBQ R10, R13 - DECQ R12 + MOVOU (R10), X0 + MOVOU 16(R10), X1 + MOVOU -32(R10)(R9*1), X2 + MOVOU -16(R10)(R9*1), X3 + MOVQ R9, R13 + SHRQ $0x05, R13 + MOVQ CX, R11 + ANDL $0x0000001f, R11 + MOVQ $0x00000040, R14 + SUBQ R11, R14 + DECQ R13 JA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32 - LEAQ -32(R9)(R13*1), R10 - LEAQ -32(AX)(R13*1), R14 + LEAQ -32(R10)(R14*1), R11 + LEAQ -32(CX)(R14*1), R15 emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_big_loop_back: - MOVOU (R10), X4 - MOVOU 16(R10), X5 - MOVOA X4, (R14) - MOVOA X5, 16(R14) + MOVOU (R11), X4 + MOVOU 16(R11), X5 + MOVOA X4, (R15) + MOVOA X5, 16(R15) + ADDQ $0x20, R15 + ADDQ $0x20, R11 ADDQ $0x20, R14 - ADDQ $0x20, R10 - ADDQ $0x20, R13 - DECQ R12 + DECQ R13 JNA emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_big_loop_back emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32: - MOVOU -32(R9)(R13*1), X4 - MOVOU -16(R9)(R13*1), X5 - MOVOA X4, -32(AX)(R13*1) - MOVOA X5, -16(AX)(R13*1) - ADDQ $0x20, R13 - CMPQ R8, R13 + MOVOU -32(R10)(R14*1), X4 + MOVOU -16(R10)(R14*1), X5 + MOVOA X4, -32(CX)(R14*1) + MOVOA X5, -16(CX)(R14*1) + ADDQ $0x20, R14 + CMPQ R9, R14 JAE emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(R8*1) - MOVOU X3, -16(AX)(R8*1) - MOVQ BX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(R9*1) + MOVOU X3, -16(CX)(R9*1) + MOVQ SI, CX emit_literal_done_match_emit_encodeSnappyBetterBlockAsm8B: - ADDL R11, CX - ADDL $0x04, R11 - MOVL CX, 12(SP) + ADDL R12, DX + ADDL $0x04, R12 + MOVL DX, 12(SP) // emitCopy two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm8B: - CMPL R11, $0x40 + CMPL R12, $0x40 JBE two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm8B - MOVB $0xee, (AX) - MOVW DI, 1(AX) - LEAL -60(R11), R11 - ADDQ $0x03, AX + MOVB $0xee, (CX) + MOVW R8, 1(CX) + LEAL -60(R12), R12 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm8B two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm8B: - MOVL R11, BX - SHLL $0x02, BX - CMPL R11, $0x0c + MOVL R12, SI + SHLL $0x02, SI + CMPL R12, $0x0c JAE emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm8B - LEAL -15(BX), BX - MOVB DI, 1(AX) - SHRL $0x08, DI - SHLL $0x05, DI - ORL DI, BX - MOVB BL, (AX) - ADDQ $0x02, AX + LEAL -15(SI), SI + MOVB R8, 1(CX) + SHRL $0x08, R8 + SHLL $0x05, R8 + ORL R8, SI + MOVB SI, (CX) + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm8B emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm8B: - LEAL -2(BX), BX - MOVB BL, (AX) - MOVW DI, 1(AX) - ADDQ $0x03, AX + LEAL -2(SI), SI + MOVB SI, (CX) + MOVW R8, 1(CX) + ADDQ $0x03, CX match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm8B: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_encodeSnappyBetterBlockAsm8B - CMPQ AX, (SP) + CMPQ CX, (SP) JB match_nolit_dst_ok_encodeSnappyBetterBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET match_nolit_dst_ok_encodeSnappyBetterBlockAsm8B: - MOVQ $0x0000cf1bbcdcbf9b, BX - MOVQ $0x9e3779b1, DI - LEAQ 1(SI), SI - LEAQ -2(CX), R8 - MOVQ (DX)(SI*1), R9 - MOVQ 1(DX)(SI*1), R10 - MOVQ (DX)(R8*1), R11 - MOVQ 1(DX)(R8*1), R12 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x36, R9 - SHLQ $0x20, R10 - IMULQ DI, R10 - SHRQ $0x38, R10 - SHLQ $0x10, R11 - IMULQ BX, R11 - SHRQ $0x36, R11 - SHLQ $0x20, R12 - IMULQ DI, R12 - SHRQ $0x38, R12 - LEAQ 1(SI), DI - LEAQ 1(R8), R13 - MOVL SI, 24(SP)(R9*4) - MOVL R8, 24(SP)(R11*4) - MOVL DI, 4120(SP)(R10*4) - MOVL R13, 4120(SP)(R12*4) - LEAQ 1(R8)(SI*1), DI - SHRQ $0x01, DI - ADDQ $0x01, SI - SUBQ $0x01, R8 + MOVQ $0x0000cf1bbcdcbf9b, SI + MOVQ $0x9e3779b1, R8 + LEAQ 1(DI), DI + LEAQ -2(DX), R9 + MOVQ (BX)(DI*1), R10 + MOVQ 1(BX)(DI*1), R11 + MOVQ (BX)(R9*1), R12 + MOVQ 1(BX)(R9*1), R13 + SHLQ $0x10, R10 + IMULQ SI, R10 + SHRQ $0x36, R10 + SHLQ $0x20, R11 + IMULQ R8, R11 + SHRQ $0x38, R11 + SHLQ $0x10, R12 + IMULQ SI, R12 + SHRQ $0x36, R12 + SHLQ $0x20, R13 + IMULQ R8, R13 + SHRQ $0x38, R13 + LEAQ 1(DI), R8 + LEAQ 1(R9), R14 + MOVL DI, (AX)(R10*4) + MOVL R9, (AX)(R12*4) + MOVL R8, 4096(AX)(R11*4) + MOVL R14, 4096(AX)(R13*4) + LEAQ 1(R9)(DI*1), R8 + SHRQ $0x01, R8 + ADDQ $0x01, DI + SUBQ $0x01, R9 index_loop_encodeSnappyBetterBlockAsm8B: - CMPQ DI, R8 + CMPQ R8, R9 JAE search_loop_encodeSnappyBetterBlockAsm8B - MOVQ (DX)(SI*1), R9 - MOVQ (DX)(DI*1), R10 - SHLQ $0x10, R9 - IMULQ BX, R9 - SHRQ $0x36, R9 + MOVQ (BX)(DI*1), R10 + MOVQ (BX)(R8*1), R11 SHLQ $0x10, R10 - IMULQ BX, R10 + IMULQ SI, R10 SHRQ $0x36, R10 - MOVL SI, 24(SP)(R9*4) - MOVL DI, 24(SP)(R10*4) - ADDQ $0x02, SI + SHLQ $0x10, R11 + IMULQ SI, R11 + SHRQ $0x36, R11 + MOVL DI, (AX)(R10*4) + MOVL R8, (AX)(R11*4) ADDQ $0x02, DI + ADDQ $0x02, R8 JMP index_loop_encodeSnappyBetterBlockAsm8B emit_remainder_encodeSnappyBetterBlockAsm8B: - MOVQ src_len+32(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+32(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_encodeSnappyBetterBlockAsm8B - MOVQ $0x00000000, ret+48(FP) + MOVQ $0x00000000, ret+56(FP) RET emit_remainder_ok_encodeSnappyBetterBlockAsm8B: - MOVQ src_len+32(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+32(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm8B - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI LEAL -1(SI), DX CMPL DX, $0x3c JB one_byte_emit_remainder_encodeSnappyBetterBlockAsm8B @@ -17818,26 +17838,26 @@ emit_remainder_ok_encodeSnappyBetterBlockAsm8B: JB three_bytes_emit_remainder_encodeSnappyBetterBlockAsm8B three_bytes_emit_remainder_encodeSnappyBetterBlockAsm8B: - MOVB $0xf4, (AX) - MOVW DX, 1(AX) - ADDQ $0x03, AX + MOVB $0xf4, (CX) + MOVW DX, 1(CX) + ADDQ $0x03, CX JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8B two_bytes_emit_remainder_encodeSnappyBetterBlockAsm8B: - MOVB $0xf0, (AX) - MOVB DL, 1(AX) - ADDQ $0x02, AX + MOVB $0xf0, (CX) + MOVB DL, 1(CX) + ADDQ $0x02, CX CMPL DX, $0x40 JB memmove_emit_remainder_encodeSnappyBetterBlockAsm8B JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8B one_byte_emit_remainder_encodeSnappyBetterBlockAsm8B: SHLB $0x02, DL - MOVB DL, (AX) - ADDQ $0x01, AX + MOVB DL, (CX) + ADDQ $0x01, CX memmove_emit_remainder_encodeSnappyBetterBlockAsm8B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveShort @@ -17853,73 +17873,73 @@ memmove_emit_remainder_encodeSnappyBetterBlockAsm8B: JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_33through64 emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_1or2: - MOVB (CX), SI - MOVB -1(CX)(BX*1), CL - MOVB SI, (AX) - MOVB CL, -1(AX)(BX*1) + MOVB (AX), SI + MOVB -1(AX)(BX*1), AL + MOVB SI, (CX) + MOVB AL, -1(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_3: - MOVW (CX), SI - MOVB 2(CX), CL - MOVW SI, (AX) - MOVB CL, 2(AX) + MOVW (AX), SI + MOVB 2(AX), AL + MOVW SI, (CX) + MOVB AL, 2(CX) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_4through7: - MOVL (CX), SI - MOVL -4(CX)(BX*1), CX - MOVL SI, (AX) - MOVL CX, -4(AX)(BX*1) + MOVL (AX), SI + MOVL -4(AX)(BX*1), AX + MOVL SI, (CX) + MOVL AX, -4(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_8through16: - MOVQ (CX), SI - MOVQ -8(CX)(BX*1), CX - MOVQ SI, (AX) - MOVQ CX, -8(AX)(BX*1) + MOVQ (AX), SI + MOVQ -8(AX)(BX*1), AX + MOVQ SI, (CX) + MOVQ AX, -8(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_17through32: - MOVOU (CX), X0 - MOVOU -16(CX)(BX*1), X1 - MOVOU X0, (AX) - MOVOU X1, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU -16(AX)(BX*1), X1 + MOVOU X0, (CX) + MOVOU X1, -16(CX)(BX*1) JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_33through64: - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B: - MOVQ DX, AX + MOVQ DX, CX JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm8B memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8B: - LEAQ (AX)(SI*1), DX + LEAQ (CX)(SI*1), DX MOVL SI, BX // genMemMoveLong - MOVOU (CX), X0 - MOVOU 16(CX), X1 - MOVOU -32(CX)(BX*1), X2 - MOVOU -16(CX)(BX*1), X3 + MOVOU (AX), X0 + MOVOU 16(AX), X1 + MOVOU -32(AX)(BX*1), X2 + MOVOU -16(AX)(BX*1), X3 MOVQ BX, DI SHRQ $0x05, DI - MOVQ AX, SI + MOVQ CX, SI ANDL $0x0000001f, SI MOVQ $0x00000040, R8 SUBQ SI, R8 DECQ DI JA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32 - LEAQ -32(CX)(R8*1), SI - LEAQ -32(AX)(R8*1), R9 + LEAQ -32(AX)(R8*1), SI + LEAQ -32(CX)(R8*1), R9 emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_big_loop_back: MOVOU (SI), X4 @@ -17933,1136 +17953,1142 @@ emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_big_loop_ JNA emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_big_loop_back emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32: - MOVOU -32(CX)(R8*1), X4 - MOVOU -16(CX)(R8*1), X5 - MOVOA X4, -32(AX)(R8*1) - MOVOA X5, -16(AX)(R8*1) + MOVOU -32(AX)(R8*1), X4 + MOVOU -16(AX)(R8*1), X5 + MOVOA X4, -32(CX)(R8*1) + MOVOA X5, -16(CX)(R8*1) ADDQ $0x20, R8 CMPQ BX, R8 JAE emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_forward_sse_loop_32 - MOVOU X0, (AX) - MOVOU X1, 16(AX) - MOVOU X2, -32(AX)(BX*1) - MOVOU X3, -16(AX)(BX*1) - MOVQ DX, AX + MOVOU X0, (CX) + MOVOU X1, 16(CX) + MOVOU X2, -32(CX)(BX*1) + MOVOU X3, -16(CX)(BX*1) + MOVQ DX, CX emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm8B: - MOVQ dst_base+0(FP), CX - SUBQ CX, AX - MOVQ AX, ret+48(FP) + MOVQ dst_base+0(FP), AX + SUBQ AX, CX + MOVQ CX, ret+56(FP) RET -// func calcBlockSize(src []byte) int +// func calcBlockSize(src []byte, tmp *[32768]byte) int // Requires: BMI, SSE2 -TEXT ·calcBlockSize(SB), $32792-32 - XORQ AX, AX - MOVQ $0x00000100, CX - LEAQ 24(SP), DX +TEXT ·calcBlockSize(SB), $24-40 + MOVQ tmp+24(FP), AX + XORQ CX, CX + MOVQ $0x00000100, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_calcBlockSize: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_calcBlockSize MOVL $0x00000000, 12(SP) - MOVQ src_len+8(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+0(FP), DX + MOVQ src_len+8(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+0(FP), BX search_loop_calcBlockSize: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x05, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x05, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_calcBlockSize - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x33, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x10, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x33, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x10, R9 - IMULQ R8, R9 - SHRQ $0x33, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 + SHLQ $0x10, R11 + IMULQ R9, R11 + SHRQ $0x33, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x10, R10 + IMULQ R9, R10 + SHRQ $0x33, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 JNE no_repeat_found_calcBlockSize - LEAL 1(CX), SI - MOVL 12(SP), BX - MOVL SI, DI - SUBL 16(SP), DI + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 JZ repeat_extend_back_end_calcBlockSize repeat_extend_back_loop_calcBlockSize: - CMPL SI, BX + CMPL DI, SI JBE repeat_extend_back_end_calcBlockSize - MOVB -1(DX)(DI*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_calcBlockSize - LEAL -1(SI), SI - DECL DI + LEAL -1(DI), DI + DECL R8 JNZ repeat_extend_back_loop_calcBlockSize repeat_extend_back_end_calcBlockSize: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 5(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 5(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_calcBlockSize - MOVQ $0x00000000, ret+24(FP) + MOVQ $0x00000000, ret+32(FP) RET repeat_dst_size_check_calcBlockSize: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_calcBlockSize - MOVL SI, DI - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R8 - SUBL BX, DI - LEAL -1(DI), BX - CMPL BX, $0x3c + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_calcBlockSize - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_calcBlockSize - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB three_bytes_repeat_emit_calcBlockSize - CMPL BX, $0x01000000 + CMPL SI, $0x01000000 JB four_bytes_repeat_emit_calcBlockSize - ADDQ $0x05, AX + ADDQ $0x05, CX JMP memmove_long_repeat_emit_calcBlockSize four_bytes_repeat_emit_calcBlockSize: - ADDQ $0x04, AX + ADDQ $0x04, CX JMP memmove_long_repeat_emit_calcBlockSize three_bytes_repeat_emit_calcBlockSize: - ADDQ $0x03, AX + ADDQ $0x03, CX JMP memmove_long_repeat_emit_calcBlockSize two_bytes_repeat_emit_calcBlockSize: - ADDQ $0x02, AX - CMPL BX, $0x40 + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_calcBlockSize JMP memmove_long_repeat_emit_calcBlockSize one_byte_repeat_emit_calcBlockSize: - ADDQ $0x01, AX + ADDQ $0x01, CX memmove_repeat_emit_calcBlockSize: - LEAQ (AX)(DI*1), AX + LEAQ (CX)(R8*1), CX JMP emit_literal_done_repeat_emit_calcBlockSize memmove_long_repeat_emit_calcBlockSize: - LEAQ (AX)(DI*1), AX + LEAQ (CX)(R8*1), CX emit_literal_done_repeat_emit_calcBlockSize: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+8(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+8(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI // matchLen - XORL R10, R10 + XORL R11, R11 matchlen_loopback_16_repeat_extend_calcBlockSize: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_repeat_extend_calcBlockSize - MOVQ (R8)(R10*1), R9 - MOVQ 8(R8)(R10*1), R11 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_calcBlockSize - XORQ 8(BX)(R10*1), R11 + XORQ 8(SI)(R11*1), R12 JNZ matchlen_bsf_16repeat_extend_calcBlockSize - LEAL -16(DI), DI - LEAL 16(R10), R10 + LEAL -16(R8), R8 + LEAL 16(R11), R11 JMP matchlen_loopback_16_repeat_extend_calcBlockSize matchlen_bsf_16repeat_extend_calcBlockSize: #ifdef GOAMD64_v3 - TZCNTQ R11, R11 + TZCNTQ R12, R12 #else - BSFQ R11, R11 + BSFQ R12, R12 #endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 JMP repeat_extend_forward_end_calcBlockSize matchlen_match8_repeat_extend_calcBlockSize: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_repeat_extend_calcBlockSize - MOVQ (R8)(R10*1), R9 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_calcBlockSize - LEAL -8(DI), DI - LEAL 8(R10), R10 + LEAL -8(R8), R8 + LEAL 8(R11), R11 JMP matchlen_match4_repeat_extend_calcBlockSize matchlen_bsf_8_repeat_extend_calcBlockSize: #ifdef GOAMD64_v3 - TZCNTQ R9, R9 + TZCNTQ R10, R10 #else - BSFQ R9, R9 + BSFQ R10, R10 #endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 JMP repeat_extend_forward_end_calcBlockSize matchlen_match4_repeat_extend_calcBlockSize: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_repeat_extend_calcBlockSize - MOVL (R8)(R10*1), R9 - CMPL (BX)(R10*1), R9 + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 JNE matchlen_match2_repeat_extend_calcBlockSize - LEAL -4(DI), DI - LEAL 4(R10), R10 + LEAL -4(R8), R8 + LEAL 4(R11), R11 matchlen_match2_repeat_extend_calcBlockSize: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_repeat_extend_calcBlockSize JB repeat_extend_forward_end_calcBlockSize - MOVW (R8)(R10*1), R9 - CMPW (BX)(R10*1), R9 + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 JNE matchlen_match1_repeat_extend_calcBlockSize - LEAL 2(R10), R10 - SUBL $0x02, DI + LEAL 2(R11), R11 + SUBL $0x02, R8 JZ repeat_extend_forward_end_calcBlockSize matchlen_match1_repeat_extend_calcBlockSize: - MOVB (R8)(R10*1), R9 - CMPB (BX)(R10*1), R9 + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 JNE repeat_extend_forward_end_calcBlockSize - LEAL 1(R10), R10 + LEAL 1(R11), R11 repeat_extend_forward_end_calcBlockSize: - ADDL R10, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI // emitCopy - CMPL SI, $0x00010000 + CMPL DI, $0x00010000 JB two_byte_offset_repeat_as_copy_calcBlockSize four_bytes_loop_back_repeat_as_copy_calcBlockSize: - CMPL BX, $0x40 + CMPL SI, $0x40 JBE four_bytes_remain_repeat_as_copy_calcBlockSize - LEAL -64(BX), BX - ADDQ $0x05, AX - CMPL BX, $0x04 + LEAL -64(SI), SI + ADDQ $0x05, CX + CMPL SI, $0x04 JB four_bytes_remain_repeat_as_copy_calcBlockSize JMP four_bytes_loop_back_repeat_as_copy_calcBlockSize four_bytes_remain_repeat_as_copy_calcBlockSize: - TESTL BX, BX + TESTL SI, SI JZ repeat_end_emit_calcBlockSize - XORL BX, BX - ADDQ $0x05, AX + XORL SI, SI + ADDQ $0x05, CX JMP repeat_end_emit_calcBlockSize two_byte_offset_repeat_as_copy_calcBlockSize: - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_calcBlockSize - LEAL -60(BX), BX - ADDQ $0x03, AX + LEAL -60(SI), SI + ADDQ $0x03, CX JMP two_byte_offset_repeat_as_copy_calcBlockSize two_byte_offset_short_repeat_as_copy_calcBlockSize: - MOVL BX, DI - SHLL $0x02, DI - CMPL BX, $0x0c + MOVL SI, R8 + SHLL $0x02, R8 + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_calcBlockSize - CMPL SI, $0x00000800 + CMPL DI, $0x00000800 JAE emit_copy_three_repeat_as_copy_calcBlockSize - ADDQ $0x02, AX + ADDQ $0x02, CX JMP repeat_end_emit_calcBlockSize emit_copy_three_repeat_as_copy_calcBlockSize: - ADDQ $0x03, AX + ADDQ $0x03, CX repeat_end_emit_calcBlockSize: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_calcBlockSize no_repeat_found_calcBlockSize: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_calcBlockSize - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_calcBlockSize - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_calcBlockSize - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_calcBlockSize candidate3_match_calcBlockSize: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_calcBlockSize candidate2_match_calcBlockSize: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_calcBlockSize: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_calcBlockSize match_extend_back_loop_calcBlockSize: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_calcBlockSize - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_calcBlockSize - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_calcBlockSize JMP match_extend_back_loop_calcBlockSize match_extend_back_end_calcBlockSize: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 5(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 5(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_calcBlockSize - MOVQ $0x00000000, ret+24(FP) + MOVQ $0x00000000, ret+32(FP) RET match_dst_size_check_calcBlockSize: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_calcBlockSize - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), SI - CMPL SI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), DI + CMPL DI, $0x3c JB one_byte_match_emit_calcBlockSize - CMPL SI, $0x00000100 + CMPL DI, $0x00000100 JB two_bytes_match_emit_calcBlockSize - CMPL SI, $0x00010000 + CMPL DI, $0x00010000 JB three_bytes_match_emit_calcBlockSize - CMPL SI, $0x01000000 + CMPL DI, $0x01000000 JB four_bytes_match_emit_calcBlockSize - ADDQ $0x05, AX + ADDQ $0x05, CX JMP memmove_long_match_emit_calcBlockSize four_bytes_match_emit_calcBlockSize: - ADDQ $0x04, AX + ADDQ $0x04, CX JMP memmove_long_match_emit_calcBlockSize three_bytes_match_emit_calcBlockSize: - ADDQ $0x03, AX + ADDQ $0x03, CX JMP memmove_long_match_emit_calcBlockSize two_bytes_match_emit_calcBlockSize: - ADDQ $0x02, AX - CMPL SI, $0x40 + ADDQ $0x02, CX + CMPL DI, $0x40 JB memmove_match_emit_calcBlockSize JMP memmove_long_match_emit_calcBlockSize one_byte_match_emit_calcBlockSize: - ADDQ $0x01, AX + ADDQ $0x01, CX memmove_match_emit_calcBlockSize: - LEAQ (AX)(R8*1), AX + LEAQ (CX)(R9*1), CX JMP emit_literal_done_match_emit_calcBlockSize memmove_long_match_emit_calcBlockSize: - LEAQ (AX)(R8*1), AX + LEAQ (CX)(R9*1), CX emit_literal_done_match_emit_calcBlockSize: match_nolit_loop_calcBlockSize: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+8(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+8(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_calcBlockSize: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_calcBlockSize - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_calcBlockSize - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_calcBlockSize - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_calcBlockSize matchlen_bsf_16match_nolit_calcBlockSize: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_calcBlockSize matchlen_match8_match_nolit_calcBlockSize: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_calcBlockSize - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_calcBlockSize - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_calcBlockSize matchlen_bsf_8_match_nolit_calcBlockSize: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_calcBlockSize matchlen_match4_match_nolit_calcBlockSize: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_calcBlockSize - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_calcBlockSize - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_calcBlockSize: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_calcBlockSize JB match_nolit_end_calcBlockSize - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_calcBlockSize - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_calcBlockSize matchlen_match1_match_nolit_calcBlockSize: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_calcBlockSize - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_calcBlockSize: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy - CMPL BX, $0x00010000 + CMPL SI, $0x00010000 JB two_byte_offset_match_nolit_calcBlockSize four_bytes_loop_back_match_nolit_calcBlockSize: - CMPL R9, $0x40 + CMPL R10, $0x40 JBE four_bytes_remain_match_nolit_calcBlockSize - LEAL -64(R9), R9 - ADDQ $0x05, AX - CMPL R9, $0x04 + LEAL -64(R10), R10 + ADDQ $0x05, CX + CMPL R10, $0x04 JB four_bytes_remain_match_nolit_calcBlockSize JMP four_bytes_loop_back_match_nolit_calcBlockSize four_bytes_remain_match_nolit_calcBlockSize: - TESTL R9, R9 + TESTL R10, R10 JZ match_nolit_emitcopy_end_calcBlockSize - XORL BX, BX - ADDQ $0x05, AX + XORL SI, SI + ADDQ $0x05, CX JMP match_nolit_emitcopy_end_calcBlockSize two_byte_offset_match_nolit_calcBlockSize: - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_calcBlockSize - LEAL -60(R9), R9 - ADDQ $0x03, AX + LEAL -60(R10), R10 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_calcBlockSize two_byte_offset_short_match_nolit_calcBlockSize: - MOVL R9, SI - SHLL $0x02, SI - CMPL R9, $0x0c + MOVL R10, DI + SHLL $0x02, DI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_calcBlockSize - CMPL BX, $0x00000800 + CMPL SI, $0x00000800 JAE emit_copy_three_match_nolit_calcBlockSize - ADDQ $0x02, AX + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_calcBlockSize emit_copy_three_match_nolit_calcBlockSize: - ADDQ $0x03, AX + ADDQ $0x03, CX match_nolit_emitcopy_end_calcBlockSize: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_calcBlockSize - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_calcBlockSize - MOVQ $0x00000000, ret+24(FP) + MOVQ $0x00000000, ret+32(FP) RET match_nolit_dst_ok_calcBlockSize: - MOVQ $0x0000cf1bbcdcbf9b, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x10, DI - IMULQ R8, DI - SHRQ $0x33, DI - SHLQ $0x10, BX - IMULQ R8, BX - SHRQ $0x33, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x0000cf1bbcdcbf9b, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x10, R8 + IMULQ R9, R8 + SHRQ $0x33, R8 + SHLQ $0x10, SI + IMULQ R9, SI + SHRQ $0x33, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_calcBlockSize - INCL CX + INCL DX JMP search_loop_calcBlockSize emit_remainder_calcBlockSize: - MOVQ src_len+8(FP), CX - SUBL 12(SP), CX - LEAQ 5(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+8(FP), AX + SUBL 12(SP), AX + LEAQ 5(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_calcBlockSize - MOVQ $0x00000000, ret+24(FP) + MOVQ $0x00000000, ret+32(FP) RET emit_remainder_ok_calcBlockSize: - MOVQ src_len+8(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+8(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_calcBlockSize - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI - LEAL -1(SI), CX - CMPL CX, $0x3c + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), AX + CMPL AX, $0x3c JB one_byte_emit_remainder_calcBlockSize - CMPL CX, $0x00000100 + CMPL AX, $0x00000100 JB two_bytes_emit_remainder_calcBlockSize - CMPL CX, $0x00010000 + CMPL AX, $0x00010000 JB three_bytes_emit_remainder_calcBlockSize - CMPL CX, $0x01000000 + CMPL AX, $0x01000000 JB four_bytes_emit_remainder_calcBlockSize - ADDQ $0x05, AX + ADDQ $0x05, CX JMP memmove_long_emit_remainder_calcBlockSize four_bytes_emit_remainder_calcBlockSize: - ADDQ $0x04, AX + ADDQ $0x04, CX JMP memmove_long_emit_remainder_calcBlockSize three_bytes_emit_remainder_calcBlockSize: - ADDQ $0x03, AX + ADDQ $0x03, CX JMP memmove_long_emit_remainder_calcBlockSize two_bytes_emit_remainder_calcBlockSize: - ADDQ $0x02, AX - CMPL CX, $0x40 + ADDQ $0x02, CX + CMPL AX, $0x40 JB memmove_emit_remainder_calcBlockSize JMP memmove_long_emit_remainder_calcBlockSize one_byte_emit_remainder_calcBlockSize: - ADDQ $0x01, AX + ADDQ $0x01, CX memmove_emit_remainder_calcBlockSize: - LEAQ (AX)(SI*1), AX + LEAQ (CX)(SI*1), AX + MOVQ AX, CX JMP emit_literal_done_emit_remainder_calcBlockSize memmove_long_emit_remainder_calcBlockSize: - LEAQ (AX)(SI*1), AX + LEAQ (CX)(SI*1), AX + MOVQ AX, CX emit_literal_done_emit_remainder_calcBlockSize: - MOVQ AX, ret+24(FP) + MOVQ CX, ret+32(FP) RET -// func calcBlockSizeSmall(src []byte) int +// func calcBlockSizeSmall(src []byte, tmp *[2048]byte) int // Requires: BMI, SSE2 -TEXT ·calcBlockSizeSmall(SB), $2072-32 - XORQ AX, AX - MOVQ $0x00000010, CX - LEAQ 24(SP), DX +TEXT ·calcBlockSizeSmall(SB), $24-40 + MOVQ tmp+24(FP), AX + XORQ CX, CX + MOVQ $0x00000010, DX + MOVQ AX, BX PXOR X0, X0 zero_loop_calcBlockSizeSmall: - MOVOU X0, (DX) - MOVOU X0, 16(DX) - MOVOU X0, 32(DX) - MOVOU X0, 48(DX) - MOVOU X0, 64(DX) - MOVOU X0, 80(DX) - MOVOU X0, 96(DX) - MOVOU X0, 112(DX) - ADDQ $0x80, DX - DECQ CX + MOVOU X0, (BX) + MOVOU X0, 16(BX) + MOVOU X0, 32(BX) + MOVOU X0, 48(BX) + MOVOU X0, 64(BX) + MOVOU X0, 80(BX) + MOVOU X0, 96(BX) + MOVOU X0, 112(BX) + ADDQ $0x80, BX + DECQ DX JNZ zero_loop_calcBlockSizeSmall MOVL $0x00000000, 12(SP) - MOVQ src_len+8(FP), CX - LEAQ -9(CX), DX - LEAQ -8(CX), BX - MOVL BX, 8(SP) - SHRQ $0x05, CX - SUBL CX, DX - LEAQ (AX)(DX*1), DX - MOVQ DX, (SP) - MOVL $0x00000001, CX - MOVL CX, 16(SP) - MOVQ src_base+0(FP), DX + MOVQ src_len+8(FP), DX + LEAQ -9(DX), BX + LEAQ -8(DX), SI + MOVL SI, 8(SP) + SHRQ $0x05, DX + SUBL DX, BX + LEAQ (CX)(BX*1), BX + MOVQ BX, (SP) + MOVL $0x00000001, DX + MOVL DX, 16(SP) + MOVQ src_base+0(FP), BX search_loop_calcBlockSizeSmall: - MOVL CX, BX - SUBL 12(SP), BX - SHRL $0x04, BX - LEAL 4(CX)(BX*1), BX - CMPL BX, 8(SP) + MOVL DX, SI + SUBL 12(SP), SI + SHRL $0x04, SI + LEAL 4(DX)(SI*1), SI + CMPL SI, 8(SP) JAE emit_remainder_calcBlockSizeSmall - MOVQ (DX)(CX*1), SI - MOVL BX, 20(SP) - MOVQ $0x9e3779b1, R8 - MOVQ SI, R9 - MOVQ SI, R10 - SHRQ $0x08, R10 - SHLQ $0x20, R9 - IMULQ R8, R9 - SHRQ $0x37, R9 + MOVQ (BX)(DX*1), DI + MOVL SI, 20(SP) + MOVQ $0x9e3779b1, R9 + MOVQ DI, R10 + MOVQ DI, R11 + SHRQ $0x08, R11 SHLQ $0x20, R10 - IMULQ R8, R10 + IMULQ R9, R10 SHRQ $0x37, R10 - MOVL 24(SP)(R9*4), BX - MOVL 24(SP)(R10*4), DI - MOVL CX, 24(SP)(R9*4) - LEAL 1(CX), R9 - MOVL R9, 24(SP)(R10*4) - MOVQ SI, R9 - SHRQ $0x10, R9 - SHLQ $0x20, R9 - IMULQ R8, R9 - SHRQ $0x37, R9 - MOVL CX, R8 - SUBL 16(SP), R8 - MOVL 1(DX)(R8*1), R10 - MOVQ SI, R8 - SHRQ $0x08, R8 - CMPL R8, R10 + SHLQ $0x20, R11 + IMULQ R9, R11 + SHRQ $0x37, R11 + MOVL (AX)(R10*4), SI + MOVL (AX)(R11*4), R8 + MOVL DX, (AX)(R10*4) + LEAL 1(DX), R10 + MOVL R10, (AX)(R11*4) + MOVQ DI, R10 + SHRQ $0x10, R10 + SHLQ $0x20, R10 + IMULQ R9, R10 + SHRQ $0x37, R10 + MOVL DX, R9 + SUBL 16(SP), R9 + MOVL 1(BX)(R9*1), R11 + MOVQ DI, R9 + SHRQ $0x08, R9 + CMPL R9, R11 JNE no_repeat_found_calcBlockSizeSmall - LEAL 1(CX), SI - MOVL 12(SP), BX - MOVL SI, DI - SUBL 16(SP), DI + LEAL 1(DX), DI + MOVL 12(SP), SI + MOVL DI, R8 + SUBL 16(SP), R8 JZ repeat_extend_back_end_calcBlockSizeSmall repeat_extend_back_loop_calcBlockSizeSmall: - CMPL SI, BX + CMPL DI, SI JBE repeat_extend_back_end_calcBlockSizeSmall - MOVB -1(DX)(DI*1), R8 - MOVB -1(DX)(SI*1), R9 - CMPB R8, R9 + MOVB -1(BX)(R8*1), R9 + MOVB -1(BX)(DI*1), R10 + CMPB R9, R10 JNE repeat_extend_back_end_calcBlockSizeSmall - LEAL -1(SI), SI - DECL DI + LEAL -1(DI), DI + DECL R8 JNZ repeat_extend_back_loop_calcBlockSizeSmall repeat_extend_back_end_calcBlockSizeSmall: - MOVL SI, BX - SUBL 12(SP), BX - LEAQ 3(AX)(BX*1), BX - CMPQ BX, (SP) + MOVL DI, SI + SUBL 12(SP), SI + LEAQ 3(CX)(SI*1), SI + CMPQ SI, (SP) JB repeat_dst_size_check_calcBlockSizeSmall - MOVQ $0x00000000, ret+24(FP) + MOVQ $0x00000000, ret+32(FP) RET repeat_dst_size_check_calcBlockSizeSmall: - MOVL 12(SP), BX - CMPL BX, SI + MOVL 12(SP), SI + CMPL SI, DI JEQ emit_literal_done_repeat_emit_calcBlockSizeSmall - MOVL SI, DI - MOVL SI, 12(SP) - LEAQ (DX)(BX*1), R8 - SUBL BX, DI - LEAL -1(DI), BX - CMPL BX, $0x3c + MOVL DI, R8 + MOVL DI, 12(SP) + LEAQ (BX)(SI*1), R9 + SUBL SI, R8 + LEAL -1(R8), SI + CMPL SI, $0x3c JB one_byte_repeat_emit_calcBlockSizeSmall - CMPL BX, $0x00000100 + CMPL SI, $0x00000100 JB two_bytes_repeat_emit_calcBlockSizeSmall JB three_bytes_repeat_emit_calcBlockSizeSmall three_bytes_repeat_emit_calcBlockSizeSmall: - ADDQ $0x03, AX + ADDQ $0x03, CX JMP memmove_long_repeat_emit_calcBlockSizeSmall two_bytes_repeat_emit_calcBlockSizeSmall: - ADDQ $0x02, AX - CMPL BX, $0x40 + ADDQ $0x02, CX + CMPL SI, $0x40 JB memmove_repeat_emit_calcBlockSizeSmall JMP memmove_long_repeat_emit_calcBlockSizeSmall one_byte_repeat_emit_calcBlockSizeSmall: - ADDQ $0x01, AX + ADDQ $0x01, CX memmove_repeat_emit_calcBlockSizeSmall: - LEAQ (AX)(DI*1), AX + LEAQ (CX)(R8*1), CX JMP emit_literal_done_repeat_emit_calcBlockSizeSmall memmove_long_repeat_emit_calcBlockSizeSmall: - LEAQ (AX)(DI*1), AX + LEAQ (CX)(R8*1), CX emit_literal_done_repeat_emit_calcBlockSizeSmall: - ADDL $0x05, CX - MOVL CX, BX - SUBL 16(SP), BX - MOVQ src_len+8(FP), DI - SUBL CX, DI - LEAQ (DX)(CX*1), R8 - LEAQ (DX)(BX*1), BX + ADDL $0x05, DX + MOVL DX, SI + SUBL 16(SP), SI + MOVQ src_len+8(FP), R8 + SUBL DX, R8 + LEAQ (BX)(DX*1), R9 + LEAQ (BX)(SI*1), SI // matchLen - XORL R10, R10 + XORL R11, R11 matchlen_loopback_16_repeat_extend_calcBlockSizeSmall: - CMPL DI, $0x10 + CMPL R8, $0x10 JB matchlen_match8_repeat_extend_calcBlockSizeSmall - MOVQ (R8)(R10*1), R9 - MOVQ 8(R8)(R10*1), R11 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + MOVQ 8(R9)(R11*1), R12 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_calcBlockSizeSmall - XORQ 8(BX)(R10*1), R11 + XORQ 8(SI)(R11*1), R12 JNZ matchlen_bsf_16repeat_extend_calcBlockSizeSmall - LEAL -16(DI), DI - LEAL 16(R10), R10 + LEAL -16(R8), R8 + LEAL 16(R11), R11 JMP matchlen_loopback_16_repeat_extend_calcBlockSizeSmall matchlen_bsf_16repeat_extend_calcBlockSizeSmall: #ifdef GOAMD64_v3 - TZCNTQ R11, R11 + TZCNTQ R12, R12 #else - BSFQ R11, R11 + BSFQ R12, R12 #endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 JMP repeat_extend_forward_end_calcBlockSizeSmall matchlen_match8_repeat_extend_calcBlockSizeSmall: - CMPL DI, $0x08 + CMPL R8, $0x08 JB matchlen_match4_repeat_extend_calcBlockSizeSmall - MOVQ (R8)(R10*1), R9 - XORQ (BX)(R10*1), R9 + MOVQ (R9)(R11*1), R10 + XORQ (SI)(R11*1), R10 JNZ matchlen_bsf_8_repeat_extend_calcBlockSizeSmall - LEAL -8(DI), DI - LEAL 8(R10), R10 + LEAL -8(R8), R8 + LEAL 8(R11), R11 JMP matchlen_match4_repeat_extend_calcBlockSizeSmall matchlen_bsf_8_repeat_extend_calcBlockSizeSmall: #ifdef GOAMD64_v3 - TZCNTQ R9, R9 + TZCNTQ R10, R10 #else - BSFQ R9, R9 + BSFQ R10, R10 #endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 JMP repeat_extend_forward_end_calcBlockSizeSmall matchlen_match4_repeat_extend_calcBlockSizeSmall: - CMPL DI, $0x04 + CMPL R8, $0x04 JB matchlen_match2_repeat_extend_calcBlockSizeSmall - MOVL (R8)(R10*1), R9 - CMPL (BX)(R10*1), R9 + MOVL (R9)(R11*1), R10 + CMPL (SI)(R11*1), R10 JNE matchlen_match2_repeat_extend_calcBlockSizeSmall - LEAL -4(DI), DI - LEAL 4(R10), R10 + LEAL -4(R8), R8 + LEAL 4(R11), R11 matchlen_match2_repeat_extend_calcBlockSizeSmall: - CMPL DI, $0x01 + CMPL R8, $0x01 JE matchlen_match1_repeat_extend_calcBlockSizeSmall JB repeat_extend_forward_end_calcBlockSizeSmall - MOVW (R8)(R10*1), R9 - CMPW (BX)(R10*1), R9 + MOVW (R9)(R11*1), R10 + CMPW (SI)(R11*1), R10 JNE matchlen_match1_repeat_extend_calcBlockSizeSmall - LEAL 2(R10), R10 - SUBL $0x02, DI + LEAL 2(R11), R11 + SUBL $0x02, R8 JZ repeat_extend_forward_end_calcBlockSizeSmall matchlen_match1_repeat_extend_calcBlockSizeSmall: - MOVB (R8)(R10*1), R9 - CMPB (BX)(R10*1), R9 + MOVB (R9)(R11*1), R10 + CMPB (SI)(R11*1), R10 JNE repeat_extend_forward_end_calcBlockSizeSmall - LEAL 1(R10), R10 + LEAL 1(R11), R11 repeat_extend_forward_end_calcBlockSizeSmall: - ADDL R10, CX - MOVL CX, BX - SUBL SI, BX - MOVL 16(SP), SI + ADDL R11, DX + MOVL DX, SI + SUBL DI, SI + MOVL 16(SP), DI // emitCopy two_byte_offset_repeat_as_copy_calcBlockSizeSmall: - CMPL BX, $0x40 + CMPL SI, $0x40 JBE two_byte_offset_short_repeat_as_copy_calcBlockSizeSmall - LEAL -60(BX), BX - ADDQ $0x03, AX + LEAL -60(SI), SI + ADDQ $0x03, CX JMP two_byte_offset_repeat_as_copy_calcBlockSizeSmall two_byte_offset_short_repeat_as_copy_calcBlockSizeSmall: - MOVL BX, SI - SHLL $0x02, SI - CMPL BX, $0x0c + MOVL SI, DI + SHLL $0x02, DI + CMPL SI, $0x0c JAE emit_copy_three_repeat_as_copy_calcBlockSizeSmall - ADDQ $0x02, AX + ADDQ $0x02, CX JMP repeat_end_emit_calcBlockSizeSmall emit_copy_three_repeat_as_copy_calcBlockSizeSmall: - ADDQ $0x03, AX + ADDQ $0x03, CX repeat_end_emit_calcBlockSizeSmall: - MOVL CX, 12(SP) + MOVL DX, 12(SP) JMP search_loop_calcBlockSizeSmall no_repeat_found_calcBlockSizeSmall: - CMPL (DX)(BX*1), SI + CMPL (BX)(SI*1), DI JEQ candidate_match_calcBlockSizeSmall - SHRQ $0x08, SI - MOVL 24(SP)(R9*4), BX - LEAL 2(CX), R8 - CMPL (DX)(DI*1), SI + SHRQ $0x08, DI + MOVL (AX)(R10*4), SI + LEAL 2(DX), R9 + CMPL (BX)(R8*1), DI JEQ candidate2_match_calcBlockSizeSmall - MOVL R8, 24(SP)(R9*4) - SHRQ $0x08, SI - CMPL (DX)(BX*1), SI + MOVL R9, (AX)(R10*4) + SHRQ $0x08, DI + CMPL (BX)(SI*1), DI JEQ candidate3_match_calcBlockSizeSmall - MOVL 20(SP), CX + MOVL 20(SP), DX JMP search_loop_calcBlockSizeSmall candidate3_match_calcBlockSizeSmall: - ADDL $0x02, CX + ADDL $0x02, DX JMP candidate_match_calcBlockSizeSmall candidate2_match_calcBlockSizeSmall: - MOVL R8, 24(SP)(R9*4) - INCL CX - MOVL DI, BX + MOVL R9, (AX)(R10*4) + INCL DX + MOVL R8, SI candidate_match_calcBlockSizeSmall: - MOVL 12(SP), SI - TESTL BX, BX + MOVL 12(SP), DI + TESTL SI, SI JZ match_extend_back_end_calcBlockSizeSmall match_extend_back_loop_calcBlockSizeSmall: - CMPL CX, SI + CMPL DX, DI JBE match_extend_back_end_calcBlockSizeSmall - MOVB -1(DX)(BX*1), DI - MOVB -1(DX)(CX*1), R8 - CMPB DI, R8 + MOVB -1(BX)(SI*1), R8 + MOVB -1(BX)(DX*1), R9 + CMPB R8, R9 JNE match_extend_back_end_calcBlockSizeSmall - LEAL -1(CX), CX - DECL BX + LEAL -1(DX), DX + DECL SI JZ match_extend_back_end_calcBlockSizeSmall JMP match_extend_back_loop_calcBlockSizeSmall match_extend_back_end_calcBlockSizeSmall: - MOVL CX, SI - SUBL 12(SP), SI - LEAQ 3(AX)(SI*1), SI - CMPQ SI, (SP) + MOVL DX, DI + SUBL 12(SP), DI + LEAQ 3(CX)(DI*1), DI + CMPQ DI, (SP) JB match_dst_size_check_calcBlockSizeSmall - MOVQ $0x00000000, ret+24(FP) + MOVQ $0x00000000, ret+32(FP) RET match_dst_size_check_calcBlockSizeSmall: - MOVL CX, SI - MOVL 12(SP), DI - CMPL DI, SI + MOVL DX, DI + MOVL 12(SP), R8 + CMPL R8, DI JEQ emit_literal_done_match_emit_calcBlockSizeSmall - MOVL SI, R8 - MOVL SI, 12(SP) - LEAQ (DX)(DI*1), SI - SUBL DI, R8 - LEAL -1(R8), SI - CMPL SI, $0x3c + MOVL DI, R9 + MOVL DI, 12(SP) + LEAQ (BX)(R8*1), DI + SUBL R8, R9 + LEAL -1(R9), DI + CMPL DI, $0x3c JB one_byte_match_emit_calcBlockSizeSmall - CMPL SI, $0x00000100 + CMPL DI, $0x00000100 JB two_bytes_match_emit_calcBlockSizeSmall JB three_bytes_match_emit_calcBlockSizeSmall three_bytes_match_emit_calcBlockSizeSmall: - ADDQ $0x03, AX + ADDQ $0x03, CX JMP memmove_long_match_emit_calcBlockSizeSmall two_bytes_match_emit_calcBlockSizeSmall: - ADDQ $0x02, AX - CMPL SI, $0x40 + ADDQ $0x02, CX + CMPL DI, $0x40 JB memmove_match_emit_calcBlockSizeSmall JMP memmove_long_match_emit_calcBlockSizeSmall one_byte_match_emit_calcBlockSizeSmall: - ADDQ $0x01, AX + ADDQ $0x01, CX memmove_match_emit_calcBlockSizeSmall: - LEAQ (AX)(R8*1), AX + LEAQ (CX)(R9*1), CX JMP emit_literal_done_match_emit_calcBlockSizeSmall memmove_long_match_emit_calcBlockSizeSmall: - LEAQ (AX)(R8*1), AX + LEAQ (CX)(R9*1), CX emit_literal_done_match_emit_calcBlockSizeSmall: match_nolit_loop_calcBlockSizeSmall: - MOVL CX, SI - SUBL BX, SI - MOVL SI, 16(SP) - ADDL $0x04, CX - ADDL $0x04, BX - MOVQ src_len+8(FP), SI - SUBL CX, SI - LEAQ (DX)(CX*1), DI - LEAQ (DX)(BX*1), BX + MOVL DX, DI + SUBL SI, DI + MOVL DI, 16(SP) + ADDL $0x04, DX + ADDL $0x04, SI + MOVQ src_len+8(FP), DI + SUBL DX, DI + LEAQ (BX)(DX*1), R8 + LEAQ (BX)(SI*1), SI // matchLen - XORL R9, R9 + XORL R10, R10 matchlen_loopback_16_match_nolit_calcBlockSizeSmall: - CMPL SI, $0x10 + CMPL DI, $0x10 JB matchlen_match8_match_nolit_calcBlockSizeSmall - MOVQ (DI)(R9*1), R8 - MOVQ 8(DI)(R9*1), R10 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + MOVQ 8(R8)(R10*1), R11 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_calcBlockSizeSmall - XORQ 8(BX)(R9*1), R10 + XORQ 8(SI)(R10*1), R11 JNZ matchlen_bsf_16match_nolit_calcBlockSizeSmall - LEAL -16(SI), SI - LEAL 16(R9), R9 + LEAL -16(DI), DI + LEAL 16(R10), R10 JMP matchlen_loopback_16_match_nolit_calcBlockSizeSmall matchlen_bsf_16match_nolit_calcBlockSizeSmall: #ifdef GOAMD64_v3 - TZCNTQ R10, R10 + TZCNTQ R11, R11 #else - BSFQ R10, R10 + BSFQ R11, R11 #endif - SARQ $0x03, R10 - LEAL 8(R9)(R10*1), R9 + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 JMP match_nolit_end_calcBlockSizeSmall matchlen_match8_match_nolit_calcBlockSizeSmall: - CMPL SI, $0x08 + CMPL DI, $0x08 JB matchlen_match4_match_nolit_calcBlockSizeSmall - MOVQ (DI)(R9*1), R8 - XORQ (BX)(R9*1), R8 + MOVQ (R8)(R10*1), R9 + XORQ (SI)(R10*1), R9 JNZ matchlen_bsf_8_match_nolit_calcBlockSizeSmall - LEAL -8(SI), SI - LEAL 8(R9), R9 + LEAL -8(DI), DI + LEAL 8(R10), R10 JMP matchlen_match4_match_nolit_calcBlockSizeSmall matchlen_bsf_8_match_nolit_calcBlockSizeSmall: #ifdef GOAMD64_v3 - TZCNTQ R8, R8 + TZCNTQ R9, R9 #else - BSFQ R8, R8 + BSFQ R9, R9 #endif - SARQ $0x03, R8 - LEAL (R9)(R8*1), R9 + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 JMP match_nolit_end_calcBlockSizeSmall matchlen_match4_match_nolit_calcBlockSizeSmall: - CMPL SI, $0x04 + CMPL DI, $0x04 JB matchlen_match2_match_nolit_calcBlockSizeSmall - MOVL (DI)(R9*1), R8 - CMPL (BX)(R9*1), R8 + MOVL (R8)(R10*1), R9 + CMPL (SI)(R10*1), R9 JNE matchlen_match2_match_nolit_calcBlockSizeSmall - LEAL -4(SI), SI - LEAL 4(R9), R9 + LEAL -4(DI), DI + LEAL 4(R10), R10 matchlen_match2_match_nolit_calcBlockSizeSmall: - CMPL SI, $0x01 + CMPL DI, $0x01 JE matchlen_match1_match_nolit_calcBlockSizeSmall JB match_nolit_end_calcBlockSizeSmall - MOVW (DI)(R9*1), R8 - CMPW (BX)(R9*1), R8 + MOVW (R8)(R10*1), R9 + CMPW (SI)(R10*1), R9 JNE matchlen_match1_match_nolit_calcBlockSizeSmall - LEAL 2(R9), R9 - SUBL $0x02, SI + LEAL 2(R10), R10 + SUBL $0x02, DI JZ match_nolit_end_calcBlockSizeSmall matchlen_match1_match_nolit_calcBlockSizeSmall: - MOVB (DI)(R9*1), R8 - CMPB (BX)(R9*1), R8 + MOVB (R8)(R10*1), R9 + CMPB (SI)(R10*1), R9 JNE match_nolit_end_calcBlockSizeSmall - LEAL 1(R9), R9 + LEAL 1(R10), R10 match_nolit_end_calcBlockSizeSmall: - ADDL R9, CX - MOVL 16(SP), BX - ADDL $0x04, R9 - MOVL CX, 12(SP) + ADDL R10, DX + MOVL 16(SP), SI + ADDL $0x04, R10 + MOVL DX, 12(SP) // emitCopy two_byte_offset_match_nolit_calcBlockSizeSmall: - CMPL R9, $0x40 + CMPL R10, $0x40 JBE two_byte_offset_short_match_nolit_calcBlockSizeSmall - LEAL -60(R9), R9 - ADDQ $0x03, AX + LEAL -60(R10), R10 + ADDQ $0x03, CX JMP two_byte_offset_match_nolit_calcBlockSizeSmall two_byte_offset_short_match_nolit_calcBlockSizeSmall: - MOVL R9, BX - SHLL $0x02, BX - CMPL R9, $0x0c + MOVL R10, SI + SHLL $0x02, SI + CMPL R10, $0x0c JAE emit_copy_three_match_nolit_calcBlockSizeSmall - ADDQ $0x02, AX + ADDQ $0x02, CX JMP match_nolit_emitcopy_end_calcBlockSizeSmall emit_copy_three_match_nolit_calcBlockSizeSmall: - ADDQ $0x03, AX + ADDQ $0x03, CX match_nolit_emitcopy_end_calcBlockSizeSmall: - CMPL CX, 8(SP) + CMPL DX, 8(SP) JAE emit_remainder_calcBlockSizeSmall - MOVQ -2(DX)(CX*1), SI - CMPQ AX, (SP) + MOVQ -2(BX)(DX*1), DI + CMPQ CX, (SP) JB match_nolit_dst_ok_calcBlockSizeSmall - MOVQ $0x00000000, ret+24(FP) + MOVQ $0x00000000, ret+32(FP) RET match_nolit_dst_ok_calcBlockSizeSmall: - MOVQ $0x9e3779b1, R8 - MOVQ SI, DI - SHRQ $0x10, SI - MOVQ SI, BX - SHLQ $0x20, DI - IMULQ R8, DI - SHRQ $0x37, DI - SHLQ $0x20, BX - IMULQ R8, BX - SHRQ $0x37, BX - LEAL -2(CX), R8 - LEAQ 24(SP)(BX*4), R9 - MOVL (R9), BX - MOVL R8, 24(SP)(DI*4) - MOVL CX, (R9) - CMPL (DX)(BX*1), SI + MOVQ $0x9e3779b1, R9 + MOVQ DI, R8 + SHRQ $0x10, DI + MOVQ DI, SI + SHLQ $0x20, R8 + IMULQ R9, R8 + SHRQ $0x37, R8 + SHLQ $0x20, SI + IMULQ R9, SI + SHRQ $0x37, SI + LEAL -2(DX), R9 + LEAQ (AX)(SI*4), R10 + MOVL (R10), SI + MOVL R9, (AX)(R8*4) + MOVL DX, (R10) + CMPL (BX)(SI*1), DI JEQ match_nolit_loop_calcBlockSizeSmall - INCL CX + INCL DX JMP search_loop_calcBlockSizeSmall emit_remainder_calcBlockSizeSmall: - MOVQ src_len+8(FP), CX - SUBL 12(SP), CX - LEAQ 3(AX)(CX*1), CX - CMPQ CX, (SP) + MOVQ src_len+8(FP), AX + SUBL 12(SP), AX + LEAQ 3(CX)(AX*1), AX + CMPQ AX, (SP) JB emit_remainder_ok_calcBlockSizeSmall - MOVQ $0x00000000, ret+24(FP) + MOVQ $0x00000000, ret+32(FP) RET emit_remainder_ok_calcBlockSizeSmall: - MOVQ src_len+8(FP), CX - MOVL 12(SP), BX - CMPL BX, CX + MOVQ src_len+8(FP), AX + MOVL 12(SP), DX + CMPL DX, AX JEQ emit_literal_done_emit_remainder_calcBlockSizeSmall - MOVL CX, SI - MOVL CX, 12(SP) - LEAQ (DX)(BX*1), CX - SUBL BX, SI - LEAL -1(SI), CX - CMPL CX, $0x3c + MOVL AX, SI + MOVL AX, 12(SP) + LEAQ (BX)(DX*1), AX + SUBL DX, SI + LEAL -1(SI), AX + CMPL AX, $0x3c JB one_byte_emit_remainder_calcBlockSizeSmall - CMPL CX, $0x00000100 + CMPL AX, $0x00000100 JB two_bytes_emit_remainder_calcBlockSizeSmall JB three_bytes_emit_remainder_calcBlockSizeSmall three_bytes_emit_remainder_calcBlockSizeSmall: - ADDQ $0x03, AX + ADDQ $0x03, CX JMP memmove_long_emit_remainder_calcBlockSizeSmall two_bytes_emit_remainder_calcBlockSizeSmall: - ADDQ $0x02, AX - CMPL CX, $0x40 + ADDQ $0x02, CX + CMPL AX, $0x40 JB memmove_emit_remainder_calcBlockSizeSmall JMP memmove_long_emit_remainder_calcBlockSizeSmall one_byte_emit_remainder_calcBlockSizeSmall: - ADDQ $0x01, AX + ADDQ $0x01, CX memmove_emit_remainder_calcBlockSizeSmall: - LEAQ (AX)(SI*1), AX + LEAQ (CX)(SI*1), AX + MOVQ AX, CX JMP emit_literal_done_emit_remainder_calcBlockSizeSmall memmove_long_emit_remainder_calcBlockSizeSmall: - LEAQ (AX)(SI*1), AX + LEAQ (CX)(SI*1), AX + MOVQ AX, CX emit_literal_done_emit_remainder_calcBlockSizeSmall: - MOVQ AX, ret+24(FP) + MOVQ CX, ret+32(FP) RET // func emitLiteral(dst []byte, lit []byte) int @@ -19783,7 +19809,7 @@ TEXT ·cvtLZ4BlockAsm(SB), NOSPLIT, $0-64 MOVQ src_base+24(FP), DX MOVQ src_len+32(FP), BX LEAQ (DX)(BX*1), BX - LEAQ -10(AX)(CX*1), CX + LEAQ -8(AX)(CX*1), CX XORQ DI, DI lz4_s2_loop: @@ -20266,7 +20292,7 @@ TEXT ·cvtLZ4sBlockAsm(SB), NOSPLIT, $0-64 MOVQ src_base+24(FP), DX MOVQ src_len+32(FP), BX LEAQ (DX)(BX*1), BX - LEAQ -10(AX)(CX*1), CX + LEAQ -8(AX)(CX*1), CX XORQ DI, DI lz4s_s2_loop: @@ -20751,7 +20777,7 @@ TEXT ·cvtLZ4BlockSnappyAsm(SB), NOSPLIT, $0-64 MOVQ src_base+24(FP), DX MOVQ src_len+32(FP), BX LEAQ (DX)(BX*1), BX - LEAQ -10(AX)(CX*1), CX + LEAQ -8(AX)(CX*1), CX lz4_snappy_loop: CMPQ DX, BX @@ -21017,7 +21043,7 @@ TEXT ·cvtLZ4sBlockSnappyAsm(SB), NOSPLIT, $0-64 MOVQ src_base+24(FP), DX MOVQ src_len+32(FP), BX LEAQ (DX)(BX*1), BX - LEAQ -10(AX)(CX*1), CX + LEAQ -8(AX)(CX*1), CX lz4s_snappy_loop: CMPQ DX, BX diff --git a/vendor/github.com/klauspost/compress/s2/writer.go b/vendor/github.com/klauspost/compress/s2/writer.go index 0a46f2b984..fd15078f7d 100644 --- a/vendor/github.com/klauspost/compress/s2/writer.go +++ b/vendor/github.com/klauspost/compress/s2/writer.go @@ -83,11 +83,14 @@ type Writer struct { snappy bool flushOnWrite bool appendIndex bool + bufferCB func([]byte) level uint8 } type result struct { b []byte + // return when writing + ret []byte // Uncompressed start offset startOffset int64 } @@ -146,6 +149,10 @@ func (w *Writer) Reset(writer io.Writer) { for write := range toWrite { // Wait for the data to be available. input := <-write + if input.ret != nil && w.bufferCB != nil { + w.bufferCB(input.ret) + input.ret = nil + } in := input.b if len(in) > 0 { if w.err(nil) == nil { @@ -341,7 +348,8 @@ func (w *Writer) AddSkippableBlock(id uint8, data []byte) (err error) { // but the input buffer cannot be written to by the caller // until Flush or Close has been called when concurrency != 1. // -// If you cannot control that, use the regular Write function. +// Use the WriterBufferDone to receive a callback when the buffer is done +// Processing. // // Note that input is not buffered. // This means that each write will result in discrete blocks being created. @@ -364,6 +372,9 @@ func (w *Writer) EncodeBuffer(buf []byte) (err error) { } if w.concurrency == 1 { _, err := w.writeSync(buf) + if w.bufferCB != nil { + w.bufferCB(buf) + } return err } @@ -378,7 +389,7 @@ func (w *Writer) EncodeBuffer(buf []byte) (err error) { hWriter <- result{startOffset: w.uncompWritten, b: magicChunkBytes} } } - + orgBuf := buf for len(buf) > 0 { // Cut input. uncompressed := buf @@ -397,6 +408,9 @@ func (w *Writer) EncodeBuffer(buf []byte) (err error) { startOffset: w.uncompWritten, } w.uncompWritten += int64(len(uncompressed)) + if len(buf) == 0 && w.bufferCB != nil { + res.ret = orgBuf + } go func() { race.ReadSlice(uncompressed) @@ -922,7 +936,7 @@ func WriterBetterCompression() WriterOption { } // WriterBestCompression will enable better compression. -// EncodeBetter compresses better than Encode but typically with a +// EncodeBest compresses better than Encode but typically with a // big speed decrease on compression. func WriterBestCompression() WriterOption { return func(w *Writer) error { @@ -941,6 +955,17 @@ func WriterUncompressed() WriterOption { } } +// WriterBufferDone will perform a callback when EncodeBuffer has finished +// writing a buffer to the output and the buffer can safely be reused. +// If the buffer was split into several blocks, it will be sent after the last block. +// Callbacks will not be done concurrently. +func WriterBufferDone(fn func(b []byte)) WriterOption { + return func(w *Writer) error { + w.bufferCB = fn + return nil + } +} + // WriterBlockSize allows to override the default block size. // Blocks will be this size or smaller. // Minimum size is 4KB and maximum size is 4MB. diff --git a/vendor/github.com/klauspost/compress/zstd/blockdec.go b/vendor/github.com/klauspost/compress/zstd/blockdec.go index 03744fbc76..9c28840c3b 100644 --- a/vendor/github.com/klauspost/compress/zstd/blockdec.go +++ b/vendor/github.com/klauspost/compress/zstd/blockdec.go @@ -598,7 +598,9 @@ func (b *blockDec) prepareSequences(in []byte, hist *history) (err error) { printf("RLE set to 0x%x, code: %v", symb, v) } case compModeFSE: - println("Reading table for", tableIndex(i)) + if debugDecoder { + println("Reading table for", tableIndex(i)) + } if seq.fse == nil || seq.fse.preDefined { seq.fse = fseDecoderPool.Get().(*fseDecoder) } diff --git a/vendor/github.com/klauspost/compress/zstd/enc_better.go b/vendor/github.com/klauspost/compress/zstd/enc_better.go index a4f5bf91fc..84a79fde76 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_better.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_better.go @@ -179,9 +179,9 @@ encodeLoop: if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { // Consider history as well. var seq seq - lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + length := 4 + e.matchlen(s+4+repOff, repIndex+4, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -210,12 +210,12 @@ encodeLoop: // Index match start+1 (long) -> s - 1 index0 := s + repOff - s += lenght + repOff + s += length + repOff nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop @@ -241,9 +241,9 @@ encodeLoop: if false && repIndex >= 0 && load6432(src, repIndex) == load6432(src, s+repOff) { // Consider history as well. var seq seq - lenght := 8 + e.matchlen(s+8+repOff2, repIndex+8, src) + length := 8 + e.matchlen(s+8+repOff2, repIndex+8, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -270,11 +270,11 @@ encodeLoop: } blk.sequences = append(blk.sequences, seq) - s += lenght + repOff2 + s += length + repOff2 nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop @@ -708,9 +708,9 @@ encodeLoop: if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { // Consider history as well. var seq seq - lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + length := 4 + e.matchlen(s+4+repOff, repIndex+4, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -738,12 +738,12 @@ encodeLoop: blk.sequences = append(blk.sequences, seq) // Index match start+1 (long) -> s - 1 - s += lenght + repOff + s += length + repOff nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop @@ -772,9 +772,9 @@ encodeLoop: if false && repIndex >= 0 && load6432(src, repIndex) == load6432(src, s+repOff) { // Consider history as well. var seq seq - lenght := 8 + e.matchlen(s+8+repOff2, repIndex+8, src) + length := 8 + e.matchlen(s+8+repOff2, repIndex+8, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -801,11 +801,11 @@ encodeLoop: } blk.sequences = append(blk.sequences, seq) - s += lenght + repOff2 + s += length + repOff2 nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop diff --git a/vendor/github.com/klauspost/compress/zstd/enc_dfast.go b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go index a154c18f74..d36be7bd8c 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_dfast.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go @@ -138,9 +138,9 @@ encodeLoop: if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { // Consider history as well. var seq seq - lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + length := 4 + e.matchlen(s+4+repOff, repIndex+4, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -166,11 +166,11 @@ encodeLoop: println("repeat sequence", seq, "next s:", s) } blk.sequences = append(blk.sequences, seq) - s += lenght + repOff + s += length + repOff nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop @@ -798,9 +798,9 @@ encodeLoop: if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { // Consider history as well. var seq seq - lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + length := 4 + e.matchlen(s+4+repOff, repIndex+4, src) - seq.matchLen = uint32(lenght - zstdMinMatch) + seq.matchLen = uint32(length - zstdMinMatch) // We might be able to match backwards. // Extend as long as we can. @@ -826,11 +826,11 @@ encodeLoop: println("repeat sequence", seq, "next s:", s) } blk.sequences = append(blk.sequences, seq) - s += lenght + repOff + s += length + repOff nextEmit = s if s >= sLimit { if debugEncoder { - println("repeat ended", s, lenght) + println("repeat ended", s, length) } break encodeLoop diff --git a/vendor/github.com/klauspost/compress/zstd/encoder.go b/vendor/github.com/klauspost/compress/zstd/encoder.go index 72af7ef0fe..8f8223cd3a 100644 --- a/vendor/github.com/klauspost/compress/zstd/encoder.go +++ b/vendor/github.com/klauspost/compress/zstd/encoder.go @@ -6,6 +6,7 @@ package zstd import ( "crypto/rand" + "errors" "fmt" "io" "math" @@ -149,6 +150,9 @@ func (e *Encoder) ResetContentSize(w io.Writer, size int64) { // and write CRC if requested. func (e *Encoder) Write(p []byte) (n int, err error) { s := &e.state + if s.eofWritten { + return 0, ErrEncoderClosed + } for len(p) > 0 { if len(p)+len(s.filling) < e.o.blockSize { if e.o.crc { @@ -202,7 +206,7 @@ func (e *Encoder) nextBlock(final bool) error { return nil } if final && len(s.filling) > 0 { - s.current = e.EncodeAll(s.filling, s.current[:0]) + s.current = e.encodeAll(s.encoder, s.filling, s.current[:0]) var n2 int n2, s.err = s.w.Write(s.current) if s.err != nil { @@ -288,6 +292,9 @@ func (e *Encoder) nextBlock(final bool) error { s.filling, s.current, s.previous = s.previous[:0], s.filling, s.current s.nInput += int64(len(s.current)) s.wg.Add(1) + if final { + s.eofWritten = true + } go func(src []byte) { if debugEncoder { println("Adding block,", len(src), "bytes, final:", final) @@ -303,9 +310,6 @@ func (e *Encoder) nextBlock(final bool) error { blk := enc.Block() enc.Encode(blk, src) blk.last = final - if final { - s.eofWritten = true - } // Wait for pending writes. s.wWg.Wait() if s.writeErr != nil { @@ -401,12 +405,20 @@ func (e *Encoder) Flush() error { if len(s.filling) > 0 { err := e.nextBlock(false) if err != nil { + // Ignore Flush after Close. + if errors.Is(s.err, ErrEncoderClosed) { + return nil + } return err } } s.wg.Wait() s.wWg.Wait() if s.err != nil { + // Ignore Flush after Close. + if errors.Is(s.err, ErrEncoderClosed) { + return nil + } return s.err } return s.writeErr @@ -422,6 +434,9 @@ func (e *Encoder) Close() error { } err := e.nextBlock(true) if err != nil { + if errors.Is(s.err, ErrEncoderClosed) { + return nil + } return err } if s.frameContentSize > 0 { @@ -459,6 +474,11 @@ func (e *Encoder) Close() error { } _, s.err = s.w.Write(frame) } + if s.err == nil { + s.err = ErrEncoderClosed + return nil + } + return s.err } @@ -469,6 +489,15 @@ func (e *Encoder) Close() error { // Data compressed with EncodeAll can be decoded with the Decoder, // using either a stream or DecodeAll. func (e *Encoder) EncodeAll(src, dst []byte) []byte { + e.init.Do(e.initialize) + enc := <-e.encoders + defer func() { + e.encoders <- enc + }() + return e.encodeAll(enc, src, dst) +} + +func (e *Encoder) encodeAll(enc encoder, src, dst []byte) []byte { if len(src) == 0 { if e.o.fullZero { // Add frame header. @@ -491,13 +520,7 @@ func (e *Encoder) EncodeAll(src, dst []byte) []byte { } return dst } - e.init.Do(e.initialize) - enc := <-e.encoders - defer func() { - // Release encoder reference to last block. - // If a non-single block is needed the encoder will reset again. - e.encoders <- enc - }() + // Use single segments when above minimum window and below window size. single := len(src) <= e.o.windowSize && len(src) > MinWindowSize if e.o.single != nil { diff --git a/vendor/github.com/klauspost/compress/zstd/framedec.go b/vendor/github.com/klauspost/compress/zstd/framedec.go index 53e160f7e5..e47af66e7c 100644 --- a/vendor/github.com/klauspost/compress/zstd/framedec.go +++ b/vendor/github.com/klauspost/compress/zstd/framedec.go @@ -146,7 +146,9 @@ func (d *frameDec) reset(br byteBuffer) error { } return err } - printf("raw: %x, mantissa: %d, exponent: %d\n", wd, wd&7, wd>>3) + if debugDecoder { + printf("raw: %x, mantissa: %d, exponent: %d\n", wd, wd&7, wd>>3) + } windowLog := 10 + (wd >> 3) windowBase := uint64(1) << windowLog windowAdd := (windowBase / 8) * uint64(wd&0x7) diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go index 8adabd8287..c59f17e07a 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go @@ -146,7 +146,7 @@ func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) { return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) default: - return true, fmt.Errorf("sequenceDecs_decode returned erronous code %d", errCode) + return true, fmt.Errorf("sequenceDecs_decode returned erroneous code %d", errCode) } s.seqSize += ctx.litRemain @@ -292,7 +292,7 @@ func (s *sequenceDecs) decode(seqs []seqVals) error { return io.ErrUnexpectedEOF } - return fmt.Errorf("sequenceDecs_decode_amd64 returned erronous code %d", errCode) + return fmt.Errorf("sequenceDecs_decode_amd64 returned erroneous code %d", errCode) } if ctx.litRemain < 0 { diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s index 5b06174b89..f5591fa1e8 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s @@ -1814,7 +1814,7 @@ TEXT ·sequenceDecs_decodeSync_amd64(SB), $64-32 MOVQ 40(SP), AX ADDQ AX, 48(SP) - // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) ADDQ R10, 32(SP) // outBase += outPosition @@ -2376,7 +2376,7 @@ TEXT ·sequenceDecs_decodeSync_bmi2(SB), $64-32 MOVQ 40(SP), CX ADDQ CX, 48(SP) - // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) ADDQ R9, 32(SP) // outBase += outPosition @@ -2896,7 +2896,7 @@ TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $64-32 MOVQ 40(SP), AX ADDQ AX, 48(SP) - // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) ADDQ R10, 32(SP) // outBase += outPosition @@ -3560,7 +3560,7 @@ TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $64-32 MOVQ 40(SP), CX ADDQ CX, 48(SP) - // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) ADDQ R9, 32(SP) // outBase += outPosition diff --git a/vendor/github.com/klauspost/compress/zstd/zstd.go b/vendor/github.com/klauspost/compress/zstd/zstd.go index 4be7cc7367..066bef2a4f 100644 --- a/vendor/github.com/klauspost/compress/zstd/zstd.go +++ b/vendor/github.com/klauspost/compress/zstd/zstd.go @@ -88,6 +88,10 @@ var ( // Close has been called. ErrDecoderClosed = errors.New("decoder used after Close") + // ErrEncoderClosed will be returned if the Encoder was used after + // Close has been called. + ErrEncoderClosed = errors.New("encoder used after Close") + // ErrDecoderNilInput is returned when a nil Reader was provided // and an operation other than Reset/DecodeAll/Close was attempted. ErrDecoderNilInput = errors.New("nil input provided as reader") diff --git a/vendor/github.com/minio/minio-go/v7/Makefile b/vendor/github.com/minio/minio-go/v7/Makefile index 68444aa681..9e4ddc4c88 100644 --- a/vendor/github.com/minio/minio-go/v7/Makefile +++ b/vendor/github.com/minio/minio-go/v7/Makefile @@ -32,6 +32,10 @@ functional-test: @GO111MODULE=on go build -race functional_tests.go @SERVER_ENDPOINT=localhost:9000 ACCESS_KEY=minioadmin SECRET_KEY=minioadmin ENABLE_HTTPS=1 MINT_MODE=full ./functional_tests +functional-test-notls: + @GO111MODULE=on go build -race functional_tests.go + @SERVER_ENDPOINT=localhost:9000 ACCESS_KEY=minioadmin SECRET_KEY=minioadmin ENABLE_HTTPS=0 MINT_MODE=full ./functional_tests + clean: @echo "Cleaning up all the generated files" @find . -name '*.test' | xargs rm -fv diff --git a/vendor/github.com/minio/minio-go/v7/README.md b/vendor/github.com/minio/minio-go/v7/README.md index 82f70a131a..be7963c52e 100644 --- a/vendor/github.com/minio/minio-go/v7/README.md +++ b/vendor/github.com/minio/minio-go/v7/README.md @@ -253,7 +253,7 @@ The full API Reference is available here. * [setbucketencryption.go](https://github.com/minio/minio-go/blob/master/examples/s3/setbucketencryption.go) * [getbucketencryption.go](https://github.com/minio/minio-go/blob/master/examples/s3/getbucketencryption.go) -* [deletebucketencryption.go](https://github.com/minio/minio-go/blob/master/examples/s3/deletebucketencryption.go) +* [removebucketencryption.go](https://github.com/minio/minio-go/blob/master/examples/s3/removebucketencryption.go) ### Full Examples : Bucket replication Operations diff --git a/vendor/github.com/minio/minio-go/v7/api-datatypes.go b/vendor/github.com/minio/minio-go/v7/api-datatypes.go index 97a6f80b25..8a8fd88985 100644 --- a/vendor/github.com/minio/minio-go/v7/api-datatypes.go +++ b/vendor/github.com/minio/minio-go/v7/api-datatypes.go @@ -143,10 +143,11 @@ type UploadInfo struct { // Verified checksum values, if any. // Values are base64 (standard) encoded. // For multipart objects this is a checksum of the checksum of each part. - ChecksumCRC32 string - ChecksumCRC32C string - ChecksumSHA1 string - ChecksumSHA256 string + ChecksumCRC32 string + ChecksumCRC32C string + ChecksumSHA1 string + ChecksumSHA256 string + ChecksumCRC64NVME string } // RestoreInfo contains information of the restore operation of an archived object @@ -215,10 +216,11 @@ type ObjectInfo struct { Restore *RestoreInfo // Checksum values - ChecksumCRC32 string - ChecksumCRC32C string - ChecksumSHA1 string - ChecksumSHA256 string + ChecksumCRC32 string + ChecksumCRC32C string + ChecksumSHA1 string + ChecksumSHA256 string + ChecksumCRC64NVME string Internal *struct { K int // Data blocks diff --git a/vendor/github.com/minio/minio-go/v7/api-get-object.go b/vendor/github.com/minio/minio-go/v7/api-get-object.go index d7fd27835b..5cc85f61c2 100644 --- a/vendor/github.com/minio/minio-go/v7/api-get-object.go +++ b/vendor/github.com/minio/minio-go/v7/api-get-object.go @@ -318,7 +318,7 @@ func (o *Object) doGetRequest(request getRequest) (getResponse, error) { response := <-o.resCh // Return any error to the top level. - if response.Error != nil { + if response.Error != nil && response.Error != io.EOF { return response, response.Error } @@ -340,7 +340,7 @@ func (o *Object) doGetRequest(request getRequest) (getResponse, error) { // Data are ready on the wire, no need to reinitiate connection in lower level o.seekData = false - return response, nil + return response, response.Error } // setOffset - handles the setting of offsets for diff --git a/vendor/github.com/minio/minio-go/v7/api-prompt-object.go b/vendor/github.com/minio/minio-go/v7/api-prompt-object.go new file mode 100644 index 0000000000..dac062a75b --- /dev/null +++ b/vendor/github.com/minio/minio-go/v7/api-prompt-object.go @@ -0,0 +1,78 @@ +/* + * MinIO Go Library for Amazon S3 Compatible Cloud Storage + * Copyright 2015-2024 MinIO, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package minio + +import ( + "bytes" + "context" + "io" + "net/http" + + "github.com/goccy/go-json" + "github.com/minio/minio-go/v7/pkg/s3utils" +) + +// PromptObject performs language model inference with the prompt and referenced object as context. +// Inference is performed using a Lambda handler that can process the prompt and object. +// Currently, this functionality is limited to certain MinIO servers. +func (c *Client) PromptObject(ctx context.Context, bucketName, objectName, prompt string, opts PromptObjectOptions) (io.ReadCloser, error) { + // Input validation. + if err := s3utils.CheckValidBucketName(bucketName); err != nil { + return nil, ErrorResponse{ + StatusCode: http.StatusBadRequest, + Code: "InvalidBucketName", + Message: err.Error(), + } + } + if err := s3utils.CheckValidObjectName(objectName); err != nil { + return nil, ErrorResponse{ + StatusCode: http.StatusBadRequest, + Code: "XMinioInvalidObjectName", + Message: err.Error(), + } + } + + opts.AddLambdaArnToReqParams(opts.LambdaArn) + opts.SetHeader("Content-Type", "application/json") + opts.AddPromptArg("prompt", prompt) + promptReqBytes, err := json.Marshal(opts.PromptArgs) + if err != nil { + return nil, err + } + + // Execute POST on bucket/object. + resp, err := c.executeMethod(ctx, http.MethodPost, requestMetadata{ + bucketName: bucketName, + objectName: objectName, + queryValues: opts.toQueryValues(), + customHeader: opts.Header(), + contentSHA256Hex: sum256Hex(promptReqBytes), + contentBody: bytes.NewReader(promptReqBytes), + contentLength: int64(len(promptReqBytes)), + }) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + defer closeResponse(resp) + return nil, httpRespToErrorResponse(resp, bucketName, objectName) + } + + return resp.Body, nil +} diff --git a/vendor/github.com/minio/minio-go/v7/api-prompt-options.go b/vendor/github.com/minio/minio-go/v7/api-prompt-options.go new file mode 100644 index 0000000000..4493a75d4c --- /dev/null +++ b/vendor/github.com/minio/minio-go/v7/api-prompt-options.go @@ -0,0 +1,84 @@ +/* + * MinIO Go Library for Amazon S3 Compatible Cloud Storage + * Copyright 2015-2024 MinIO, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package minio + +import ( + "net/http" + "net/url" +) + +// PromptObjectOptions provides options to PromptObject call. +// LambdaArn is the ARN of the Prompt Lambda to be invoked. +// PromptArgs is a map of key-value pairs to be passed to the inference action on the Prompt Lambda. +// "prompt" is a reserved key and should not be used as a key in PromptArgs. +type PromptObjectOptions struct { + LambdaArn string + PromptArgs map[string]any + headers map[string]string + reqParams url.Values +} + +// Header returns the http.Header representation of the POST options. +func (o PromptObjectOptions) Header() http.Header { + headers := make(http.Header, len(o.headers)) + for k, v := range o.headers { + headers.Set(k, v) + } + return headers +} + +// AddPromptArg Add a key value pair to the prompt arguments where the key is a string and +// the value is a JSON serializable. +func (o *PromptObjectOptions) AddPromptArg(key string, value any) { + if o.PromptArgs == nil { + o.PromptArgs = make(map[string]any) + } + o.PromptArgs[key] = value +} + +// AddLambdaArnToReqParams adds the lambdaArn to the request query string parameters. +func (o *PromptObjectOptions) AddLambdaArnToReqParams(lambdaArn string) { + if o.reqParams == nil { + o.reqParams = make(url.Values) + } + o.reqParams.Add("lambdaArn", lambdaArn) +} + +// SetHeader adds a key value pair to the options. The +// key-value pair will be part of the HTTP POST request +// headers. +func (o *PromptObjectOptions) SetHeader(key, value string) { + if o.headers == nil { + o.headers = make(map[string]string) + } + o.headers[http.CanonicalHeaderKey(key)] = value +} + +// toQueryValues - Convert the reqParams in Options to query string parameters. +func (o *PromptObjectOptions) toQueryValues() url.Values { + urlValues := make(url.Values) + if o.reqParams != nil { + for key, values := range o.reqParams { + for _, value := range values { + urlValues.Add(key, value) + } + } + } + + return urlValues +} diff --git a/vendor/github.com/minio/minio-go/v7/api-put-object-fan-out.go b/vendor/github.com/minio/minio-go/v7/api-put-object-fan-out.go index 0ae9142e1d..3023b949cd 100644 --- a/vendor/github.com/minio/minio-go/v7/api-put-object-fan-out.go +++ b/vendor/github.com/minio/minio-go/v7/api-put-object-fan-out.go @@ -85,7 +85,10 @@ func (c *Client) PutObjectFanOut(ctx context.Context, bucket string, fanOutData policy.SetEncryption(fanOutReq.SSE) // Set checksum headers if any. - policy.SetChecksum(fanOutReq.Checksum) + err := policy.SetChecksum(fanOutReq.Checksum) + if err != nil { + return nil, err + } url, formData, err := c.PresignedPostPolicy(ctx, policy) if err != nil { diff --git a/vendor/github.com/minio/minio-go/v7/api-put-object-multipart.go b/vendor/github.com/minio/minio-go/v7/api-put-object-multipart.go index a70cbea9e5..03bd34f76b 100644 --- a/vendor/github.com/minio/minio-go/v7/api-put-object-multipart.go +++ b/vendor/github.com/minio/minio-go/v7/api-put-object-multipart.go @@ -83,10 +83,7 @@ func (c *Client) putObjectMultipartNoStream(ctx context.Context, bucketName, obj // HTTPS connection. hashAlgos, hashSums := c.hashMaterials(opts.SendContentMd5, !opts.DisableContentSha256) if len(hashSums) == 0 { - if opts.UserMetadata == nil { - opts.UserMetadata = make(map[string]string, 1) - } - opts.UserMetadata["X-Amz-Checksum-Algorithm"] = opts.AutoChecksum.String() + addAutoChecksumHeaders(&opts) } // Initiate a new multipart upload. @@ -113,7 +110,6 @@ func (c *Client) putObjectMultipartNoStream(ctx context.Context, bucketName, obj // Create checksums // CRC32C is ~50% faster on AMD64 @ 30GB/s - var crcBytes []byte customHeader := make(http.Header) crc := opts.AutoChecksum.Hasher() for partNumber <= totalPartsCount { @@ -154,7 +150,6 @@ func (c *Client) putObjectMultipartNoStream(ctx context.Context, bucketName, obj crc.Write(buf[:length]) cSum := crc.Sum(nil) customHeader.Set(opts.AutoChecksum.Key(), base64.StdEncoding.EncodeToString(cSum)) - crcBytes = append(crcBytes, cSum...) } p := uploadPartParams{bucketName: bucketName, objectName: objectName, uploadID: uploadID, reader: rd, partNumber: partNumber, md5Base64: md5Base64, sha256Hex: sha256Hex, size: int64(length), sse: opts.ServerSideEncryption, streamSha256: !opts.DisableContentSha256, customHeader: customHeader} @@ -182,18 +177,21 @@ func (c *Client) putObjectMultipartNoStream(ctx context.Context, bucketName, obj // Loop over total uploaded parts to save them in // Parts array before completing the multipart request. + allParts := make([]ObjectPart, 0, len(partsInfo)) for i := 1; i < partNumber; i++ { part, ok := partsInfo[i] if !ok { return UploadInfo{}, errInvalidArgument(fmt.Sprintf("Missing part number %d", i)) } + allParts = append(allParts, part) complMultipartUpload.Parts = append(complMultipartUpload.Parts, CompletePart{ - ETag: part.ETag, - PartNumber: part.PartNumber, - ChecksumCRC32: part.ChecksumCRC32, - ChecksumCRC32C: part.ChecksumCRC32C, - ChecksumSHA1: part.ChecksumSHA1, - ChecksumSHA256: part.ChecksumSHA256, + ETag: part.ETag, + PartNumber: part.PartNumber, + ChecksumCRC32: part.ChecksumCRC32, + ChecksumCRC32C: part.ChecksumCRC32C, + ChecksumSHA1: part.ChecksumSHA1, + ChecksumSHA256: part.ChecksumSHA256, + ChecksumCRC64NVME: part.ChecksumCRC64NVME, }) } @@ -203,12 +201,8 @@ func (c *Client) putObjectMultipartNoStream(ctx context.Context, bucketName, obj ServerSideEncryption: opts.ServerSideEncryption, AutoChecksum: opts.AutoChecksum, } - if len(crcBytes) > 0 { - // Add hash of hashes. - crc.Reset() - crc.Write(crcBytes) - opts.UserMetadata = map[string]string{opts.AutoChecksum.Key(): base64.StdEncoding.EncodeToString(crc.Sum(nil))} - } + applyAutoChecksum(&opts, allParts) + uploadInfo, err := c.completeMultipartUpload(ctx, bucketName, objectName, uploadID, complMultipartUpload, opts) if err != nil { return UploadInfo{}, err @@ -354,10 +348,11 @@ func (c *Client) uploadPart(ctx context.Context, p uploadPartParams) (ObjectPart // Once successfully uploaded, return completed part. h := resp.Header objPart := ObjectPart{ - ChecksumCRC32: h.Get("x-amz-checksum-crc32"), - ChecksumCRC32C: h.Get("x-amz-checksum-crc32c"), - ChecksumSHA1: h.Get("x-amz-checksum-sha1"), - ChecksumSHA256: h.Get("x-amz-checksum-sha256"), + ChecksumCRC32: h.Get(ChecksumCRC32.Key()), + ChecksumCRC32C: h.Get(ChecksumCRC32C.Key()), + ChecksumSHA1: h.Get(ChecksumSHA1.Key()), + ChecksumSHA256: h.Get(ChecksumSHA256.Key()), + ChecksumCRC64NVME: h.Get(ChecksumCRC64NVME.Key()), } objPart.Size = p.size objPart.PartNumber = p.partNumber @@ -457,9 +452,10 @@ func (c *Client) completeMultipartUpload(ctx context.Context, bucketName, object Expiration: expTime, ExpirationRuleID: ruleID, - ChecksumSHA256: completeMultipartUploadResult.ChecksumSHA256, - ChecksumSHA1: completeMultipartUploadResult.ChecksumSHA1, - ChecksumCRC32: completeMultipartUploadResult.ChecksumCRC32, - ChecksumCRC32C: completeMultipartUploadResult.ChecksumCRC32C, + ChecksumSHA256: completeMultipartUploadResult.ChecksumSHA256, + ChecksumSHA1: completeMultipartUploadResult.ChecksumSHA1, + ChecksumCRC32: completeMultipartUploadResult.ChecksumCRC32, + ChecksumCRC32C: completeMultipartUploadResult.ChecksumCRC32C, + ChecksumCRC64NVME: completeMultipartUploadResult.ChecksumCRC64NVME, }, nil } diff --git a/vendor/github.com/minio/minio-go/v7/api-put-object-streaming.go b/vendor/github.com/minio/minio-go/v7/api-put-object-streaming.go index eef976c8c4..3ff3b69efd 100644 --- a/vendor/github.com/minio/minio-go/v7/api-put-object-streaming.go +++ b/vendor/github.com/minio/minio-go/v7/api-put-object-streaming.go @@ -52,7 +52,7 @@ func (c *Client) putObjectMultipartStream(ctx context.Context, bucketName, objec } else { info, err = c.putObjectMultipartStreamOptionalChecksum(ctx, bucketName, objectName, reader, size, opts) } - if err != nil { + if err != nil && s3utils.IsGoogleEndpoint(*c.endpointURL) { errResp := ToErrorResponse(err) // Verify if multipart functionality is not available, if not // fall back to single PutObject operation. @@ -113,10 +113,7 @@ func (c *Client) putObjectMultipartStreamFromReadAt(ctx context.Context, bucketN } withChecksum := c.trailingHeaderSupport if withChecksum { - if opts.UserMetadata == nil { - opts.UserMetadata = make(map[string]string, 1) - } - opts.UserMetadata["X-Amz-Checksum-Algorithm"] = opts.AutoChecksum.String() + addAutoChecksumHeaders(&opts) } // Initiate a new multipart upload. uploadID, err := c.newUploadID(ctx, bucketName, objectName, opts) @@ -240,6 +237,7 @@ func (c *Client) putObjectMultipartStreamFromReadAt(ctx context.Context, bucketN // Gather the responses as they occur and update any // progress bar. + allParts := make([]ObjectPart, 0, totalPartsCount) for u := 1; u <= totalPartsCount; u++ { select { case <-ctx.Done(): @@ -248,16 +246,17 @@ func (c *Client) putObjectMultipartStreamFromReadAt(ctx context.Context, bucketN if uploadRes.Error != nil { return UploadInfo{}, uploadRes.Error } - + allParts = append(allParts, uploadRes.Part) // Update the totalUploadedSize. totalUploadedSize += uploadRes.Size complMultipartUpload.Parts = append(complMultipartUpload.Parts, CompletePart{ - ETag: uploadRes.Part.ETag, - PartNumber: uploadRes.Part.PartNumber, - ChecksumCRC32: uploadRes.Part.ChecksumCRC32, - ChecksumCRC32C: uploadRes.Part.ChecksumCRC32C, - ChecksumSHA1: uploadRes.Part.ChecksumSHA1, - ChecksumSHA256: uploadRes.Part.ChecksumSHA256, + ETag: uploadRes.Part.ETag, + PartNumber: uploadRes.Part.PartNumber, + ChecksumCRC32: uploadRes.Part.ChecksumCRC32, + ChecksumCRC32C: uploadRes.Part.ChecksumCRC32C, + ChecksumSHA1: uploadRes.Part.ChecksumSHA1, + ChecksumSHA256: uploadRes.Part.ChecksumSHA256, + ChecksumCRC64NVME: uploadRes.Part.ChecksumCRC64NVME, }) } } @@ -275,15 +274,7 @@ func (c *Client) putObjectMultipartStreamFromReadAt(ctx context.Context, bucketN AutoChecksum: opts.AutoChecksum, } if withChecksum { - // Add hash of hashes. - crc := opts.AutoChecksum.Hasher() - for _, part := range complMultipartUpload.Parts { - cs, err := base64.StdEncoding.DecodeString(part.Checksum(opts.AutoChecksum)) - if err == nil { - crc.Write(cs) - } - } - opts.UserMetadata = map[string]string{opts.AutoChecksum.KeyCapitalized(): base64.StdEncoding.EncodeToString(crc.Sum(nil))} + applyAutoChecksum(&opts, allParts) } uploadInfo, err := c.completeMultipartUpload(ctx, bucketName, objectName, uploadID, complMultipartUpload, opts) @@ -312,10 +303,7 @@ func (c *Client) putObjectMultipartStreamOptionalChecksum(ctx context.Context, b } if !opts.SendContentMd5 { - if opts.UserMetadata == nil { - opts.UserMetadata = make(map[string]string, 1) - } - opts.UserMetadata["X-Amz-Checksum-Algorithm"] = opts.AutoChecksum.String() + addAutoChecksumHeaders(&opts) } // Calculate the optimal parts info for a given size. @@ -342,7 +330,6 @@ func (c *Client) putObjectMultipartStreamOptionalChecksum(ctx context.Context, b // Create checksums // CRC32C is ~50% faster on AMD64 @ 30GB/s - var crcBytes []byte customHeader := make(http.Header) crc := opts.AutoChecksum.Hasher() md5Hash := c.md5Hasher() @@ -389,7 +376,6 @@ func (c *Client) putObjectMultipartStreamOptionalChecksum(ctx context.Context, b crc.Write(buf[:length]) cSum := crc.Sum(nil) customHeader.Set(opts.AutoChecksum.KeyCapitalized(), base64.StdEncoding.EncodeToString(cSum)) - crcBytes = append(crcBytes, cSum...) } // Update progress reader appropriately to the latest offset @@ -420,18 +406,21 @@ func (c *Client) putObjectMultipartStreamOptionalChecksum(ctx context.Context, b // Loop over total uploaded parts to save them in // Parts array before completing the multipart request. + allParts := make([]ObjectPart, 0, len(partsInfo)) for i := 1; i < partNumber; i++ { part, ok := partsInfo[i] if !ok { return UploadInfo{}, errInvalidArgument(fmt.Sprintf("Missing part number %d", i)) } + allParts = append(allParts, part) complMultipartUpload.Parts = append(complMultipartUpload.Parts, CompletePart{ - ETag: part.ETag, - PartNumber: part.PartNumber, - ChecksumCRC32: part.ChecksumCRC32, - ChecksumCRC32C: part.ChecksumCRC32C, - ChecksumSHA1: part.ChecksumSHA1, - ChecksumSHA256: part.ChecksumSHA256, + ETag: part.ETag, + PartNumber: part.PartNumber, + ChecksumCRC32: part.ChecksumCRC32, + ChecksumCRC32C: part.ChecksumCRC32C, + ChecksumSHA1: part.ChecksumSHA1, + ChecksumSHA256: part.ChecksumSHA256, + ChecksumCRC64NVME: part.ChecksumCRC64NVME, }) } @@ -442,12 +431,7 @@ func (c *Client) putObjectMultipartStreamOptionalChecksum(ctx context.Context, b ServerSideEncryption: opts.ServerSideEncryption, AutoChecksum: opts.AutoChecksum, } - if len(crcBytes) > 0 { - // Add hash of hashes. - crc.Reset() - crc.Write(crcBytes) - opts.UserMetadata = map[string]string{opts.AutoChecksum.KeyCapitalized(): base64.StdEncoding.EncodeToString(crc.Sum(nil))} - } + applyAutoChecksum(&opts, allParts) uploadInfo, err := c.completeMultipartUpload(ctx, bucketName, objectName, uploadID, complMultipartUpload, opts) if err != nil { return UploadInfo{}, err @@ -475,10 +459,7 @@ func (c *Client) putObjectMultipartStreamParallel(ctx context.Context, bucketNam opts.AutoChecksum = opts.Checksum } if !opts.SendContentMd5 { - if opts.UserMetadata == nil { - opts.UserMetadata = make(map[string]string, 1) - } - opts.UserMetadata["X-Amz-Checksum-Algorithm"] = opts.AutoChecksum.String() + addAutoChecksumHeaders(&opts) } // Cancel all when an error occurs. @@ -510,7 +491,6 @@ func (c *Client) putObjectMultipartStreamParallel(ctx context.Context, bucketNam // Create checksums // CRC32C is ~50% faster on AMD64 @ 30GB/s - var crcBytes []byte crc := opts.AutoChecksum.Hasher() // Total data read and written to server. should be equal to 'size' at the end of the call. @@ -570,7 +550,6 @@ func (c *Client) putObjectMultipartStreamParallel(ctx context.Context, bucketNam crc.Write(buf[:length]) cSum := crc.Sum(nil) customHeader.Set(opts.AutoChecksum.Key(), base64.StdEncoding.EncodeToString(cSum)) - crcBytes = append(crcBytes, cSum...) } wg.Add(1) @@ -630,18 +609,21 @@ func (c *Client) putObjectMultipartStreamParallel(ctx context.Context, bucketNam // Loop over total uploaded parts to save them in // Parts array before completing the multipart request. + allParts := make([]ObjectPart, 0, len(partsInfo)) for i := 1; i < partNumber; i++ { part, ok := partsInfo[i] if !ok { return UploadInfo{}, errInvalidArgument(fmt.Sprintf("Missing part number %d", i)) } + allParts = append(allParts, part) complMultipartUpload.Parts = append(complMultipartUpload.Parts, CompletePart{ - ETag: part.ETag, - PartNumber: part.PartNumber, - ChecksumCRC32: part.ChecksumCRC32, - ChecksumCRC32C: part.ChecksumCRC32C, - ChecksumSHA1: part.ChecksumSHA1, - ChecksumSHA256: part.ChecksumSHA256, + ETag: part.ETag, + PartNumber: part.PartNumber, + ChecksumCRC32: part.ChecksumCRC32, + ChecksumCRC32C: part.ChecksumCRC32C, + ChecksumSHA1: part.ChecksumSHA1, + ChecksumSHA256: part.ChecksumSHA256, + ChecksumCRC64NVME: part.ChecksumCRC64NVME, }) } @@ -652,12 +634,8 @@ func (c *Client) putObjectMultipartStreamParallel(ctx context.Context, bucketNam ServerSideEncryption: opts.ServerSideEncryption, AutoChecksum: opts.AutoChecksum, } - if len(crcBytes) > 0 { - // Add hash of hashes. - crc.Reset() - crc.Write(crcBytes) - opts.UserMetadata = map[string]string{opts.AutoChecksum.KeyCapitalized(): base64.StdEncoding.EncodeToString(crc.Sum(nil))} - } + applyAutoChecksum(&opts, allParts) + uploadInfo, err := c.completeMultipartUpload(ctx, bucketName, objectName, uploadID, complMultipartUpload, opts) if err != nil { return UploadInfo{}, err @@ -823,9 +801,10 @@ func (c *Client) putObjectDo(ctx context.Context, bucketName, objectName string, ExpirationRuleID: ruleID, // Checksum values - ChecksumCRC32: h.Get("x-amz-checksum-crc32"), - ChecksumCRC32C: h.Get("x-amz-checksum-crc32c"), - ChecksumSHA1: h.Get("x-amz-checksum-sha1"), - ChecksumSHA256: h.Get("x-amz-checksum-sha256"), + ChecksumCRC32: h.Get(ChecksumCRC32.Key()), + ChecksumCRC32C: h.Get(ChecksumCRC32C.Key()), + ChecksumSHA1: h.Get(ChecksumSHA1.Key()), + ChecksumSHA256: h.Get(ChecksumSHA256.Key()), + ChecksumCRC64NVME: h.Get(ChecksumCRC64NVME.Key()), }, nil } diff --git a/vendor/github.com/minio/minio-go/v7/api-put-object.go b/vendor/github.com/minio/minio-go/v7/api-put-object.go index d769648a7e..0981757841 100644 --- a/vendor/github.com/minio/minio-go/v7/api-put-object.go +++ b/vendor/github.com/minio/minio-go/v7/api-put-object.go @@ -45,6 +45,8 @@ const ( ReplicationStatusFailed ReplicationStatus = "FAILED" // ReplicationStatusReplica indicates object is a replica of a source ReplicationStatusReplica ReplicationStatus = "REPLICA" + // ReplicationStatusReplicaEdge indicates object is a replica of a edge source + ReplicationStatusReplicaEdge ReplicationStatus = "REPLICA-EDGE" ) // Empty returns true if no replication status set. @@ -385,10 +387,7 @@ func (c *Client) putObjectMultipartStreamNoLength(ctx context.Context, bucketNam opts.AutoChecksum = opts.Checksum } if !opts.SendContentMd5 { - if opts.UserMetadata == nil { - opts.UserMetadata = make(map[string]string, 1) - } - opts.UserMetadata["X-Amz-Checksum-Algorithm"] = opts.AutoChecksum.String() + addAutoChecksumHeaders(&opts) } // Initiate a new multipart upload. @@ -415,7 +414,6 @@ func (c *Client) putObjectMultipartStreamNoLength(ctx context.Context, bucketNam // Create checksums // CRC32C is ~50% faster on AMD64 @ 30GB/s - var crcBytes []byte customHeader := make(http.Header) crc := opts.AutoChecksum.Hasher() @@ -441,7 +439,6 @@ func (c *Client) putObjectMultipartStreamNoLength(ctx context.Context, bucketNam crc.Write(buf[:length]) cSum := crc.Sum(nil) customHeader.Set(opts.AutoChecksum.Key(), base64.StdEncoding.EncodeToString(cSum)) - crcBytes = append(crcBytes, cSum...) } // Update progress reader appropriately to the latest offset @@ -473,18 +470,21 @@ func (c *Client) putObjectMultipartStreamNoLength(ctx context.Context, bucketNam // Loop over total uploaded parts to save them in // Parts array before completing the multipart request. + allParts := make([]ObjectPart, 0, len(partsInfo)) for i := 1; i < partNumber; i++ { part, ok := partsInfo[i] if !ok { return UploadInfo{}, errInvalidArgument(fmt.Sprintf("Missing part number %d", i)) } + allParts = append(allParts, part) complMultipartUpload.Parts = append(complMultipartUpload.Parts, CompletePart{ - ETag: part.ETag, - PartNumber: part.PartNumber, - ChecksumCRC32: part.ChecksumCRC32, - ChecksumCRC32C: part.ChecksumCRC32C, - ChecksumSHA1: part.ChecksumSHA1, - ChecksumSHA256: part.ChecksumSHA256, + ETag: part.ETag, + PartNumber: part.PartNumber, + ChecksumCRC32: part.ChecksumCRC32, + ChecksumCRC32C: part.ChecksumCRC32C, + ChecksumSHA1: part.ChecksumSHA1, + ChecksumSHA256: part.ChecksumSHA256, + ChecksumCRC64NVME: part.ChecksumCRC64NVME, }) } @@ -495,12 +495,8 @@ func (c *Client) putObjectMultipartStreamNoLength(ctx context.Context, bucketNam ServerSideEncryption: opts.ServerSideEncryption, AutoChecksum: opts.AutoChecksum, } - if len(crcBytes) > 0 { - // Add hash of hashes. - crc.Reset() - crc.Write(crcBytes) - opts.UserMetadata = map[string]string{opts.AutoChecksum.KeyCapitalized(): base64.StdEncoding.EncodeToString(crc.Sum(nil))} - } + applyAutoChecksum(&opts, allParts) + uploadInfo, err := c.completeMultipartUpload(ctx, bucketName, objectName, uploadID, complMultipartUpload, opts) if err != nil { return UploadInfo{}, err diff --git a/vendor/github.com/minio/minio-go/v7/api-s3-datatypes.go b/vendor/github.com/minio/minio-go/v7/api-s3-datatypes.go index 790606c509..5e015fb827 100644 --- a/vendor/github.com/minio/minio-go/v7/api-s3-datatypes.go +++ b/vendor/github.com/minio/minio-go/v7/api-s3-datatypes.go @@ -18,6 +18,7 @@ package minio import ( + "encoding/base64" "encoding/xml" "errors" "io" @@ -276,10 +277,45 @@ type ObjectPart struct { Size int64 // Checksum values of each part. - ChecksumCRC32 string - ChecksumCRC32C string - ChecksumSHA1 string - ChecksumSHA256 string + ChecksumCRC32 string + ChecksumCRC32C string + ChecksumSHA1 string + ChecksumSHA256 string + ChecksumCRC64NVME string +} + +// Checksum will return the checksum for the given type. +// Will return the empty string if not set. +func (c ObjectPart) Checksum(t ChecksumType) string { + switch { + case t.Is(ChecksumCRC32C): + return c.ChecksumCRC32C + case t.Is(ChecksumCRC32): + return c.ChecksumCRC32 + case t.Is(ChecksumSHA1): + return c.ChecksumSHA1 + case t.Is(ChecksumSHA256): + return c.ChecksumSHA256 + case t.Is(ChecksumCRC64NVME): + return c.ChecksumCRC64NVME + } + return "" +} + +// ChecksumRaw returns the decoded checksum from the part. +func (c ObjectPart) ChecksumRaw(t ChecksumType) ([]byte, error) { + b64 := c.Checksum(t) + if b64 == "" { + return nil, errors.New("no checksum set") + } + decoded, err := base64.StdEncoding.DecodeString(b64) + if err != nil { + return nil, err + } + if len(decoded) != t.RawByteLen() { + return nil, errors.New("checksum length mismatch") + } + return decoded, nil } // ListObjectPartsResult container for ListObjectParts response. @@ -296,6 +332,12 @@ type ListObjectPartsResult struct { NextPartNumberMarker int MaxParts int + // ChecksumAlgorithm will be CRC32, CRC32C, etc. + ChecksumAlgorithm string + + // ChecksumType is FULL_OBJECT or COMPOSITE (assume COMPOSITE when unset) + ChecksumType string + // Indicates whether the returned list of parts is truncated. IsTruncated bool ObjectParts []ObjectPart `xml:"Part"` @@ -320,10 +362,11 @@ type completeMultipartUploadResult struct { ETag string // Checksum values, hash of hashes of parts. - ChecksumCRC32 string - ChecksumCRC32C string - ChecksumSHA1 string - ChecksumSHA256 string + ChecksumCRC32 string + ChecksumCRC32C string + ChecksumSHA1 string + ChecksumSHA256 string + ChecksumCRC64NVME string } // CompletePart sub container lists individual part numbers and their @@ -334,10 +377,11 @@ type CompletePart struct { ETag string // Checksum values - ChecksumCRC32 string `xml:"ChecksumCRC32,omitempty"` - ChecksumCRC32C string `xml:"ChecksumCRC32C,omitempty"` - ChecksumSHA1 string `xml:"ChecksumSHA1,omitempty"` - ChecksumSHA256 string `xml:"ChecksumSHA256,omitempty"` + ChecksumCRC32 string `xml:"ChecksumCRC32,omitempty"` + ChecksumCRC32C string `xml:"ChecksumCRC32C,omitempty"` + ChecksumSHA1 string `xml:"ChecksumSHA1,omitempty"` + ChecksumSHA256 string `xml:"ChecksumSHA256,omitempty"` + ChecksumCRC64NVME string `xml:",omitempty"` } // Checksum will return the checksum for the given type. @@ -352,6 +396,8 @@ func (c CompletePart) Checksum(t ChecksumType) string { return c.ChecksumSHA1 case t.Is(ChecksumSHA256): return c.ChecksumSHA256 + case t.Is(ChecksumCRC64NVME): + return c.ChecksumCRC64NVME } return "" } diff --git a/vendor/github.com/minio/minio-go/v7/api.go b/vendor/github.com/minio/minio-go/v7/api.go index 1d6b665025..83c003e499 100644 --- a/vendor/github.com/minio/minio-go/v7/api.go +++ b/vendor/github.com/minio/minio-go/v7/api.go @@ -99,6 +99,7 @@ type Client struct { healthStatus int32 trailingHeaderSupport bool + maxRetries int } // Options for New method @@ -123,12 +124,16 @@ type Options struct { // Custom hash routines. Leave nil to use standard. CustomMD5 func() md5simd.Hasher CustomSHA256 func() md5simd.Hasher + + // Number of times a request is retried. Defaults to 10 retries if this option is not configured. + // Set to 1 to disable retries. + MaxRetries int } // Global constants. const ( libraryName = "minio-go" - libraryVersion = "v7.0.77" + libraryVersion = "v7.0.82" ) // User Agent should always following the below style. @@ -278,6 +283,11 @@ func privateNew(endpoint string, opts *Options) (*Client, error) { // healthcheck is not initialized clnt.healthStatus = unknown + clnt.maxRetries = MaxRetry + if opts.MaxRetries > 0 { + clnt.maxRetries = opts.MaxRetries + } + // Return. return clnt, nil } @@ -590,9 +600,9 @@ func (c *Client) executeMethod(ctx context.Context, method string, metadata requ return nil, errors.New(c.endpointURL.String() + " is offline.") } - var retryable bool // Indicates if request can be retried. - var bodySeeker io.Seeker // Extracted seeker from io.Reader. - reqRetry := MaxRetry // Indicates how many times we can retry the request + var retryable bool // Indicates if request can be retried. + var bodySeeker io.Seeker // Extracted seeker from io.Reader. + var reqRetry = c.maxRetries // Indicates how many times we can retry the request if metadata.contentBody != nil { // Check if body is seekable then it is retryable. diff --git a/vendor/github.com/minio/minio-go/v7/checksum.go b/vendor/github.com/minio/minio-go/v7/checksum.go index 7eb1bf25ab..8e4c27ce42 100644 --- a/vendor/github.com/minio/minio-go/v7/checksum.go +++ b/vendor/github.com/minio/minio-go/v7/checksum.go @@ -21,11 +21,15 @@ import ( "crypto/sha1" "crypto/sha256" "encoding/base64" + "encoding/binary" + "errors" "hash" "hash/crc32" + "hash/crc64" "io" "math/bits" "net/http" + "sort" ) // ChecksumType contains information about the checksum type. @@ -41,23 +45,41 @@ const ( ChecksumCRC32 // ChecksumCRC32C indicates a CRC32 checksum with Castagnoli table. ChecksumCRC32C + // ChecksumCRC64NVME indicates CRC64 with 0xad93d23594c93659 polynomial. + ChecksumCRC64NVME // Keep after all valid checksums checksumLast + // ChecksumFullObject is a modifier that can be used on CRC32 and CRC32C + // to indicate full object checksums. + ChecksumFullObject + // checksumMask is a mask for valid checksum types. checksumMask = checksumLast - 1 // ChecksumNone indicates no checksum. ChecksumNone ChecksumType = 0 - amzChecksumAlgo = "x-amz-checksum-algorithm" - amzChecksumCRC32 = "x-amz-checksum-crc32" - amzChecksumCRC32C = "x-amz-checksum-crc32c" - amzChecksumSHA1 = "x-amz-checksum-sha1" - amzChecksumSHA256 = "x-amz-checksum-sha256" + // ChecksumFullObjectCRC32 indicates full object CRC32 + ChecksumFullObjectCRC32 = ChecksumCRC32 | ChecksumFullObject + + // ChecksumFullObjectCRC32C indicates full object CRC32C + ChecksumFullObjectCRC32C = ChecksumCRC32C | ChecksumFullObject + + amzChecksumAlgo = "x-amz-checksum-algorithm" + amzChecksumCRC32 = "x-amz-checksum-crc32" + amzChecksumCRC32C = "x-amz-checksum-crc32c" + amzChecksumSHA1 = "x-amz-checksum-sha1" + amzChecksumSHA256 = "x-amz-checksum-sha256" + amzChecksumCRC64NVME = "x-amz-checksum-crc64nvme" ) +// Base returns the base type, without modifiers. +func (c ChecksumType) Base() ChecksumType { + return c & checksumMask +} + // Is returns if c is all of t. func (c ChecksumType) Is(t ChecksumType) bool { return c&t == t @@ -75,10 +97,39 @@ func (c ChecksumType) Key() string { return amzChecksumSHA1 case ChecksumSHA256: return amzChecksumSHA256 + case ChecksumCRC64NVME: + return amzChecksumCRC64NVME } return "" } +// CanComposite will return if the checksum type can be used for composite multipart upload on AWS. +func (c ChecksumType) CanComposite() bool { + switch c & checksumMask { + case ChecksumSHA256, ChecksumSHA1, ChecksumCRC32, ChecksumCRC32C: + return true + } + return false +} + +// CanMergeCRC will return if the checksum type can be used for multipart upload on AWS. +func (c ChecksumType) CanMergeCRC() bool { + switch c & checksumMask { + case ChecksumCRC32, ChecksumCRC32C, ChecksumCRC64NVME: + return true + } + return false +} + +// FullObjectRequested will return if the checksum type indicates full object checksum was requested. +func (c ChecksumType) FullObjectRequested() bool { + switch c & (ChecksumFullObject | checksumMask) { + case ChecksumFullObjectCRC32C, ChecksumFullObjectCRC32, ChecksumCRC64NVME: + return true + } + return false +} + // KeyCapitalized returns the capitalized key as used in HTTP headers. func (c ChecksumType) KeyCapitalized() string { return http.CanonicalHeaderKey(c.Key()) @@ -93,10 +144,17 @@ func (c ChecksumType) RawByteLen() int { return sha1.Size case ChecksumSHA256: return sha256.Size + case ChecksumCRC64NVME: + return crc64.Size } return 0 } +const crc64NVMEPolynomial = 0xad93d23594c93659 + +// crc64 uses reversed polynomials. +var crc64Table = crc64.MakeTable(bits.Reverse64(crc64NVMEPolynomial)) + // Hasher returns a hasher corresponding to the checksum type. // Returns nil if no checksum. func (c ChecksumType) Hasher() hash.Hash { @@ -109,13 +167,15 @@ func (c ChecksumType) Hasher() hash.Hash { return sha1.New() case ChecksumSHA256: return sha256.New() + case ChecksumCRC64NVME: + return crc64.New(crc64Table) } return nil } // IsSet returns whether the type is valid and known. func (c ChecksumType) IsSet() bool { - return bits.OnesCount32(uint32(c)) == 1 + return bits.OnesCount32(uint32(c&checksumMask)) == 1 } // SetDefault will set the checksum if not already set. @@ -125,6 +185,16 @@ func (c *ChecksumType) SetDefault(t ChecksumType) { } } +// EncodeToString the encoded hash value of the content provided in b. +func (c ChecksumType) EncodeToString(b []byte) string { + if !c.IsSet() { + return "" + } + h := c.Hasher() + h.Write(b) + return base64.StdEncoding.EncodeToString(h.Sum(nil)) +} + // String returns the type as a string. // CRC32, CRC32C, SHA1, and SHA256 for valid values. // Empty string for unset and "" if not valid. @@ -140,6 +210,8 @@ func (c ChecksumType) String() string { return "SHA256" case ChecksumNone: return "" + case ChecksumCRC64NVME: + return "CRC64NVME" } return "" } @@ -221,3 +293,129 @@ func (c Checksum) Raw() []byte { } return c.r } + +// CompositeChecksum returns the composite checksum of all provided parts. +func (c ChecksumType) CompositeChecksum(p []ObjectPart) (*Checksum, error) { + if !c.CanComposite() { + return nil, errors.New("cannot do composite checksum") + } + sort.Slice(p, func(i, j int) bool { + return p[i].PartNumber < p[j].PartNumber + }) + c = c.Base() + crcBytes := make([]byte, 0, len(p)*c.RawByteLen()) + for _, part := range p { + pCrc, err := part.ChecksumRaw(c) + if err != nil { + return nil, err + } + crcBytes = append(crcBytes, pCrc...) + } + h := c.Hasher() + h.Write(crcBytes) + return &Checksum{Type: c, r: h.Sum(nil)}, nil +} + +// FullObjectChecksum will return the full object checksum from provided parts. +func (c ChecksumType) FullObjectChecksum(p []ObjectPart) (*Checksum, error) { + if !c.CanMergeCRC() { + return nil, errors.New("cannot merge this checksum type") + } + c = c.Base() + sort.Slice(p, func(i, j int) bool { + return p[i].PartNumber < p[j].PartNumber + }) + + switch len(p) { + case 0: + return nil, errors.New("no parts given") + case 1: + check, err := p[0].ChecksumRaw(c) + if err != nil { + return nil, err + } + return &Checksum{ + Type: c, + r: check, + }, nil + } + var merged uint32 + var merged64 uint64 + first, err := p[0].ChecksumRaw(c) + if err != nil { + return nil, err + } + sz := p[0].Size + switch c { + case ChecksumCRC32, ChecksumCRC32C: + merged = binary.BigEndian.Uint32(first) + case ChecksumCRC64NVME: + merged64 = binary.BigEndian.Uint64(first) + } + + poly32 := uint32(crc32.IEEE) + if c.Is(ChecksumCRC32C) { + poly32 = crc32.Castagnoli + } + for _, part := range p[1:] { + if part.Size == 0 { + continue + } + sz += part.Size + pCrc, err := part.ChecksumRaw(c) + if err != nil { + return nil, err + } + switch c { + case ChecksumCRC32, ChecksumCRC32C: + merged = crc32Combine(poly32, merged, binary.BigEndian.Uint32(pCrc), part.Size) + case ChecksumCRC64NVME: + merged64 = crc64Combine(bits.Reverse64(crc64NVMEPolynomial), merged64, binary.BigEndian.Uint64(pCrc), part.Size) + } + } + var tmp [8]byte + switch c { + case ChecksumCRC32, ChecksumCRC32C: + binary.BigEndian.PutUint32(tmp[:], merged) + return &Checksum{ + Type: c, + r: tmp[:4], + }, nil + case ChecksumCRC64NVME: + binary.BigEndian.PutUint64(tmp[:], merged64) + return &Checksum{ + Type: c, + r: tmp[:8], + }, nil + default: + return nil, errors.New("unknown checksum type") + } +} + +func addAutoChecksumHeaders(opts *PutObjectOptions) { + if opts.UserMetadata == nil { + opts.UserMetadata = make(map[string]string, 1) + } + opts.UserMetadata["X-Amz-Checksum-Algorithm"] = opts.AutoChecksum.String() + if opts.AutoChecksum.FullObjectRequested() { + opts.UserMetadata["X-Amz-Checksum-Type"] = "FULL_OBJECT" + } +} + +func applyAutoChecksum(opts *PutObjectOptions, allParts []ObjectPart) { + if !opts.AutoChecksum.IsSet() { + return + } + if opts.AutoChecksum.CanComposite() && !opts.AutoChecksum.Is(ChecksumFullObject) { + // Add composite hash of hashes. + crc, err := opts.AutoChecksum.CompositeChecksum(allParts) + if err == nil { + opts.UserMetadata = map[string]string{opts.AutoChecksum.Key(): crc.Encoded()} + } + } else if opts.AutoChecksum.CanMergeCRC() { + crc, err := opts.AutoChecksum.FullObjectChecksum(allParts) + if err == nil { + opts.UserMetadata = map[string]string{opts.AutoChecksum.KeyCapitalized(): crc.Encoded(), "X-Amz-Checksum-Type": "FULL_OBJECT"} + } + } +} diff --git a/vendor/github.com/minio/minio-go/v7/functional_tests.go b/vendor/github.com/minio/minio-go/v7/functional_tests.go index 780dc89979..33e87e6e16 100644 --- a/vendor/github.com/minio/minio-go/v7/functional_tests.go +++ b/vendor/github.com/minio/minio-go/v7/functional_tests.go @@ -160,7 +160,7 @@ func logError(testName, function string, args map[string]interface{}, startTime } else { logFailure(testName, function, args, startTime, alert, message, err) if !isRunOnFail() { - panic(err) + panic(fmt.Sprintf("Test failed with message: %s, err: %v", message, err)) } } } @@ -393,6 +393,42 @@ func getFuncNameLoc(caller int) string { return strings.TrimPrefix(runtime.FuncForPC(pc).Name(), "main.") } +type ClientConfig struct { + // MinIO client configuration + TraceOn bool // Turn on tracing of HTTP requests and responses to stderr + CredsV2 bool // Use V2 credentials if true, otherwise use v4 + TrailingHeaders bool // Send trailing headers in requests +} + +func NewClient(config ClientConfig) (*minio.Client, error) { + // Instantiate new MinIO client + var creds *credentials.Credentials + if config.CredsV2 { + creds = credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), "") + } else { + creds = credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), "") + } + opts := &minio.Options{ + Creds: creds, + Transport: createHTTPTransport(), + Secure: mustParseBool(os.Getenv(enableHTTPS)), + TrailingHeaders: config.TrailingHeaders, + } + client, err := minio.New(os.Getenv(serverEndpoint), opts) + if err != nil { + return nil, err + } + + if config.TraceOn { + client.TraceOn(os.Stderr) + } + + // Set user agent. + client.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + + return client, nil +} + // Tests bucket re-create errors. func testMakeBucketError() { region := "eu-central-1" @@ -407,27 +443,12 @@ func testMakeBucketError() { "region": region, } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - Transport: createHTTPTransport(), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -462,20 +483,12 @@ func testMetadataSizeLimit() { "objectName": "", "opts.UserMetadata": "", } - rand.Seed(startTime.Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - Transport: createHTTPTransport(), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client creation failed", err) return } - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -531,27 +544,12 @@ func testMakeBucketRegions() { "region": region, } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -598,27 +596,12 @@ func testPutObjectReadAt() { "opts": "objectContentType", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -697,27 +680,12 @@ func testListObjectVersions() { "recursive": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -817,27 +785,12 @@ func testStatObjectWithVersioning() { function := "StatObject" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -935,27 +888,12 @@ func testGetObjectWithVersioning() { function := "GetObject()" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -1075,27 +1013,12 @@ func testPutObjectWithVersioning() { function := "GetObject()" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -1223,28 +1146,12 @@ func testListMultipartUpload() { function := "GetObject()" args := map[string]interface{}{} - // Instantiate new minio client object. - opts := &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - } - c, err := minio.New(os.Getenv(serverEndpoint), opts) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - core, err := minio.NewCore(os.Getenv(serverEndpoint), opts) - if err != nil { - logError(testName, function, args, startTime, "", "MinIO core client object creation failed", err) - return - } - - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + core := minio.Core{Client: c} // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") @@ -1347,27 +1254,12 @@ func testCopyObjectWithVersioning() { function := "CopyObject()" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -1485,27 +1377,12 @@ func testConcurrentCopyObjectWithVersioning() { function := "CopyObject()" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -1646,27 +1523,12 @@ func testComposeObjectWithVersioning() { function := "ComposeObject()" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -1787,27 +1649,12 @@ func testRemoveObjectWithVersioning() { function := "DeleteObject()" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -1900,27 +1747,12 @@ func testRemoveObjectsWithVersioning() { function := "DeleteObjects()" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -1996,27 +1828,12 @@ func testObjectTaggingWithVersioning() { function := "{Get,Set,Remove}ObjectTagging()" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -2164,27 +1981,12 @@ func testPutObjectWithChecksums() { return } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -2204,9 +2006,13 @@ func testPutObjectWithChecksums() { {cs: minio.ChecksumCRC32}, {cs: minio.ChecksumSHA1}, {cs: minio.ChecksumSHA256}, + {cs: minio.ChecksumCRC64NVME}, } for _, test := range tests { + if os.Getenv("MINT_NO_FULL_OBJECT") != "" && test.cs.FullObjectRequested() { + continue + } bufSize := dataFileMap["datafile-10-kB"] // Save the data @@ -2230,7 +2036,7 @@ func testPutObjectWithChecksums() { h := test.cs.Hasher() h.Reset() - // Test with Wrong CRC. + // Test with a bad CRC - we haven't called h.Write(b), so this is a checksum of empty data meta[test.cs.Key()] = base64.StdEncoding.EncodeToString(h.Sum(nil)) args["metadata"] = meta args["range"] = "false" @@ -2263,6 +2069,7 @@ func testPutObjectWithChecksums() { cmpChecksum(resp.ChecksumSHA1, meta["x-amz-checksum-sha1"]) cmpChecksum(resp.ChecksumCRC32, meta["x-amz-checksum-crc32"]) cmpChecksum(resp.ChecksumCRC32C, meta["x-amz-checksum-crc32c"]) + cmpChecksum(resp.ChecksumCRC64NVME, meta["x-amz-checksum-crc64nvme"]) // Read the data back gopts := minio.GetObjectOptions{Checksum: true} @@ -2282,6 +2089,7 @@ func testPutObjectWithChecksums() { cmpChecksum(st.ChecksumSHA1, meta["x-amz-checksum-sha1"]) cmpChecksum(st.ChecksumCRC32, meta["x-amz-checksum-crc32"]) cmpChecksum(st.ChecksumCRC32C, meta["x-amz-checksum-crc32c"]) + cmpChecksum(st.ChecksumCRC64NVME, meta["x-amz-checksum-crc64nvme"]) if st.Size != int64(bufSize) { logError(testName, function, args, startTime, "", "Number of bytes returned by PutObject does not match GetObject, expected "+string(bufSize)+" got "+string(st.Size), err) @@ -2325,12 +2133,12 @@ func testPutObjectWithChecksums() { cmpChecksum(st.ChecksumSHA1, "") cmpChecksum(st.ChecksumCRC32, "") cmpChecksum(st.ChecksumCRC32C, "") + cmpChecksum(st.ChecksumCRC64NVME, "") delete(args, "range") delete(args, "metadata") + logSuccess(testName, function, args, startTime) } - - logSuccess(testName, function, args, startTime) } // Test PutObject with custom checksums. @@ -2350,28 +2158,12 @@ func testPutObjectWithTrailingChecksums() { return } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - TrailingHeaders: true, - }) + c, err := NewClient(ClientConfig{TrailingHeaders: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -2387,13 +2179,16 @@ func testPutObjectWithTrailingChecksums() { tests := []struct { cs minio.ChecksumType }{ + {cs: minio.ChecksumCRC64NVME}, {cs: minio.ChecksumCRC32C}, {cs: minio.ChecksumCRC32}, {cs: minio.ChecksumSHA1}, {cs: minio.ChecksumSHA256}, } - for _, test := range tests { + if os.Getenv("MINT_NO_FULL_OBJECT") != "" && test.cs.FullObjectRequested() { + continue + } function := "PutObject(bucketName, objectName, reader,size, opts)" bufSize := dataFileMap["datafile-10-kB"] @@ -2441,6 +2236,7 @@ func testPutObjectWithTrailingChecksums() { cmpChecksum(resp.ChecksumSHA1, meta["x-amz-checksum-sha1"]) cmpChecksum(resp.ChecksumCRC32, meta["x-amz-checksum-crc32"]) cmpChecksum(resp.ChecksumCRC32C, meta["x-amz-checksum-crc32c"]) + cmpChecksum(resp.ChecksumCRC64NVME, meta["x-amz-checksum-crc64nvme"]) // Read the data back gopts := minio.GetObjectOptions{Checksum: true} @@ -2461,6 +2257,7 @@ func testPutObjectWithTrailingChecksums() { cmpChecksum(st.ChecksumSHA1, meta["x-amz-checksum-sha1"]) cmpChecksum(st.ChecksumCRC32, meta["x-amz-checksum-crc32"]) cmpChecksum(st.ChecksumCRC32C, meta["x-amz-checksum-crc32c"]) + cmpChecksum(resp.ChecksumCRC64NVME, meta["x-amz-checksum-crc64nvme"]) if st.Size != int64(bufSize) { logError(testName, function, args, startTime, "", "Number of bytes returned by PutObject does not match GetObject, expected "+string(bufSize)+" got "+string(st.Size), err) @@ -2505,6 +2302,7 @@ func testPutObjectWithTrailingChecksums() { cmpChecksum(st.ChecksumSHA1, "") cmpChecksum(st.ChecksumCRC32, "") cmpChecksum(st.ChecksumCRC32C, "") + cmpChecksum(st.ChecksumCRC64NVME, "") function = "GetObjectAttributes(...)" s, err := c.GetObjectAttributes(context.Background(), bucketName, objectName, minio.ObjectAttributesOptions{}) @@ -2519,9 +2317,8 @@ func testPutObjectWithTrailingChecksums() { delete(args, "range") delete(args, "metadata") + logSuccess(testName, function, args, startTime) } - - logSuccess(testName, function, args, startTime) } // Test PutObject with custom checksums. @@ -2533,7 +2330,7 @@ func testPutMultipartObjectWithChecksums(trailing bool) { args := map[string]interface{}{ "bucketName": "", "objectName": "", - "opts": fmt.Sprintf("minio.PutObjectOptions{UserMetadata: metadata, Progress: progress Checksum: %v}", trailing), + "opts": fmt.Sprintf("minio.PutObjectOptions{UserMetadata: metadata, Trailing: %v}", trailing), } if !isFullMode() { @@ -2541,28 +2338,12 @@ func testPutMultipartObjectWithChecksums(trailing bool) { return } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - TrailingHeaders: trailing, - }) + c, err := NewClient(ClientConfig{TrailingHeaders: trailing}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -2574,14 +2355,18 @@ func testPutMultipartObjectWithChecksums(trailing bool) { return } - hashMultiPart := func(b []byte, partSize int, hasher hash.Hash) string { + hashMultiPart := func(b []byte, partSize int, cs minio.ChecksumType) string { r := bytes.NewReader(b) + hasher := cs.Hasher() + if cs.FullObjectRequested() { + partSize = len(b) + } tmp := make([]byte, partSize) parts := 0 var all []byte for { n, err := io.ReadFull(r, tmp) - if err != nil && err != io.ErrUnexpectedEOF { + if err != nil && err != io.ErrUnexpectedEOF && err != io.EOF { logError(testName, function, args, startTime, "", "Calc crc failed", err) } if n == 0 { @@ -2595,6 +2380,9 @@ func testPutMultipartObjectWithChecksums(trailing bool) { break } } + if parts == 1 { + return base64.StdEncoding.EncodeToString(hasher.Sum(nil)) + } hasher.Reset() hasher.Write(all) return fmt.Sprintf("%s-%d", base64.StdEncoding.EncodeToString(hasher.Sum(nil)), parts) @@ -2603,6 +2391,9 @@ func testPutMultipartObjectWithChecksums(trailing bool) { tests := []struct { cs minio.ChecksumType }{ + {cs: minio.ChecksumFullObjectCRC32}, + {cs: minio.ChecksumFullObjectCRC32C}, + {cs: minio.ChecksumCRC64NVME}, {cs: minio.ChecksumCRC32C}, {cs: minio.ChecksumCRC32}, {cs: minio.ChecksumSHA1}, @@ -2610,8 +2401,12 @@ func testPutMultipartObjectWithChecksums(trailing bool) { } for _, test := range tests { - bufSize := dataFileMap["datafile-129-MB"] + if os.Getenv("MINT_NO_FULL_OBJECT") != "" && test.cs.FullObjectRequested() { + continue + } + args["section"] = "prep" + bufSize := dataFileMap["datafile-129-MB"] // Save the data objectName := randString(60, rand.NewSource(time.Now().UnixNano()), "") args["objectName"] = objectName @@ -2620,7 +2415,7 @@ func testPutMultipartObjectWithChecksums(trailing bool) { cmpChecksum := func(got, want string) { if want != got { logError(testName, function, args, startTime, "", "checksum mismatch", fmt.Errorf("want %s, got %s", want, got)) - //fmt.Printf("want %s, got %s\n", want, got) + // fmt.Printf("want %s, got %s\n", want, got) return } } @@ -2635,7 +2430,7 @@ func testPutMultipartObjectWithChecksums(trailing bool) { reader.Close() h := test.cs.Hasher() h.Reset() - want := hashMultiPart(b, partSize, test.cs.Hasher()) + want := hashMultiPart(b, partSize, test.cs) var cs minio.ChecksumType rd := io.Reader(io.NopCloser(bytes.NewReader(b))) @@ -2643,7 +2438,9 @@ func testPutMultipartObjectWithChecksums(trailing bool) { cs = test.cs rd = bytes.NewReader(b) } + // Set correct CRC. + args["section"] = "PutObject" resp, err := c.PutObject(context.Background(), bucketName, objectName, rd, int64(bufSize), minio.PutObjectOptions{ DisableContentSha256: true, DisableMultipart: false, @@ -2657,7 +2454,7 @@ func testPutMultipartObjectWithChecksums(trailing bool) { return } - switch test.cs { + switch test.cs.Base() { case minio.ChecksumCRC32C: cmpChecksum(resp.ChecksumCRC32C, want) case minio.ChecksumCRC32: @@ -2666,15 +2463,41 @@ func testPutMultipartObjectWithChecksums(trailing bool) { cmpChecksum(resp.ChecksumSHA1, want) case minio.ChecksumSHA256: cmpChecksum(resp.ChecksumSHA256, want) + case minio.ChecksumCRC64NVME: + cmpChecksum(resp.ChecksumCRC64NVME, want) } + args["section"] = "HeadObject" + st, err := c.StatObject(context.Background(), bucketName, objectName, minio.StatObjectOptions{Checksum: true}) + if err != nil { + logError(testName, function, args, startTime, "", "StatObject failed", err) + return + } + switch test.cs.Base() { + case minio.ChecksumCRC32C: + cmpChecksum(st.ChecksumCRC32C, want) + case minio.ChecksumCRC32: + cmpChecksum(st.ChecksumCRC32, want) + case minio.ChecksumSHA1: + cmpChecksum(st.ChecksumSHA1, want) + case minio.ChecksumSHA256: + cmpChecksum(st.ChecksumSHA256, want) + case minio.ChecksumCRC64NVME: + cmpChecksum(st.ChecksumCRC64NVME, want) + } + + args["section"] = "GetObjectAttributes" s, err := c.GetObjectAttributes(context.Background(), bucketName, objectName, minio.ObjectAttributesOptions{}) if err != nil { logError(testName, function, args, startTime, "", "GetObjectAttributes failed", err) return } - want = want[:strings.IndexByte(want, '-')] + + if strings.ContainsRune(want, '-') { + want = want[:strings.IndexByte(want, '-')] + } switch test.cs { + // Full Object CRC does not return anything with GetObjectAttributes case minio.ChecksumCRC32C: cmpChecksum(s.Checksum.ChecksumCRC32C, want) case minio.ChecksumCRC32: @@ -2690,13 +2513,14 @@ func testPutMultipartObjectWithChecksums(trailing bool) { gopts.PartNumber = 2 // We cannot use StatObject, since it ignores partnumber. + args["section"] = "GetObject-Part" r, err := c.GetObject(context.Background(), bucketName, objectName, gopts) if err != nil { logError(testName, function, args, startTime, "", "GetObject failed", err) return } io.Copy(io.Discard, r) - st, err := r.Stat() + st, err = r.Stat() if err != nil { logError(testName, function, args, startTime, "", "Stat failed", err) return @@ -2708,6 +2532,7 @@ func testPutMultipartObjectWithChecksums(trailing bool) { want = base64.StdEncoding.EncodeToString(h.Sum(nil)) switch test.cs { + // Full Object CRC does not return any part CRC for whatever reason. case minio.ChecksumCRC32C: cmpChecksum(st.ChecksumCRC32C, want) case minio.ChecksumCRC32: @@ -2716,12 +2541,17 @@ func testPutMultipartObjectWithChecksums(trailing bool) { cmpChecksum(st.ChecksumSHA1, want) case minio.ChecksumSHA256: cmpChecksum(st.ChecksumSHA256, want) + case minio.ChecksumCRC64NVME: + // AWS doesn't return part checksum, but may in the future. + if st.ChecksumCRC64NVME != "" { + cmpChecksum(st.ChecksumCRC64NVME, want) + } } delete(args, "metadata") + delete(args, "section") + logSuccess(testName, function, args, startTime) } - - logSuccess(testName, function, args, startTime) } // Test PutObject with trailing checksums. @@ -2741,25 +2571,12 @@ func testTrailingChecksums() { return } - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - TrailingHeaders: true, - }) + c, err := NewClient(ClientConfig{TrailingHeaders: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -2881,7 +2698,6 @@ func testTrailingChecksums() { test.ChecksumCRC32C = hashMultiPart(b, int(test.PO.PartSize), test.hasher) // Set correct CRC. - // c.TraceOn(os.Stderr) resp, err := c.PutObject(context.Background(), bucketName, objectName, bytes.NewReader(b), int64(bufSize), test.PO) if err != nil { logError(testName, function, args, startTime, "", "PutObject failed", err) @@ -2932,6 +2748,7 @@ func testTrailingChecksums() { } delete(args, "metadata") + logSuccess(testName, function, args, startTime) } } @@ -2952,25 +2769,12 @@ func testPutObjectWithAutomaticChecksums() { return } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - TrailingHeaders: true, - }) + c, err := NewClient(ClientConfig{TrailingHeaders: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -2997,8 +2801,6 @@ func testPutObjectWithAutomaticChecksums() { {header: "x-amz-checksum-crc32c", hasher: crc32.New(crc32.MakeTable(crc32.Castagnoli))}, } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) // defer c.TraceOff() for i, test := range tests { @@ -3108,20 +2910,12 @@ func testGetObjectAttributes() { return } - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - TrailingHeaders: true, - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{TrailingHeaders: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName err = c.MakeBucket( @@ -3315,19 +3109,12 @@ func testGetObjectAttributesSSECEncryption() { return } - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - TrailingHeaders: true, - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - Transport: createHTTPTransport(), - }) + c, err := NewClient(ClientConfig{TrailingHeaders: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName err = c.MakeBucket( @@ -3401,19 +3188,12 @@ func testGetObjectAttributesErrorCases() { return } - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - TrailingHeaders: true, - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{TrailingHeaders: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) unknownBucket := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-bucket-") unknownObject := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-object-") @@ -3565,16 +3345,10 @@ func validateObjectAttributeRequest(OA *minio.ObjectAttributes, opts *minio.Obje } } - hasFullObjectChecksum := true - if OA.Checksum.ChecksumCRC32 == "" { - if OA.Checksum.ChecksumCRC32C == "" { - if OA.Checksum.ChecksumSHA1 == "" { - if OA.Checksum.ChecksumSHA256 == "" { - hasFullObjectChecksum = false - } - } - } - } + hasFullObjectChecksum := (OA.Checksum.ChecksumCRC32 != "" || + OA.Checksum.ChecksumCRC32C != "" || + OA.Checksum.ChecksumSHA1 != "" || + OA.Checksum.ChecksumSHA256 != "") if test.HasFullChecksum { if !hasFullObjectChecksum { @@ -3663,27 +3437,12 @@ func testPutObjectWithMetadata() { return } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -3770,27 +3529,12 @@ func testPutObjectWithContentLanguage() { "opts": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -3840,27 +3584,12 @@ func testPutObjectStreaming() { "opts": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -3912,27 +3641,12 @@ func testGetObjectSeekEnd() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -4035,27 +3749,12 @@ func testGetObjectClosedTwice() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -4126,26 +3825,13 @@ func testRemoveObjectsContext() { "bucketName": "", } - // Seed random based on current tie. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Enable tracing, write to stdout. - // c.TraceOn(os.Stderr) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -4223,27 +3909,12 @@ func testRemoveMultipleObjects() { "bucketName": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - - // Enable tracing, write to stdout. - // c.TraceOn(os.Stderr) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -4307,27 +3978,12 @@ func testRemoveMultipleObjectsWithResult() { "bucketName": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - - // Enable tracing, write to stdout. - // c.TraceOn(os.Stderr) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -4443,27 +4099,12 @@ func testFPutObjectMultipart() { "opts": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -4549,27 +4190,12 @@ func testFPutObject() { "opts": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") location := "us-east-1" @@ -4719,27 +4345,13 @@ func testFPutObjectContext() { "fileName": "", "opts": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -4820,27 +4432,13 @@ func testFPutObjectContextV2() { "objectName": "", "opts": "minio.PutObjectOptions{ContentType:objectContentType}", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -4925,24 +4523,12 @@ func testPutObjectContext() { "opts": "", } - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Make a new bucket. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -4995,27 +4581,12 @@ func testGetObjectS3Zip() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{"x-minio-extract": true} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -5179,27 +4750,12 @@ func testGetObjectReadSeekFunctional() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -5349,27 +4905,12 @@ func testGetObjectReadAtFunctional() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -5527,27 +5068,12 @@ func testGetObjectReadAtWhenEOFWasReached() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -5647,27 +5173,12 @@ func testPresignedPostPolicy() { "policy": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") @@ -5695,50 +5206,22 @@ func testPresignedPostPolicy() { return } - // Save the data - _, err = c.PutObject(context.Background(), bucketName, objectName, bytes.NewReader(buf), int64(len(buf)), minio.PutObjectOptions{ContentType: "binary/octet-stream"}) - if err != nil { - logError(testName, function, args, startTime, "", "PutObject failed", err) - return - } - policy := minio.NewPostPolicy() - - if err := policy.SetBucket(""); err == nil { - logError(testName, function, args, startTime, "", "SetBucket did not fail for invalid conditions", err) - return - } - if err := policy.SetKey(""); err == nil { - logError(testName, function, args, startTime, "", "SetKey did not fail for invalid conditions", err) - return - } - if err := policy.SetExpires(time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC)); err == nil { - logError(testName, function, args, startTime, "", "SetExpires did not fail for invalid conditions", err) - return - } - if err := policy.SetContentType(""); err == nil { - logError(testName, function, args, startTime, "", "SetContentType did not fail for invalid conditions", err) - return - } - if err := policy.SetContentLengthRange(1024*1024, 1024); err == nil { - logError(testName, function, args, startTime, "", "SetContentLengthRange did not fail for invalid conditions", err) - return - } - if err := policy.SetUserMetadata("", ""); err == nil { - logError(testName, function, args, startTime, "", "SetUserMetadata did not fail for invalid conditions", err) - return - } - policy.SetBucket(bucketName) policy.SetKey(objectName) policy.SetExpires(time.Now().UTC().AddDate(0, 0, 10)) // expires in 10 days policy.SetContentType("binary/octet-stream") policy.SetContentLengthRange(10, 1024*1024) policy.SetUserMetadata(metadataKey, metadataValue) + policy.SetContentEncoding("gzip") // Add CRC32C checksum := minio.ChecksumCRC32C.ChecksumBytes(buf) - policy.SetChecksum(checksum) + err = policy.SetChecksum(checksum) + if err != nil { + logError(testName, function, args, startTime, "", "SetChecksum failed", err) + return + } args["policy"] = policy.String() @@ -5834,7 +5317,7 @@ func testPresignedPostPolicy() { expectedLocation := scheme + os.Getenv(serverEndpoint) + "/" + bucketName + "/" + objectName expectedLocationBucketDNS := scheme + bucketName + "." + os.Getenv(serverEndpoint) + "/" + objectName - if !strings.Contains(expectedLocation, "s3.amazonaws.com/") { + if !strings.Contains(expectedLocation, ".amazonaws.com/") { // Test when not against AWS S3. if val, ok := res.Header["Location"]; ok { if val[0] != expectedLocation && val[0] != expectedLocationBucketDNS { @@ -5846,9 +5329,184 @@ func testPresignedPostPolicy() { return } } - want := checksum.Encoded() - if got := res.Header.Get("X-Amz-Checksum-Crc32c"); got != want { - logError(testName, function, args, startTime, "", fmt.Sprintf("Want checksum %q, got %q", want, got), nil) + wantChecksumCrc32c := checksum.Encoded() + if got := res.Header.Get("X-Amz-Checksum-Crc32c"); got != wantChecksumCrc32c { + logError(testName, function, args, startTime, "", fmt.Sprintf("Want checksum %q, got %q", wantChecksumCrc32c, got), nil) + return + } + + // Ensure that when we subsequently GetObject, the checksum is returned + gopts := minio.GetObjectOptions{Checksum: true} + r, err := c.GetObject(context.Background(), bucketName, objectName, gopts) + if err != nil { + logError(testName, function, args, startTime, "", "GetObject failed", err) + return + } + st, err := r.Stat() + if err != nil { + logError(testName, function, args, startTime, "", "Stat failed", err) + return + } + if st.ChecksumCRC32C != wantChecksumCrc32c { + logError(testName, function, args, startTime, "", fmt.Sprintf("Want checksum %s, got %s", wantChecksumCrc32c, st.ChecksumCRC32C), nil) + return + } + + logSuccess(testName, function, args, startTime) +} + +// testPresignedPostPolicyWrongFile tests that when we have a policy with a checksum, we cannot POST the wrong file +func testPresignedPostPolicyWrongFile() { + // initialize logging params + startTime := time.Now() + testName := getFuncName() + function := "PresignedPostPolicy(policy)" + args := map[string]interface{}{ + "policy": "", + } + + c, err := NewClient(ClientConfig{}) + if err != nil { + logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) + return + } + + // Generate a new random bucket name. + bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") + + // Make a new bucket in 'us-east-1' (source bucket). + err = c.MakeBucket(context.Background(), bucketName, minio.MakeBucketOptions{Region: "us-east-1"}) + if err != nil { + logError(testName, function, args, startTime, "", "MakeBucket failed", err) + return + } + + defer cleanupBucket(bucketName, c) + + objectName := randString(60, rand.NewSource(time.Now().UnixNano()), "") + // Azure requires the key to not start with a number + metadataKey := randString(60, rand.NewSource(time.Now().UnixNano()), "user") + metadataValue := randString(60, rand.NewSource(time.Now().UnixNano()), "") + + policy := minio.NewPostPolicy() + policy.SetBucket(bucketName) + policy.SetKey(objectName) + policy.SetExpires(time.Now().UTC().AddDate(0, 0, 10)) // expires in 10 days + policy.SetContentType("binary/octet-stream") + policy.SetContentLengthRange(10, 1024*1024) + policy.SetUserMetadata(metadataKey, metadataValue) + + // Add CRC32C of some data that the policy will explicitly allow. + checksum := minio.ChecksumCRC32C.ChecksumBytes([]byte{0x01, 0x02, 0x03}) + err = policy.SetChecksum(checksum) + if err != nil { + logError(testName, function, args, startTime, "", "SetChecksum failed", err) + return + } + + args["policy"] = policy.String() + + presignedPostPolicyURL, formData, err := c.PresignedPostPolicy(context.Background(), policy) + if err != nil { + logError(testName, function, args, startTime, "", "PresignedPostPolicy failed", err) + return + } + + // At this stage, we have a policy that allows us to upload for a specific checksum. + // Test that uploading datafile-10-kB, with a different checksum, fails as expected + filePath := getMintDataDirFilePath("datafile-10-kB") + if filePath == "" { + // Make a temp file with 10 KB data. + file, err := os.CreateTemp(os.TempDir(), "PresignedPostPolicyTest") + if err != nil { + logError(testName, function, args, startTime, "", "TempFile creation failed", err) + return + } + if _, err = io.Copy(file, getDataReader("datafile-10-kB")); err != nil { + logError(testName, function, args, startTime, "", "Copy failed", err) + return + } + if err = file.Close(); err != nil { + logError(testName, function, args, startTime, "", "File Close failed", err) + return + } + filePath = file.Name() + } + fileReader := getDataReader("datafile-10-kB") + defer fileReader.Close() + buf10k, err := io.ReadAll(fileReader) + if err != nil { + logError(testName, function, args, startTime, "", "ReadAll failed", err) + return + } + otherChecksum := minio.ChecksumCRC32C.ChecksumBytes(buf10k) + + var formBuf bytes.Buffer + writer := multipart.NewWriter(&formBuf) + for k, v := range formData { + if k == "x-amz-checksum-crc32c" { + v = otherChecksum.Encoded() + } + writer.WriteField(k, v) + } + + // Add file to post request + f, err := os.Open(filePath) + defer f.Close() + if err != nil { + logError(testName, function, args, startTime, "", "File open failed", err) + return + } + w, err := writer.CreateFormFile("file", filePath) + if err != nil { + logError(testName, function, args, startTime, "", "CreateFormFile failed", err) + return + } + _, err = io.Copy(w, f) + if err != nil { + logError(testName, function, args, startTime, "", "Copy failed", err) + return + } + writer.Close() + + httpClient := &http.Client{ + Timeout: 30 * time.Second, + Transport: createHTTPTransport(), + } + args["url"] = presignedPostPolicyURL.String() + + req, err := http.NewRequest(http.MethodPost, presignedPostPolicyURL.String(), bytes.NewReader(formBuf.Bytes())) + if err != nil { + logError(testName, function, args, startTime, "", "HTTP request failed", err) + return + } + + req.Header.Set("Content-Type", writer.FormDataContentType()) + + // Make the POST request with the form data. + res, err := httpClient.Do(req) + if err != nil { + logError(testName, function, args, startTime, "", "HTTP request failed", err) + return + } + defer res.Body.Close() + if res.StatusCode != http.StatusForbidden { + logError(testName, function, args, startTime, "", "HTTP request unexpected status", errors.New(res.Status)) + return + } + + // Read the response body, ensure it has checksum failure message + resBody, err := io.ReadAll(res.Body) + if err != nil { + logError(testName, function, args, startTime, "", "ReadAll failed", err) + return + } + + // Normalize the response body, because S3 uses quotes around the policy condition components + // in the error message, MinIO does not. + resBodyStr := strings.ReplaceAll(string(resBody), `"`, "") + if !strings.Contains(resBodyStr, "Policy Condition failed: [eq, $x-amz-checksum-crc32c, 8TDyHg=") { + logError(testName, function, args, startTime, "", "Unexpected response body", errors.New(resBodyStr)) return } @@ -5863,27 +5521,12 @@ func testCopyObject() { function := "CopyObject(dst, src)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") @@ -6058,27 +5701,12 @@ func testSSECEncryptedGetObjectReadSeekFunctional() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -6241,27 +5869,12 @@ func testSSES3EncryptedGetObjectReadSeekFunctional() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -6422,27 +6035,12 @@ func testSSECEncryptedGetObjectReadAtFunctional() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -6606,27 +6204,12 @@ func testSSES3EncryptedGetObjectReadAtFunctional() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -6791,27 +6374,13 @@ func testSSECEncryptionPutGet() { "objectName": "", "sse": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -6901,27 +6470,13 @@ func testSSECEncryptionFPut() { "contentType": "", "sse": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -7024,27 +6579,13 @@ func testSSES3EncryptionPutGet() { "objectName": "", "sse": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -7132,27 +6673,13 @@ func testSSES3EncryptionFPut() { "contentType": "", "sse": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -7261,26 +6788,12 @@ func testBucketNotification() { return } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable to debug - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - bucketName := os.Getenv("NOTIFY_BUCKET") args["bucketName"] = bucketName @@ -7356,26 +6869,12 @@ func testFunctional() { functionAll := "" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, nil, startTime, "", "MinIO client object creation failed", err) return } - // Enable to debug - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") @@ -8035,24 +7534,12 @@ func testGetObjectModified() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Make a new bucket. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -8131,24 +7618,12 @@ func testPutObjectUploadSeekedObject() { "contentType": "binary/octet-stream", } - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Make a new bucket. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -8251,27 +7726,12 @@ func testMakeBucketErrorV2() { "region": "eu-west-1", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") region := "eu-west-1" @@ -8311,27 +7771,12 @@ func testGetObjectClosedTwiceV2() { "region": "eu-west-1", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -8402,27 +7847,12 @@ func testFPutObjectV2() { "opts": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -8563,27 +7993,12 @@ func testMakeBucketRegionsV2() { "region": "eu-west-1", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -8626,27 +8041,12 @@ func testGetObjectReadSeekFunctionalV2() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -8781,27 +8181,12 @@ func testGetObjectReadAtFunctionalV2() { function := "GetObject(bucketName, objectName)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -8943,27 +8328,12 @@ func testCopyObjectV2() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") @@ -9162,13 +8532,7 @@ func testComposeObjectErrorCasesV2() { function := "ComposeObject(destination, sourceList)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9260,13 +8624,7 @@ func testCompose10KSourcesV2() { function := "ComposeObject(destination, sourceList)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9282,13 +8640,7 @@ func testEncryptedEmptyObject() { function := "PutObject(bucketName, objectName, reader, objectSize, opts)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return @@ -9436,7 +8788,7 @@ func testEncryptedCopyObjectWrapper(c *minio.Client, bucketName string, sseSrc, dstEncryption = sseDst } // 3. get copied object and check if content is equal - coreClient := minio.Core{c} + coreClient := minio.Core{Client: c} reader, _, _, err := coreClient.GetObject(context.Background(), bucketName, "dstObject", minio.GetObjectOptions{ServerSideEncryption: dstEncryption}) if err != nil { logError(testName, function, args, startTime, "", "GetObject failed", err) @@ -9543,13 +8895,7 @@ func testUnencryptedToSSECCopyObject() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9558,7 +8904,6 @@ func testUnencryptedToSSECCopyObject() { bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") sseDst := encrypt.DefaultPBKDF([]byte("correct horse battery staple"), []byte(bucketName+"dstObject")) - // c.TraceOn(os.Stderr) testEncryptedCopyObjectWrapper(c, bucketName, nil, sseDst) } @@ -9570,13 +8915,7 @@ func testUnencryptedToSSES3CopyObject() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9586,7 +8925,6 @@ func testUnencryptedToSSES3CopyObject() { var sseSrc encrypt.ServerSide sseDst := encrypt.NewSSE() - // c.TraceOn(os.Stderr) testEncryptedCopyObjectWrapper(c, bucketName, sseSrc, sseDst) } @@ -9598,13 +8936,7 @@ func testUnencryptedToUnencryptedCopyObject() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9613,7 +8945,6 @@ func testUnencryptedToUnencryptedCopyObject() { bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") var sseSrc, sseDst encrypt.ServerSide - // c.TraceOn(os.Stderr) testEncryptedCopyObjectWrapper(c, bucketName, sseSrc, sseDst) } @@ -9625,13 +8956,7 @@ func testEncryptedSSECToSSECCopyObject() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9641,7 +8966,6 @@ func testEncryptedSSECToSSECCopyObject() { sseSrc := encrypt.DefaultPBKDF([]byte("correct horse battery staple"), []byte(bucketName+"srcObject")) sseDst := encrypt.DefaultPBKDF([]byte("correct horse battery staple"), []byte(bucketName+"dstObject")) - // c.TraceOn(os.Stderr) testEncryptedCopyObjectWrapper(c, bucketName, sseSrc, sseDst) } @@ -9653,13 +8977,7 @@ func testEncryptedSSECToSSES3CopyObject() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9669,7 +8987,6 @@ func testEncryptedSSECToSSES3CopyObject() { sseSrc := encrypt.DefaultPBKDF([]byte("correct horse battery staple"), []byte(bucketName+"srcObject")) sseDst := encrypt.NewSSE() - // c.TraceOn(os.Stderr) testEncryptedCopyObjectWrapper(c, bucketName, sseSrc, sseDst) } @@ -9681,13 +8998,7 @@ func testEncryptedSSECToUnencryptedCopyObject() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9697,7 +9008,6 @@ func testEncryptedSSECToUnencryptedCopyObject() { sseSrc := encrypt.DefaultPBKDF([]byte("correct horse battery staple"), []byte(bucketName+"srcObject")) var sseDst encrypt.ServerSide - // c.TraceOn(os.Stderr) testEncryptedCopyObjectWrapper(c, bucketName, sseSrc, sseDst) } @@ -9709,13 +9019,7 @@ func testEncryptedSSES3ToSSECCopyObject() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9725,7 +9029,6 @@ func testEncryptedSSES3ToSSECCopyObject() { sseSrc := encrypt.NewSSE() sseDst := encrypt.DefaultPBKDF([]byte("correct horse battery staple"), []byte(bucketName+"dstObject")) - // c.TraceOn(os.Stderr) testEncryptedCopyObjectWrapper(c, bucketName, sseSrc, sseDst) } @@ -9737,13 +9040,7 @@ func testEncryptedSSES3ToSSES3CopyObject() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9753,7 +9050,6 @@ func testEncryptedSSES3ToSSES3CopyObject() { sseSrc := encrypt.NewSSE() sseDst := encrypt.NewSSE() - // c.TraceOn(os.Stderr) testEncryptedCopyObjectWrapper(c, bucketName, sseSrc, sseDst) } @@ -9765,13 +9061,7 @@ func testEncryptedSSES3ToUnencryptedCopyObject() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9781,7 +9071,6 @@ func testEncryptedSSES3ToUnencryptedCopyObject() { sseSrc := encrypt.NewSSE() var sseDst encrypt.ServerSide - // c.TraceOn(os.Stderr) testEncryptedCopyObjectWrapper(c, bucketName, sseSrc, sseDst) } @@ -9793,13 +9082,7 @@ func testEncryptedCopyObjectV2() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9809,7 +9092,6 @@ func testEncryptedCopyObjectV2() { sseSrc := encrypt.DefaultPBKDF([]byte("correct horse battery staple"), []byte(bucketName+"srcObject")) sseDst := encrypt.DefaultPBKDF([]byte("correct horse battery staple"), []byte(bucketName+"dstObject")) - // c.TraceOn(os.Stderr) testEncryptedCopyObjectWrapper(c, bucketName, sseSrc, sseDst) } @@ -9820,13 +9102,7 @@ func testDecryptedCopyObject() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return @@ -9880,26 +9156,14 @@ func testSSECMultipartEncryptedToSSECCopyObjectPart() { function := "CopyObjectPart(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - client, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + client, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return } // Instantiate new core client object. - c := minio.Core{client} - - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + c := minio.Core{Client: client} // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test") @@ -10078,26 +9342,14 @@ func testSSECEncryptedToSSECCopyObjectPart() { function := "CopyObjectPart(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - client, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + client, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return } // Instantiate new core client object. - c := minio.Core{client} - - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + c := minio.Core{Client: client} // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test") @@ -10256,26 +9508,14 @@ func testSSECEncryptedToUnencryptedCopyPart() { function := "CopyObjectPart(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - client, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + client, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return } // Instantiate new core client object. - c := minio.Core{client} - - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + c := minio.Core{Client: client} // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test") @@ -10433,26 +9673,14 @@ func testSSECEncryptedToSSES3CopyObjectPart() { function := "CopyObjectPart(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - client, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + client, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return } // Instantiate new core client object. - c := minio.Core{client} - - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + c := minio.Core{Client: client} // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test") @@ -10613,26 +9841,14 @@ func testUnencryptedToSSECCopyObjectPart() { function := "CopyObjectPart(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - client, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + client, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return } // Instantiate new core client object. - c := minio.Core{client} - - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + c := minio.Core{Client: client} // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test") @@ -10788,26 +10004,14 @@ func testUnencryptedToUnencryptedCopyPart() { function := "CopyObjectPart(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - client, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + client, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return } // Instantiate new core client object. - c := minio.Core{client} - - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + c := minio.Core{Client: client} // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test") @@ -10959,26 +10163,14 @@ func testUnencryptedToSSES3CopyObjectPart() { function := "CopyObjectPart(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - client, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + client, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return } // Instantiate new core client object. - c := minio.Core{client} - - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + c := minio.Core{Client: client} // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test") @@ -11132,26 +10324,14 @@ func testSSES3EncryptedToSSECCopyObjectPart() { function := "CopyObjectPart(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - client, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + client, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return } // Instantiate new core client object. - c := minio.Core{client} - - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + c := minio.Core{Client: client} // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test") @@ -11308,26 +10488,14 @@ func testSSES3EncryptedToUnencryptedCopyPart() { function := "CopyObjectPart(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - client, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + client, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return } // Instantiate new core client object. - c := minio.Core{client} - - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + c := minio.Core{Client: client} // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test") @@ -11480,26 +10648,14 @@ func testSSES3EncryptedToSSES3CopyObjectPart() { function := "CopyObjectPart(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - client, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + client, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return } // Instantiate new core client object. - c := minio.Core{client} - - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) + c := minio.Core{Client: client} // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test") @@ -11654,19 +10810,12 @@ func testUserMetadataCopying() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // c.TraceOn(os.Stderr) testUserMetadataCopyingWrapper(c) } @@ -11831,19 +10980,12 @@ func testUserMetadataCopyingV2() { function := "CopyObject(destination, source)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client v2 object creation failed", err) return } - // c.TraceOn(os.Stderr) testUserMetadataCopyingWrapper(c) } @@ -11854,13 +10996,7 @@ func testStorageClassMetadataPutObject() { args := map[string]interface{}{} testName := getFuncName() - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return @@ -11942,13 +11078,7 @@ func testStorageClassInvalidMetadataPutObject() { args := map[string]interface{}{} testName := getFuncName() - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return @@ -11985,13 +11115,7 @@ func testStorageClassMetadataCopyObject() { args := map[string]interface{}{} testName := getFuncName() - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - Transport: createHTTPTransport(), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO v4 client object creation failed", err) return @@ -12112,27 +11236,12 @@ func testPutObjectNoLengthV2() { "opts": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { - logError(testName, function, args, startTime, "", "MinIO client v2 object creation failed", err) + logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -12188,27 +11297,12 @@ func testPutObjectsUnknownV2() { "opts": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { - logError(testName, function, args, startTime, "", "MinIO client v2 object creation failed", err) + logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -12279,27 +11373,12 @@ func testPutObject0ByteV2() { "opts": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { - logError(testName, function, args, startTime, "", "MinIO client v2 object creation failed", err) + logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -12344,13 +11423,7 @@ func testComposeObjectErrorCases() { function := "ComposeObject(destination, sourceList)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return @@ -12367,13 +11440,7 @@ func testCompose10KSources() { function := "ComposeObject(destination, sourceList)" args := map[string]interface{}{} - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return @@ -12391,26 +11458,12 @@ func testFunctionalV2() { functionAll := "" args := map[string]interface{}{} - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - Transport: createHTTPTransport(), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client v2 object creation failed", err) return } - // Enable to debug - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") location := "us-east-1" @@ -12844,27 +11897,13 @@ func testGetObjectContext() { "bucketName": "", "objectName": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client v4 object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -12947,27 +11986,13 @@ func testFGetObjectContext() { "objectName": "", "fileName": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client v4 object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -13039,24 +12064,12 @@ func testGetObjectRanges() { defer cancel() rng := rand.NewSource(time.Now().UnixNano()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client v4 object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rng, "minio-go-test-") args["bucketName"] = bucketName @@ -13146,27 +12159,13 @@ func testGetObjectACLContext() { "bucketName": "", "objectName": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client v4 object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -13324,24 +12323,12 @@ func testPutObjectContextV2() { "size": "", "opts": "", } - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { - logError(testName, function, args, startTime, "", "MinIO client v2 object creation failed", err) + logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Make a new bucket. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -13396,27 +12383,13 @@ func testGetObjectContextV2() { "bucketName": "", "objectName": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { - logError(testName, function, args, startTime, "", "MinIO client v2 object creation failed", err) + logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -13497,27 +12470,13 @@ func testFGetObjectContextV2() { "objectName": "", "fileName": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV2(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{CredsV2: true}) if err != nil { - logError(testName, function, args, startTime, "", "MinIO client v2 object creation failed", err) + logError(testName, function, args, startTime, "", "MinIO v2 client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -13586,27 +12545,13 @@ func testListObjects() { "objectPrefix": "", "recursive": "true", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client v4 object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -13690,24 +12635,12 @@ func testCors() { "cors": "", } - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Create or reuse a bucket that will get cors settings applied to it and deleted when done bucketName := os.Getenv("MINIO_GO_TEST_BUCKET_CORS") if bucketName == "" { @@ -14426,24 +13359,12 @@ func testCorsSetGetDelete() { "cors": "", } - // Instantiate new minio client object - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -14525,27 +13446,13 @@ func testRemoveObjects() { "objectPrefix": "", "recursive": "true", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client v4 object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -14659,27 +13566,13 @@ func testGetBucketTagging() { args := map[string]interface{}{ "bucketName": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client v4 object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -14715,27 +13608,13 @@ func testSetBucketTagging() { "bucketName": "", "tags": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client v4 object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -14801,27 +13680,13 @@ func testRemoveBucketTagging() { args := map[string]interface{}{ "bucketName": "", } - // Seed random based on current time. - rand.Seed(time.Now().Unix()) - // Instantiate new minio client object. - c, err := minio.New(os.Getenv(serverEndpoint), - &minio.Options{ - Creds: credentials.NewStaticV4(os.Getenv(accessKey), os.Getenv(secretKey), ""), - Transport: createHTTPTransport(), - Secure: mustParseBool(os.Getenv(enableHTTPS)), - }) + c, err := NewClient(ClientConfig{}) if err != nil { logError(testName, function, args, startTime, "", "MinIO client v4 object creation failed", err) return } - // Enable tracing, write to stderr. - // c.TraceOn(os.Stderr) - - // Set user agent. - c.SetAppInfo("MinIO-go-FunctionalTest", appVersion) - // Generate a new random bucket name. bucketName := randString(60, rand.NewSource(time.Now().UnixNano()), "minio-go-test-") args["bucketName"] = bucketName @@ -14967,6 +13832,7 @@ func main() { testGetObjectReadAtFunctional() testGetObjectReadAtWhenEOFWasReached() testPresignedPostPolicy() + testPresignedPostPolicyWrongFile() testCopyObject() testComposeObjectErrorCases() testCompose10KSources() diff --git a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_web_identity.go b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_web_identity.go index 596d951525..8c06bac60d 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_web_identity.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/credentials/sts_web_identity.go @@ -25,6 +25,7 @@ import ( "io" "net/http" "net/url" + "os" "strconv" "strings" "time" @@ -57,9 +58,10 @@ type WebIdentityResult struct { // WebIdentityToken - web identity token with expiry. type WebIdentityToken struct { - Token string - AccessToken string - Expiry int + Token string + AccessToken string + RefreshToken string + Expiry int } // A STSWebIdentity retrieves credentials from MinIO service, and keeps track if @@ -85,29 +87,59 @@ type STSWebIdentity struct { // assuming. RoleARN string + // Policy is the policy where the credentials should be limited too. + Policy string + // roleSessionName is the identifier for the assumed role session. roleSessionName string } // NewSTSWebIdentity returns a pointer to a new // Credentials object wrapping the STSWebIdentity. -func NewSTSWebIdentity(stsEndpoint string, getWebIDTokenExpiry func() (*WebIdentityToken, error)) (*Credentials, error) { +func NewSTSWebIdentity(stsEndpoint string, getWebIDTokenExpiry func() (*WebIdentityToken, error), opts ...func(*STSWebIdentity)) (*Credentials, error) { if stsEndpoint == "" { return nil, errors.New("STS endpoint cannot be empty") } if getWebIDTokenExpiry == nil { return nil, errors.New("Web ID token and expiry retrieval function should be defined") } - return New(&STSWebIdentity{ + i := &STSWebIdentity{ Client: &http.Client{ Transport: http.DefaultTransport, }, STSEndpoint: stsEndpoint, GetWebIDTokenExpiry: getWebIDTokenExpiry, - }), nil + } + for _, o := range opts { + o(i) + } + return New(i), nil +} + +// NewKubernetesIdentity returns a pointer to a new +// Credentials object using the Kubernetes service account +func NewKubernetesIdentity(stsEndpoint string, opts ...func(*STSWebIdentity)) (*Credentials, error) { + return NewSTSWebIdentity(stsEndpoint, func() (*WebIdentityToken, error) { + token, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token") + if err != nil { + return nil, err + } + + return &WebIdentityToken{ + Token: string(token), + }, nil + }, opts...) +} + +// WithPolicy option will enforce that the returned credentials +// will be scoped down to the specified policy +func WithPolicy(policy string) func(*STSWebIdentity) { + return func(i *STSWebIdentity) { + i.Policy = policy + } } -func getWebIdentityCredentials(clnt *http.Client, endpoint, roleARN, roleSessionName string, +func getWebIdentityCredentials(clnt *http.Client, endpoint, roleARN, roleSessionName string, policy string, getWebIDTokenExpiry func() (*WebIdentityToken, error), ) (AssumeRoleWithWebIdentityResponse, error) { idToken, err := getWebIDTokenExpiry() @@ -130,9 +162,16 @@ func getWebIdentityCredentials(clnt *http.Client, endpoint, roleARN, roleSession // Usually set when server is using extended userInfo endpoint. v.Set("WebIdentityAccessToken", idToken.AccessToken) } + if idToken.RefreshToken != "" { + // Usually set when server is using extended userInfo endpoint. + v.Set("WebIdentityRefreshToken", idToken.RefreshToken) + } if idToken.Expiry > 0 { v.Set("DurationSeconds", fmt.Sprintf("%d", idToken.Expiry)) } + if policy != "" { + v.Set("Policy", policy) + } v.Set("Version", STSVersion) u, err := url.Parse(endpoint) @@ -183,7 +222,7 @@ func getWebIdentityCredentials(clnt *http.Client, endpoint, roleARN, roleSession // Retrieve retrieves credentials from the MinIO service. // Error will be returned if the request fails. func (m *STSWebIdentity) Retrieve() (Value, error) { - a, err := getWebIdentityCredentials(m.Client, m.STSEndpoint, m.RoleARN, m.roleSessionName, m.GetWebIDTokenExpiry) + a, err := getWebIdentityCredentials(m.Client, m.STSEndpoint, m.RoleARN, m.roleSessionName, m.Policy, m.GetWebIDTokenExpiry) if err != nil { return Value{}, err } diff --git a/vendor/github.com/minio/minio-go/v7/pkg/lifecycle/lifecycle.go b/vendor/github.com/minio/minio-go/v7/pkg/lifecycle/lifecycle.go index e706b57de6..344af2b780 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/lifecycle/lifecycle.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/lifecycle/lifecycle.go @@ -434,12 +434,34 @@ func (de DelMarkerExpiration) MarshalXML(enc *xml.Encoder, start xml.StartElemen return enc.EncodeElement(delMarkerExp(de), start) } +// AllVersionsExpiration represents AllVersionsExpiration actions element in an ILM policy +type AllVersionsExpiration struct { + XMLName xml.Name `xml:"AllVersionsExpiration" json:"-"` + Days int `xml:"Days,omitempty" json:"Days,omitempty"` + DeleteMarker ExpireDeleteMarker `xml:"DeleteMarker,omitempty" json:"DeleteMarker,omitempty"` +} + +// IsNull returns true if days field is 0 +func (e AllVersionsExpiration) IsNull() bool { + return e.Days == 0 +} + +// MarshalXML satisfies xml.Marshaler to provide custom encoding +func (e AllVersionsExpiration) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if e.IsNull() { + return nil + } + type allVersionsExp AllVersionsExpiration + return enc.EncodeElement(allVersionsExp(e), start) +} + // MarshalJSON customizes json encoding by omitting empty values func (r Rule) MarshalJSON() ([]byte, error) { type rule struct { AbortIncompleteMultipartUpload *AbortIncompleteMultipartUpload `json:"AbortIncompleteMultipartUpload,omitempty"` Expiration *Expiration `json:"Expiration,omitempty"` DelMarkerExpiration *DelMarkerExpiration `json:"DelMarkerExpiration,omitempty"` + AllVersionsExpiration *AllVersionsExpiration `json:"AllVersionsExpiration,omitempty"` ID string `json:"ID"` RuleFilter *Filter `json:"Filter,omitempty"` NoncurrentVersionExpiration *NoncurrentVersionExpiration `json:"NoncurrentVersionExpiration,omitempty"` @@ -475,6 +497,9 @@ func (r Rule) MarshalJSON() ([]byte, error) { if !r.NoncurrentVersionTransition.isNull() { newr.NoncurrentVersionTransition = &r.NoncurrentVersionTransition } + if !r.AllVersionsExpiration.IsNull() { + newr.AllVersionsExpiration = &r.AllVersionsExpiration + } return json.Marshal(newr) } @@ -485,6 +510,7 @@ type Rule struct { AbortIncompleteMultipartUpload AbortIncompleteMultipartUpload `xml:"AbortIncompleteMultipartUpload,omitempty" json:"AbortIncompleteMultipartUpload,omitempty"` Expiration Expiration `xml:"Expiration,omitempty" json:"Expiration,omitempty"` DelMarkerExpiration DelMarkerExpiration `xml:"DelMarkerExpiration,omitempty" json:"DelMarkerExpiration,omitempty"` + AllVersionsExpiration AllVersionsExpiration `xml:"AllVersionsExpiration,omitempty" json:"AllVersionsExpiration,omitempty"` ID string `xml:"ID" json:"ID"` RuleFilter Filter `xml:"Filter,omitempty" json:"Filter,omitempty"` NoncurrentVersionExpiration NoncurrentVersionExpiration `xml:"NoncurrentVersionExpiration,omitempty" json:"NoncurrentVersionExpiration,omitempty"` diff --git a/vendor/github.com/minio/minio-go/v7/pkg/tags/tags.go b/vendor/github.com/minio/minio-go/v7/pkg/tags/tags.go index 7a84a6f349..33465c6326 100644 --- a/vendor/github.com/minio/minio-go/v7/pkg/tags/tags.go +++ b/vendor/github.com/minio/minio-go/v7/pkg/tags/tags.go @@ -69,7 +69,7 @@ const ( // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#tag-restrictions // borrowed from this article and also testing various ASCII characters following regex // is supported by AWS S3 for both tags and values. -var validTagKeyValue = regexp.MustCompile(`^[a-zA-Z0-9-+\-._:/@ ]+$`) +var validTagKeyValue = regexp.MustCompile(`^[a-zA-Z0-9-+\-._:/@ =]+$`) func checkKey(key string) error { if len(key) == 0 { diff --git a/vendor/github.com/minio/minio-go/v7/post-policy.go b/vendor/github.com/minio/minio-go/v7/post-policy.go index 19687e027d..26bf441b56 100644 --- a/vendor/github.com/minio/minio-go/v7/post-policy.go +++ b/vendor/github.com/minio/minio-go/v7/post-policy.go @@ -85,7 +85,7 @@ func (p *PostPolicy) SetExpires(t time.Time) error { // SetKey - Sets an object name for the policy based upload. func (p *PostPolicy) SetKey(key string) error { - if strings.TrimSpace(key) == "" || key == "" { + if strings.TrimSpace(key) == "" { return errInvalidArgument("Object name is empty.") } policyCond := policyCondition{ @@ -118,7 +118,7 @@ func (p *PostPolicy) SetKeyStartsWith(keyStartsWith string) error { // SetBucket - Sets bucket at which objects will be uploaded to. func (p *PostPolicy) SetBucket(bucketName string) error { - if strings.TrimSpace(bucketName) == "" || bucketName == "" { + if strings.TrimSpace(bucketName) == "" { return errInvalidArgument("Bucket name is empty.") } policyCond := policyCondition{ @@ -135,7 +135,7 @@ func (p *PostPolicy) SetBucket(bucketName string) error { // SetCondition - Sets condition for credentials, date and algorithm func (p *PostPolicy) SetCondition(matchType, condition, value string) error { - if strings.TrimSpace(value) == "" || value == "" { + if strings.TrimSpace(value) == "" { return errInvalidArgument("No value specified for condition") } @@ -156,7 +156,7 @@ func (p *PostPolicy) SetCondition(matchType, condition, value string) error { // SetTagging - Sets tagging for the object for this policy based upload. func (p *PostPolicy) SetTagging(tagging string) error { - if strings.TrimSpace(tagging) == "" || tagging == "" { + if strings.TrimSpace(tagging) == "" { return errInvalidArgument("No tagging specified.") } _, err := tags.ParseObjectXML(strings.NewReader(tagging)) @@ -178,7 +178,7 @@ func (p *PostPolicy) SetTagging(tagging string) error { // SetContentType - Sets content-type of the object for this policy // based upload. func (p *PostPolicy) SetContentType(contentType string) error { - if strings.TrimSpace(contentType) == "" || contentType == "" { + if strings.TrimSpace(contentType) == "" { return errInvalidArgument("No content type specified.") } policyCond := policyCondition{ @@ -211,7 +211,7 @@ func (p *PostPolicy) SetContentTypeStartsWith(contentTypeStartsWith string) erro // SetContentDisposition - Sets content-disposition of the object for this policy func (p *PostPolicy) SetContentDisposition(contentDisposition string) error { - if strings.TrimSpace(contentDisposition) == "" || contentDisposition == "" { + if strings.TrimSpace(contentDisposition) == "" { return errInvalidArgument("No content disposition specified.") } policyCond := policyCondition{ @@ -226,27 +226,44 @@ func (p *PostPolicy) SetContentDisposition(contentDisposition string) error { return nil } +// SetContentEncoding - Sets content-encoding of the object for this policy +func (p *PostPolicy) SetContentEncoding(contentEncoding string) error { + if strings.TrimSpace(contentEncoding) == "" { + return errInvalidArgument("No content encoding specified.") + } + policyCond := policyCondition{ + matchType: "eq", + condition: "$Content-Encoding", + value: contentEncoding, + } + if err := p.addNewPolicy(policyCond); err != nil { + return err + } + p.formData["Content-Encoding"] = contentEncoding + return nil +} + // SetContentLengthRange - Set new min and max content length // condition for all incoming uploads. -func (p *PostPolicy) SetContentLengthRange(min, max int64) error { - if min > max { +func (p *PostPolicy) SetContentLengthRange(minLen, maxLen int64) error { + if minLen > maxLen { return errInvalidArgument("Minimum limit is larger than maximum limit.") } - if min < 0 { + if minLen < 0 { return errInvalidArgument("Minimum limit cannot be negative.") } - if max <= 0 { + if maxLen <= 0 { return errInvalidArgument("Maximum limit cannot be non-positive.") } - p.contentLengthRange.min = min - p.contentLengthRange.max = max + p.contentLengthRange.min = minLen + p.contentLengthRange.max = maxLen return nil } // SetSuccessActionRedirect - Sets the redirect success url of the object for this policy // based upload. func (p *PostPolicy) SetSuccessActionRedirect(redirect string) error { - if strings.TrimSpace(redirect) == "" || redirect == "" { + if strings.TrimSpace(redirect) == "" { return errInvalidArgument("Redirect is empty") } policyCond := policyCondition{ @@ -264,7 +281,7 @@ func (p *PostPolicy) SetSuccessActionRedirect(redirect string) error { // SetSuccessStatusAction - Sets the status success code of the object for this policy // based upload. func (p *PostPolicy) SetSuccessStatusAction(status string) error { - if strings.TrimSpace(status) == "" || status == "" { + if strings.TrimSpace(status) == "" { return errInvalidArgument("Status is empty") } policyCond := policyCondition{ @@ -282,10 +299,10 @@ func (p *PostPolicy) SetSuccessStatusAction(status string) error { // SetUserMetadata - Set user metadata as a key/value couple. // Can be retrieved through a HEAD request or an event. func (p *PostPolicy) SetUserMetadata(key, value string) error { - if strings.TrimSpace(key) == "" || key == "" { + if strings.TrimSpace(key) == "" { return errInvalidArgument("Key is empty") } - if strings.TrimSpace(value) == "" || value == "" { + if strings.TrimSpace(value) == "" { return errInvalidArgument("Value is empty") } headerName := fmt.Sprintf("x-amz-meta-%s", key) @@ -304,7 +321,7 @@ func (p *PostPolicy) SetUserMetadata(key, value string) error { // SetUserMetadataStartsWith - Set how an user metadata should starts with. // Can be retrieved through a HEAD request or an event. func (p *PostPolicy) SetUserMetadataStartsWith(key, value string) error { - if strings.TrimSpace(key) == "" || key == "" { + if strings.TrimSpace(key) == "" { return errInvalidArgument("Key is empty") } headerName := fmt.Sprintf("x-amz-meta-%s", key) @@ -321,11 +338,29 @@ func (p *PostPolicy) SetUserMetadataStartsWith(key, value string) error { } // SetChecksum sets the checksum of the request. -func (p *PostPolicy) SetChecksum(c Checksum) { +func (p *PostPolicy) SetChecksum(c Checksum) error { if c.IsSet() { p.formData[amzChecksumAlgo] = c.Type.String() p.formData[c.Type.Key()] = c.Encoded() + + policyCond := policyCondition{ + matchType: "eq", + condition: fmt.Sprintf("$%s", amzChecksumAlgo), + value: c.Type.String(), + } + if err := p.addNewPolicy(policyCond); err != nil { + return err + } + policyCond = policyCondition{ + matchType: "eq", + condition: fmt.Sprintf("$%s", c.Type.Key()), + value: c.Encoded(), + } + if err := p.addNewPolicy(policyCond); err != nil { + return err + } } + return nil } // SetEncryption - sets encryption headers for POST API diff --git a/vendor/github.com/minio/minio-go/v7/retry-continous.go b/vendor/github.com/minio/minio-go/v7/retry-continous.go index bfeea95f30..81fcf16f1b 100644 --- a/vendor/github.com/minio/minio-go/v7/retry-continous.go +++ b/vendor/github.com/minio/minio-go/v7/retry-continous.go @@ -20,7 +20,7 @@ package minio import "time" // newRetryTimerContinous creates a timer with exponentially increasing delays forever. -func (c *Client) newRetryTimerContinous(unit, cap time.Duration, jitter float64, doneCh chan struct{}) <-chan int { +func (c *Client) newRetryTimerContinous(baseSleep, maxSleep time.Duration, jitter float64, doneCh chan struct{}) <-chan int { attemptCh := make(chan int) // normalize jitter to the range [0, 1.0] @@ -39,10 +39,10 @@ func (c *Client) newRetryTimerContinous(unit, cap time.Duration, jitter float64, if attempt > maxAttempt { attempt = maxAttempt } - // sleep = random_between(0, min(cap, base * 2 ** attempt)) - sleep := unit * time.Duration(1< cap { - sleep = cap + // sleep = random_between(0, min(maxSleep, base * 2 ** attempt)) + sleep := baseSleep * time.Duration(1< maxSleep { + sleep = maxSleep } if jitter != NoJitter { sleep -= time.Duration(c.random.Float64() * float64(sleep) * jitter) diff --git a/vendor/github.com/minio/minio-go/v7/retry.go b/vendor/github.com/minio/minio-go/v7/retry.go index d15eb59013..4cc45920c4 100644 --- a/vendor/github.com/minio/minio-go/v7/retry.go +++ b/vendor/github.com/minio/minio-go/v7/retry.go @@ -45,7 +45,7 @@ var DefaultRetryCap = time.Second // newRetryTimer creates a timer with exponentially increasing // delays until the maximum retry attempts are reached. -func (c *Client) newRetryTimer(ctx context.Context, maxRetry int, unit, cap time.Duration, jitter float64) <-chan int { +func (c *Client) newRetryTimer(ctx context.Context, maxRetry int, baseSleep, maxSleep time.Duration, jitter float64) <-chan int { attemptCh := make(chan int) // computes the exponential backoff duration according to @@ -59,10 +59,10 @@ func (c *Client) newRetryTimer(ctx context.Context, maxRetry int, unit, cap time jitter = MaxJitter } - // sleep = random_between(0, min(cap, base * 2 ** attempt)) - sleep := unit * time.Duration(1< cap { - sleep = cap + // sleep = random_between(0, min(maxSleep, base * 2 ** attempt)) + sleep := baseSleep * time.Duration(1< maxSleep { + sleep = maxSleep } if jitter != NoJitter { sleep -= time.Duration(c.random.Float64() * float64(sleep) * jitter) diff --git a/vendor/github.com/minio/minio-go/v7/utils.go b/vendor/github.com/minio/minio-go/v7/utils.go index a5beb371f2..cd7d2c27e6 100644 --- a/vendor/github.com/minio/minio-go/v7/utils.go +++ b/vendor/github.com/minio/minio-go/v7/utils.go @@ -378,10 +378,11 @@ func ToObjectInfo(bucketName, objectName string, h http.Header) (ObjectInfo, err Restore: restore, // Checksum values - ChecksumCRC32: h.Get("x-amz-checksum-crc32"), - ChecksumCRC32C: h.Get("x-amz-checksum-crc32c"), - ChecksumSHA1: h.Get("x-amz-checksum-sha1"), - ChecksumSHA256: h.Get("x-amz-checksum-sha256"), + ChecksumCRC32: h.Get(ChecksumCRC32.Key()), + ChecksumCRC32C: h.Get(ChecksumCRC32C.Key()), + ChecksumSHA1: h.Get(ChecksumSHA1.Key()), + ChecksumSHA256: h.Get(ChecksumSHA256.Key()), + ChecksumCRC64NVME: h.Get(ChecksumCRC64NVME.Key()), }, nil } @@ -698,3 +699,146 @@ func (h *hashReaderWrapper) Read(p []byte) (n int, err error) { } return n, err } + +// Following is ported from C to Go in 2016 by Justin Ruggles, with minimal alteration. +// Used uint for unsigned long. Used uint32 for input arguments in order to match +// the Go hash/crc32 package. zlib CRC32 combine (https://github.com/madler/zlib) +// Modified for hash/crc64 by Klaus Post, 2024. +func gf2MatrixTimes(mat []uint64, vec uint64) uint64 { + var sum uint64 + + for vec != 0 { + if vec&1 != 0 { + sum ^= mat[0] + } + vec >>= 1 + mat = mat[1:] + } + return sum +} + +func gf2MatrixSquare(square, mat []uint64) { + if len(square) != len(mat) { + panic("square matrix size mismatch") + } + for n := range mat { + square[n] = gf2MatrixTimes(mat, mat[n]) + } +} + +// crc32Combine returns the combined CRC-32 hash value of the two passed CRC-32 +// hash values crc1 and crc2. poly represents the generator polynomial +// and len2 specifies the byte length that the crc2 hash covers. +func crc32Combine(poly uint32, crc1, crc2 uint32, len2 int64) uint32 { + // degenerate case (also disallow negative lengths) + if len2 <= 0 { + return crc1 + } + + even := make([]uint64, 32) // even-power-of-two zeros operator + odd := make([]uint64, 32) // odd-power-of-two zeros operator + + // put operator for one zero bit in odd + odd[0] = uint64(poly) // CRC-32 polynomial + row := uint64(1) + for n := 1; n < 32; n++ { + odd[n] = row + row <<= 1 + } + + // put operator for two zero bits in even + gf2MatrixSquare(even, odd) + + // put operator for four zero bits in odd + gf2MatrixSquare(odd, even) + + // apply len2 zeros to crc1 (first square will put the operator for one + // zero byte, eight zero bits, in even) + crc1n := uint64(crc1) + for { + // apply zeros operator for this bit of len2 + gf2MatrixSquare(even, odd) + if len2&1 != 0 { + crc1n = gf2MatrixTimes(even, crc1n) + } + len2 >>= 1 + + // if no more bits set, then done + if len2 == 0 { + break + } + + // another iteration of the loop with odd and even swapped + gf2MatrixSquare(odd, even) + if len2&1 != 0 { + crc1n = gf2MatrixTimes(odd, crc1n) + } + len2 >>= 1 + + // if no more bits set, then done + if len2 == 0 { + break + } + } + + // return combined crc + crc1n ^= uint64(crc2) + return uint32(crc1n) +} + +func crc64Combine(poly uint64, crc1, crc2 uint64, len2 int64) uint64 { + // degenerate case (also disallow negative lengths) + if len2 <= 0 { + return crc1 + } + + even := make([]uint64, 64) // even-power-of-two zeros operator + odd := make([]uint64, 64) // odd-power-of-two zeros operator + + // put operator for one zero bit in odd + odd[0] = poly // CRC-64 polynomial + row := uint64(1) + for n := 1; n < 64; n++ { + odd[n] = row + row <<= 1 + } + + // put operator for two zero bits in even + gf2MatrixSquare(even, odd) + + // put operator for four zero bits in odd + gf2MatrixSquare(odd, even) + + // apply len2 zeros to crc1 (first square will put the operator for one + // zero byte, eight zero bits, in even) + crc1n := crc1 + for { + // apply zeros operator for this bit of len2 + gf2MatrixSquare(even, odd) + if len2&1 != 0 { + crc1n = gf2MatrixTimes(even, crc1n) + } + len2 >>= 1 + + // if no more bits set, then done + if len2 == 0 { + break + } + + // another iteration of the loop with odd and even swapped + gf2MatrixSquare(odd, even) + if len2&1 != 0 { + crc1n = gf2MatrixTimes(odd, crc1n) + } + len2 >>= 1 + + // if no more bits set, then done + if len2 == 0 { + break + } + } + + // return combined crc + crc1n ^= crc2 + return crc1n +} diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/agent.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/agent.go index 47fab98972..0c64528743 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/agent.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/agent.go @@ -119,13 +119,8 @@ type Flows struct { rbTracer *flow.RingBufTracer accounter *flow.Accounter limiter *flow.CapacityLimiter - deduper node.MiddleFunc[[]*model.Record, []*model.Record] exporter node.TerminalFunc[[]*model.Record] - // elements used to decorate flows with extra information - interfaceNamer flow.InterfaceNamer - agentIP net.IP - status Status promoServer *http.Server sampleDecoder *ovnobserv.SampleDecoder @@ -178,7 +173,7 @@ func FlowsAgent(cfg *Config) (*Flows, error) { m := metrics.NewMetrics(metricsSettings) var s *ovnobserv.SampleDecoder - if cfg.EnableNetworkEventsMonitoring { + if cfg.EnableNetworkEventsMonitoring || cfg.EnableUDNMapping { if !kernel.IsKernelOlderThan("5.14.0") { if s, err = ovnobserv.NewSampleDecoderWithDefaultCollector(context.Background(), networkEventsDBPath, networkEventsOwnerName, cfg.NetworkEventsMonitoringGroupID); err != nil { @@ -190,7 +185,7 @@ func FlowsAgent(cfg *Config) (*Flows, error) { } // configure selected exporter - exportFunc, err := buildFlowExporter(cfg, m, s) + exportFunc, err := buildFlowExporter(cfg, m) if err != nil { return nil, err } @@ -214,6 +209,7 @@ func FlowsAgent(cfg *Config) (*Flows, error) { FilterIPCIDR: r.FilterIPCIDR, FilterProtocol: r.FilterProtocol, FilterPeerIP: r.FilterPeerIP, + FilterPeerCIDR: r.FilterPeerCIDR, FilterDestinationPort: tracer.ConvertFilterPortsToInstr(r.FilterDestinationPort, r.FilterDestinationPortRange, r.FilterDestinationPorts), FilterSourcePort: tracer.ConvertFilterPortsToInstr(r.FilterSourcePort, r.FilterSourcePortRange, r.FilterSourcePorts), FilterPort: tracer.ConvertFilterPortsToInstr(r.FilterPort, r.FilterPortRange, r.FilterPorts), @@ -290,6 +286,8 @@ func flowsAgent(cfg *Config, m *metrics.Metrics, } return iface } + model.SetGlobals(agentIP, interfaceNamer) + var promoServer *http.Server if cfg.MetricsEnable { promoServer = promo.InitializePrometheus(m.Settings) @@ -298,30 +296,22 @@ func flowsAgent(cfg *Config, m *metrics.Metrics, samplingGauge := m.CreateSamplingRate() samplingGauge.Set(float64(cfg.Sampling)) - mapTracer := flow.NewMapTracer(fetcher, cfg.CacheActiveTimeout, cfg.StaleEntriesEvictTimeout, m) + mapTracer := flow.NewMapTracer(fetcher, cfg.CacheActiveTimeout, cfg.StaleEntriesEvictTimeout, m, s) rbTracer := flow.NewRingBufTracer(fetcher, mapTracer, cfg.CacheActiveTimeout, m) - accounter := flow.NewAccounter(cfg.CacheMaxFlows, cfg.CacheActiveTimeout, time.Now, monotime.Now, m) + accounter := flow.NewAccounter(cfg.CacheMaxFlows, cfg.CacheActiveTimeout, time.Now, monotime.Now, m, s) limiter := flow.NewCapacityLimiter(m) - var deduper node.MiddleFunc[[]*model.Record, []*model.Record] - if cfg.Deduper == DeduperFirstCome { - deduper = flow.Dedupe(cfg.DeduperFCExpiry, cfg.DeduperJustMark, cfg.DeduperMerge, interfaceNamer, m) - } return &Flows{ - ebpf: fetcher, - exporter: exporter, - interfaces: registerer, - filter: filter, - cfg: cfg, - mapTracer: mapTracer, - rbTracer: rbTracer, - accounter: accounter, - limiter: limiter, - deduper: deduper, - agentIP: agentIP, - interfaceNamer: interfaceNamer, - promoServer: promoServer, - sampleDecoder: s, + ebpf: fetcher, + exporter: exporter, + interfaces: registerer, + filter: filter, + cfg: cfg, + mapTracer: mapTracer, + rbTracer: rbTracer, + accounter: accounter, + limiter: limiter, + promoServer: promoServer, }, nil } @@ -339,12 +329,12 @@ func flowDirections(cfg *Config) (ingress, egress bool) { } } -func buildFlowExporter(cfg *Config, m *metrics.Metrics, s *ovnobserv.SampleDecoder) (node.TerminalFunc[[]*model.Record], error) { +func buildFlowExporter(cfg *Config, m *metrics.Metrics) (node.TerminalFunc[[]*model.Record], error) { switch cfg.Export { case "grpc": - return buildGRPCExporter(cfg, m, s) + return buildGRPCExporter(cfg, m) case "kafka": - return buildKafkaExporter(cfg, m, s) + return buildKafkaExporter(cfg, m) case "ipfix+udp": return buildIPFIXExporter(cfg, "udp") case "ipfix+tcp": @@ -356,12 +346,12 @@ func buildFlowExporter(cfg *Config, m *metrics.Metrics, s *ovnobserv.SampleDecod } } -func buildGRPCExporter(cfg *Config, m *metrics.Metrics, s *ovnobserv.SampleDecoder) (node.TerminalFunc[[]*model.Record], error) { +func buildGRPCExporter(cfg *Config, m *metrics.Metrics) (node.TerminalFunc[[]*model.Record], error) { if cfg.TargetHost == "" || cfg.TargetPort == 0 { return nil, fmt.Errorf("missing target host or port: %s:%d", cfg.TargetHost, cfg.TargetPort) } - grpcExporter, err := exporter.StartGRPCProto(cfg.TargetHost, cfg.TargetPort, cfg.GRPCMessageMaxFlows, m, s) + grpcExporter, err := exporter.StartGRPCProto(cfg.TargetHost, cfg.TargetPort, cfg.GRPCMessageMaxFlows, m) if err != nil { return nil, err } @@ -376,7 +366,7 @@ func buildFlowDirectFLPExporter(cfg *Config) (node.TerminalFunc[[]*model.Record] return flpExporter.ExportFlows, nil } -func buildKafkaExporter(cfg *Config, m *metrics.Metrics, s *ovnobserv.SampleDecoder) (node.TerminalFunc[[]*model.Record], error) { +func buildKafkaExporter(cfg *Config, m *metrics.Metrics) (node.TerminalFunc[[]*model.Record], error) { if len(cfg.KafkaBrokers) == 0 { return nil, errors.New("at least one Kafka broker is needed") } @@ -422,8 +412,7 @@ func buildKafkaExporter(cfg *Config, m *metrics.Metrics, s *ovnobserv.SampleDeco Transport: &transport, Balancer: &kafkago.Hash{}, }, - Metrics: m, - SampleDecoder: s, + Metrics: m, }).ExportFlows, nil } @@ -517,9 +506,6 @@ func (f *Flows) buildAndStartPipeline(ctx context.Context) (*node.Terminal[[]*mo limiter := node.AsMiddle(f.limiter.Limit, node.ChannelBufferLen(f.cfg.BuffersLength)) - decorator := node.AsMiddle(flow.Decorate(f.agentIP, f.interfaceNamer), - node.ChannelBufferLen(f.cfg.BuffersLength)) - ebl := f.cfg.ExporterBufferLength if ebl == 0 { ebl = f.cfg.BuffersLength @@ -530,17 +516,9 @@ func (f *Flows) buildAndStartPipeline(ctx context.Context) (*node.Terminal[[]*mo rbTracer.SendsTo(accounter) - if f.deduper != nil { - deduper := node.AsMiddle(f.deduper, node.ChannelBufferLen(f.cfg.BuffersLength)) - mapTracer.SendsTo(deduper) - accounter.SendsTo(deduper) - deduper.SendsTo(limiter) - } else { - mapTracer.SendsTo(limiter) - accounter.SendsTo(limiter) - } - limiter.SendsTo(decorator) - decorator.SendsTo(export) + mapTracer.SendsTo(limiter) + accounter.SendsTo(limiter) + limiter.SendsTo(export) alog.Debug("starting graph") mapTracer.Start() diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/config.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/config.go index 9968b01a5b..8afaeaa6bf 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/config.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/config.go @@ -11,8 +11,6 @@ var clog = logrus.WithField("component", "config") const ( ListenPoll = "poll" ListenWatch = "watch" - DeduperNone = "none" - DeduperFirstCome = "firstCome" DirectionIngress = "ingress" DirectionEgress = "egress" DirectionBoth = "both" @@ -77,6 +75,9 @@ type FlowFilter struct { FilterDrops bool `json:"drops,omitempty"` // FilterSample is the sample rate this matching flow will use FilterSample uint32 `json:"sample,omitempty"` + // FilterPeerCIDR is the PeerIP CIDR to filter flows. + // Example: 10.10.10.0/24 or 100:100:100:100::/64, default is 0.0.0.0/0 + FilterPeerCIDR string `json:"peer_cidr,omitempty"` } type Config struct { @@ -131,21 +132,6 @@ type Config struct { // CacheActiveTimeout specifies the maximum duration that flows are kept in the accounting // cache before being flushed for its later export CacheActiveTimeout time.Duration `env:"CACHE_ACTIVE_TIMEOUT" envDefault:"5s"` - // Deduper specifies the deduper type. Accepted values are "none" (disabled) and "firstCome". - // When enabled, it will detect duplicate flows (flows that have been detected e.g. through - // both the physical and a virtual interface). - // "firstCome" will forward only flows from the first interface the flows are received from. - Deduper string `env:"DEDUPER" envDefault:"none"` - // DeduperFCExpiry specifies the expiry duration of the flows "firstCome" deduplicator. After - // a flow hasn't been received for that expiry time, the deduplicator forgets it. That means - // that a flow from a connection that has been inactive during that period could be forwarded - // again from a different interface. - // If the value is not set, it will default to 2 * CacheActiveTimeout - DeduperFCExpiry time.Duration `env:"DEDUPER_FC_EXPIRY"` - // DeduperJustMark will just mark duplicates (boolean field) instead of dropping them. - DeduperJustMark bool `env:"DEDUPER_JUST_MARK" envDefault:"false"` - // DeduperMerge will merge duplicated flows and generate list of interfaces and direction pairs - DeduperMerge bool `env:"DEDUPER_MERGE" envDefault:"true"` // Direction allows selecting which flows to trace according to its direction. Accepted values // are "ingress", "egress" or "both" (default). Direction string `env:"DIRECTION" envDefault:"both"` @@ -248,7 +234,8 @@ type Config struct { EbpfProgramManagerMode bool `env:"EBPF_PROGRAM_MANAGER_MODE" envDefault:"false"` // BpfManBpfFSPath user configurable ebpf manager mount path BpfManBpfFSPath string `env:"BPFMAN_BPF_FS_PATH" envDefault:"/run/netobserv/maps"` - + // EnableUDNMapping to allow mapping pod's interface to udn label + EnableUDNMapping bool `env:"ENABLE_UDN_MAPPING" envDefault:"false"` /* Deprecated configs are listed below this line * See manageDeprecatedConfigs function for details */ diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/packets_agent.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/packets_agent.go index 1157901c33..21cba9b44c 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/packets_agent.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/agent/packets_agent.go @@ -34,7 +34,7 @@ type Packets struct { exporter node.TerminalFunc[[]*model.PacketRecord] // elements used to decorate flows with extra information - interfaceNamer flow.InterfaceNamer + interfaceNamer model.InterfaceNamer agentIP net.IP status Status @@ -78,27 +78,26 @@ func PacketsAgent(cfg *Config) (*Packets, error) { debug = true } filterRules := make([]*tracer.FilterConfig, 0) - if cfg.EnableFlowFilter { - var flowFilters []*FlowFilter - if err := json.Unmarshal([]byte(cfg.FlowFilterRules), &flowFilters); err != nil { - return nil, err - } + var flowFilters []*FlowFilter + if err := json.Unmarshal([]byte(cfg.FlowFilterRules), &flowFilters); err != nil { + return nil, err + } - for _, r := range flowFilters { - filterRules = append(filterRules, &tracer.FilterConfig{ - FilterAction: r.FilterAction, - FilterDirection: r.FilterDirection, - FilterIPCIDR: r.FilterIPCIDR, - FilterProtocol: r.FilterProtocol, - FilterPeerIP: r.FilterPeerIP, - FilterDestinationPort: tracer.ConvertFilterPortsToInstr(r.FilterDestinationPort, r.FilterDestinationPortRange, r.FilterDestinationPorts), - FilterSourcePort: tracer.ConvertFilterPortsToInstr(r.FilterSourcePort, r.FilterSourcePortRange, r.FilterSourcePorts), - FilterPort: tracer.ConvertFilterPortsToInstr(r.FilterPort, r.FilterPortRange, r.FilterPorts), - FilterTCPFlags: r.FilterTCPFlags, - FilterDrops: r.FilterDrops, - FilterSample: r.FilterSample, - }) - } + for _, r := range flowFilters { + filterRules = append(filterRules, &tracer.FilterConfig{ + FilterAction: r.FilterAction, + FilterDirection: r.FilterDirection, + FilterIPCIDR: r.FilterIPCIDR, + FilterProtocol: r.FilterProtocol, + FilterPeerIP: r.FilterPeerIP, + FilterPeerCIDR: r.FilterPeerCIDR, + FilterDestinationPort: tracer.ConvertFilterPortsToInstr(r.FilterDestinationPort, r.FilterDestinationPortRange, r.FilterDestinationPorts), + FilterSourcePort: tracer.ConvertFilterPortsToInstr(r.FilterSourcePort, r.FilterSourcePortRange, r.FilterSourcePorts), + FilterPort: tracer.ConvertFilterPortsToInstr(r.FilterPort, r.FilterPortRange, r.FilterPorts), + FilterTCPFlags: r.FilterTCPFlags, + FilterDrops: r.FilterDrops, + FilterSample: r.FilterSample, + }) } ebpfConfig := &tracer.FlowFetcherConfig{ EnableIngress: ingress, diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/decode/decode_protobuf.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/decode/decode_protobuf.go index f98e6b3407..efb723f1b3 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/decode/decode_protobuf.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/decode/decode_protobuf.go @@ -67,8 +67,18 @@ func RecordToMap(fr *model.Record) config.GenericMap { "AgentIP": fr.AgentIP.String(), } - if fr.Duplicate { - out["Duplicate"] = true + var directions []int + var interfaces []string + var udns []string + for _, intf := range fr.Interfaces { + directions = append(directions, intf.Direction) + interfaces = append(interfaces, intf.Interface) + udns = append(udns, intf.Udn) + } + out["IfDirections"] = directions + out["Interfaces"] = interfaces + if len(udns) != 0 { + out["Udns"] = udns } if fr.Metrics.Bytes != 0 { @@ -82,21 +92,6 @@ func RecordToMap(fr *model.Record) config.GenericMap { if fr.Metrics.Sampling != 0 { out["Sampling"] = fr.Metrics.Sampling } - var interfaces []string - var directions []int - if len(fr.DupList) != 0 { - for _, m := range fr.DupList { - for key, value := range m { - interfaces = append(interfaces, key) - directions = append(directions, int(model.Direction(value))) - } - } - } else { - interfaces = append(interfaces, fr.Interface) - directions = append(directions, int(fr.ID.Direction)) - } - out["Interfaces"] = interfaces - out["IfDirections"] = directions if fr.Metrics.EthProtocol == uint16(ethernet.EtherTypeIPv4) || fr.Metrics.EthProtocol == uint16(ethernet.EtherTypeIPv6) { out["SrcAddr"] = model.IP(fr.ID.SrcIp).String() @@ -137,11 +132,14 @@ func RecordToMap(fr *model.Record) config.GenericMap { if !model.AllZeroIP(model.IP(fr.Metrics.AdditionalMetrics.TranslatedFlow.Daddr)) && !model.AllZeroIP(model.IP(fr.Metrics.AdditionalMetrics.TranslatedFlow.Saddr)) { out["ZoneId"] = fr.Metrics.AdditionalMetrics.TranslatedFlow.ZoneId - out["XlatSrcPort"] = fr.Metrics.AdditionalMetrics.TranslatedFlow.Sport - out["XlatDstPort"] = fr.Metrics.AdditionalMetrics.TranslatedFlow.Dport + if fr.Metrics.AdditionalMetrics.TranslatedFlow.Sport != 0 { + out["XlatSrcPort"] = fr.Metrics.AdditionalMetrics.TranslatedFlow.Sport + } + if fr.Metrics.AdditionalMetrics.TranslatedFlow.Dport != 0 { + out["XlatDstPort"] = fr.Metrics.AdditionalMetrics.TranslatedFlow.Dport + } out["XlatSrcAddr"] = model.IP(fr.Metrics.AdditionalMetrics.TranslatedFlow.Saddr).String() out["XlatDstAddr"] = model.IP(fr.Metrics.AdditionalMetrics.TranslatedFlow.Daddr).String() - out["XlatIcmpId"] = fr.Metrics.AdditionalMetrics.TranslatedFlow.IcmpId } } diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_arm64_bpfel.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_arm64_bpfel.go index f12dda23f2..019c122b40 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_arm64_bpfel.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_arm64_bpfel.go @@ -13,14 +13,19 @@ import ( ) type BpfAdditionalMetrics struct { + StartMonoTimeTs uint64 + EndMonoTimeTs uint64 DnsRecord BpfDnsRecordT PktDrops BpfPktDropsT FlowRtt uint64 - NetworkEventsIdx uint8 NetworkEvents [4][8]uint8 - _ [1]byte TranslatedFlow BpfTranslatedFlowT - _ [6]byte + _ [2]byte + ObservedIntf [4]BpfObservedIntfT + EthProtocol uint16 + NetworkEventsIdx uint8 + NbObservedIntf uint8 + _ [4]byte } type BpfDirectionT uint32 @@ -42,12 +47,11 @@ type BpfDnsFlowId struct { } type BpfDnsRecordT struct { + Latency uint64 Id uint16 Flags uint16 - _ [4]byte - Latency uint64 Errno uint8 - _ [7]byte + _ [3]byte } type BpfFilterActionT uint32 @@ -64,61 +68,63 @@ type BpfFilterKeyT struct { } type BpfFilterValueT struct { - Protocol uint8 - DstPortStart uint16 - DstPortEnd uint16 - DstPort1 uint16 - DstPort2 uint16 - SrcPortStart uint16 - SrcPortEnd uint16 - SrcPort1 uint16 - SrcPort2 uint16 - PortStart uint16 - PortEnd uint16 - Port1 uint16 - Port2 uint16 - IcmpType uint8 - IcmpCode uint8 - Direction BpfDirectionT - Action BpfFilterActionT - TcpFlags BpfTcpFlagsT - FilterDrops uint8 - Sample uint32 - Ip [16]uint8 + Protocol uint8 + _ [1]byte + DstPortStart uint16 + DstPortEnd uint16 + DstPort1 uint16 + DstPort2 uint16 + SrcPortStart uint16 + SrcPortEnd uint16 + SrcPort1 uint16 + SrcPort2 uint16 + PortStart uint16 + PortEnd uint16 + Port1 uint16 + Port2 uint16 + IcmpType uint8 + IcmpCode uint8 + Direction BpfDirectionT + Action BpfFilterActionT + TcpFlags BpfTcpFlagsT + FilterDrops uint8 + _ [3]byte + Sample uint32 + DoPeerCIDR_lookup uint8 + _ [3]byte } type BpfFlowId BpfFlowIdT type BpfFlowIdT struct { - Direction uint8 SrcIp [16]uint8 DstIp [16]uint8 - _ [1]byte SrcPort uint16 DstPort uint16 TransportProtocol uint8 IcmpType uint8 IcmpCode uint8 - _ [3]byte - IfIndex uint32 + _ [1]byte } type BpfFlowMetrics BpfFlowMetricsT type BpfFlowMetricsT struct { - Lock struct{ Val uint32 } - EthProtocol uint16 - SrcMac [6]uint8 - DstMac [6]uint8 - _ [2]byte - Packets uint32 - Bytes uint64 - StartMonoTimeTs uint64 - EndMonoTimeTs uint64 - Flags uint16 - Errno uint8 - Dscp uint8 - Sampling uint32 + StartMonoTimeTs uint64 + EndMonoTimeTs uint64 + Bytes uint64 + Packets uint32 + EthProtocol uint16 + Flags uint16 + SrcMac [6]uint8 + DstMac [6]uint8 + IfIndexFirstSeen uint32 + Lock struct{ Val uint32 } + Sampling uint32 + DirectionFirstSeen uint8 + Errno uint8 + Dscp uint8 + _ [5]byte } type BpfFlowRecordT struct { @@ -138,17 +144,23 @@ const ( BpfGlobalCountersKeyTNETWORK_EVENTS_ERR_GROUPID_MISMATCH BpfGlobalCountersKeyT = 6 BpfGlobalCountersKeyTNETWORK_EVENTS_ERR_UPDATE_MAP_FLOWS BpfGlobalCountersKeyT = 7 BpfGlobalCountersKeyTNETWORK_EVENTS_GOOD BpfGlobalCountersKeyT = 8 - BpfGlobalCountersKeyTMAX_COUNTERS BpfGlobalCountersKeyT = 9 + BpfGlobalCountersKeyTOBSERVED_INTF_MISSED BpfGlobalCountersKeyT = 9 + BpfGlobalCountersKeyTMAX_COUNTERS BpfGlobalCountersKeyT = 10 ) +type BpfObservedIntfT struct { + Direction uint8 + _ [3]byte + IfIndex uint32 +} + type BpfPktDropsT struct { - Packets uint32 - _ [4]byte Bytes uint64 + Packets uint32 + LatestDropCause uint32 LatestFlags uint16 LatestState uint8 - _ [1]byte - LatestDropCause uint32 + _ [5]byte } type BpfTcpFlagsT uint32 @@ -173,8 +185,6 @@ type BpfTranslatedFlowT struct { Sport uint16 Dport uint16 ZoneId uint16 - IcmpId uint8 - _ [1]byte } // LoadBpf returns the embedded CollectionSpec for Bpf. @@ -244,6 +254,7 @@ type BpfMapSpecs struct { FilterMap *ebpf.MapSpec `ebpf:"filter_map"` GlobalCounters *ebpf.MapSpec `ebpf:"global_counters"` PacketRecord *ebpf.MapSpec `ebpf:"packet_record"` + PeerFilterMap *ebpf.MapSpec `ebpf:"peer_filter_map"` } // BpfObjects contains all objects after they have been loaded into the kernel. @@ -272,6 +283,7 @@ type BpfMaps struct { FilterMap *ebpf.Map `ebpf:"filter_map"` GlobalCounters *ebpf.Map `ebpf:"global_counters"` PacketRecord *ebpf.Map `ebpf:"packet_record"` + PeerFilterMap *ebpf.Map `ebpf:"peer_filter_map"` } func (m *BpfMaps) Close() error { @@ -283,6 +295,7 @@ func (m *BpfMaps) Close() error { m.FilterMap, m.GlobalCounters, m.PacketRecord, + m.PeerFilterMap, ) } diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_arm64_bpfel.o b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_arm64_bpfel.o index 240486c5286b3f3ed1a6482d10be8e048598147e..ea9d91d425e84ebd321b4d66a69c3aefa5017b7d 100644 GIT binary patch literal 294232 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 ruhtLfg}*kc(SX-_Tk_W{J=pP4^I+tw@!@4h@i3 literal 185504 zcmeEv3w&Hvwf>oDrVSO^QkVeI%Cx0W3Wc^%z=AM+qz@=fXd7Bk$h++%edOd6N;)Ew zwjfp>h4Ql3iwPhUpNL8k9~p~C#f#t@5wLhgxjs=*@yY-D)>?bc$t05&(d+fz|NiC7 z`t~|&@4fcgYd_DK%oSA&=f-0(&xM%xdoPSRuIF_>7B587g3{hZNcK)tc5j8!!-pw# zpAEjET}aLxCXXH}j4Sa;QFnhOa0=H3qwgODfKcnbNoYf6q0*H#LVJ6Jc*CG<_p7hI znyq~DRdRNj^4ZE)B%ZB&$>@tl_Zof5=pLhaqYoOr&*)C0-9po28;mwI>ix-MHRA?W z0HL?RXophfdkn5x??+}Itw(mN+PTTvr)lFi<^IZHTF&7p2j&qTbE-a!pU6LAKe4Bk zcQ~CW5_$uTu->S$M?H?fmGHhLd1fcQ_*Y8wl8La(>fN?g^>q4Wx2peSx0*j}HGkM@ z?QiXn-FlnmyLFqNu+xnE$JG*hO(1shFUwv5g?Cepy1eL0H)7EzgKXZ@PJ9D?% zr&#~q573I}yQt(lsE@V3^S|C^y-)ov?c;xe=+)4p<G9WWV>3B73c z4!Pks9xXH(zs_UPweg!hjC>Jf8H{D zoB=w|;v+3x!wu@EM~)V8FY2!^(;se7{w~yuIkKH9arIg|yYb~w#8cqAc33m|y&{nv zuJ+9A{GIyay)XCaSG`&dulLM^U>X`&(kl(7Np+E*(!ko?Z%m0?FxKkdc%;Rx{*7<8xYfULjK#IyexuIg z!C0$*;~VY1)xVKm!v1CTZ`1)h7;E)!JlyVE{Tp?n2*z6d8+8E^*gWMoCQaVz-$-v~ z{#O6SLo9CfZ&Zg4##;RwwFA5Uo@p2-@@75mKd3?Rcv9S7+nNfA zz1B`U#uw7Do}G8&N=C2b9iF z>z|pb{iLl@>z^5``LV3niaoeT&OwIuzk0y{|~Zm^tmM`?j*b|a7@9!zH z6W9CBE(z~3k?ZW)Dec)bO8wu>8%?8*xBK08KPB<-{!w=SHoLEWAKuq>T4&ETyRY>R z?^{3Wx!UfleZ%{@-s|ki*?lRlaGuaKO2^gC9`)DkDD79BJ?77&PBZeXh$z99u}bf0vj#oa#X%@%k2B-ALPqKYNVV|V_9PX2BpHSE***>ALPqKYNVV|V_9qyBCpHSE*>4YEdlWd%`D3(vlhyC?$9cQ$?qxF?@mpi36Zx|}MfBjYs z`f$CbyID!$oU~LuYh&s!yG*{6TrzgOSRov*o{@HIs?_#ss#LqXbKzv!9N8Eq%SL$5 zUZwjUwm;J|qo&Hel0LMbo{vZEuy@e$S?lY@=ZEW&DMG@#QE2w;`y~JDB%SxNGjx8; zUbs{E{*Bu2xb9~U^Ka00aO;16yY|zSus=rt{|4>HTvu>Js5U1s!-pXbeyW5W%qB=agFtm{I~H_^^yG367{N6N}Glkwf_uj z{|legc7^&mh`RYXJE^_}Tv) zd!X?rP*M4$J*n@NxafI)R|=nKCug5cM@ro7bNo$eD7U}$H;+^K687P97b@t+>w?}x zD)d|n_gSA(<3x6b)ib8;K)EZVME#)toROXWERXs9z3buh@NYO;3idZ?`8;Q5xM*~j zfEMUUO_Q-tO1*n)_@OT?8*;>6kUDH(}f9r>1#@qd_ z68W3lMdKGr#Y_2HGN$_T{&vwoKj>#%$z?CRTKe6Uz?AI#fX4Z}iy8Zyblms5Y(4-} z>NgfQ5kkA_eBf`kd7#K%pije^rJ2&ALwKyx7+c&R=z1?{C)iez9C= zSKS}@n>lNtpY+S`QMK!Kv+GoCr_g`3ef=#~UYC{U{9>lsVa!zZ+cEBW#TF~K%gXI1 z4+g?TV}C7lf9x)fE7CfTQqz6;vl}9|?E-U-|9M3L{jL)TXqjs1?q_orURt0_dD{zMOP&({n6v|Hy-TAAVrd3r&;bbsjT znT+ZF)4%Z;$?u}EUlO`MdYn0s9wo*LSDw?y@6vs1GN%6H-#F3Ae_+4MuXzpSbG)MC zIz8NZ)G#P?JopLO4dEF&+K<^zK1DN6co&L3?woU^TeoU=^O9wM5I5T&dp%R6FFn3g zyZJXrv0kl>&%HNlyt7Bwf$m)1t(S(OavU)dvYJIb_d}lQB*ZGHHzJI`wPBJJg~@FG0&f_bWGLn#SZjGhU_Huzf#ZRlJQQFOL#iYhUJeH{y)C_jFgkL zeUv{&@&|nr=Z)U-DOA3_z@Z-1=-rMn6dcBv7>3l^0 z@gw;qWYiffT{v$yM$%CaTD182WN$sS(04>A?r+j_rEomcbER-R({reBJkxQa^msN> zJgK<-ee=VM#-1+a?@vF;71f6>xX=1@>G;KUCxh!3ZXeOvbDOj)^-tmc2BXQCjywCK z*Y+a4IK%BrFW0}_`E)X-e1v&Hihx4RC%5D{*-$T8C`FFsi=Ie6ndL9 z-`@2~-F((E^b{FcI(zPuc1*?&k#mv5(G9Sj5FS(1#-_%(0P=4L{S{Hqzft|UVBZ^$ zlmZI&-Ja4o#(%Nzc!_%Z-uJ3Le2)%YAN_rbB=m38b}sa<8+6_+^snvO-wOTf2J4To ziIhK8%lB`x^%F9edTiHqRd_z4>!$F0#MV!)9!o5rZKDOO#HZwQv-Xqld_)KO@O;G9 zlbAO}pBBxh^!bR{8?7Yy-(>clW#!*w_C`I#pSPvt2KABr(-M6h=ObY|F#p$l{-DEY zzi}fu^n2o^y;KyTl%FRf@9zaFDxVw=`X{D8fAp#6{Sr#jFv5d1(Lhy9rC>COoX`>75cZ~cIG z2g>hpQ7qg)S^j>B{I#2Uh5f%@B7c*+X#8f$zqH?~{=C0kG}I6JEk}s#g}UCn5}1;m zAJBMV|KDNze_!=3ZCBg>2m9Fnci8?s(0Q!1U2T6J&^rdQ>nF^v+J6fBf4@Zj{p?yI z|AJkY@3&nC-v95*t~x&ZzKz=`P5f)DR5v_V=}?9Iz{cw$KP;T9bl848u=%7&F7#L1 zhX>(267}ok5PdH-v#$tTp9_lu zq@zFU{(o@0yYZ#p{=efWDZenE`{N~En9qX=dLMR`aoayyzva2f8AFkV+*Ar{mpPl1b>swXXppgpQi~M^X)v5 z%WPNwo;>xczw*xH@mC5h?FVN`I^MravyxBtGxmgpcbeSaAH8Yme&-NfHIkp(5A5?C z;v^CG#>{@L=Me9gg#FGTy5{{im4CgIQ#f~+q2~>S^9MVh_}kAPHcS4=*mUy;n};{q zJlxM8rkFpBlXR1(&M|+Oy$^qwSn!9ZC8d6Z{xDYkL7Nrx*Ammm=C4gQe--KD#*JkB z+#UiPv#edSdO-IqWjbC(b z6O0jc3;Rm{%^F7?2cC!i$>%oyF{0nU%(;zUbZ*lzQS^87y5CWBZgZ)f+hCp%`|Gm6 ztJY;v;rt{y^mU%wG>IA|-$O2(+cc=0J1;6VzW=?>ZIVOp{S!+}4%_)BbS+R_7rOJg z+F^&vdVq1>fBo;Zq>u~Fk?s&8-)H(;o;SO5bn3+!^!4kd`=i&Z*DkFV#wXn$K3uPi zkWVXm-oy3$#JU$3s^Hzs2tqQpK*mKsuysL4sda&l`{B6ykSwPskN>pLQht++olzKf z2VNIUm;1?Blj&jeQAery=wgv``;Ey{?=?Mk?n96B3wjJZA63i!!u%5JGJR}5>e$zO zlr7SWR>t#_e)G|G)Az=G=&SG7(XIo}N2|2FL)1>o*nHS%B!_7G$@46v%^Yg?$%ZS` zmgzntGgvyv^+|_(YRhz78#Eot=#vid+On}UgS_vJZ2I1pe06@JzVy^S=|x}NpYT5S zQGM=%QCnu?2kx_qeeO&7x^HHBu5BMvYFTjn9_#TY<3yl;B?)z-X zcqK~0`Anr-FYXojti4a@zW<-C+++N_Q0Bi4>D>253+w70Eo2z(p9a0T4x)Xp#O32^ z=s8W&hrpR@}cQm`b>|?jnrceulH`r#v6utne}!1JJy>saqnim z&-CJFtF)b|$AjQycTAM}jZ}B-Qx9i9mhbc}=yA8&BdV{HFI8{O9Le&Sch$4ub1mx0 z{K=Pe=2x9}YW~UiTjfpR+W5CbZe$aL5%|6+LsRQ~ZJ$2nLh1-FlhiN#8>t2FtAF^T z^_W}P)^cVO2*8X-;e+})TejD0F{Wr9W`f+F%_2er!N)W7{3bzlo7sh@{- zQNIiAqW%`z#r&*b7xlx?F4~_%yJ)`-?V|lDw2SsD{{|gs`upu{@!Mx$M)nl??E|!5 z(YQX)_(;!i<0#YZLEMeMnSG6`mcL8y#!1%?T>ojR9Js#>HeW=?#Y}_x?=#Sk^=qsA zq4dK{10o0^{|Ca4?gxGsnTPoQLU!YOt<;N_3@Y{ik1#$8E;-Qr>E;p6SH<&ZgV`r@ zhpsE4_RVwN#d?OJcZ*U!S7e|b-~Yp_uPy^d(fHn;uGcp}DJD4v^hJPZJ(yqd{(yF8 z`lQUJc#agCf*9X7A{XOUy~f=>#kGfff5ZKsm~7=v8`rvx-ez>0(W{N-j9zB6-RLT# z^+xw^yv(+0y5f39&*flL=AmS3tpi_^LD zvxKMPd8zx!*yp8vcz<3|y-t9x{C^HGx5yw`s8_<4GXf zpL6fC2URw|RN1^zr418QsU3qVwhr^t4j5FiH#4psG^kQz1XWN(_%`lW>4G|_(u1X- zO7}@YmF{DMszXd(7bZcK?vsKleGU^;=|Z-lS?kf87IEY7@X{4If^V6ok)z43>-mYGL+SU&V<@;%C=Y;b8w6%9a`F`5kH(}=* zX=~?%^8K{6cS8Ao+S)y#d_QgNpHRM^Ha|!x-%p!AB$V%`%`Xzl_tWMd3FZ59oS!J) zZ?^Kye`puBM}NCGJ7{}^c1l4Sd%}Vpw4FjbSvwW%p#C4)N&7`;2lYF@U?=s*&<^U? zp`FyX<+^t zm|q6wkAeANVEz}F-vtR*f3B?^za;U7Ql0&BGI$}u7_CIVD z*j?3>_qVC}&c!xdAzpUzS0-h zGa<9#K>67?W_AlE(2LREZ6D^|OODn<^|0}%M7m(YM9C+6sQR62=iXC=?e%Iid%b$Q z@E%@Uh2ChZFn_7g_G_z1Ny4@YwO?C>`deFt`dM3rX4F=p_Gzn7e{QQ#1=}jvy6}ez z9p~CAwBBtMI!?D$=s4L{G1TPBjKYx++B91)nK(}3nJ&$*u)a4vGhM28$WMuUvTUiI z&y;0k9^-oVRon?GY(6nPf(q+DRxh_M4k~P3F+GC{oi75@H>j|AqeAr#Dr}ypQ2m1n z8%L}jL4}P2X0M>a#sRZiP+{YM*)OQD^@G_lsL*~LnBAS8?i|gX*Y!3?_2v5pY%%Vi zso|BlNSTf;mGCCv6YI2o_S5$7Z|{`IC(EXpUC;bqYggLmZ?P*4G*~+J0M{M~?9>?c zryc3}Oh?+k9kn01b{(wzQu$DiQt67zb$-!ysrI|T#*f2Q4Q3@F{64Gp|7F(y@PC=u z4ZTcbO60PWbYGTfRKF{{modQiLY}hy-wf?)lAii;*~ zZ(xjZwUghFu=tB&N54VG&rnYtr(Um~1L?&k4)xLo5B1XV(mgNn8+4ox_0n1~{mDNZS9+V0v}#hrbQfj(z=0 z=j~809hXAAbOH@UKJ$3yQ>Z$Ab*Q=*n-|f)GQ!0+*jf7pD*`f?<7?~gjW zXEx~gOFbUM{p{9JQf}e7a1V3S@54H~v3%Dq&VKuP-q3lc+QZ4SJkB^-`@fw@IAHX7 zZs#2;&-s|;@&9Z{f6(Et;D4Px+CIs$8Me;7I7a!xa}1qsOF!S;31Ng`$Xx8zrE%Je zML9cBUm7N`|4S59+VfO z`1$N!%h#TZw(9e#pjDqs1+Dgcxz#;i?)yA9Xw~N`LF@C9PeYfscmLT|daumjs6sMP0l4YtpVrsH@Mxb>jze>cFMn%|GLK9w&B4fE6IIewQ8kO^-I za?$aN^ff=n9i&|+BELerLNC_G{Xg6O&nvY(!{?RSuHo}a_Z*d@3G3~iqv~WIK1Zcj z^1geH3PVcVo}+G}7QC;|QN!nz+AiVqN^Otud8K<^s_hy~a?eX`-#p1ZFV*#3Fv&eH zwf*uWdtO?2j;qg0>HloU(soh54DI5cqb95#?m4Qni+hgh?BbrII=i^%sLn3-9CZ`5 zpk3@aYT@~|j{l)u)UQIjm_HSs(aaVndLK-dXDSH z$-n)1?$4wj_kW)I6X8eKD_`Pzr9t)Kx#3qZM^Qi8E2#X1=5vqE*9mWv2!{3@ujh!d z*?Nu$J8ywR!s`~ff3}^S9mD^}otFA!H|jcJF#EFSvfbEISP#~#V2^&!&->at;puwy ze_H+br`{a#qV?vAeShm+I6tgZKTF83QKxt<4dJo5!4lofq@6>f+^u3KgV5(V$dn~V3 zeg#PVr5*9X*1PPNZv1xRt9ySWI=->|;{7P)Szgl9bB)fP!$tpKl%D6h^{e~8%x&!x zA&vJ-V><6~U&i!Jqcq+bOCbh*8-#e-Q7Hkv+caL-XEG7O|CIMd3iYgPmiia$P}wN) zwvF{dv#ra8(yyi7_TFBxoulV@oIi{0&V2*Z)BapxBt2bUxc?(wEbrdKNFFfM{x5j~ zsjvn@CVEmKQ90LT3%U2Rm_O&Q+5?_=mG7ez>segRf0sYFbB2WXS+ysYdr+^RoeK4i z?GicaJ6o$NpIiq{0pj~mOz-NOu-^}G>;BHMnkX6LsE+m|OQ5)HmSj`Ws+ z&vxQ-K?bf1_$YXn#KP}s6qi%TKc?pmf3I>_Uk2*I`WEZK`_y!>`_c65wakY+hC=@= z%BPfEryeVMoky5mM?*1$PWwHAV*hgOS?YW#8E=vrE<+{6?lE0p@OPsak_Tuz)DF{v z*$>$hn%sNqXiiErwdSQxQGXw(A3A@p^_EBh#q!a9oQIu?>%)G`z#xcBu-*=3CV?hx~($G-mhP8U5Bp6(l%FN6CYgFA0@=aBB)d9d#(uphej z827i{EO#Q(x%VRr^HvYF>3gn24|DlDyDft;*wF6x5+)3leFd08x(mQ{wjXxv(s<3X= z;kxvB*&yeO1D}`KdDp+{_aXdJ=Vf{>EYX^9;t z{UaIMX6p`jPPS0=<#;6f_U#fKbY72+pG>z0NnY>w9^82Nk2@#(+rRhF_nb`6H8c0> z_ZILwQ(~}W>}We5n_F}~mXiDbZ2K1G7agv=rlRL)ul;%pM&13ga>S|6s&j{a)+$ZTg*?{ge9N-@^`iZf58H4dV8& zi#-=8b#C@ATwgSOq20rC!oKwl?ER?dIT`m^yKJ53{vXj`-*@VJZg#yGHgNmD9<{T3 zf53eovv3Z#Q}+YW^E1wH(S6`R`#$zDMjya~gulXZt5J536l5W7a+NAQQR)x-aH z=f~e7arb`*{j$^bJ__Y}%8#F+aZDndDc$dtR8JGO=MOnk?_=6!Kl97pDslJwCw|#k zdf(-jNNXI^xa3zQQLlQsQvM&(6kzoPjd$Lm{d>%W6~gd`%o6JUub&^EDe+MM*?QlV z7oVf?lKRi>n_rnK6zV^(Z+?mS8i$^*P5(ub&L47i-}2%MBp&L2j@~cmuk$_sZ`{E4 z*L(~1C_7j4Q!}7Fs{7`bsL}Xq*8dbq=MPz|>0Nur&y#ql{}R1l(0{4MOX`1q-~7sI zHNS%XJb{M4y8IH$HU66Q*XKU&{UF*4e_k*2VsO95?e=}{`xqNg?rFFm%u3@E@+S+C z?{iE63}&f+NBI+lul*v*PYGZ9N0iTY4Q6RSi}GbZGfVqpl+S(^%+h`wOw<1B&b^mm z5MaFm``tgTV<`Xn&u5SkLc;sVUq~OW=V$+ON0vv)z#AP5tN z4e2w!ai7IIlSennzJYo${7*U0kJ`b#Qx{` z;rAicGWzMxKa;Sg{(kK+xxsVAORR5@LHiyDTKGPw&4*WlN7!4B4}@Cpo%;KtJsM{{ zUKymm#q}ya&t(2=%A}W(3?~d*)u-Jj#8&)^&TFqoJCB+09-;qw^P1B?F#Z44<~67P z+f4s|wRz3yKU?(Q_q?X^_@0@_7x%NmI1tkfAMbY;^?%Mp{hw=bw(0*p@T50I%HcT7 z5#{yIKT{>Yg!k;9Szf2UE{*3poZX<860dFRbAM&LZR;~aOV{%>shwNbXIu66*0Zg9 zBwe;OZ}dT<_Zi(Ol=b3D%AGe4bbh@T|9>G{nNxX`)(&}&XPl>)o-4cT#;fJN`#rkC zbM;$s6CwKlRh~h9?*D{vJZ1%o=Z}5eZ)<(K*s&?{+?eHLD{r&<)fC!o5A(m2cR^Pv zE$G*yagOg#aeoA5*aT61c(liQK16<#$~!yZ_spf7=)CCiVZCT4rqA@KoI9_IzOP%u zd4)m(q>9c2Fru7K4yr$N^ z?*(LAP4At0pYQF8-MUOaC^7JJh)+tsLFFfme$nW|N?Wx*1g#&l_(zR?#OQ~Oe#qzt zjoxeYexn~Zs{Ji!?X~#ljegGPXN`Ww=tD+7ZFINMF9vC4_JO&jl+LN3-LC+1K)mEFqonK;E&h!dN4!%!XK~mMKDAC!ynID!_G6* zPyF#(;b4aPi*LVs7|c+=@yF};nSvSGj{bP|dZyR*^T+FZL%|GfH-EhL|6qo;t3Te} z^PQpo?T=^gWP0^;f4t6r!3_0J-`>jzCaIr>|F25@HGFQPejC2$to|GRUnceA@c%NY zKZpO9N&VV=Pdb>S{_Pju=T$!s-*Z;K3*YBee+%E|H9sr7&#QhIzR#=uIeed2`*rv} zulA?#eO~QX?tR|O-8!y3gXT}ee)M0S5G(^d3$!IR&7NO;K-TY_cj-9g=9wg(gVS>o z-Uay7dEx=k&Ye0gyLn_^<8$GA^+@aHn?1mVc}lkpp3`@K$8R_Oy8hQxs=wL17CnEK z@wEX;AaEXuj<5aCoBu<`gZ}RWKPLR>{^&W*|CVp>Et)^ytKstw_kRTVJ}vDUZ2YR` zd#|pC5}qbV#!j^79_Pt(kAd1{3(_aNqon}WU)tp!YZn_|_Sr7;O+S!6?Q)p%d-u0p ztUNalyLNHs-_8#1{jH`Q%XNI*Ve{TSS{}dOQ@mc_$l%67_kXK0_WLg3`?A(Pw$2Fo z+CH?m+DpeVr$^^Kw~75-J0!dnqR8KBPgj4Y7yov4T&4Bfr+@Fuj#p_uPXFwF*snZd zzrV$92P1vLn<)kVZ?%j2erizpg!qGRKhhUeJ}Ghf4^Q$EUh4n69pKu9am$TM(eZjG z|DPS54x#utOzHQQvnp@rj`TCG&pLPNzRb-NrS^%PciQ^ferM7BAGfRr%Nyz!omaT;a_hW;ecd|J?PC(i41x1a3zkgodz5XJIu2%f z{wU*aTcwScJ^EZRsMK}Y2I$YG3o3Qpmg&*w&OwRwcBaR^hiChbFuktZGCg~xyr5Fo zW#N5Yw`F?ldw-R>E)DPNx;4{d-vg}Fb!m8C*R7cz`(9wBu1mxFx^8v*(x6h;rQv;D zw`O|u`#C|St_#Ead7YPg^m{2mrLGIZ`?_w-^yv3Af=XQ%hWB;dnCW@Z>aXj<@V>4a zGd=pgLr|&f!tlPX8#6sGTl#_bCz+mK+kIUZhUsuPld@?(^=X0HRn!VPG8lL;zLgxo= z+)8+#6ThUM47|StbeF^;euDeXk4oK-rsrN5%_n)2U+}l0d`ihN&4A(6S6ezd)^()X z8=Bf$)~A{~*0raaI$9dmXV$Jvt!>$mTCsZFhSY@S;a-2aOWK=Nu3>Ge<+4m5X$tZk zm#l6{typ)-TBL1gTAx|BHnpZ zDTjMOM^oQa#t2gxqfe^#J_Rur$}`qSczsj*+|>;$gRsy{)0+0Bo$W1sIkVR_M>tS+ zK}{$CEuzupOh-!}8=$&0^@_~u^(`HdWDRTDSJU)nu}qK(&@AiMiOD)zf=gDfr}^A{ zHcX~HwRYY5)W(*Mb*W7I+a@$$G{e|yGJzQmH>TPh5pMA>X;{r{Gwss~DYS(<)}y=* zxI^d%g*Gjg7~BI?dTq=44eL7EQZ1LZtX&_3nGWDwMWQPjGOJsfsilFlUdzKW^>TgE=KI*$EfJq02$Cb2X_07>(;i^ zWty2qAa2CG9H3(?;5|5IQ^$fDGvx^rn)OeddLXtc(a_w?wl0{rRE3?;aIb0IC99j) z9%a@$0l0_IMNX{P{RXZSSW+YG0H?*LBXst5iMC_*_;Y(FZ{E5~%~eL}H(6Q*aPM7Op;Ig@U=?jnFC#k zi}l?Gy2kKrpdGj*PtYtb{FTur?*?EUBSCz~*^K^oEo2bN=`%MNJ`(s=#qw>#G~x`9 z7oVU#=u-?Igd9)E)3`ngOkd35az2;`{v`M!59<7pb^AOngb^uxC}h-&j~5~zeSF^f zk;qKI=M$Q!{Al1G08>Buyd>OE`E%24V z&PNbs=+kb+ec)IKu)TTRinO!?>wGUT`zyo84CjD91uS(zeLrKEefJB7Q@~#aratVu z49t_h%(fp#210S$9|c|x*Z#Eq*N{KLh~x2LMKB)cUco}2wrAZe#AzFcr#VzKKDtcV z2DAnBKEY(EH|vtdMV}?k;iBGCapiG2KV?4uWxAdOepJ^}5Vz1rR~=>KPMl-J?=^k- zTY!f^(zTBpH!0bHi)})ma^q|YxDglIup5{2!4#A@82Loo2e;$&LxyNuxqiyJO~;kS z#rmHLn#0BV^E@$+t5iR&l-hYCPKQji{%0a?p-=r$z6ZMDL0QoAq$ubY zq`Wl5YaA-_S?0+A|1OM$vy~-%stP!bi+ySyXbuugTD-PFRn9yF92l$vw=}$8EwUJk@5_j z*H}kh)sP`Q9M?s_Fq4A8PM^d*MS}d%I9ShK)(ihH0ZBDj{$uHDmxK$BIvQ8 zb3iA7atC)D=+&T{D?bc68T8AbCxE^P$~kj5j5G!G7|^Mp^FgP9wt#Zpx)Stc&~DJ_ zpbvp^{(1_ObHQ&wPXiqZBXgeOYY?0l&IIMSe=#V>JN`REj?>#gIsShFlwWz2l{@{`Jla^3qYR*Jsb27pyz<{XSNoC zP6s^~bTQ~6&^4g!U)O@xfPMs&{pjnUi$Q+}x&(9#oMb6z6)5{q11S4X7byG4ouJD> z9|2`Qc@gwN&_9FnB=2xK7u=SQm9+{Ve-$*_*7y(Ql&H;}$+ztFjVETR@c)Z~! zfsZr17x*o}mqO+x;03^}E^w^I@UMW+H~i}%Ui>1%FN5D~__x4o4gU_f(=g_c*cQXD zAb*Ap{D84;0sk7ny%-Gs%`gXq_XA%Gej4~L!#Uu4fmz2q@cqEoF)i?ez&8TRAOeD{ z?UyFtv*aT@44Ec{-ebTmhMxdlX_y2m%6k1f;MW=d8N+Fd*MsH^gTyiZNkEgxFKj#y z`3B>?0L(Uug!ozr{tA4A!rtmt#9i6LMu%yR0B(k08rL|(IbaKM)@c&>$g+&?NxfIt zP3ldYwm3+f^*$N$a3vZ0DZeVbPZW3dK%P>cvmoDUGPAU-Xo~oDi#hovkXdcK3xV4W zuL4FWUxSZ!!)t-p8(s&zQL(d2EV?(vZ3dVr>~B*TK>#zs`ZEMdye-JfwezjOjm9T| zu41pA2>&C%>v1nl0S)m>48UF(g)}(7KumODe}T^x0`0(YlHoEX-h;?{i(wMzy@fJ) z@Y(kmz78xy4f6e-VH6O1!7$2*{lYN1O#BtY!@!TBlQS*Hr2`COT8SNO7*j-SoM8;} zvB`!pM8{4xj0(nP8OD$qJI^rkjlCV1deX+18Xq`zm0`G1>{i22D}IMz%(t-z3}eoX zec5mY@Y9CTr(-V~#{3)qyxKC@c7$P!ow1_~V;+v3WEgXC>(b6pnsm4gVH=1Uc&>fV`Xy{n_#%k3W%4-CQ4Xc^(4(p!#KU5PeG2+?|NYTY`B*LUJFbe^1vH` zk+ruMcq_2{YdlQww*j-P6!0CuyMfbh@?!TJo(as~?IM2`@K+7b27cD?oHu!8KQTNX z`TP;M3-UFw!lYZU=rdu+#T@6P=YSsq&I3ON%(C)h(VoD3*2F`F9{`U4 zP6PiESlSEtPrzJz=Yh-62GZ}wBc0(CFn`ud^aLIYyc_cMz>^KH0zS=f`*`dF4g0{W z40nw8hIRsvf(|*zZw5Y}2`oP!b~K*7IeFmW@Ee|0=71}Kk6`}5#{&Nm+4Ep!3UDQ5fKLbR2Ag;RHH>c)JgL%z}YX92ewUI_d#!$#tKR%$`YWt3&QfVkB6e5CC*W*zYThSvf^rqD*8 zFh1MplfY?6?zk4SF=zFZLeE`rH&@*j%uABf;bBiOQtcS6B$gO5=D zX=9?yvOMq)!GFkjKLLiQe7pqwO~5o5zXARta2|>N1dLGr8GH=oMj82}$wBz668S{3 zL>g!$WIh++f8B5r{Dh?)2mE>C9|z2Sn!+{Ja2oh@V9pCUTm^lAXM&GV-iwd(fT<7E zl#n+{;_Sxv7`8?DUx?s`BN+OZ(H3t*p1Y0TXqY}`J}&Q<@HXXHZYyNE$Uxw^Br$!y z6a1l&nF!2hl8=BgTnYZyK-0Kx0Db~AkLwm-DHpPL8|J#_0mGaxEyVf%c^rNeAP*Uw zyOiaDzXIG1%J6OA7SJ57=MB?fKX-g!>b3{>S)o6I&$dVd4>?kCJ@5$NM(}gMM*x2n zI1hX@Fo>5%!@9cUfSvw%U{|j_z^*P&0$YfG*&$5HtC*RF_*WbP|383FLRql4oUumh z$n%!VaX*LaOvn&-<5~dxIA|W11-OLPgY6ax!hZ}5^0BmcA^xO8U@s4`$bSiO$~%=o z%hHIShjPCG$`JKi<>=VB8xf{G9M{_*k5K+Ce5?UxJ~hBxuepB8bL|#N;pXL#fdXYt zpYM>5uoZmHfjL|*Z625b$z)6;eu^ImJj?#BLiuF5^xIPB*VmhFgUK)>)JxjveURTK zIm3TY7V`H}xLB7u&@?Xg7vdZ)3vs^J!T=&;`#s3#S!H=2iC|;JSDQSOd>VcmJ{xNV4_{YFfuc5eS zzLx_2xyh%2f8){ubHDskrUm{3_&)>A1IJT1cOxHz%TVB75ySZo0{%7e8?f~Q{ta;Y zK=ei6mw~xA#M)EFiao%52EQBeCxIJK2jZuIk4`Dx3w#1_7x*s$PY3=TF!z;b0{;P! z`^tI1-NYCJE(GQpnB&UDz<(tlx;FwNls_+|?|A+Lw!y+=WQw6M4tbN zkIs~|yR7%f{2@OOx>7n{fJlg=Xf&_)o>b^#yzv4*EI>xa=WQvq1KGC${|J=hxdm8H z?=wF}dQw`i8sHBDcY`wApRzF!_#xmILG!q1bNUI#RgU>z1f(xni2s)Xunuy}pE!W( z(yty)h4p?MnEjaHiIidx?`!yg8_0Wud>`xQ;4$z$E#e$5zK?YUD0TUMN-^gRzOzMs z3iv0+p8`z3I0Ss^`&;0Vz%{_Jv5J=iA7r>5_z+-ZC3}lE0{;@Y8~hY7LisO*=-fLB z_(bq;Gu|}d4;h{ge2?L`SX$0IX9J^c%F@7Z2ZlK%tTvoR>>Y-4z}Feh19v<57~b75 zoCf~7;T-T!4d;Q&#^J(W3TgQ+r7Mf?+YzU6RX~O~hwDhgdEkk_ail#Q_$=TSP=?vS zyFqif<^#i@%I*Wc5cu1m3@yNH^L!lV`M{09=>(ql03($D79W=@jzJZ%2X7$6TjSU- z;~s_vu@T?tdPVOQ{2-6`wUEKkB<;EbSjI7A)(yNHeA?mzhOY+xkl}5>pEP_M@MnRU zwj20i!?fLFhW7%04Vd+$Euwz;UGUlVIb6<%x`8c7zxzERXajF3u4f@1N0ffUIp|NI z3_k_`&!A~WG{iYJS&09|08}aTFQ$D7>5%W16maypYHU27$b*;0br5ia;R@hJ;2f?A zz`H^7P|1z8h{ulwAEDesVHT*q3quH=!$oGC5d=_~$4*DuI%RqDf$b+Xyz_yPos4;W zmfLJH7lV&b&U~5`7oKfqnBHs^0Q3LiFkA-Au_KM^3d8ll7UJ#5Yzz1Z3T@r$QX%`p>^_pnI~2U-?mOFq72g=ilV8FAveoO2mL4+Fu49f? zJC6Y4DBv-6|2V@_z&{z7V{1Jw3qwfh$IN6XuHPLa>&h+clYa*0IEzrmmv)FDS5|Hq z; zbs}WO8Rjh%Eq=*4hJBfVeVjPO2*SQ()*dUbS8QSNTrUk&_e&vj6w0MOR{*>Ez6Y4{ ztnYTirvWoefP7kze2C4>mYzhwhHicenTxB=|ywx!LI(D7m zHsBi#uLi!w@EYJ9hSvh$Zg?H=9l+GH9hdW&9Pquy-v)feWGI3^tUF59>s^p>^|}Ul zlC{gtzzA|yw*3UnhwWR+KHMX?c6a))-QRa&nDzs}Y-5J|3^UKq0MqAb=SP7j1E+u) z(Entu_)YLn0H5JGV9xUlF9LHd#PBQNsfJ$xo@O`>MNTrTlAgF2>ka#Okz2xNJ;;aO zxFGzIh>_20IP#=l5mx{^pBZa-6!?>Xu{791nYRGjx-c=zFz&_9F^qb~Y7Gwqe!F4V z=kOK4;7LBNA0bQ0lR80WNB|k)H$bf`3?GDiwi?D57~5tTa~mh{wZe6ZNRiI!)?G^qcPA9uDuv{Hgw}8c~Kii zW&R!cI6L2MnEG3YA87zZ$^5Z?I-X}Bav3Pdfp0M#AQnFZxcL(M-RC&x*mPbY$Qz}3i z_>L5D3YU9^od)LnjO5qj;yg;6!xbPO;%;1gAB8xNi_g)C_u}GwModL=CZ7W4K8gG^ zFy9{{t_SA(nDaq%xZHa}DO7NqrA-6#y+x4+{x{?2fcb2m{BGbAQi}7GH<`V_A2Un~ zej0cI%1Hr#(Qr5LS4}2`26)1I?El@s6~K~@$%74TRF*}C?7n=%`nLNb$+~;0k0rLJ3CZ2^&oPMpzQXP=2W~q{<~2DBh`y8Rp6}$KXeVSi*5q+*HoO;@>k#r;X?M<( z2A-5gg)m33nr8yT-6Sjkrs-0+mKp}}>hS?Hd-b?h0*?XB;aUb^;ykX7w46(`tk@NX zv8j!1GmLi*Vz(Q{ekgXoVT=W3p9X$A^rCK$08^hFu!Z@~prUL`Tdop%7IfwzNyIr9YO{`j51dEi^Y2b6WeUBK5NDZ@@+ zbQs}tuIo~E;mmIo;%?u1IPgP|hnV=t*MaXh`R@WZqktUZ-#3|wz`q7=0iWS_!0o`@ zz<&g0xm?@6VIKU@WJUn5vV2AXuLIr&nF`$0p@of z8KUPxlfVaC>N^eCrF{$VFyxQAN&Z(zO6+&Q&saW7fm;nP2W~Tb5%6lmjlgRRuLNFe znAri!v!FKcUH<#SkFG)XN4`}4AA|y~+;-@IP~Ig3ij`;!{;RJXWHv(n5@5Ck{ejro zZdeJsbwGxJb_)#CZtD%xZkHOS-8LAe-7YiC^nkC)ZuC#KBiD@7lYwhSVlG2ABY%YQ z-9lb_{!X8$JuNG^G~Vl{04Q~^z^DuHdfdOpbl|vPA^sjDxCQ*7uxA=f+UE+$GSEJo z4AUpCG)&v_tc`(oYlP?*PC0!jtiL0SHLKv6euCn)UZJpwum^hcoOpkOyOS76v)`21p}^DEA4#3_?Q+CFQS71fg8fm?Bd0eSSf ze;#<8W4{79gafZJx#D~-Z`ORSD{=pEyT7f({WrE~`Wx*&{N@HE3*3!G*6GUPemFy{Q&d4{vV7aM*D@H)en17BhIoxs-_ zz5@7mVAef{{6A#48~8zB@fqMR8RjALw+*L(pEvm&@P8TZ2L6@dJn&x(?*$%)f>;(e zRU-i&g`HEthZ%n_@OUSKG3-RcDd4jVr-2s%v#slamjSaK+kqPlUk2P^@;Ttk4R-@y zZ8#5nJ@8}DVK4A4PUalEPw8ZUKWum}@TU#)3#EGur+~k0I1T)Q;dtk z_#4azcr5TYf%&D{DGt{n4R9UUeDUjC;5c9!_-(*2omUUsYB&cR814q{GMop#7MN-G z0`CB(-S|b_ohFk8e!y@&@aKU!KjwfRH{1>UEHLxQ1HS-FAKMH3C&Mo;^I`|*)DK?* zKLt!Z`K8|D4X1$50{#|l0(=hew`m99^MSuZ{spL;$>)IE40i*s2j(1@2fiGbYYl$6 z_}#!yGcEAVz~2MT0p9`q3E({N$AF)q{M+ESz$wgA6U%W11bjRB2v6m(Hw4a|fOi9c zA0R#%?}Y&G0?q>;&}D0k=@_?xe~ff#;NuPFPlZncSCBsg!=~YS;H8Fhz|DrcfiD4m zFoyhryMP}8=9k5<1^z5>8h8gVn$XJu?*#rl_<7(@1LuMHrSeCCN3z^Ayu`N*SDoR- z{>$)O;6EFl2Rw3<%FjpIl;IlS$%dB$&oEpMe2(E&z;6RS1ZA}YuLj;7gKof=06z?z zek=9?!1RGU@QsG|0^bGvMab}r?;i(#Gundh!EtS|9c+frfd78VOhn$mw*jVs9|!IR zzaIFTz@h{2_kr&KKL`9GFx=A11OLWko&Mc^Tu6~6>L-0&;FhZx2` z5{SLga1407;W+T|hKB&3Y`6^g48sZF`G$uAR~sG%yxed(@EXGh0AFr+IPiN6k2)5% zF?=|1H*g&Kr-1J@oCdxhn6|11ehBzZ+5~tv@Lj-pU<>gaGI$hxgz_HTdt7mh`Hqt1 zr`(Hok)a{J8TcEJ11V!UKLGv!(lY!Q_#T#l>nFemLFP2@xu!f!B+!4sXSx)wKLFp2 zduiam08=K1Yv>lOTQ@MzUv`1!aUBHyZcq;(Fj~fH_y?fdAca9{8icpJYYg zfEMEG!G92ZSC>akp7+0HI1PLd(ovrrE|!aAlK+1~hPWFaJX8M^&}x)6vk?D6M9z&R#c~Ir9S%nVzN_y1 z;%BHUG1|!cwPE_vpA1tzc9phg3Yg~uji6~<3FGI0M*wpy>BjXY!}kF*Brtz5&!fOc zJtRyqoI>n$VAds#M~8C_*P+-&hU;<9g0ylwBIti&kc%M$-M3KBmB75mu-4M1fiH>V zbGhLh_}2jM2JObR!|+b1`$5AWfexQC{88yL5HwGtzSMyVeI7C}zu5K>;4fQSJPM5Z z%2@I(VAo!cr_A4x)`HY)4>JLSk?%krkN2crKhu0f^v{-03bCQ@D%i~%Ww;*vO5iTg z9Mqa%81dMNhBpCEH@q46EW=w+^gP2Lu|)tJi%l87`3S5plP65lEM5kCn&Wkvyi z#&8Pw5tk1z1MDhimtO<_S@8G_o%wwW@#hd9jf-b}-$fkZz~_M(n2t1doyxm(d?$c9 zxb!1%AK}3Nv~hWM+9TNu6wV2sKAwMZ@=`t)!d2YC}rj+=up3okAYA2q|_m7sjD2Vn#k zXi+(Nc~@?E!;c1?Z29r`6{2!)h?IK_nP418)xx*rIhXdC_4y0@q(y&jn%@~@%=h`y|W!fyS3fzzC_C~}l41W`F z0J-6q_Sk;!)->MxL78S3D8(NEWn+H>lyW}+#rnhhE$C3tBQQA)1AQwf#v1QD&;vj( z21OWAS){{}5gq12V1>!OxkzqYL~bGE)|uScBDo0>x%rU0%;b*hD<}T?B<`~gY`-p( zJ0?sIuKKl;I{M%p za%aR_EuU#c@qyBD-Mqx)(u3%UZMnDJcF z{vdMGAomlKJ9`khagh6q$t@g2?gYra>EG}He_1q$9LKFQO|E7TIUEOiZ!@{YCYQDN zVEyGpq`SrBYAs!_#a(~=j>VmQeq9tl=zYip^>B6`XYs-6kFBRS!{pv>=vCd4@fv1pR6AP$G^#f6yrEr0>{rY3{z&7Ve%J8_;(|Jw6)~_ zQ?m)j-(N)R^UDZ+DT03$!M~2+-x_8$eiz~YK7wC~;6EDX7(Ee*-bjjT67XzL>VG_N z07{t?fUf}MSUm-JJ1EEFX~1`Za?Cvm_{+vW8Te`Ap91_UFvru=fO#ImF>?m+@xUAx zPX|8J@EO20hR+0U1g5dh0`?8h1m>L1F>N;Rc3_TMRlqziWlyU1%QG6!*?waxa{yAfDD4*My8l^M5-z`9DVZ{9nnAU-s`I9vQ*>zL%3Z zG{QfK%9;*GNBC1C_+z( zegv4p_z5U)O~Yk%{5hOVOW@%rcGluoc0B!cr#k+QPvG$rKN#d_-Fmx?pBUn=SJh?O z`Ab(MjPaL*BrZUHj)pBSo>k_9#4N2k2Zin`3&=9bI6OHPBL__$#a3Dy)Zs_E)^#*{?QQGp`14$54g4aOXFp973DZfqS$q!R`_LEiWIw(0(-9AmNE$1rD`a9o^V3bqvMaK@jm8;h^!l3v$s^JE=_iJxXMQwNSNC=~^x?gUC+6xxV zTU@ndiC3lM+?mVk<}6rTHGAoT>P0TS{%~907?RGMJ-e!AskgZ5Y>0bIId{RrrB#dT zW=iTM)WiIsfRJqNf<<+67tWmLExEwJ;w4L!Q?q2gf|;|=QBb>ho`R~`RSIS=TdaV| z3v$e~5Mh3Wh&3a66Wy(;McuuwqhUi`+lr2smb##=5&api*VZU*hkhzQo`x6g8UhS( zb=usPn7P1Ux&#jsx5#Fp@Ts3n^^&$~oQd2d1!Q2G{-mP0wJ^LKXB$}?~oTYV3tE=mloI7*j z!hX3fon2Em8wK{ep}ARu^}Aa;r$n+vRZFdnsYAbX)l27BEuLS!MC%$=b3us=!C$aw z{+z}AvciqUHCk4`d$o%e%$|uhMw>63R(Edg!le@LC%1g=;&bb2suwPpeL=r_$bV6F z&Eo2%)%|XnZ5Gcye^%|>x&3ZSqPlad`Wuzjo>{wee%(M7;>~mCOovmL$HwAJTVEgmfG z-0E|y7S9{lq>JayKJ}z&C)L%=TsE-kEO|-Qd9_uGW)Gahf<@=gT)1FAg*a{vnj1#z z0fqruw@}Univ~2&?1j}!2G(#cdQ){x)xgPEKWH^zmK=EoyU*IxE?QEx2qR&shOM4k zT?gycR@K!khIBaDX1SsA|Ey`E|1~L@%wP+y6h--UYtS>#7soeyEk(n97cwD2bDtyxe2QR%FL< zlxLOLPUPlc#dcb?NqZzq$Cj`j$9mXG2^Y<@%&0?4MVoTPP(YU(W<=?|70}`82Za$s z2Sh30DdmnXv=>pr{b^_bmG(CXrgZNAzxG<+S!e4=c7QLj&iCJIzxUdEueJ8$Ta~xy zfuuDNa@}MLANvrjE2eUs$Ve zwjEtPmY+TXhKfQ#T4&Ec+w$16M^R+7Sk(cP6J6C=2ZSe2VX`{5dVF9a&mTF_`kulQ zk6}b#Rn1s2h(4Q5~t(rAQ zZ-Kz{^zmnoug;wF#H5a#IJ$ZyN&K8>rI1^#c9GwhpJz`M)|P2>(1M7%Iw|y?Bj}*V zj}@c|SJh=JM#f{OMW|cD2V-b?3?j}t(=i(C$kUIVI(7Vs_Y|H!QAHqwP`)bZQ_nws z>OH3l&pdYOsUW&_#~^gfvMeluZfO8o^gWPj?WZo6C0%6iipnJ@QDdk+jAK4+vdj8#-UWCxFl9_98#I zM{<@(=DbIS`4cCP$v}{23j1;@&hL2$vbh8goo7O!|7<5zRA_Nj;Y6K-zAwMsU4!y_ zVWc=xgf&1uHVomv6KXm1-+{Ad@zv@OQRp9l_i$EFC>4w6i(R3+*a7`~u;W}Po$V|3 zb@W1!2&EEr(U&@VqjGi;l`;yQc?in;P#DI?plM2wppqk~C?mz8o(~iQ)MMzN&hy}z zeyVuA_$GPi?JWrC2c62u#n2W174XSsevrJEg%*vn#CC@VW`y-nD3Il7GP2|i2N;P428)HR zv!VZNL3o#W9UAHDLz@f?3={^=cf1sO4;8vQhPuPhrTBZP=WI`b--quiK!Jw>S9U<- z7S6(I1j|N82_Gkq%AlYEnWPhO2maBJF>e=pJNjWz!Y8azx5_Mo#Xj)|*gJq470@|= z&!HEGp?6-24!y9y^wK&|D1jGXdqdOopY0j!3u1EWD)#nVEDpj50oxN)YSa|U*V)@K zG}LqUB|3D#^41Rv(a=yp_@Pc|vuIu`T^yp7t5h5uehEFbzc`o~y`lk5Y9F6*M_r-% zBg+4@3=~HAU2Y~GjdrEMo`Jz0q`_wF={XyuvZV_Y zI!hyAsMy)pF$gY_ETEP8#keDkRvc7kvq!~7S4VbFbyyWF3E;d+8x;zdvZexu!dPgn z!JaG)h8)Hhu?NN1;m#iL+nFM4jr|>^9@;(8s9-}Wi4;S>RNhr!4;~yC=u7HWVNWSW zs{@eO5nuoTn~RajzebKH3Ff}xfxezjP}LO0;qbx6iUAQ8Opbi~@smy?xsgT($Y)sGL8EML)!iS59 zvN6U(SH^|RV0<5<1-8K6kKO<-2ip_|M+@xy*;@fUR1Cspm(GEK^F2j+5nC#L)v|@q zofpBc9THwXL|>3`T%s#>7SV&s4rkEsdk4;uc6MO!QpX_1BN?ojQv3!zth>cNNvOAg zk+_qu88b*~n2;m_F%t5vG|<}vQz+ipl{-5+yCtUsh^QR>P=A*OyhL}&BaKG|fmtqw zhc2k$j3jg{mwV1O9AG4rkaXCvq|;G^dF$xpxWYCWfj#?t0r}u?GQfAf4D!WwV$6T& zt>uuIRHQUqDbUEwNoG9w92^)yHaTQ6+_@nb%W0d`cLtPs4Oog9M^&KV(Ks;2Fc`l& z&h%n50_A*hu)iRz0)RmoHQGu4q-AhWAZJVRgrsey?e4*R#uPLknavk&%%9|`2-yd? z7xjZdl0z&IeHJ>w_rsWjfIE?8a!tl}U@^Mm2N{g1knA{%kta?gVkbla28&i?Oc-Y| zu$&ngdWj6w%SbbTx2|&>a*?4Td>PZ9LBA-Jx`io)5Dk#g6LKw;hYpdouuRX4W_XCp z3wZeeWgu;{utdteW>v>>ma=##qA~yzD|Jv>E5FjcoUL-6ID=wQj$~!_PA=c^ol9zPW(#O+*{j4x zBt9@#$*(ZH3ZgL_a}pb*yDX(*wuKa28h~JgA*8?xmPIbi#)l=t@-l+;H$hlpj4xbN zjBm(roO}--LQrPLdIxj_NW(=4P~tp%2~$tZW9$wPx<-0?hbr<^c3@0B{g~@G3X41h z2iDakty#oJ*bi}@eg|z#>?~XY??DiQyeGmon(`7y@90%}mW&I`u8a@p!02|DE;D|&|#4iC2$kV=ZgIl=SGIm)loT6YvQY@4UnFZsRCqeYG;}_SBygcV75HY)VNFz zp&vX*8CVJtl}5^`sGGzEEh_qF)T%B}`7{^uR2Zy~5YTd=Bhp$qXX)(L$C z40uC9JcDZrh2A)9O8#Svu|bQYC9G0n6?UY*lS|z(b0U^p#OF~YOIhJ$jW{-F)GMTI zIl1=I%EG6hKXcOrlxxH-DY%%5WSpfgAy@8^>@KQLpubz7$`khCN|&bja2_) z@1+f6&?Zwco(y1?h9-lVL$+^}II=_|5XA|kKwVQL-xzh_ETqa2@ELgN+*w#e!g;V3 ze&SyWOB9C&MpPh*@31>j--nW39CorvC{p-YZc+1{i^UguO2q;!qFy-926Va*bJbdb;*#Vvr1Sanzy8xGyKuZdrT8 z_8w@D(bfRhN^_qoxng(F=%{Iy{UgTQ%P+eK9?2b`7FxDvjtuwo4#Aema<9%bwhH-N z12Wr<4<3xAWOY)bCihj(94Y0>Ids3I!y+?S*=kWeaG9=!OPg4-rwz=!p@r3M3Iu}{ z8XIc2=I`z#O_n5j3*G1wm|8H+4~z_A*3F9?FBzpd?q! z!xhB@<6asVJg>H#>P4;eqs3)gCP_b%JBCGeEO@q>(P8LP53HWKeB>c>MQg6=5Iv^^~etRgx#o6k}e^D2&^2cgeVWmG92dOZlFz{f~0r83Xl{4q>u!86&)6XxbUp z4J~B~J>9TzsZcXaQ31Lwg%C65hT-8}ECfKe=0G;m2XUA);Sd`B0rcf)c)CIna^R~t z#KfYYVt4nH8bm#D#flEG_b~2gjuXmLx##j zT-uw~=8ubqua-lo=fQ8>gxGtg7yAicq5)W{oi=+CyRi!{3Ji@89%emXZC#UHVnsGk zu^DMFeP&+{>w?^d_4Ki4r5`d{SPrk$gk?TzkUCsHTGlF`q-M2Pv0|+|T6MESVi;i& z58W3S+D1Q2EfuEV>H|aSOMBt!9*FtbcR@hwMQJ;WPvu#9E03B$)f;+ME|87r88V;@ znKFP56)#{T9;Jp0kkE&)@sHLzNSk5krT#F8A-05t2>1vigXaQ_lcDnxbRW_4=u{{T z4@w=0R9i97BDDslq2=cg!p5V*41eOE6O-DC)ww)QGkDCYi-2R0`V`q&TM)vkOv3ry z2&EIU3stTQYhz^Kcx&7ng|*-q3&lT7I6Wm0qxBAw7VHy<8ai#0#Znb7wikHk*}*T=_{|V>mB!HpRB$pp|MhV`viPIuHl*&(2wnt4c57 z=8$(Cen@uj%5))_iuR898aKu>s|8pzz%kL8cF>W2Eb)p(6da^)vN>MdVA?7avBHWU z^tX<#i%>84HrOFiz<4Oso-XLx(1W1>W3U>*5@*~?47vrw09G8l2u*zeBE%p9V5q}7 z2UaAyf>`{qgsfiThU6F)2}LRd#v)b&u?kXvJ_K9mz;HK`>+9$TL=;qsqb@C+z)E8w zr53>LeD7|E#ikiQ4l9{2R#4)LPCED`s*uFBE=RnvE^$>29Ge#rV=)hvhh~$S=Vty( zSe6z|5oZCSvAl11WSv^LQu)gzj|*)*r8w=X9Devv4pJX#tBUpng7#fVe#yy#++GMQ zgB^CzK!+e6PUyvQ9Mn`;nELX&T|mDfAHoV%pBx_MsxqqE9*N^Rqyu{3Q{iF%qveez z{v-kNAew57_iBQb&m16Z)K;%PuqmVRdlkW=WoIaNH}uS_@Ggf;=ozi>5N_OHd0cJk z0gqgN5i=&HO%&k!#1H*7lq<+mMWXwJ4&~i7)<_A%2CPNvHqyDh1G!Yj|7IM#Oj z)M?j>j2UewTXmQVK5SjE2@EHFu%V%I59N06MpcW?{l{VyF6Rsr=PPU=I-kE?)^BpL z5IHtiPS)Qb9kApu2%zM5b-mbsJ0%1YfGlAt>La-|l3~^?%gj_|HodaQ`1q`!F{w&s ztfL?N3KK5hS7)#jE0vI)#IS!h8a3n3J?08Y4vU>VSP|)R#t0nEG2@eNuVRmdWc6g; z0>*eSmc`vxG#b$cQFe$HXR%9I`Qo6!EmoAJXb^!>z{6@Au~-?XIvRmsW$WZ-7?`&x zyh$!QORy{;)$?b-9XJnxQ%XYt8$r$$MjIjR4$(4)15t5!!(vcZv8OORd}a_QSo*MX z+Hn!n$uJ~g41+K}(mYHnJq@TmgBQ5_3F`wiFw;gGBbPTzNs=2Xg%b8z$$$`OhqFpL zk2&{DF~py$b;*u7{iZB=E&ct0kF~6nG4(=DjQLUI=$_l8;0^PMtj&tFvMl_hQ zxhkwSZdHG2g@TS6Hx=t}qRfTOjyN<_IPny$QPqNmhGEPMWR~Hc&KwrBum*vjVf4SM z3B`VqHHLJAeYx!16W=QOg&x++J(@ef5hBk4088(XUZAiH^znRQeoyYMob6QHlZ}69 z^r+EZ9O&uF?PVKa)XhhTamA%8pPP^e6K}e002!{FwB=HC= zE9$aZB!wTZ{{osgN`>32RES5n=5SzuD%M*78G;I}d8jIGk3`b2<4Byleb_x5Hn?B+ zv6DxmjBy~UoIPC)WwR@X1xRyonI#qh^l}?OVeJ`=?r%s>WId>^2+`Z;t3pj=v1Dr> zhb;1IR5v3Nvi*$#a1b+xl`+{A$#o0V44Xf0Wh4{y59O6xX@`zHeF}YvjRu!Jd8@44 zeyKM%Q##KNLug@zP}XwuAhXHjKr586Vl47|%w*=>{IhSbU%}#og+Nc~6Rq17EY`Jn zK^<~@Kncn@jN~Znyv(8m>9E*S8X1oH-W@|>z~;$Q zwH<(wm@-DyXeT7tBW-};ByKsBR$6Pc(Orq`I&1WK4lePK2O40wbJPZ?wW7sNCO3*P z;%qQ#E8v*a=@`rUd5e)~<_5dDL@Q=)JyVOlZ9Q0h#ZYPU5d4(lNzAzI8N4Y=gKijI zGY%&X=#;fyirEBa>B*{6Zm;}gM4hhU2ua%!to{5O*EYzV#eVL{TDxSjYn$@KS^@+k z0WW)5qYvX)SrCaCQwL*qS@S{dy{m(^TNR|^E+5?&Ss;V6@2pZrlB2xfJxp${Ti%w$ zV`-8JEW!$bxoU*8amNfsLHV&~--9$NYCFW0JZ@y+Vm*%*2PVR)E0SbHuT;sjfwG`3 z<5?Jp-)pi7ckPZ~PneZz&Be9K(G!)48Nu--({H@wnSFN7*GR(x}vS z-_V?QHS^tC_9inu#j#tsZ>?zS^IHY~O!W`#8J zu2Dp9#jVI@xzb|Ht1J|iQSlN5G82F9<|^}DRcfUiCj``&(6e9w!|p1Y#-aD;ld)+Z zqKP3mGP&k4Exn;K3okTERk4RuYqB*$G2?gNUCtRx8`JaZxu%qhv)k2b=vH%AjPERV z)8oRA;elKne6OHjGhWUuqTD~CYJFv8M1iCa`wTLHo!UP)bK^#jj((h^fGA{hGfqHM zx|eqdP+&sH{-JmrMAaPAzn!|x)=!=Hw4TPvq$f||4Drcl4&-4N&=ysXNEf?(`g416 za;h9WbFBz|&;?&-VAuOH5M3f8(_!(`vasFc2mtqz>Y6iaEpVu!Gy7g z;Sro;iF-TazH)d#?PC`mw?pZQSV2x)K@@`~ubW}8H;cRUsLyHC(j-*!D;x@viuY2G zB;$V4?ta-2DlV15q7#<2c&4V3gciqzF<~V1-peT&aq~=z>;}c5A@2C%1cy!tgLwR@ zNFKr20kL@uHU=(Wh&4TQb@IL!tk+<+FUs8s8^|FQt+(2K##!|F>Dm;?l_MVMObl^*k$`FPYDg< zKp67HKf+?MrnxA^n<$<=eUb;XpFP1-*OhK^RvhP&6W4g8@!gN{0A^Lvu_G-fcoe#l zcnh{xsYN1<>J$CZ+<2bv01uBnX zu8N(<)vJcX^Z;IA)shK@impK5%JJ!9K9@nD9>>l(%w8q(V=0^{y4maZBMcfV-KS`B!Ab9kfL8J zPK%#@Dt~($M)?PG(j&Qb>&v zu+YT?6i)oAZO{-`u^KMMRH<*;y-U3~2FS|am&-sK5$!p8$;Y5*GQO+|fP8lJ z4izt)p)FVCt{5j=B?dZ125CNOL8YB|A#R%9t%B%@eWkuVzi`@Vm5qm;9`Dn!Fo z=agj!|04T8C6srYKPtkqU?dL3%$49t^`YO&d(?I?<{WvjWTiA+#w z5cgygL{mFBcC2P*SmSAk6b+dbbVyk%v4Q69xhHp0jCwh&;+xSlCq`2oSRNW~kV4R) z8jXu)!Bl~BmD-7;31FZ|rM*Y*>M|=ka-p*78&Z~8l(iJ*-ANKQ{y`Q_C}P&K+F{$Q zqGziCTD&T8TxmTaiLQHZ`k_N=G$~Ia3|)w8LP66MRvEFRL*br8uZ641=M< zV5qMc<6)dfBwSme86)#ho+Bze1ZFkc^k=cjcovsuC^Tax_0_4m4}>V$c7b0sw{fhw z?va#vc)v@R3Yd~;E)0OI_L^Oq z27SbH@F6n$(PvNPxbY>29c?+NI=O?nxLQAOmNA?g?#^}KvJ3PDIcg^tXEJs^} z)dEEpN^f*U`(~YrO_|YStW`EjnZ&32PsCpm43T2A*~cLT(tfdtwIzg=V8a-yUGa@Hw*R3D68uHY@4vTS){g7-+2!n3_z^a~ExmK=n4r?h{ zBzF{2^VLM?HJGfdrg)z8ye8=(=as5U!fskL%#`J_S!ZAb6@jC#xbz#hD@aSlps`xl z4-=Wf8VxBrzF0q`E-D#wFiCZa>9QPax5wJ0i0v0=E_p8(!`Ex|9eT_%PHVud2Vo3Z zOZs8lsz*zJZ?d8 z8xq;us_yQyI^wTo1)Q{3gTbz`avp&0|}%qtAp7bZS`}tn`AS~%G!dN6=qG=qK;8@W2=R{ zdhTL~fByNw^1)x`rDCAuv?gbB+?FN_U_H3O2GITJujR4Ryzw{oi^v!-+_JK`X$E&C zLHd;w2>IR7WFdTB)^cP3j^SWfZgg^|Mb9kXrar15z9q4vqqnR7 z?ZXh~C6_t5k0#fHGt*ECwFnKlqu9?3DJ$+0zP(B&WByb_vh97AAb-t6xpP_VuC7pD zd$|4rcM@Qrj9anN3POW$Z|~X-!?b;Y*IJ^r!eN89E8eO(h|@2d%pHAIv%{Lo(mHW? zh07GUs!AJ6L95hWY)2Wf4SuVHa?704yIffq2N@+su@2j3@=kdGf_}VT6R+M}%nL61 z?q(b-VkNC8K2J zO`uix_N^6Tw)-zIpQ|G)+f%tyQ1|$)9huAD>bSCu$tja~x+I?RlRX`<)=8Ks`JtmE zR$H-cu6H_8LZb!u(te*AaPUeC6Gj&9*1`1)aav;|>Y_fwp}UFV$NmX*#FqOzJ2=9X z?SkH`8U`!+om}34J#>C^F}Kud|Bys0ZUM4#=zry^b+ghxCW_~LaJT%)kD0b2gv zXgu4O+Y235(^3sxtAmo%S>D%G zIoh!nNZbEt{9p#>Ms6n3FDB?$F?_774*E!!#jXc4xxhu5j7WPm2u?LQPvt?T zoTsvdZ7mZU86?Ky{jS``cDl59%z)+bkzD*_2ooy1UAc-_O^iot7sGxl4AZBm zD@8?{Cyk`|N;<|J_0Yigl#8U412MqMF9$}NJ{6H16t8J{EJ(RxE3$)B&HQJ^^NL6h zFkgv}U~#6u6(J9%A=k8ckq=~~sRq$<^`l&h&;^?J3{Tag{D zJh)|R6S0!A^jG@`R>t(VB4k#*7WdUwucmy})l0Uh#=3N`Qn7Ttnp&m5tF6*<7FO4m zjR09L-!Q+%9IqSmKcW}J@~s*Of@ZyL{hahtmWH!h6*1j z4h~>ZN@qPPNR)ys9o%k+ea6_c(gPD=<3sp)SQZa+J$K)2eyp@TC2XLsTF8oAm2$Y| zJI7>k#mozLb-nLFHB9tCE@Kpl@WG7ATxQ=Blg^;$`>N>L;ve?#3nOy6(G|>QMBEf| zcg}=9Us{&Lp7o>Q_`Pm461;RkYow=ikOfO}n^a3*&ycnh>fwOaj8vACg*%oRPg-M4 z12xCWlSIm5nH7bBRncZ< z+*gsdXDA1Ci9DgbCq|p}oxNESy6U92R`{4>1yKz!aXB*-a)gFj6qD4brS@d(#=7OI zspTs4F3y|Mb*kxIR{Q+@{#+4z2iLp&8iDB%v#y&9)d3?obBrC0B^28GkbYIyMHUrXAvF=eqtM1YEz+Cn19d=j;S8rIp z*@l_12E%Kji9q&`A5f5EE<9r-w`0VMt>g?Pu4m%9E59-<`!!%ol&@v*=IC?S$)F!f zGGLdK<9hiX1e7c8c#Zi8jvHW)hTLDya5(TO-!qcSCj`aV`E?vk2yBOIPr8QiTj(0$ zS0lI$zQ03$hx&SPvox;k9g>d>_3HO3;xUNVywr>D?eZ5#Ecnd^y@#(4_dv&Qcti)ifSu6~4GniA#ctf6 zj)NDtTnm1aYy=cYvSVLx8SbT(R(7?)GCasnNuy-Aa=Q$&cllgJJQ9nqN68hDsHn3z zAcF7s^vf|G?3*n+@KYG^!zdV1q&jhxLGfJKLuYRfsvQ?D<7-p>_-OPwoHrTn=B6K< zGD3T!0O!!sysc2~<3Bqn?tHh8rr@R)9#!NGhH^oHyjYeh0Pmx&bimiBEEwwqWkEhW zQQukFSUcVL3YG8^c@{S;V>JZ#V-Z{u9^ludh~&!@+BC%R+f(>tGH%Vmw@vzZ(X;)s zJ@F3G#g0LJi#!X@xQjpNCMID}Z60}NKu?q0#;fAxj1?|vl!MX5&VKDY=ZmO2eyAy) z&_tp|+u$=Q5dx?C% zCB{+0he`CqQSe73J+dgDl7dS{E8xnv-T|DG!}rdz_K>~YYy_>`vTt<|?#x`#5qNJ6 zznTqmywo$t1QbQT(Sc)7P%Ne6VMziX=_!ry&Le3GCN7yH=faKoMAc)xLO)ECbZ~Zh zUh$7m+ztyi<_DFeXJMhU?8YPK17{1;2+GC$7?_;1LO}LV++)X#GhvK&yeFUS2gKH6 zN5`vj8o3j9YDB-1I2tD=9&0@t6f!%8F$&6q^i(row(u;WICY=_@4C+s5qvJi+nIda+AS>@z|(f)*|^#fMcG>TjC1lX6ri_4vI0rFj^9W zhxdm8BjOT^Z^JP&hbuk=&sN z0}b(TZ4U;Y5141^a;3~#qk$e-d zO&Q;6kpMWLCtr=n6~*$=L`K4IAyA-@s~d&Uun&q72*eE0C@ki};MvYYO-+X|*zy}s zl)gA`voG-)ZeW}&z-Oj-u_uZY&y6C1?1k|%Mfpky_HW4j+_*k!2%k>W^3k<$7S{%a zGaWcSeYV#+3_MG4Rtj?}mv^9baAYB1V2{<7jhbu%1Rl7=FW;T*MPB8rY`lO>T+KlM z?)Shaiu9G=`qS6mdpY?Uk}q{Ag~ip^AxMsz6m(iSORbccCG&>i0x}PCgwF<*Ux#tk zDHdvt(g!O@PpJbd&(hh&KTbcQqI+>XUB2}Kvqur1p%l`gFw)x-UkiLApOB$3O!4Tp z#N3B(VT$L&^3&UK264eyEeT+t!sj``hhR({Z!lb4kZy&Wo$(giI*v#bdl1zCgv$Lbgf-)H(Vvc4l*B6>CDj)2esCT+X8uZrQpQO(+bfN~B8zx$F)2={Tnm}Cr>`{Uq9U~ySNcEk>0+|e7L zilaBWgpz!#L+UI0ObEA|gRh1Mv>AjI;?}0P(Vbf$BlE;Ve~}kKvpk4>nxhduXR{Yq z97oU0WkmpY^iT7(%Kl9|GA*fGSc_k+$j;71XuF%LhNLw0j|&;oELWr^#$y>cpOk(w zLtU;SFKfjp-*j+A!wC(F1{Nb)8ZNxa0H*fR#Y1xMB{A+|uvQ|I_2Qc(X9p^3*W0fpH*2x(K;={i3qQezy zkKX*n{fDulAVI~kED{L2fdj-pw@z^6ku=Re9n1cGtIyh$CwvRRM4%cvB5lr3z6d`E6JQIm-;%gO}Z5qJ;?{OfJs9t40$cxj{ty+F;JAin(Mjl`E;;*MArk1Er1}uGfLP2Rj=^8lc;vKjDVN z?1SU1oEU8N2S{Yz7|w!OJ=)UK>Thw;M@4zK{a0h>0CJV!zTwOx`xO`GKhZ}};f{VQMPmMUsZ)L<}Tf2)Y)}i!fIr?Bt zC7%+(vD7%YL|=N75{3qSi$uRwz`S51M(hT>{7JeIUYN@9E>kfo;^aE69Co2!0}`-& z2F<54)H!&(Rksl}+|?ET$A(?mM5Ix%qrA`v=H%WY?{*-%W$oo7MwMMDV&VBD;^<}( zQ?V-FAArwz%Duo)x$G79DcdV`6;Z^X4VfD=>&_#HKEsMJI&61q+?~88#jd)wC?FU3 zYZ}X0h+P<;;)=!t<_dPT<d1t5?l7>hA&l#WjKQRTdbH3slP6kRara#2`q=TO3(vRW?zv+H z9G?k#a^U2#cOE-(+ECm>Z|K<*&pdYeNK2@^c(risdg(pv*c)s=c(ZVywPpuWq z($8|4#`ENf6GsC#?H@Vu{IjQzojj#Qen5Y57ksQC+_S4M_$Y($4x5Kt8X5|C&i288 zQ`NbF-%NuYGW$jt3~c<=OcrciYQw?xLpR)e1v)IY>!sds-xcVGuRy>53iPHc&>y%0 z9SyL40njj4@NlInJaDBtJaDB-#8(rpkcTT(Icp<t405iI;29FSEo8<=UUq|FqTQyTpV`F$Asq`Nq(F;({k$SR0@8yf4DxT6zBV+6v= z5k9MqCW3jM-*yf#4tB|MDWb%BD|S|3i3IDJ#XkM^GR)FtOTWeumsV&nl@Gk*d)Qca z7=&7Y$rU$r@+6N3*efX(wYzVm!pIsY5;J?l7A>=wj`06zw)Pl6H zE(AEs^8)_<>-)<1K@k4O;W9o3{CHCtp8)=KV8+AeIpC>{A$%0Sm#+`ullX0aG=v|+ zZ)0-^KaSt=r$YETep{Xk;WfIS3SkMqGY^;JJq7&cN6Pql;HMpaH}D4?eh=`i$IAW- zz%QRD;~xV4cvl&J4EQyNe+2kIu}uF2FseoB=F=<~o?~!$fsPX!q`btRz`rf8#5(r4 zMg9LG==)#Y5JnR`ncykKU)UMK?&%F-Msdw`A?*3ghA^l2KHx2L8^UG9=YX&I!iKP@ z`1^sk&Li{qpZWRP9l)12gnGsI+!?}M3mZbS;z8h=-VjQPKLxz=q{gHNkC)=RtpbYE$S=!j~Mq2J{KV&AXA0S2u;(#Q&V)i=f}~rA=WW!Apt% zWyMn7%bP;|rdYoJ3*om+Zwf7njozmCtDx5`Ais+L2KdO*rZB4b>9-^NYn#HPVyh1n zLF$kGx4{3L;t$aO>ze|yAoN+{q>m|nBoF`JMtH?PM!d2q^l8OE3;$boZ4Ps9it&fNz&YSINBk6UeSUM8 z2PS`?2d?=X`f9EE*9xgu{87+zPj3#*32sgNw<(tPXx$vT6FjQ;%S^9*bC^*4UEs&N zH-{<3)*jQ2UIY4^;-9}8{jsz;Tvq&L;O(QE!-C>v(t9_DCB@h71ATaNSW#^8hb^(Z z`$4aHd2^^&d>nWe8ZQUT`WXT~Si2!KDYp6=RsR;>m}03fH1>3YXA}Q(ilx53g7PGI zLGe7&KlVDxqj>jzX@oD(q6>37G;!go@{WjWDvDDvpHis6) zzef7<<}j)_E1zO1-vr8+;Mv6goMI{8D=1%r7ZiUT={^1#luz*^4aoniXfMTH%y$>D2(n-zbN^cQPFNwJl0RI!w=t|m++cqZ{bt60jnqbAHJ__E?Y$i0%cxNJO;ew5K8$yF+cws@IB2K zUllI^A8Nsvs(9zUpdSq(ulQ-;y^sf+6@MRa9&%lq;!gu_cx^){DgF#_edC6(qWCiK zwTB>|ysff6+7vH?{??}9_12n&k; zfVh1_SW;~5y{y>ktF|uY&+4mAvDH^jvDH_jVymwv#a3UfimkrJ6n_)>xw(5om~?m> z@RZ_PA**le-5@eMrbKyu8g9Rge-!F4Z3M$Lzz8Pze}cYa7;<4k&n5I$#Z8CN#m6>; zw!}Ym1N44*n9gtZS`0i>1e=GiB;63}mpNjD#&p7@v{W;LDnT0&9_{+dGufkoi$mgF4VOjBaLEkci z{;F8g`vL&uX~rk%&7r?421TB{;`#>>{xbS!f?E_z{{(1N+zJ2nuc7}sybZWr@drWQ zz7zsjQquo%;O1{feS-NRJ`6mjbj#1U^S=%BX~lmH|67{SKNZ(Mg!B>5oZ=(EcVP@% zR9phy^>ox9nI7>L;AN$M9C+(#)CZV}bi?(E{}bppj)ss^{2K6%F^pM`el6&YirK;3dVDpRhUB2mNmY9V&va;_}}>zluz*&fwz&lF{rYA{{(o;>##2* z7$QXYE@;wTbts?W>rP_ou1EPC-VWUC@GZa)u_QeGza6;U;d_C*9exKe^*5$R|1H4d ziray&o5GOqa1HR3;vWM2&@}qD;@@s?BIzggId9DW<{lH&8A?`z%=mK}Zo zc*Wrxfoq{JGJp2eDgG?uM}KN@cq?$5;td!ZcA`JEE4~}}x;B(w@hRZ#?HIourhG7- z_@7WbO8+lnJXib);9J^J9}d?8Pb;?k&MUV3EGYg0!f!=?T~hpA;4LqselXdyypKN* zJO*5wlpp$*uaCUqe+B>7mcYM?{}6Z^`Zx7I`u`^I&QbJNhwlWQSG?z4pkutKg?>Z- zL%@gTF}^DPKY_P@3FD*UzXX2ULJ)n8{_Eb2@+@L}1fBeCPq*S0&=0MkeicsxZ}|@T zm*Ou1KM*#CNyR(b&{dXEpNby^zWLjjFBG=}-?V~pR`I_i4yaGXKL@=3JD4vLI`uc^ zkM!N32k1M*e+GQpW|ZII8-eQ-Z+Q>eyB6cI;)B37*P#CxEUV+nm+@vnh?$G10zDaAY9i}+VIhH1qQ08?I}KFIW*2i~2- zc&zxtz>Rle{&9E@@Vw&R0R3PddW>e>I}NI=lsVMe$9b?>U6}yC(W? z1-|VXluz*>@D2Mm2I_Z=&*&41e;o9;??U@0^l8Pv%kY@IXA=5?;%|Vy<q$OVCr9t@A~(F{`5xCmxxai zpGJE_-yt3bzUxJ#ulPR$?`%i=EB+Snu`bk)V&nHQ#m1lGijDs!6q8@cpOcEMf6OSh z{&88c^^ax6#=qfhF~7&(A3|>Pra=9Q`5y(|RSSEh;-3NDbIm5vw>*7X=?kFWUAIZ} zFHfISy2Vd@jP$n^P+vLNixtawbtfkOx=5GtDi8ar!*>Gb755|j&V8FgyW-CfAKDa3 zioXne4}_ly#fRF#KSxm>#nxY@6qEnS@6(FeU)Vop6kC6qQ*8ZV!D04?Ma9-1mK7I~ z{_UUI7*-t40f%j|ydMGm&R4;|ioXH8b9!TFRQ#3>BFxG>vjsD;K4)||| z3=hol|C%%CPftT$0cQJ3etVJM1h*=_3;u5?Z4BeUKK)6>mj0AtOMh0er9ZFu4(8`5 z*k?z~&j8}z(ha;b;$I~01->p~i@zzs&5HjP{%@Rs{Gj-uPSn>ckRKGk2)t(!@{_}N z0*^ZUcHl9GZwH=mnBgZCe}wUW3gffl-vZt>gYjAMH-K+|{JRLu`uf-rl;>&8Z@{eY ztzDQOTQ`N;>nm}c;)h5-y(u&U`}%HGZ1vHm*y_8a*y?*svDNpSV$07wF!Lk&=7+Gp zp!6RuB8AJ~H^u)S@RqM`49gDZfN4-*{z$(AxZYv<&jVj~7JVE4xSrCY_yyoCDBr01 zH+~*hY~`C!Y~`C)Y~`C(Y~@)3W_mw>e_O{fp4{kg7wY?_h%NqlVCLVRoYH>_;UE4K z^lim^&LO|ALcdPJmlQuh`ZU&56FiaN8O85||7&N!-@9Udh_?dg6@QHQbCB^9+?wD~ z#lH*xH_xKU6n_)=jxRypa`;-{MTZXqFDq_F-`jc_bIQ%JK8#=56!(LEdmGvdnDuM^ zCl&t!=(}FSdZWV)z;h1Y54`Ab3-FS|&jHuo660rl1>icx*Y-eOT!KvG=sQ7gQv4|B z_r8vNIs7nii^Io&yB&T%a7pn`BK)n((4QRr2GA!JFMxgnIotx=?C^8I?G6`!yA=;2zMGmLuRHoq&?glC1nBoZjPc9i zhk>UYJ_bDJ@cV)175@Xm-`Wg$-O+CVeOdAS=TSdLAy4LF`3%=3xKXjyPmAIb!teSJ z%H#0ez$J$d0Z%ymIPj#yPXW(5{4U@*#q)^&rg4nNj=mH0CB@62H+}@=argn?6^Bm& zhudQL=>J9FTE)-yqJA*{-INctLR==(jE+f49f{6W;*bsQ6RBH@^mcQ~U?SOUQ46+Y>yYcw0Zlo7cfl zith)$X$Rzghj#+cDn0}HJuv>wIeY`~yyBk#{f1o|!(xJ$5?p^rEYE+1|66mIZxsI> z@gc}#4&MOWq&Po-{s4WW+2NakTNIxI{pN?E4|2xMvhE|8S0k2>LxA zg8b?5Vc>Daze+mf+i8an1J5d!@^oQ*cen<4Uh(D&$S=n51&6N(UUr!Dl?2yfF6R7l zC&QypZ_gunJn&`%uR3S9g4n4en)QFoBv>K)z&oKt)f^le{3 ze@Jk1f=h~j5dN=U0KX{yDd20r4f}_~TY)DO|2pV5ub@9TybYN9Uf3Rg&h)>tFr{fL6TGPSU%~(NcS7G){O^Ek zps(ik#QYe}C%8@VpThr^&Dg)9*yP=D#ed8E^gvWn+}V-sW_829bM#2 z#hJY6u*jPZi@fQu$eW5YdDGEF-c)SzWo=_DpW(U$H!8OJX;GZXn+}V->9EL~4vW0$ zu*jPZi@d2glQ$h*vWn+}V-c_5ZAlQ$J-@}|QgZz|5@O@~F^RGi712_8@I zv|_8jdBvH$>9EL~iZglhV9b9eZz|5@O~skKnc(&WPbkjhO~skK>9EL~iZglBVUaf# zXYyu(ml9lmZ!AwHZz|5@O@~F^RGi714vW00IFmOM+@0V_#hJXRIFmOOXY!`QB5x|r z@me1tfMu#cyHY+xHv&CV`o2`mX-fVZ6^5&?+ zlsCr`JfYa+&6xzxDYo?I9cKEM6l9o1jS1#{BQKA)E4J~V zJE2c1eq;pg`6Bc|haUl+b9fii*$DZ$GLu5F6tGkqbK;CzCc6kGeWD>i*$#$oCUbBax0xa=_Xg$2c?FDxf`CBgXz zVt!3uXjE+aLX*SP7upn?zR>M3^@WmR(-+1QJdt4Tt0BLdzHnKw=?jaBt$vywjQ)+@ ztl0F0wgk5)cv7+H3p0vMKUhfcVuI@)iuTrjeF^rY*Px#%{&V21(05uDn|-`pvE{#8 zvDwGR6q|i~Lb2I%mlRukD~c_?0GkBu;TB)LVvCP^NJ+Q&N{Y??KAzx7#j?II3jGV1 z?PKHpw8I?l=N;yFe_64O_X`elykAmm<9&D}#&5Vb!Fk0tJ~cYb@u}5ej!$ihZG38X znB!APv5i0D37$ystYRCV<{akuwB#_yr)9-9KCL*+@u~LFSY8{S>Kx|ylv8ZuQ&WPQ z6U;MWY~Q+3@E_)jZil%(S8{k8@R-B(z~c_@0G@D|;U^V0ApRXC?8kAq4tUz(df-`y zZv~!n_$J_ahZ+8|;!}+OW!Rq_t^;0lxE^@f;ah=M9KH!Syd%~J<74aHHZMrT+=6S2$b;+??Q6#WVCjiS;Lk>ww!6TvGf+`k#Wl;cy-BSb`@MFVX)r z+QZ>G;Hd=9DBk!I{Li309IgYNOYmjIyXb!w_3v;U@M40O6+cA(b6Edrj`dAk2VAE( z=#y70;|c5ojlkUR+zbEVMcDro{~hD)hJ2>@S3!RZ+OOMT?%ygYmi?S)zj?)Sz7FlP zkl;nda=vadgz#9*ubr=JQVfbb&5Gr`!zB5m%9@-Uoo~}-@(c2UHjAA=a7mmj8KbA-M70kDazX{Cq zblt$@udjfAw#=bFDc#Q3O)IwZb+ZY5&e3_kZdviq!Vbvub+u1ud+Y_y0Y4eBov+IQ z`}FgQt$y0nzns5$8t1JNJf8TUP`b2VE6!gfct)|Er<+r3=j|4OnIC(WoPVCLDgH7r&)3x}w)1s)#df}~3E0QqtaLkH*QWS5?20^JH=6h#Q~cyOwhF$6 z@h!nqia&;aaq!z%&sA*YnRRsThhJ1I`j(qB+)^|7qj>SIN*)kki?6WbwUn9o)==_O@e-G(>&*z}8JA4iB zlHxag6zMl(|B&K6!27X3lLwI4UiRb_cY(g;RjlVe7wJC>eBBJza~1yv@n^7prTA;W zIqbh{RxJJJ^H|SSEbaMKB&YaK(EoQWLcUTg=W#J!j4HnIhoR3eL!NbbEAWKkR?v50 ze3)|hM&N11A0!>)#jL|O0?#S_9O$=y2jh#wTYRs0|5zaIU`;TwS`6fcp!3;Qn=Tl>u@ zzF`9NVc2^d-U>Xg_<7Lp8pZhG@J+xAihq#wm%%@Z{{!$%r_p~L=6S+!D%RIugMMcl z`jf*q0oN(6{}Irk&($lo{N@!4zf7Wjf$u*S!h7I9bc0_M{}OOb3HpNK*MPSSLtjw* zUEu3SF@Bwn;fZ$w*D1d5;dl~$% zSn~T7@Owh9dsob#(MJ{k0rR_n{^syj;2Fi%UQ3D}Mpk|#jnHv9Rd8Vc>5=@zP%az?&#NoKB@Q~&}$AMe+iydZ1K+}^p%9pgPi0y zi!ZPE6NsPtV;d9PoZz_xFC=&=!QJnP=~?`x1dk;+ytmSSZG!6)JgN9~=KnOt#{|zL zxbcM;zxi)Ua7%*c6MQ+riwSOju`>SA1dk`U_I=U6j0dnk%{*Lr{`I$k?ffp!5z6^j zjBC6j2eX+xbeD6o;~0P7LVP>uH6Pg^cjtJ265mwf5A!zf)cIqL?|;YpZ!>%y<~z6% zAA+4?OFj1YIL!T27_x-^673k6zbAn?znZ-dU8G{Zol$J|zInxF?^{r8_CAP^68}e_ zU+;iC01>PLw<;F90OW&ihqnNuN-FY$A-5tws0zWBpIOD0ABa?vp6K^qg?_GB^!H_q zA*fu|k3Efw|EL-A$qL551h*&tyA{_xhWYV381EAQuf1#UwU_S8=6<_FPA6QH< zRPKuSp+XBb`v6p4!Db(5R&43DC^r94NyWd}3#d}E{>)wg6;iO-3nmp?drvw4a{rEE zvj<#OZ1#f1gx**a<2U-4VzU?Ud?fQ@_JZ7-A~t(LlVYaMr`(hd0_Ip$cy_R|7=nJS|N3c%|6hW;O4}Ci(<16v?sWv*z5u0ip^dy zsW@v7N2h(j?yoWXz`VtGceD>&R&4fxMa5G1xY1;uv%&az@lf5rLd z{X6wf0RCqTl(R9Vtn+^`*?DS?LHpfPs8*+eE|Ag9{2A!%=>tF9+UJhl8*a$nt^?L zwkl?S-iH1>p;+v5AHsaB_)U+)J^%%2r#&7cM zxMFKBo+l*T9-b#8w)UD!=<|xLy%rT)do3x>+G|IQPwc4>E+-ZLI?8+V7r-wL*8tBc ze$&wqa`UinDYpErC>HzZmtbGm8RHjwD}>dYVzIY=1@;<;cLBF3-h=qJLYN&>EcVq! z@V8=1Z&I<<$818MQ*8CIpxEkTQL)v>QWAbSp|2=5ex124me25Pf_eUs?Pc`Q1UJ@K z(wh>zoZuD3#=rG9#PG!A-@IbEpJ@s9ZHKo3w2|H%z_E`$raqZh8uuq5>}~Ha#V5tPEcZ%>0l}JteQ$^oF*?f4kC6 zPbnpMEb&i0j`2(Wq2$acHa%rQv8A_|_+L_NdP<$@J*KDBD>gmF^g1+yJk8EO^^|tS zrl*t?XL?9NN0uf3M$c`I*z}Z=V$)OR6q}whuh`ZJmKB@cQeP9}Gra{Dif!HVvf@myQJm>DiY6W+UMBT*8TYm--S9%<-}El2FX%O< zXBiGoPoZ8zJ&WyOdQGEZOTWqar(V;h*z_3F!%UAcJ1E^q4lK8*W!@dd#R|(__Yy_)L#7J!V?z zrni`0MNGYAR_Ug<%sG55?iCG*9$|Wulm~i@=}Cr7FS7EPUL@t&Q6u-rWaB$dcZ_*&>O)T2DVE+?3JllA9q=+D%Xh()i# zFp@imm>e6^ovLbx-P13{SiZxLfhQXVF#0 zP=AU=Pk^vCrTAsg4}1jWSNtcy+a^$c#kD7J1mG2v-(lX9@-o~Z(#Z31yuXTn*Ferg zwafh=#5KUYyWji!_rTXom;Djf0P{|N@9%%m{qtpivL5n)=2_xEHG{uUB{ixKnt z2)mJ=JpP@=zt1vrcuM&9BL4jvbQL}`_(%E%=q7xY@b44&_h0WILU_oY^xu7_z;Idd zskN~E_{pPEIe>Uc*Pc;bL-tMJm*$o3(vXKho4kz;Tx}k&gA@aE+e+`v;zC^ zoU45Pb6c@q=E8F>A-3=w`|1Dh55)T5UAp8+R8x2q{@!wOMfZBb*Nv`t-hNQ+>W(Mrf20DQ*8Z( zd&WJTd%}sWy}0Mw)48Xccyu)8zYc4a-hZQFi@#N|rC(BP;U^Tort!@ve(Pf~{>zI0 zuvzO%@!^*uo`O61%f_2}g!BB_rr5?C?%8F1S^X|5-Nqa4VfEt;_plP%c*8xc#8$oq zU_aipAFIU6ifz0ZeWG%_seLkH8*dtcnSUE^x)oc04K1<0t-b3N8-KO~e+v0~d_2|< z_u%>Ra*vxYANRQV@^OzFvDFXvwE6N*0{ik#VGi_oMzNK58grW;U%5w(*viX2U*sRl zKlgYMTltz!#_`eUt%{943hc)_?xFJIA@@Z2@ohn|h36h8KYnpflOMmh2dNAB`R_jx z>yvwqi1&Xy;#v$+#G5}6akJv{in%Aq`{y1YA7A^sA~ye%iY>m&iW^_i^xhr)e^_yS zf?E}vf9}CydS6%nAB6qz?J=r~@wXOkkHVjgzcwD{(ck&h;~(h_hVlMh{4+kO#klzb z@EdjtsgG}`+k|jI7w{%athefAnj4)d~?1DX^Y-(Sr< z?)kn2^Mvmg-M~KmDaAIfaNh9!ggT#>1KNOnc$?QPJasDHkD3%)KcnsTYWQvpZQhP{ zw(((3@q6Ei7k&5jHVwbT#z!z`Rq#=x@}2P!ZF!!LN{Wq-Xv_0_L|Y!Q@p%jQ&hu5f zV&kKwgw8vSJzvpQ=lSX~u&>v8Ou3Qfz$Dt$b+n#Z1DNv;}#-qV0#+!p|xn zTKE;kmOgDOp08+2@qBd|*yq14;j3w2&sUUZJYOxSe@nk!`OMOv0rq@FTYw**$!DD? zkMY?uF!{&$MVMxtKbu4vUF~60K*J{wR4j;>w`Q(LMxJeGW6S{Z{g3Dp|DHhE=$q4>Yp;bf4;Vj2Vx=XCwZj49SPO9G}l?{LK?rjyWSR2*+H#SE?o2w_>VwCvC-Qbe{ z+Eww;<0cx9lZRs#>&KoceSKZ(CGKl98h`&-vL5#zdiQOb&+(_C>zwlALCFv7XbGR! zN!GC*S57*MZc|8@P$`>etgG@wE5&NUrXZcBf^b0iczfV_xPSgws%Co_^Nx7`JM~|m z;I7^+#V#Zee;*V-R)A6BB>y5IDf9{a-Apc2zIyL|4_;yP3!~HJ)`MTz(F5#2d zb-^cz`~Rx-mP^KsBN{*Vd-&&e%}?zP?~3pDXu8~w;GgdY;CM2kd~&xEA5uQ#`nrF1 zYP$KveHit_c&wj4yMIvl9O)+f@M+CIWhwvMF73S|EG7K; zl;)qZkAMD9+INTC`|sU%b4+}}UZ_{+SFUmg+7%$jff2{3p z^T>ZhJ#yUUxfwoOH{|nvtq1N$^3MyJAKI_|!}e$VZ^ih{=brc@e>a8e9Ez`-b(}Z; zX;ePlDD{kUX*$nZz$c|WASWd4e!bKi=HiK|R z%u|W`pJ@D)#r^XkX8QbP5A2HA}I4eq3v!h{finu@8kE+`!$}% zq<$V3ena~v{%QMV{Qscw+i;dw|MLldc56NGo_7E2)q0ps;&0b_9+hzA5YM8VOm|+> zy-!IW)pGG3cK>`s`XTPuOx&;2d|poS^Ii3y$`8}XC)53Rn(pnI$nOiE;e2Wm&k@Z( z_i_2>ZCc*OBtIWVyE6Xm+FyJy+|KEv$lf=F8?$%+vI$=lO`q4aALWv$-l}}X`(*sn zBjXL$Lz5(GwOsQ_Jb$D8u|0ABMU98|$@^!wrdxlrcf~ibHU755{SUN%@t%4AJfiNr zPt-qeQGVmS@c#KM0PA^39jzN5*LLSU@BWG34!sC{#Xdsq@8gFm-S5`? zPbU7K(*ClPxPMOj<0mv4>#jeh?RYuyU#s!+{&xRd(EK!)Rcs-@S^1Xtt^4Nz%@6NI z^Uq%>zw!Qb|2(Mt)|~UMm}60I*~I-O_-FqAr}~rX!uv-xo~gwDceMWJ6Za^u;GBBGpRd3_ z5mrw`?dZT68}G{<(f;}JFUO$ zj`_5|w`#q$+-WZH_ci=5-LGmsZ8%<0J{eE^zbqMpym41$Jlixs^NIhT)_%u(z5Vl~ z#>4xq{d2qWKkvcz&u{Ad(v-M=TI-YdUi;@b%ENMfOUrdoi9ewJrxO1khCBUVQ2#O< zA7{BwiWC-05+&vV)?yzkjRzpwp;_d5IM zV;cWx;{InE&y+EU2KuOuSCfhVFKYcv-|J(?`6G>IDe?b#%}-N9rT_n~^~U?^{4=Ea zoJ{=xs`js?#Jy4L`Eug^E{%uxHT&o5nr`zw-WB^?|e^m&nNC5(0F)nvVT6P=}so@f1~`cl(@g7{%4YWp40fd5BS(a_$#fq z*~I;aHUCqI`=s(M?X0`!)}+x-xcKN`sYKMPu{EQpZ|hdEcmi7OY<+&wYF zd_nWMkhp(a`FuPXf4EPR^~`%W{WGZZb?u|x6>H*}&s^gERpmGCt?^G>FWDICn!PK& zC9mzmy*B>o(DK&4!@J`CQ02pXbEW&O+V6PJm4E(1-Mb(6u6Wn>;=OYI*{|gtJ?dS- zBU+#NCoA25#rj>6Zkvu*Gw-bQ|F?kTx4Sk*cM~_irS;JGRHgsD)_)WC&nn+Osqr*u zuwSxq{<+F{-lO%&dzt+6J2ua@dROe3(0W@rQR)7UP2>{Dfg1mk_M6{QzT!PY{yD4p z=Y2c=d8g)QG|A@)%@6O-@y`$Gc#=!pe?$HA{vrSTg0{;{;=W>ho4D`V&d|8mB60t} zl}~uTkAE&`{<+7+KYy?F#=R^4`6KOL+>_#;cWJv%CH{X++mU-*{By1H;b`LisOG;d zaeuG23-5pN&vj@w^5KJMPd@qh6S_42y#K{ND@d3A?FmG~)b7vBHkpFh`p@}3v} zd{XOy_qq6ItLBsUw)p2OXfLMwQj+fDnor)_;-9mcpY|8ME7oT?XqW9+pS9<*@DuhFpdW4vw{eS_JdOJMHF3Ws3!&WwWnw(SyyCN4{r?W4-tN{t z&3#ndrO@Itr~dyV>SdeDzvb+Y@WT9zsy}PrpO$!p=_=wmBks~!#ohdWRNS?YpqTqp zNOwE_vuEjs_|~oYu@tPlzpC|fSp!%+OOj8_zv^!OU&PCHw_cM|!_!wae#@!(zfJOK z+DQmGjgNLx){n3S+|2($ywlxkREN>ykFdRt#bbv&3~;@EdQSXA2R>OLFRr){NEN<)W7Bb?ZEUe!wTNb|3etZ z=q}w7?$&Ox_m;%{-%EYoD(7EGvUsiq zi_?Ew;{UI;yzPnm94eCjyAyY-7uNe}{3$8J5kHSV&04`mpLX~eI4&f(RvVK3+Zo>B z4q%?+<3l=a6=M$5*2Hsqd`N#9f4a3J5OYsa)F&eS1n{VKP@_*dEb%$a_-wt|{M&vL zV#a5T!dHgRYXuQAyzMt37XLDS$NX?lC%=cxhjfPL_mBAyGd$1D@FC{jOk39>7XR0h zTK3O#E{5rUF~Q9`v@ksDb27oUu4D1n=>$p4{P26ae25wUWP%qQ?xrX0FnsO7p9zN< zp5K$@L;CmP55E`7hnVH#_hI=EGkt#lm5p5^tv2l zFQ;erTceNPR!MKZy^NXPc83{1zt_me!t?u#hDmR^ql_88+hNjI945W~&a!{f>+ULJ zsjmbtIZXd%uf(g=Z`1B_c+$-dY4lP;&v5|8WAtW+8J_2@J$=Dp()qnPPv`gL43lo_ zKNf#}PbHn-cQgOw7kXbkI~y5X83uBnLmC{$^4Vva&H-v&hH(0`ijG(^ZP@d&hPygCY|5+G0gZU z)lPv|;fMOeWxAy2F#Rt&Ogg_W!-ub=n_YsK^qGWy*B2|NI__r}KLvhB>}WCz#&{@$}{d z^LrddXZp2j?_+wBe}^Ui4wG(n3i>C#S?vuLzO|XL$ND-C$J*m%Ec4GhD{-^KjBnIo zrnlfQ!`G?)j#o+F^nAmuj?VCt?=Gju_)P%etI*rZbYj!jNSE@dK4$(G5?p$3W%$|` zD)Cf;n_jG>n|@{KEhco6pGc?tQmgXDTY%|i@`T|CV@{r+|0##*Ux!bLkNInr*l{O{rg0^@mCyXYQJmBCkhIi~c1Ot%&z8(MI{V9V zf`upG#_-gYruc$~KlE>kjpc7l6(++=is_a0)ttyXJm<^D=)8}}P>}M+p&AjSsJcIlNJWGW z;X;4~4lod4p@-@}BEj$3{&_uLc5;V=rCq1$-%knn$POs$`#E-Z9G4b)1&F}ke%jWsXb1j?sJ>9Z- zKDFAi`F%ZT*_>Z5wrqYMx>oxU*gNlaz4#`9e^K$ZFmk|fKR|4ybO=vOK=Fk1Yd`5zzO^+e6O~7 zd|oi;Pc=Q|w6Yx!D~uSZ)B#gDiAN%36EpAx$*oB5Pm zfs~8co^kmcU)E}KO*D%-gd;eH6F7x4IEM?^yr;FjKl(lv-9PhQ!*<+(UD$(tIDkVq zf@3&=Q#gZjxPYxk#`81xU2ErS!{%NI?YIkjunz}t2uE-XCvXa9a1Ix+We&6~dc1qE z{$IGp9mHMOgMB!FLpXwCIDu0*gLAlm_4QR#ZB7ky-#W9XZPi^t#^EL0yZtq|9|G2wx2XPnnU>^?P z5RTv&PT&;I;2bVseZHy3yH~${p|)WMc42*=ulDy558x1v;22Ke6wcrrE?|AXk?wEL zJaLspUHxDEt{uc(Sl{oY{q^rn>HzISID%t1fm1kxbGU%5uNlv`2kZNpbpIX1UD$(t zIDkVqf@3&=Q#gZnS~kDm>mPniKE~!=24+!D!!z&#tnWkB{`x*vWApqWXtg&E;Ruf5 z+bx^tA9vxrW%H|T0bBL!jb?vLya(H`1Dktp0AALPdZ6of$`aWiD?;-BP0UW{+9K#8m!Wo>y1#H!?2kQP;|NppqJZ;1s*oF1= zYTcfXxW4|V@euI{j^PAO;SA2<0=DYc!*zeE|L1JwkGKQ7um}6F{yksE3lWdt7*606 z&fpv_V5@%pSNEp}+pq(>um@M~_uQS&0Pzrx;22Ke6wcrrE?{$C()RUB-%qXcVI%Iq z`hI_H?;-BP0UW{+9K#8m!Wo>y1+1^<>;CKeqSbc&`n}qLUD$(tIDkVqf@3&=Q#gZj zxPbNV5t?7`(ed-ah8@_2J=li>ID{iOh7&l2GdPC}*sA|N)#MM`umkJgyR^TDxDN+# z2uE-XCvXa9a1Ix+Rsa8z?tc%qVFz|$5BA{z4&exn;RH_M49?*Kw!U%veDA?F?7%MU z!9E-}qVdm-Wx9K#8m!Wo>y1#Fd1`gV_J54K?kc3}_p;Q$Wd2#(sB;R4qCDCqI%ebe~)ZNm=i!XE6y0UW{+9K#8m!Wo>y1#CSwo^KD<{}p3RID>PzfUWxfmo=XrY{L%h!XE6y0UW{+9K#8m z!Wo>y1#C^1r~mHx58JQy1#CTz{9zk*U>Eja9}eIUj^G$h;1tf_94=t%+mSzP!+QUj zebQ}8zVtpgYV-L}W>Nca0Ech{$8Z9ta0cga0bB1L-(P)yi|)UTxW3;-<1XSJ?85;Z z!Vw(937oID{iOh7&l2GdPC}*m@80hi%w_UD$(tSnofkkGBwUz2BI|W5g3U zg)=yZ3)nh@{9zl``;2mFcsq#eecLqdA@0Kg9Kw3PH{D*0cmk(z2Ip`ATYcmY+pq(> zum}5a0Ech{$8Z9ta0cga0b8@kAGTo!c3}_p;Q$Wd2#(sB;R3b}BY)V29a!IA zuIH4*n#yvgPNa*xDN+#2uE-XCvXa9a1Ix+ zHIMvZ8+Kq9_Fx|l;1JgP3Fv&rh$nCgXK)S|uyq9a!#1qFo3z$u);Ib6VczX;u*o-;lldjANGJBYim z2m5dUhj0YPZ~~`r2Ip`ATgS%p?ZGzez%J~;J{-Uy9KkW1z$u);Ib6WjcOie+h8@_2 zJ=li>ID{iOh7&l2GdPC}*!phd58JQ03*ZZFF`Oy1bYurKHg+17Z12}{uIEE8Ag)=yZ z3s~>xtNHc57x}{u?7|-G!vP$^5gfw_oWdEL!v(DO6>jqXKI9KOunT*z4+n4vM{o=$ za0+K|4i~VsFrIG@wqXZ$VGs7<01n{@j^PAO;SA2<0=B-tQ!dT%hi%w_UD$(tIDkVq zf@3&=Q#gZjxPYyvkw0w14(!4ntoPg2`3(>c;Ruf51Ww@$&fx;K-i!QU8+Kq9_Fx|l z;1G`B7*606&fpv_VCxy=58JQy1#GpX!14r^gbZpWKr9&1G}&X`)~kHV{ z?7%MU!9EEja9}eIUj^G$h;1tf_94=t%hmk*Q!w#&UZ=}C3c!>M3evXm04-t>x7*606&fpv_ zVCzSaKWxJe?7|-G!vP$^`ngIvKQZD7oWdEL!v$>pDDsE(^QClu9K>DNgMB!FLpXwC zIDu0*gLAlmt>=(GY{L%h!XE6y0UW{+9K#8m!Wo>y1#JBo@`r8MfnC^xeK>$aID%t1 zfm1kxcUmrg_51PNe2ovl)9?(u0H1_U!z1`Id={X@MZWad>y_C--hqP+wcyopATTJXXWwt#^+-io`DzOlkjPH1Yd@)!q?%O@NM`m zybbTbou3@f_W(Q%&%g`tN%%B8f-l2Y;p^~C_%?hO-iCKz{hYn#`2W=Sd`!bL@B(}i zJ`L;VN9cH$5x)vwhi}5S;k)oQyaRWBdOY6)@HDKSGpPH&fcQ!HG(3VY!&l+!@J;wO zd>7t^cVN9Cx8`%;)cAZ%!!z&#d=fqlkKoJjRror56TS`Kg}31yxbxxhd=J3W@C>{F zpM+1tBlt3W6}}GNgm1%l;ca*a?tBFK!_)8#ya1nsPs1blGJF-j4&Q`t!*}6rcn9tb zkUu;P&%g`tN%%B8f-l2Y;p^~C_%?hO-iCMJ&S~TiPs20t0(=ra4Ugc<@Krc&d9gG8 z`6I@6Tk%l54HqqcQsS2BB#XJ;8Be$TDe(+^qUEl{Pr>ca3o-Fah+l#A^Fqw{ru_}X zZ^3uqd+>eu0lfc=3?hq;_ZY07|Do~Yh@XJ<^FFlwD&m*mEATb=27C*?1K)%1!w=y7 zOUNHS2p@;_^Eou%Q;4s^`gt7M{tDvP;8$AyX4zH!ybaUe_+BeMCB6?ofcGy;BUwy; z)BZ8|AbcD?0iS|b;Y;up_!@izz6IZb@4@%s2k`!($-b38d=NekpMX!ntMDcG3VaQ| z0pEh}!1v($@B?`NS>z8Ngpb1~;8XA_d|R-GAuj-7k0lt^2RtFLwXBd%yel-8Z_ucmB%MuTK5e)W^HOGxe$N z?@s-4_xGlLf9emW{&?yOQ-3n`r&E76^~I^rPyNx8f+{*KR7#F+uC@cb7*6@dT47HY*nSFpL_oygW=lZnbqN7V{5CkytX+Q zt#52~wl)^mHdhz7hJ)4h_45};gT=Mw!Nt+CsX4p4{?S7NSHW$&JVZ7 z0>i=DaO6B8~$Llxp-kDb6&4T<bDQQ2 zmGj|(B)xcUD3i3jyt1{jz9wC&lWVxOv9h$;X`g8wIkQ#=!!6%m-stRomY62y z+j?sA{F$fDpWPVBgZliL&Y{h%4cWe|U${`NH`e9axu~a#WZPVWI~Uh3ZVs1^bxu6} z^szy?>O0kXcBc0H;8+#t4~|rY`N3>c>Nlm?d5!j~k~5gon!{ybW>BsB^Mig>at5>7 zq%QP#Yx-5yu|dCT(-e+sjciA|_oY-lEXR+CUV0BneEb1`i~ONu^<+5JWR$D^u|c(V z>h*lJo~u?fyR}s_*&#WJ*Jl=i+N?M|NaCX?sXlXuiio--&{{iF4IzFN=K z>^IfNs&*3B!faKNS*vPfvYJp+>NmmpCfJnvRY~Tui8ZBuQ#!1huL^QzYQ=0>kV$R2 zS0$Ojs-`LQ>l&HLqi-@jbyu0|nKx^Cw6ijj>;92?LXVgUmD8|X%e0i#^^w~1)mjc} z6*rHIrsQbps1|0MQoku3X@X6uUzMD}yvCZsY*ms;)=*QJtxC?|u!j0oNlw_ZMjrE3 z!iMe~9lkooO~BrH6OYBQbAw z@z|hT$(+;&qFNuVJzuS5zpHvV)vJP}Se4|^X{auk?6pz9Db1HvGQs8g*x+#OYTfVG z73M)-SILxUquH{tOkTMzFAVczzl}5x?5c%KZ`HCX$R)O_IbsSApP;&>?8%Id*O$`6 zJI&YU_gp!TM+W73u3F7jE4ld9XGOW5se|=evN~49&DpLcM+^O?bhN6HL!q(Rrqpjr z^V+H|$VQv0Iqlf5N^)+OHFDL^$ZTDbbGoUj+f)_iRMtpeO6}hbcaKKdLQe9krObWP zr7Xymrd-R$b|X@H_*6GdXJ_85>0EtO4p--Txsr=dwU!Cjf}@3gU6R?=s@b|Emu{_^ zD+@AhS}|Ld|+v~;v8$Q)_SY*muWh=%HdY_2Kwo6_u@cI;OrIV5F` zOsQ_5D#(o1fofeo_RS8;gq8tw9#&msC@Jkdv$J)s{j#adaMeYA;^{`}8reuw>PzWO zX1f`AMoWDuJ-k!1FXg<;K|R_pOLBfy1v6(_n$uWakXTicnbI~*VYVsttCGxK*+_mw zm1~(R?KCT;3D4dSNvQfgx?i=H`Kk(X71jP#!8~xaW>!iM&s-W*ztZxRheJBxOg$4v ztAb?Pl#XbuE|?2iStUPHn$}fG=0+P=1-Y=56|%c^M7CU&WQxj=OpP|F3gwwLGkK0? zbdIW_WRA*$JZh^7nX9rOGgPk4R8=l|rP1D(#rjwNZf0m#7icaT|JvQ}d z{ekhHc*l6q{H?XUJSs4CU)ipd@je9hD3|2Fy3{#ySV6UINVUX3tat(x!JUn_oX!uakU|BDmG_uk_8KR;o7e~-bv}#`iyIdUZO}<^t7Pw7*u3CX63F zBNHRbcKN*;-)u_z>-b-uFn;*!RmbVNzpk{u`b!hW58hXeuj82fzd^pVzt;N`j(_|X z$6uas{KGxQ@9i=Ey$SiJ_4u|XTCa8gwK|)Sf3(N=@7!bj4^7B_=Pi!^!3p`tdyN0s z9^?N~ef^cqj4i!SSNwqaq0w5vj`=Zb=7c|k{m)dLMy5t4SM9;Lg3m=4mGzGrUx=={==#VakN@|b$GvxYx-*?1 zi2K`0?wqgc*5lNvQ&p$x*1i3nQ%;+oOe6w#iQrE`eGE0Li z2PmC7PO1OR^(wkA83gzrv`ro>0axHJqx$`&z!_X?jecYj09(+|q?Y zD+5A;abR}cbI(0jYUzKDA@>>crIv@pUuqdLdcV=Tjczk~lhI8^uQpmXx=v_M%Oyf{ zIpbrI@v+tT7!w5j;G=Sj`5~@L;J*U(7m$36YelOg<+0>a%SD>sczEE_%`c<)gX(s1JxeFh zpm4ocu(lenAV~kPAI}545Bg45yhYoA?Mlhq2Qjb!@*gihcXX;pB_1t7WIirPT7I(IocwH^O66)=g3UmOh3~Ib_V21i%iH#4n+Kuv}V?D_KNc}&R z!O)tINO{gjabT12@q3|bQLhZ*dA*7QSKEE%GrF(!CEsOnG=G^kXgaAhf0>RK?N*=sW!gd0$%&F6Ke$EeJ*_n*eB?K1{AsP)!SWk4 zekh058zf%+`e}OJe**<;j`btIu0LMS>UPL)(D5&-kB*a3eRMpH>cdeJ?VfD1`rK4i zAB`W?N8?BJDM|W9>QmUG`slzP)rX^o@GCTbnfBYLK2z=f|43>1tyZ78s)$j0={T9+ zpy{X0)%Kg#YVE#3^O-hR^&+ZohveT#eebBMFC{rz`?-F4e`-(6lYWugaIn@Zaja11 zr#QGk+N-1W%?%UW@$Y1K`p+K&e zso=E|-n*eisMjl<$Y}WBhlOviM@Q?C65fbhpQy#ZjqhH*_X{uA>(RU6V!O5RM- zp4cxzJ2slPhuc@FAT1gDd>XgwXgTb;{iyTr$o#av@$ih4qvOVC_TwJggF1Y{{(D^N zTd!T*-r8gP55pqWIjE(6`-#(x?1YlUF$^m+&+Ba?XGoF&qnR8an?RQKScJH3an%DpycQC zLTSC)!`+F!&F)$y?VAqmt!pHHy>?9}ZVK-|AV~jke3=R8{W%rrgyHs9@piYv7m3}~ zo_LqoFTQTtbGvJ@RMh8jFDII}RsW{7>R{ydS4Zo6!g|E25w6eU@~>rgc|BeJdv0fq zH~!tu(s3id!R;*PTkWil){7eEyOw=5lJ7mWr$lXn$eu!HgY$Nn)~a%k>?y5RWH(Ng z_|xW^p0>VK{Pp!t)AN2UJF2=~-XC1=+Y_&@vYXnZypGo68!oq&om5?JDwr<$`TCUn z?%FOoLgKq!luoF9)NA&T>vKozs~YCBmOWI>XJq&2dZ2eu?VhMSwTl{Qk6Lz5ygX`f zWZ&rgQElIJw7#t2`qi>);^k4JLOZ4?*m10 z?}N2Br=!u&)M%1bez)kqV-H6|PvF-;h6>Z+3rw zQ0Lp{&!4vA_ElO>-(O+-r*Qdx*+Dnz{fg~ZFGaEpf_(nYEziC<>&5|3XYqptP(64m;Ekc(KudtVutMge@?m8=X?I`7HJy`C>n&tjk%Jp?qI`IlCU-tpR z@Z^ER_-M0v<_$;M{5nD|i;cgoQTW?CyzhOQvY}iK0>yr?-1l)bop@UOQM){)ek;Fi z?h0wYwiy=-t=}HM3(KwD9>13R=|oEM$zSH}F-HBi@6k55)5^PWl=A)@mRGwS{wVh= zt5q}7iG8hHYll-UJh{)X@+%e|wTJDCh4MJf_E{WGYlVW zI^`Dgjp=jcJP||edD^3r{=RTNx94<&8jthyqtDiVo>m-CIYiIZPLhP%J2ibOc$0wA z>}^s`F?@dTq_opoC`|@2yq?kXgD0x)N9*D;;-}X<;LeEB1bg~g7nx~j8=C)A>7C4p2KJo&!$N6vp)@gj-_&8`7GL>YkIl4 zu8gEhkJ(H4KxZaD)%^SOkjl{#9d@Lssl?mme#TQh2DRwF%pLc&We zJB+H{q?=oGAEWs#wvVCq1)lp#Ja30o@JeAUZdXyS;{CB!yNq~Fb%*vN*Vpv8GQ|<3 z$Gu0MbfkiJiJ$lB>dA@EmFbFus=w*PCP|kHE)`lFFng)xr&5ndPgM@Z0Ue*bp3!}k z59?h<{&=n`>8tBq&6n$6b-1@{I`|;jZTLBtulI|$XnW?m4wv+<*Xc1j@766Zwm*81 zXuKpB`++U#`dXd8ms>eTODw z_4!;E-hV)l{$W3x3785rL*L&?C)P;+bGx-Yaicy@%Sp3G&(jvE{S`icTBHgUKCfA% z3Y1R%Q6lCCKPvSM_j7U@KitpBY5b1XeqpeFebB+-c)!+uPUY=#dxZQeW^lXw^SP?$ zX^Y&>(t70=>Ap==A53^~>Eti1J~|(V&j)k9&trB_PUE}X+|f#nsNdgwTx7j!?e{cZ zud02ZMQRU4?WF72s9w5%lTQ9X>$TPD6+Tz^WRGF0^X+;K!xEb+o=l{EhUd zTKi32Kj*{C_xgA}!{=~0e-5Ym-#d7h@ZoarXw~*;gr8dbQKRw0{>_of`O4+|dECBg zADEru^IAu%_LutnMD1T|zsmX9-S+Rb{fFIsK9^2J{Ot0%+&R+hp zRo6SOuh%~vv`W3}wR>qozt|;wo?pU-mzx)!kPywzOIVaA=UP;&c_}vS_jp$FRzwy<;AlvZME`KS z=1Ai5bUUNM05~5vUCy~NHvZ$>9bLWljN1jfv@=bQyd2Lz1j?M*cw zVfVScd8?$W&+q#1{sV&aPknpy616w2oc6>&sJ)p`2E+3~c5W-QW0F<&W>WP%o%|0m zz(&}cX0M0#Wis@}+cfL{W&V<{YCrG^;w>KmHYTBEP z@`r3VM5lsROZh$y#n1KZlso#z?ak_W!S&bmIVHUn&*c(kcUt|^iRqG2Z)kVwfKz{* zi0WC>?rgB0F8^^>-`+%R`?I5UhVa)2KQ-;n2Kfo?Pm@b7;r8c5nZF~uQ(quxgrAyr zXQTXta+xLdue?{=yV2*Ue`$L&J^pR_ys7C-d9LdFqv@vol)v+oKesQ6wx8ABG+FeS z;hY(K-^lm5x|WT!3wO0I+a7eVdklNdT5G>8C9_dvzp#7`SkBk;=fmutL2`p<5vW`( zKI-k)Rqy|$L^{!P#d_(&eY1qhy?DFsleag^a6G~uvE_aE{y^IX9hW)pac5vDt_-g5 zxk(uwIDI95vzjyr4!e=gEK_7iMg#212d_r}-QJ0+lWjrx6mvO2%0UhiWz zc&@QfXz>nx?vcNCy7;H+G$NRP@+T>rc4SIG{<@6PlQld&CK+%Q7(%<7k`ce<=Y7KPqcLYJm;Xvk}Rm+NA~CG)F0-^cI1d&VPnAgbM^<} z&%p2Xym;~z5~DOh_f7M+JuZCbw`u=lK9pc-!cGZ)4C4Kl z`P5_B?|uwwl|}pqLFa(_`z#lCT`%S4uT}e~r&VeGT9rpntJ3_n+Mjw_mFBMn18_a9 zO7qvM-uARA&0h-v$bF^xYbiy>SDL?8yznc{U#sK!QrylUD8KoYa)a_Bzh{K;RPc<) z`sc6XU);C$$zP}Q=TdYxxqtmsy>EKhHShN#pRU=z61o=oXAlGDCdHrMtoD_+Q~ufm zBt6R$KCIoTCz8(eGQXKV)X(CL*~rCYl`}dz0@j< z2b+Zir77w!4(M~?lD%J-?|r32@aMCxzdchlym#PXX@kO)c@hulMNhh>94&t5i~PJ3 zS1MRcHt_sc#|O@r;%}KG`IK6kjRr<-+-$LNv(A2k%ggnrFkAEMYH5;uiUUK!SIN@n z2lTmfPmA`WknfhgB|iBQd0Dx|J4`NHY`os0<8}UaeQw>eUe8JNZZmmYGdawM^($_D zSju<(nP~klZ{tW$i`F+kSHyw-r{iDV)^R;8dJckoQ4>ezW8+kdokN+c`kJ4v9mvO- zGpyV$n~$pXGTxtS*+h+V-dTWoW{!+S;y%_e!RkihbwEk2aR6U#6D%phn%KK4q zP|L0EMj_CNA>(lf;-eNqHjCnp|6Y8D{ekY8&zHirI0O6mL zcvopPg2Dtn_fsuzw%tx9;CM+{9Y55I#3iBLjISD(X+JR^szM4YNoEv{ z6J;A0))`%8^dh63M$a?4(C7lAS)<1qonv&C(TvflMkg6eK65Ym&;`Lkz|&U0(QFIWtECaFE;=MLiOG(WYE;^CT~+EG1|m`j{L9Y}p2I-XAR zQ~NU>uKAfgI!VWwh(EPQ{rpZmo#w~h0J+=vy%zmW^RsbZ*^Ay^pM(f-#Q~kCN|SUP zC=S^CWzQ#y1GWyCbgadyH~+U*7+D)jTpCDSh1V@xq@6Mf(6dRX+!%7+F8nIyd9` z-yWPM5##-Z@#FJkJ-e3)nGdU;3QndMcF#5$SM%4Z{zmH*)7x;JqWT)GQ&gX$b&Be1 zv`#TS^?l!KRZ*gKiYiF7PEkFK)+ws5BiAY99_u|2=8(63AFWeVZ=-dJ>h&2XNwQ${ zb&9rUv`$eyAAOxNT?&ZSDH-$EUZ+&+leaJJbJj2&SpT!}tvIN9a**{mtj|a2O)dL~ z`BE*5+wPWj?y>Xz7#G#w@-4~7_qA|dO2W5yA`zUY%ipH)+Q+JVDjW2^%ZcMg20`hB z?qkIDbJyz&ZRhk@4BBu$U-fjVewA!o$`9y!3DLNz^)J~tSf8Jgh_6`AGP#o(we97m5QWC)1BKCd`S2Xx zA?mm1f_{#pZSKty-ZtYyLhF}1Excd*y@#~i_j5w&#IfSf+j+S#Jb8?U8z0g84%)bR zlSjng)e^sL##KV=^QZOYeIGkrE(eKRGLk->c-_+s&xg;yU#tGG9Uc;Y+l&W=`t!T` zM#bN2C{C&gwoRNmz zM?ia%p0{ECndVNA%5|8 ztEcJtL^Vf;mH&j5&vvU^jz4hD2lM$f{5~!_|HV6=Q27l=bouU}=R^JS^!WjeH&N9q zsN81p$6{X}<@){{>rV?h-2VU;JwJdg-==b`6~A76xnfC= zPXt$fKbj-RAMsj z-uT;vT(|;deJBsSS7qrR5~|~1^t`6azVFy&@3ZA{D!;ClFG~Dej=h`Dv(%36&1t`D zPfQ+zCV^e>M!E0$Rce`~<+beE{`Y!Twn_4U=R%}?H>jWTn+53gVE!UU(>K?v{E?Je zY+by8vCxlA-ua^`1>6V8faYyKK3rcb`$7I_TR$TnYn(sE@;MtG@!R;3vV4xRbvk+* z$CES8l4t>UyV+&@9M43=r^}yXd_riFe_1=$85AP#pKE-g-81wr)Ei5ICI3|baA$N1 z34C4e``7um8UH9o@;}@7KT+f7&o=&D4(-N2_>=rk(Rig6)0cTe+Kv-cZ_b!$_s@S= z!h7vpf$MR5;$b=I_ZZZJ<+Hu+0S(8Kf~NO&tJS|Kp(}84JY)JHQ18F_(fXz3@9Djt zRjxuNaNJ*@>$=AJ(>2zguF?J!>f>!1kNd#Y<4wF@<#XDekAY9t*VmgpE#DLQ%6zsdB^mih_0_@?kqv^UHQd7I?nFzZ{3=3*Ej-2+sXj`D67xy7bsf?Y%mksY`a=1J5Is@4DY3 z(*EG@tFA?H85H5~v9caz_@nnYbzdSkpyQ{fV?0eavVKqOqJF*~8_G?GU%UtKZzy%- zIh|;Is}o4$-=R{zDOc*9?|b-ns6u(-eLHDCG#+VnyLkDP*We~x{2b%QHAwz)eE0t3 zw*18(?5OQ9o^UQiS;fc zAMYpC{8r1~`$cuQw@W(sA=yH^Xhj(BaS72sY!^~aIYU{74$=suix)zT`1vo+c&{h(fZdsFFtDh)Nl&V^IyhZ3VpGC zjr!mFlBJnxQ~vYz{m&>KIwV{q57m>7)*~dm5qZ=+ zM?Q)?qVIlcJ4NN|c-hhV%7)9Yc}{%P@?RnO^Sur#keA-zfpb0h_lIlWM=`miTWO-=lFodhaZQ98xlR?W+I(T*h0< z?Ez&${&L)#3FQ4g73jI7X#7??CmNsC{)xtKt3_Ws{8 z-yg2+f%c)RKi}`I@2!nLQQvzsJ&o)xolhzM4Dv~dmCkwZ_OSg`<5&v%725w$(5U?f zC7#<6k)5dfCs8~5Jbu5#cRM4x|3b~=kfITCb8esW5+y8dnG;Ao&!j) z!Fqk{{<31{xXk;$u8E$rj+`fVz5ZV#4PU)3ia%d%WF40Z)=56(i6z?WO4a zLdwp0)r%irr!TLnKUaKw?*z>xZ3k~S?)&q)`uTQB8s2|^3C)eP|1XeuSog?y7JX0h zxo4Qf*I~u2x(;od+adA%9A{hW1>&#I#~&mg-mmq1KNb8&?ql6&t!hDXJ%uo0A3iCNz)35!YFrT%e zUkIo^urAEkg9e59TH(TcZJ)yY{Vcxj(-r3LYku7?EX>yj=Y{!GB|K-({VG}U%6z~( zg|QPQARf*f3S)I0Q<$&vTnn~Yv%-8`2jtGya^mSUzk}-J_eu#b%-8uR%5R#4_nxiw zXE-HNI4Psy?JCz4-Z!FSJF#ioT2B!_#_FB>(4X=J=T7Cd(PTp?MJ>SkCA*iA1a54PnA!^ zhqhb9r|Mh8hw4GZr|L=mY)#iQU)v|*Q}raT=3DR>_@k&OZ_4vr&=Wu-xoiFX`$Uzq za1)NtC8?QwzD<{sr#F$mXY6zd?-`phs`cs_tM%;}Yv)kM8lPj8?;flN=z7K~pFLxh z{~puBp0OskvDR*8pZ1u&+GFRkdvtpp`ABxqo&(XOSU$>?L<&)n_We-n--+4k4_TEOTWE|&{l4_e_`ZNlkDft?}@OrW*w9PPm z8YO*oJyS9o*UC@Zuh;S`%$zBF_v+7xK;EWrF?lN=I&RiWSD1N->qvNj6S$@8&H>c_Foh_NC zdvnMT4(9{RuX^IYr_-C$`2f%5<$iqK@u;oe-lb6_AKEk051XR%G5>@+wfI7m@Z4E% zjz0RGFO_e^m$pO1m(F7^1Yd05NM1VrMtteGAMvIAKH^K~TSfA&VLbK zI=@7G>3sS^@TKkcsOgW6j}c$0hY?@e(IURIW9^Es>;EG9rQ>+Sm)b26UplTte5sxD zLhvj#WDD z^)7r`^my8wS4l+L@oX>Or>!s%T-%9%ka*0Fd{k7uf{9js;pnRwE$CXz(vcq7bEGY_ zD*vfK<;U@vBT83`mK&WjGPw;hwWfdC##;^1za00OZ>@bi#*dHJyY(K&D$T#Xp6K|@ z``1{VnS$g0Nud6IG5O=j?d|C6*n0a-?a2vEtPk^{+}(bdI0GK~WAfm>m(QpEUXZ6_ zxxKh3U-q!#?Y56rfCp|@=loc%r_U`?y=Ojb=eE{AlHk0xu6O+$Ut!BQ(FdPz(_^4m zaP)J;t5x1O@K1hOUzSHP_6}%1=vU9eE9p0Zme%Wjs-K_p{7PGNzASCg@wc?)Vd0~+ z@wtxNqux5a{q3C3w)ciu-+RHo z%e!)@RHtS;QV-dV_#f)csOLd1*Zf@WERU8%8Vkvq=d=+n{lV;1*SmD`KuPEQsy#U< z=d>$DJz?;A^N1_L$uG?)uMXmzjGd)*Z!KskIrj9CVoG!oeHwTsPpam z_J8NKZM{xKf&1G#uWkA=&&Hz(syESjZL=Hgymoiu2wAsQZq)jw6W7W3==#lbKAcZd z!6`BhQ%~-Jzj&LCJEreGKGquV;{BBAhmhXqD^E9C|Mh3TA zc8{%>;`8F?IWOi=DLAg*KLZ1U{84TN`|fpqo6ZNR;7W-X$}g1rOkLL}PLXweT>cx8 z0_Rg-Qu25CM(615`I()c-_?6Mv~$^>oPQ}N)-RM()j9g=cJSX@VLIwzwI01#`d3~5 zQUmpNJICuy%fHcj`+Ebff2rUNNUiewTbBd(v0M(mUs7oKnax*dXt?Tj5BtwwY5e(1 zv_ES$TD=SQKH+09Z!xsgJ;yxydm1Y^3`>6__1~rP_ZIwjo#XxXR~XmQ;|`I9L3-Ri z`o0E~m>IGEQIDVRxrpd}jWftru)ULi+1~9!OV>OqcDbLcjDKfm4r25iqWdoK@Qj3W zl)?Q2*z0272RcCakNo^zJe}spQ5)lm*?ntK*$n(Whp@KHPe}AVp94g!B9Ag|h3|bB z-?;&`!=CqhAG!?|wjcHdbiHEjksklBFjjy4sOzKN8(2%#BU_q@pY}BSp+DCv-lB5n zI8BLgolkwuU6;XM?msv9-p8>LefQt{xG5tEdp9e;>BN!Zr{2-koA=Y>^mpRg#~mYj zTYB@uBB$Jd+P{7tllf$jPfEUWhxQ(1uDb4*b?#R4W7d5F{h(T|zVAW#Py@pGx;Y~X zk#0W7-Y119q$Pel{@bLGrHtTp1e#d{ajyD~x?-ai3*Gu~&@7H|qWPv0PMfK5fFRG7@k5PRlsl1YltUkJ*5!FZINA=P89jzxfT%VfnnKWDHeKC;B~tLmIAc&G$$e ztgq{-_oMd2^)lY(?0d`Ugm$drppM5Kt-60-U$3;DykG16lF~fwzhQs2@1OGhHY7oR zQbmi82RlU)`iK3FTQi>C$77$5>hV>)L+7jbIj&v44`TZ6<+P7~71_gn&A8g{fsC6e z8#d86ukT+(<9u2w;Nx$6e&-Cc=XQjS*CX@Oc8G^(q?{(CO$e+M-_zSo+EC?5)@ zQpY|>kN=aDSFc_C`R5+n1*j&=kL&{bJx_$QL)I&|650i+kiU-$(m&KQ_Iz*u+z5MM zi9~e$t8Wi1(Dy>d<;5O|?6KH?r7cIFh5U850d1v-_Mb@QGPhzusxlx z+-BXUPbbt4Y)_O&;Y0faGi!1dcB;=7hzHj-~@&7Rm_io362&*9V8 zn|uCVj;;se_DrpHwy&eBfzR)X_$*@Y=b ziofS7TEPr|Qr4GUQw|ruf9Ia(ZJBS^lvxs9?9B+Bm=l8U>8sz{ud+$QZ%`83x4K*A z)0g^tL7{wF^nHh(YmPNLz~s|%wAN$UETvWN4^b~gUM+Lves#OW&xx=f)Y2=aXM3{$ zxm?r1BbuMt`_<_}J9PY5`+WztzS`kxL5f%G1Gc2wJuHVaWBd4ro~!=8Y$JM>rhy2@ zd|0A?_hfq~JaDPtv%)v)f$EN^Z^(Dzeu>9=ouo!GQULazD4~Ze?Jm`+YHsi=iA<1 zZYubD$v2(YYUO+T4p{l#zTdR+bzM@w{C|*mykDzbQ^ECe-`7*=#3!^IYd7aBoxD@S zM{PHKFRg7x^d6VCoc@i*&uARmReO2)so+CWzVA~NTQ$G5?PC|18!a0ucy$L#=gZMqhdOt7fc0h4*M(!8))%{lAfBH-1PramL`J5-J%jbP^xU2i| z^yHHHFpSRYQJqh{c=gU*7N>AFgS|C1qjW!&M}2);onpjujeo3j#n0b2q)Rue+}p?L z{xI8~5k}hWI={y4ky`c#`!#cH4;D)~)$!x@ORe|HN80P}kbKA&Yud2=Yv&{D$e6^LHitZmNGTlj+#Pex9+>`Z68uGXJil z+yAxJ3GA7kKiiAzg>xYUGM={gpk|I8Bj*^4CdZQfo>{x>>QG1am3ArF?<_?1)$iK) zb4UOEH{KsY{{9_J=QGY9_o>-GYVpVPpJw{Y@dwW3^4Izva5W$Cdaz%x9_(Q*-_g#g zRksK0E9Xqd*Ewg3aFLU4yI_6TEPChP0rvK2Pu?zkgy&B5@!?DMd%(~8JHWS#dIbEQ zJ=-Dt-BUCM`v=>DGacm<*E83r5#IssWvrLLcYt-1lGG?RXE+?)FEf z8$voi_daU>v~kD#v-daeXZ4;VdB2OFj}pDi3HxFX`|~QcRQ30O>wO2fk?;QwKToRX zSn{{)cYLGgwTIaG(fM-zf#-HNf{&DFi}sVhrhHv~(Yg3ZGR~D6_}}0z5F}K zqsciHv?6vC-^)+Qudu%KPCO*aq8 zN+}hrk$RNY>-%2y&w=jgxl&tSnLW1_rEwk5bBNA^zRqTNM#5S9-8ffjd`I849DdGa zkI#*uZ73KYAJgNzl{edqlKAVNC!I^SV){H)=cB6ch!+Rc zp5nQS?_bI1(?^RQ`}Z26@6J}AC!sX}duC9GypJmO!dCM`E>FO&t=8x2b#uBoFA_`z zw`+emRnte`p{@7*(T61di+3J@voiX3Y#e!9S(U$BN3lzI`}=n-d>^*g&gVww5~z)l zK6XsLSNz>Lhrn?xow!u`eYpRb*hlm#72GWGs^uDuV;>FgKOji|kiVIL&R;6HRc`n> zg>+&?)w$9S3_Dl4`{xvnlXlGy>hD8LYfVXc`S3ic+{QTw&h{}mv|cCv`t{RshWBfo zQ*gcYdRDi?o}XLLAKuCjs$CJ)$Ip{`eb{>O`sj<3jnt>s`GwKzqXTi&KH4v%b0qrQ zJ32?A>#sC^e}{bLw_1JXVgjWg)Z%`%^nk)leg%^Q6a0`Oc4jm$##JLBo92I`>d{tt1cokMD!{d8$V!)(K$SQ zp58mC_Ep5kK@Ia!>$zV&KI)&pv+uyGI%0lOz8cZ5TF(VXYe#=h=<&GDr1SdME7$iW zMm_&qkn93~PUrg2K5nuUlpb&Ae^FmdpEAcWMf>=D?EJ4jAFqDj#(&?#=gqhsruNyM z+Iu?Bj?7Q>Egqf$pN+mpw8wUw=|Ot@k0_QG&VEDn*dQZYI{w`cV7?GKj*3T{flQ;T_W{u)UFE8CycPCw4ZiN{zu8rpT|e<=d6_WOow*V zdnI1I{+v$elQ73^m*CykLF?R zha=B>zDxM3Uq4-!@qR5k%Eu*__nzBLCma86H)*-~&2BfzZOBLMrjFJn4f9>gUK+{w zp4vyRSH460NbOW_hiR=U_sBlddQEF}JJ9VT)63SkG+eJ*c2RY`BKv1fmHl&sloQ!K z$2DATExV_>+?0Ghl=<-45|onKP>#`U?QmDbU&#`8#DYuPu|d`5N* zcUST3(CnCwRy{w}NWZ9Mzj!&$H~R+_W#suK{eD^_<eExiCyKV0j zF%J8V5%*7ux9j=KN}t{@+VA30AJ_xp<<~lwz<4ade@8Ffyb?a>|CPEg!22m&rDh$^ zW{&HT=ZiDPE)zNRUiL;t50*ly8KZYYmfrC9MSCwlQT$6GRF2ra8%|O`3gw9BzbAY~ zs{{wVmz|>bJ-^FO7XKMX+WpJt>wV8}eu+pUn&(N>ST%70C=gHId z&wvB)bJ?3nV*Km6&wn4a_wqOEeJ^i=j>}8y^8eQ1`CYEh^CJFFAD-XFGt|G^{ObXi z-ph1%Hvln%>LX zaGv-h{?FI@q5O5fpuYS&hUa(rJ2bzL|91}0Z{vmP-);UMm2{PykbwMv#lU|LV&Y^C zcYP~O&Psrf&pemH_=StKpQVCt$bIi`K3@LK{BA_mdGGkSkp&p1>Wxpm1NwWAexAP2 zV!sbLDB_TPVvbw!^Hm)8s^>}HKd1blNAtFQx==Mv7plhT)w?@RJOBDVU2k92INe({P8X`i>E2Ps>AtFQ zx==Mv7plhT)w?@RJO498t|P|jJ_!z@aa!Zo9jBN2IDMcbtUI10)b8W`f2|rvD9MrU zYoNoy(M-?aT5B|IzX!v4fL(v2J*xXIar>^;xXAGkS>SoFt}jx-wx{3?ws-O`_`yxu zZO=b{mO@+c=HdBEXmn0Eo%r_C42sUX|GWCP>T@4opR~E!pVeBEz|%3omRpW0yg-wMmGeg6IHa^LsQ(}`ajA8MF} z;mKbP<0pD=0R{@?HbPEE8J|Zs$fxE*Ik}C&d^yi?r=I%4DURn1*`og3A{BgB`0{mZ zIExCavpN^m zV-3@Zo5aueVChQBwn@IFW&K8PGP=p=)k0aPNr+#(UHNo9^Yf~4`|f7)9);bTOl;afzWy^GW?@N;)- z!9S~%3QiS?6Qng#0hp?A9TLbn7%n>7EdSLy9-VQD-M9BLmZCi}2=d?UVR@4OVvlEhA|ClHU9(Q)TDi&Yk2k(Q=zilH zV$UEbZ@<5?6j<`zr12{6Ra)Gp`JK_J{xj5^4t(Dxzn|5^<+R4iQ!_otr`fBto*B^m zzF-uN`vOwlnc@xiyGkvlU$bpoe6x*{6I7pi`!s!iK=t-93wvLaiukyQ4>RXyU`gqA6=Htum zwgbzjoLH{PYn7F+@+!?9F86BwQo-_J@p=EHpx@Q(KCxpHKAK60f#vRqPpr~Lm3 zIYsB&_4gxvo-MT8CHhQ#n`d$%_2-f=_5S&M^`{ZJud=UG^RLF8h9bc)lk#?mq^5vpAshayo(W6di--F?jBHm8k!*L}Y2od|>rzq`Ce=gs1P&e!pCOq}2M{CkON2aL>btdt)Q&qz6HXN>l} z#PGYz#&>Q&?b5CmeP4?0!2JAoGU9ULdZV74!tW}gEzqUHb8hMJ`aG&SUAWJlfPo6v z`1yF9huA)pgzxW1=c``q?=2ri_NAYY*0WzCeYNi{Ct$5XR=$6g8_@MYSIgmI-+MdM z`tGvW^IKUO*0ZoXYqd-D`FLOFr<-p@3a+PavG+V$*<2wX#R0W5yX?C?YeRidyR0~% z_Nen2-H+^rGV<$cF*{+9xr0xXva5bpS3krGVEE=W zzutLy?N6hhm)CLnZ|}Uk+KIm3|JOS&Z}zFGL(tKBkmx}p`ur4h+MSP&yV7TBus>&r z&Y%5loR{CzbMnPI)NX4ZmlkP7^K-M*Gyw^4hG`*3WRk#?4Js~|c@zd+X8 zFa9}tEjOL`OP!6X9KYZz)qxawE*e2}}@$L4M*)uP>bM&1m_t0)q z`_iIw6D&D?I^l0Kzc;F~kK6fc@ zEo=CG54Or^Ket_o^JD@SPIw=Pu4ge99@EI6$83wPYMRl1+X(xvP?T_fc^Vd*G|-6_w{ zeZZT>!^tBkHNs?QI5W-T-SMMjqxU2Jrb(N3cq zg^uh86C6dtvGt^Q-&|Qw!$Tb|_5k6~FUcyhG*Y z=aj;82^%Du=rvosR=;I`56?lx;dcWFjy>0oZq#vQTmVafNh&AAA2Ula98#%5YV&nR2 z!*QJ%7N(m1POZ}4siwbEO@FyTBk@gtr<(pwHT|^@Fc<8=V!;NSf^MH;o>RGuoHtZX zp*}3r`LyyuDGuL_tfP+udY|L$EwTB4;~F_)elq`Dr|~LzrN!Io&)3(-^1=6KCBgII z>!v#MO+$QH|6#x32)(b*{h$LT*I2C%}!sk|r)5TxW z;j_MdhKFkU-j3=A+jmZtJ@snj6u!5k>Lle-lPYB?2G4!7`o7Mf`uY5-k$H>!O8L#4 zjWHkp-~1(V7&(6>ZT^}l{XZ2PD&vXkcinzwdd7an8KYVsy`P2SzD_4$JfBBG{k>?T z@aNynb^Ud{yFu0=C$Dbdx&7CFZuiIuEDzw_}iJpUR zk@UP@>%4m^xK8e;6L(v=wDw^iC-1Uy)eeiwJK0Az$k?$u|%Oz#}HI2gGCnR6;=eofX+3p8{;=L8Q@B0Y&-2}-mYL_kQ zw{~fpySL1rZ8P=~TE9K64f(3w9`BR;&;u*a+hePhr|r=;_gV3`&3Hy={qjB(-ml#b z`nwyI#U}5>KWRDs`xf&pJb9Of+df&v!lU-k!7v}nDR+54o}SY+rY#v881DVCI-h#+n5L$C?z!&1zLkBMRk^O7 z?$w#aeJfXGy860vtMe$2s%`92Ia&2bj;t9dXcxzTI)_A!UneKJ@f}{!K_pMpp zomsMS&5Fg6>xIa)uyO^mLYBFu1%kyZFI?5#-FMQPPJY{k%U7=KS+hz?%5|;IBj&}q z)m;~LFPm$=<3XpJQ&Jp z=B%S6EaWa;wVXaHI$vP!EQB>*Tv)wuW#4LNC=57jbq=99R#0P{0vHxu=<6Du$^xQP z7BDQ;s$m7u7saPF&AueR ze06tUl(Mh8ux9ycir>W&sX^arNT&}v6DdpB@Tw?Lj9sgV#$M6AdhN=-o=o>8-78iX zqD*UOU{%yeAEcaav_}nPJa2gpHCffSa`notmCIQrRl+&zX0C%uU7TNDWZ>dLm#W|} zWk*F<6p#UxvUcBCzj8(Qh55zIq985EybMeT3SE6~T6n?C#U1lzEFQ(RpqOT_mk2E0&`vF>)d4k_uS9d1ABD4CU?o1yd zE?TqXh|I}Qh*h4-y1o^5^66)xo)dx*W#NX862rJ(yrPgntM*aC69TUbiiEZ;Vc{3& z3x)2*nOV8MzFaZWl>ZZXd3oJuYC97Rw2^;F|e# zF3OMYkGP1lxVWw$F5`L`Fxznm7f*?>-aBwjH~b_p>qxm%u&g67>9M$&wiEO; zT(niopl4cmKj`_mSid3Am4+VzU1RuR(Dk_Bn%U0pHrxViHlqCcR2Kdl?cOVZKV*0s z@POiK9Tc5%*-{_xLOlF$qO3m)zvJ1b8Pf_-MKtxL%vS3>h7Y z`(<3*4x)au;OW3@Yu4p3VDiWgJP+4l#Ngu1z-@q82*!0F3x>`^IOVqxxX18$z?T9e zY7_PFy}+(xJmpUP$>MVTSqSXy-U)m?;vfs@*RF>M4)rh#+>bb-SHSmJo@L+)F!|Yp z%bdv2+qk-4y$X@Qr(9pNaw*Rr0DHgxso^rhe+lgU{z=1=Ah$mn&Hz6PjQ>q6Yaf)( zvgx=LN1ikEs1x1}2X-D99M`ky8c*6Lu4e}$yo{?6J+n{f?Q;a;gFSc2xsIyFR`Oyl zNq!w4?WiigXUaCCPO*Q?vA9Dh@JQe+F7^-NGA{Cc6s{p$-Y1yP>qH{KKF1(D&g-%8 zo0AxjugFYCM7fjXdn>1E`sUXIp9M@=lBaOI2EGUv+mO2H<9i19JX~z^eq64n88E?< zw`@a>XXcWw&+)eMF@be^Ev_ss*8g>&Wn8TPaSX#%Z%kOG{O|Jy#EFUvl3Do8Ner() z%6FGM(NR_VOtA2H``COZ{MBopHzM5-u6X;bHvUdRc$~la@S7XPA9dDTasj|b+y(DV zoUb+myMEmaOxb5}nM=MI;1+~qOl_j>c{}j_ClT&#IAl13@UI%C{ykzi3;cb<3xR)W zxD)sfhF1YUYq$(N4xNDcZ^E^&;eOx)4c`rXkl`WVnZVSMhjATY_)%c?|F?kd!1Y>$ z%hNmv?s#CnNs|FS)#7J?&jzMUI)N{+@G>y-forDKy8_|x%A3LKf$1&-MYQ0(pwx{U zHN5$B;9G$`{--oN_$(;nZwF=k?`U}QLf{?1XgA6KR~GLN7VlY5{13)KnVLZ-fldNF z5Htfi9W)Di7-$*vXiygPMp6`XIw>gt$1b!zd3-}~3#4B?T$6>~&<6KLb@~R*X zDaWv{1EX1j3@&r@2H!+D@)sTW5is2!Kv@SG?ve(SYB`UU06hI_#b=#e>f&? z1EsD!2uj=gN1z;&{s)xf!(>FF4SobD?eB9y*&cnMw2|KjN`CJIO*MKen zx830;&FJ8LNW(m@1x482v@b4(azc+b?f|A+ zq(uI%z~3SBuOdaFHHd!+VAe`p3p|9(*CBiI>QeG zf5`9-;5&dzi1Q@yKLbM?#EBupzXkr1;opr3l3zFcdxSq?81rM|2ZsL${0qZ>0{*?> zoyec=QvQLk#-ej>1{}g*u$SQ-!2FijwTy#)zrW!u@PWWmN8ste*C9$j@GRgPnGY}> zvQDud({(8cjzXM^49^2zX7~i)<%UVXqO2!QMfhS1Kh1E~{N12s!yw6=VKhk!Lqu>U z;xDnVc3`$q%q6=KF^6!ta6P&belL4%EX{j?^N5(mb*4bv<2bFQr1x9yT@*l zZ{n=^L6WTZEeMAy$=J{M7f1Jrk}ePADfRgT;;ghd_W&b2?vgi|&*N`LoL&q23h)}k zj{?Ir_u34Z!aPor8<+J-D*CK7w$> z4LWgc14g?9Wn6b#ct0@RWw?e2;I72A1J|c44m%3nRk$*SuLjNne-3fT!$ROk40i(m z!tg3!+G1BAP8s+q3*Q917lgsI{lG1T?*_gLVQ{i%M?hVoZp}oTG6T$QFghFIaLueI z9pcNL)LhGxVaFNv{^5BpK=|d1U~Z$)_}&h5T=nF4YKe`6;&EjgbAN@Vz4&kDEKdv3P zs{7Fg5SD?S(`~|)1%4s=5%YH)tL{60$D8I5XOH{K`#cj+&!=7=VN~bmh3*%hL?3}` z_P)oW+4sL-;nxFy9T=jQx_=+|287Z5*y4Opy>!9pPXc#8Q@m|bDYcqXMv@Tz-IzKh43LSL%>TcJ{QP+ zhBLtHfyqM__`Qb9z&8W`nQ4J<0e*&YFwouuENut;d0@)3ANU)<&oVynW5DEX2k_&- z4+3K$p7^8T1n`&xH5`hVm~40qaI0Y$V@*dG=0mRIfjOs70-kR;1N=6_bAT5COI?6h z0dGV6GH@CA+rUG>n}Nwcjg^}WXMk@3rVO*dpETSF{3YP$5MBoUIxy?f5Bwj7w*mhe zn7rK$oPd#10UiS02bg8;0B#}XI0wV%5a2PuS>U69pF(gM_ypiyrUhOAOkJW;aHio5 z@cF>PCvZ0~`RN4iHGC29rG{7S7bLDX+zWiC;lBNXv7ZC}1=6lV{BHoKz)u# z0T%-Ed0`fKCGbAXANbwC|3!X)uK=FNIOrdnfNw=O@jn8i2{v90Kiw83^7kL{H*5ZW z&`w+*MSQRulyQ9ucq`~8ToqubNN^Lz!7m%W8BO|K!yg9zsbS=s_-|mgZ$B=&TW}5G zYJ&1p_c)im4EPS4vk&;3(jKVmLE{`y~I2fzBiRQ-E1ux=-UGJ`>^O ze+YPqVXoonK7(rqa0%hpF#u!fm6lHinC@S2IYyDPrn?bwJ|uVb&&`H!K{%W|KP5nX zStou1;gE;8e>R+f??H>NMBCTi=SHu`*(-)$5yO^6ay1w{4B>FipSM8d z)06>z9l|+Z(47E`s6htTDZpO_&Ei@B4A(q_KW70`H(W*!@QyizOI_Z9IA5@^MX~rR zfwx=uI$*fwFXGSDu{aF;SN<^vek4zxY4G~;)|Wg2DB=h|*CL;HTlhZ!KLkvD!+1(3 z=T;P|PIB&IJ&-;aM0~jBui($Uz|3UzSUr>+Sb_$9UUS9A<=i32#3^{2L@^$Od)*@((h& zSeM11SzO%rBrfAJm%M}#;XtHM{Ra7bOM`;n$FKz@S6O@}c?5r+MI6YXDGMP@I7sIp z#@!c~{V0oTis2z(%Ie#oS_gI`q;U5A<^T@o(+y7y49zytb;Eeg% z)~H7CErh$y@YeV2J_++-obMtI>qYlN;QtSlW3M?#R_`+|Jx?GGaMLW{{|1&i0{;*2 zQqVH4LY+KIrS>WRk&iQU3@B+i< z0iSKS6Zm{!WF7SK{Rm$Q4A=Y^C*h^ua2|OQli6&P zF)(SNpfWFAhO~<<>;u3%4SyII^^h@-&$99sek;P^nv?kRF~#Atox97&68M)E=ckOIE_qSX zVUTRHv9^jfeR+?jVgLlkS+3o|}1+2evj{a_V4#Eq-SAcfnGKc0+8;+S! zw~skgwz@X5Pre?Q<1Ad$35F4`=~Tm%$yLoH&E)EDLA3@38n;U_KvVo*ZjB z5xzg_u@IP!=SMq1mmnN&*z*OJMR$PJdj;Z5G0bojEp5cHg?*Wha}RNb9=Orse0-Mn zLlCifYSsNyxOpJTB|o1B_WFJWnDJTPZyDzNN7sV*SwZqgWX`yhxp+XqTPg!e_j0Qj z>-Y-83@85?P}b4sB-W9*jEioxI5*9ftublej{uW@y4wu19X|%_a{GkgEW+;t<{aD! zK0a%BG4KP1FG3gjSHl<&5??mF4EXDYdw{=bcscO54POlWABI-|f8X#*;2!~#&s8kj zbfygagoSSce&BGCXVc!m_3HIy#PNE41Nb0om+u0@$v(rk+ccl%UF1VM-`m~!VY~m} zh$!vPflYsc-x+3}&j3^BDd+L8Ry!;MOo#p__Td2tpJDBu0Y2F9Y~Y!Oj{-i#@I2r{ z4WA6mGxsqkD#m(K-(t5Uob_Nh^v0cpPlS)*yiP-&)GOlifL&+046`oFfm4{n7>8>^ zvkOxtgcIXlVxwWyGx2`Iz@`zPQgKoS1Dy-S9Sg0O7MCw2Z`(w9-ajMEGGQ z%r65|zI5LNKHS172X8Ola~b+L$*{N#<8i)&d|b{yG(3qB)FrV+D-K1;{Bh%aoDqZP zL!cmgA7MNoQgSZvRi|qCWeYztx-aiyP?&V!G1ZBCA3*%0VsVZ!{0|6+teY6;HsGTz z{G-52nE?cNm*Fh%J%-D`pEW!LJY<;9UjEhN1Ap1$1ApD)1OL0npMX7Vj}QEq#|Qqg z#|Jhiy1Wz~>Se|P|JwYMjn_bKS>yAyz~vhJvn?R1u)a+93#%hBoyT!GFzh!q;$(OO z?se8)zeAkY8)i8BL;ICVF8JN$88Qu@fH7@ZG@OLcE4&WadrUd^J_>Cwh1N=wB{lGjx$+Q^=c5lO3 z;3ix?sL4RzAv}?3xPj* zhS&hIZxTPV=+6<#$o~Pvxg2x|*H;bi0H)2xa5CWgT3O(}g)&~t*|RHwU(Psin}I31 z46d6EXMwi?L(D-Zu1^4Stz5?C?`jPJe+J>0V_8<>LBm*UB_1`L1b*Bwo`WWyGK_Ur zQ{qglWx*GDdl@kKDFd5Jwnun^lz|(JN?u)N$F-|W&%uo=&XM{xab5a8;I~_PwnqhF z8C=}Eplq_ZZbF>%ajz5j!@zyOW#HR^mx2aR%)5Z^0L%h^3iwvwGVm9GTd(D zMp`O3&%CSw&H_J%@JpB{@Yxyt-LWCy9SBFT*igR)z79$0ehWOt!f6-0TZ6+r&Pni7 zS04mrTZ}nZ+D&xi<-qrOeBgJmT=-{MoLRuH2kt;P-3h=K0rvx+1k7@|&O00UofhX@ z;7-fu?Z8WcHzCf2z^I1ouX7)XV-VePguCst68LTn4hp~*TAWKW(R$?)gdiG18idc_aWT#ZzMc! zuQd|CUj9R1z{~wCcz|p6_J(Y0wnZLk%82+S#J?DrZSilwy}&mCQ#Tk+Ojl2a%Mgc- zGVC!-87?G zm#yX$pvQ&|s*ZCHj0{R0Fc*)LGjGxOr2BKey1UnHv7W$b*IAygCap@?ll40tq zy@M=r-eBRB;bn&RIxl)oegH7reG>9%1uj~gLx3qCh97QtD)2FeGr-3KuSc9LusNwC z(|H|FLmW8SGdl;^%VPeQT3K8ZzY92nh&hBm1loy=(_ONVvBm52 zVcbXAO~)bb?Z9Og3g`05!tXNTe10e5P#&CH?={Ret^jkq?!@(wVdnKs!~MYD1LoK_ zgzG23%;#ZT|7G}5;HQA06Vh)doUeJ3pM4EyfM0Gn3p~?sC-AF*nP(Z8@+H0+*qpTG zdl2SzKNj)nrMylAUTP6f1BT2c{2btE7S1`3IAeaK9cI@Y*)93)eK~H>A&+7A{r%({ z5f5(fD=c1hKL6i)G@q;L+&`?W_upIRe$np#o!v)S$!Rf6TZE4Mk$$m^c^>yEv-jhA z5PrD5KVWIR9<&u#;s))(#h?dV#%RIbn-TAR;J?EjLqCN10Pyve_N%}gkIRRt9Zb9l z_sHne7NBu;A0H$ z06qzrW%1>&(+y{V&$l>b;BLeHz!w`H0$yWy2XNUiUmkm};SBJH3}=DwG299KFTl%C zY#I2AhWWzTcP&mC_=kr3fq!mz2>5q~cK|ylBzy|54g3egzX5*Q@P7d(uF(2E z34Zo5yc2m&G5i$bWDNfqxXtj>z{eYY2KaQt&jNQCeh&CzVAh>4|E)Ki0lo^D`jZ8| z!EhP)R>MQUcUyeEFnGV=4DgWQEb!M1cLIOMa2faqz!k{3ANX;Pb2N0o;{ZQvxF2|* zE0xb7;Ay~Y>m9&{0J9yR1fFAfC-56BK3`ru&2R?zT*F!5cLIL_Jahtgdz{z6uJ<^= zCBvP-R~s$^-)OiW_*TP1!1o&70bDW67bd@MI0O7`!&%@T8tw%CmEkh*Zw>bYKLfl5 zbsPeI*;UrBkH!0>z-+rLaGT*y;NuOKf#)0U2VQ7+2>6|bcL3)N^F_`+!x`Xr0dI$V zvcT6kem&-D;KeNW4LE;hxD5ON@J{jx{D_6~rOzJ$f0g+FKMDLb;4<)Yj!(e+jtPu; zma`b^fRoGzcs4NWxC8ighJ!a^9y6Q)UT8QA{0?BI?F7yPQ*LG8wf{eD?*d-ub(INk z-)Q#o;3C3TuFH%E4CS-!+oE>0!Oa-{g86G={$UO1AaBTHD9V_jmoO{oegh*AbK z6F~5XBA^VS1jdDy5l|k~pEA`j1>7kEnujt7+8<0Qe+6_H!E~7aeb-*=JNxW&Bs(4c z^H~1YyZ74n+uCd2lxG3-hm>9h{r#Zt0S^zKzM^yj`c=^MryletL4OW(7wF$ny8oEl zund~@Fc0&ugJwLZK>tsrXF=cgy(s$)NDJt@LH{1;`bLcBpnsp{p!b8OTON3QT4?4kkl-~lm4D=7doWJh|{c-ZV74kjkUj$u$A7mfU z{|@vN=zkCTJa`vCe-`wY=&pB=m$Vw zh5tOXydU&0fvyMr1n5tKo&wzr`dwgI0R0^3Um^c4#0B&``9V*Bej~%(<+gm6(jVI8 zHvEXv-wpcXN`DXN-%xrQZhuedE1>^a=^4=1m7WFtk4n#h-uiuhZR#rMyFvdN;;;bv z0noqBI6sW`1zO6e8u3#)0o?}r(~L9dEa)AOrDd{RyR4 zK+h|^3i>ljQ{na>mFC9XKLouIZWGXds&qZ*>!2C8F3>BWe~fVez2PGm`~?s11H-5kaZc3+~Z&am-24EiS+C;Yt)^fvI+!Tf$;Y1^P1$d7M=zZ0N83cGsH&wwV+6#m*l z!+$r6Kk7R^jqd{f-U;*1;p^bW)}t#xvkX{fmH4CH_dQ@qKvUnzwA6y`fm`-L^`NO^ zW*wRWt-p;QK!6v)1EbAdFr*G;wqWm2mA26Q5_o=6&A$uu$CRete;^LI zmq9Zv{QZQ|3Fwb2T@QL5G~0F;{yqy@+8gNKR~p@z`;yXEK>wA}%>RD?O}Df7+w}eZ z9K-_X+d%&mEq^{pO%-22MDqYHmuggNOc{QXzZ z99I@Ve^qHF;(vmE72kUN>2KpjguCTm`Lv+Bb2~uOEr0hbT@Tvyr&FLAE}Tg{sRa+| z1^iJT`wMg%_CjOV98(~iI2Qn&S>e<$$gKPx>2^FIU4Iyj5JuPZ%==>Bh|e*tm0xpH+Vnpm!-<4?3rG7w8etl=r3(t@kSZLC`NL{hgpctTf`Z;bo;?LeQ@${XH=M zX{DzTtzT3c-Rb6E1aOkp&HRUV z5>`LH{Bgf9!&)Hlzm5L^{QTjw?Q=@g?+3geq6<6(n!hG|m4$F4=N|go$d~obYPd+J z>jiD)ZuKxRZeP@LUlYr{;Ehy))SPzwp4YBo-^LGt(P;k?qM(i23klfx2cW-u$L~M?kmomdTwiA#%>5gFm|X5w)-(NWd_)Nt zi62k>DCQ^tjrihs>mMsGyb^oX{Rd%D1p}@Tnm+Ppe~j$z)<02x(6=lXXsX`i4pDq= z`%{<~tlTYME`Y6U69>E?aoe9OUsHrTBAkuzw@3IpB8(vTyXCKgaM}0#kn(+1!~JOF z?l&X+XAu@(wSAn0A1D{fjBdk6#pbpZ^|wN?)DLxp4|3GYxpc?B9m@Cj>W=pKZTtsd z{oRrQagXx-_lWNw1HMz>dr0|KBff72e3(YLeaiPgBfkF~@a+QMqssTs5#Po_Tf609 z@Euh?PE-nBxQ()?2z&f)sm6az%11#k+mw%uFAR5kz;`?7KJekQxgT!WAFyos8;ALu@U4gA7uByy*oS`I39P?c-URw3 z@S#7EKKjSJ8+R37x>>}R?0<+aE5%pvWqtU2d?A;(*ZqXZiEag*uUFsq!`<&IU#q%XRlHuk;aIT!r|}>1qfOoI zj9^u0w}M9KRoeBg(Oi|HGhJ2N>twpvUm#Sn&wxU%;37ybtte@MWLBAM{_~ z%YOX;=v92#cOL?MFT!B|{3z(7pxFl>0euEE-M$Sp_pH&p4)jZE&O6+xb7bH8BxveV z*nb`cO?jVTJq4P1LHg~WS^r2kfMy+Hzu1T`%btB-6Ta-%*}pxFFZ-DLLAT&Lh(GpI zC-MC;{E2*p?{DLe{mmJC+3PY-GN5ZgvtB$4It!X?gIT`(2bzq{4tR; zqz-=rdB7j6+`TZzkD`&|9!>m&-V>Pf9$hovADABt=wG|Pz_a0j0^JetbR-4yY+&9O z(D{Jo`VxK;pZ5pmKNQeE5zxE~$@pIl%zr(ge=nfF9MFFq(Ek|FdTEBlVcX9X{NEYS z4+r#-fPOllpAYDXfc{`W|8PJ%yddMU*@m{ZhUc^GE$?i~c08YH%4Xd-9zb$K-IH0q zIx~q=P(PpBR|wB#o05G(vQF+4VKei#qi^z?U+x`_ivXpH|;^Ra$}W5n>ccqX~F+#S_Vh(4iW!z6Ne7c z691=`EU0t&zU&wZ0uOy5s292i9bVqzcYFQE`N5HMC>%pXKt7AN;kwOUikXr0@1)6-W(M%0nUM#KILJzyLF@3G zg@@A2{D2V$9UG))BSqi%Js|%dlm^NN(S+bTXwEi=wYF(gbp@^kKR}{vsJI zXP$0rYHxQ<{&TvaGkd(Ht*No2rS**Yr@?3jc?72ojg3v24%gQ74A>oAo@hDM(bSf0 z5ZCRDmsXIJg0mAXXR;?wH9YOwpI4%-y~CSi+M7Mm(0I}lXWO3kL{npvCmP?;<_S7a z`RHj1=wAvn)@YaVrXIQhJ`I;8=BsZx-;lDS-IuZ#`bKlP?AV2K=$TM!FPxJai$*T* zr8)oVA36l74(gbXfuVNgazpuXUzgBD_tLR%E$XQK3H_}rVdB5 z#?~|KXHPdB7eLEwTT?@O>ltBg&oni*oM7r%sjl z+R>QFHX^_h3-6m2V2SP7<7+rO)6}75&N!5~Ywc)mYHMz7_h}8I*|LU*FmE~2e7vp1 zD_FE;d{`xRXV0`WHlWN=2TmQ#o<4i3LvRUS=ZUt{*-Y!Hmd58x?BM^I)=XP#M{9|d z=1p7UbH~n}I8kCPjd#0%q)u5wH zB~XqN4K1h6wl$T+OG0m5*Z&5Dysq~RttXqFzkwHPg|FFm3@!0gD_T2hdsqV)J$3`_ zWo;UcwYGI+(GHF`bTpLZcxO{v>pNP`9B+L`S?ktQ$Jch-`dm}ndTvj&o^EP;x_p+l zooIa9p@WCAnTB_ik2*tcZ+iA@)0xKdKD3;9uHjV6O){|`Th}-A-etN0=589!^JmIt zQRAuB_VO`2f!5TTX)5oG=|il_ddZ$=J$t6+?3wnaGw2D|D%jQ&ty$#W*`{o!4b`)3 zIOHkYf4x4aZKEX>n(oTApss zHlmB}XkxW5iJNDj)tas)X(!H>>72de<4q0aI)k<1+uqc8wymY(`D}A*YiXH0i=;G` z&#A`D+3Z?vv-5aqU*6G(3gv}_IM2?WX>K@k97#rrmF++|(3Kr^VDWT22CJsh{(*s< zZEVdvpFPol9=#;1k2gJ6wqK<=3g~!g7tc)3wjmKEew{&kFYUh3YiB!91shBFI~ve; ziL6uBs-tra%a+E|YmIx_CzQ`X85J9jA8%`FYin&Qt=3|{W~Dcg;8;s(%8#QZoM@vk z7In`w6j|hSwxi{A6Pi5)J>+#Z_B;sk!Q0Og}yNIuk&zbh@+A@uHS`b-FgF@?RL<4PU z%1RNIK}atNy8Z02_UGHP zryJT&I+@;gk7D*(kcCCi&5vN>yB|{R{(?nK&3^pDWO#o%Rjlc!CL>9Cs>jAhCwlz* z%4H?(WDi5zoxIN__zmE>J8nxrGZTfFDT_9iOM?|uTZxj1({=UjHUuLqM}%(j>`AqL~bI- z=>p#nhVb75%>X9bBYk~%R@-^xhDX5e`UG*BaUs|1`g7fw`Hyy=clo}d+)(!*CK4{6 z=Unx2&!C^Yy?{)a#Eg3kYJo8~j`zT+6cMKqBTP{ya$^JUg(e119782iU>-d;%qid? z-YR#4gINK?u;*mt1=s8UvUsnVPmdS$7oyh~J?HteSy1`zQA~F*cNrWRb-<$o=ljP= z4CeaaHT=&qDF}q5gfn(QX2m(C&T?WLv;QHenlSMh5;BVvUGSi$%*qa+1cp*0mT>z9-n8{|l zp-CHtMrRD=)Pv~3r=G#?v9W=^%a|Ds^}t(tFgSv&63{b(huCxDm{4Bw27^%945EDu zWBO_O2(NG(Je=+C9_x2wm;Cnpwh!7hXlc6hc+}iaO$B9H zWf`;&&bvhN$9kmHM71Zmizm~O0mD#YF%>zVs4?mg&yS8Ub)r*qQe(3{`3Y31fss+X zV=bjSFwp0GY;!$B-J_@qk|I$=QC%UmB{!SThyyTnaD0J?9s$1 z>dw$I*qfmvt9|^ic#s>O7=lTW#v$>F2YANrZ{JfMJ|X<l1QFJQOyYpjEDK;+E!pc#x~TmkMulv#<=YKR&~b9@j%9}2C5ipB&-MiZj@ zLjp!~mSl{_eduS-O^jV;1sbHMDFD@b9vv4WlmnNwfph4Bv-y6hqhjHeik=Cvmdr!@ zNK06TTzWG;#>EH_@5T5b#Q2ylo?OU|^-qlVj$D$q31Ow@f<>49WP35XB9kEPP_m$3 zlVU!alYU*ApyZ^QPYk0>BqsQx+k^|NDJ)W-EEb#Bn8F&ZZbAo=Y|r^o)vUt;Eu}{q zuXHh}2HhwtMnU8P@OaNi z{xZh6^8+kjj5U+K^GStQiDp^DLX=W}D2LJk1Iu?)BrA|KFGQ;lCyuaKETgs7{vIw9 zlE%6ojadTfTS|&=M8biwOuo_rRND0J7!zM0{RL4JqcKF?{0Iaw^eI_pu&j|`v_2vc z7GeVHe1fo)=?N}gdI}NtgY%KYaLUM7bHPLaB5w}zni!8?!qDX7=-UV6s)@nDv7$H? z4CvFqFvdcWKOtq%fO&OEa~A#)4nt-aE9)eCvX@ZzAdNx36p0!|c`1wT+_Or{l8%DW zl@0?f8tw4XMaNZ1n$Si`C!MC_`bNPBKpb|D_VlO5aC9+cp*8%pq0?RJ9vIi^M9B@j zkqOcu(<(n%xX3w`nJ^dKXwe|axMJA5$aNPt**7|5W9wv|W$4abrrdDuGFL3M!Jv#C zyQ5KeJ~xbh%L}Po0Y*j54PvxLM?Q#-8eI%Om%0ZppkfSO^q!&J4Gg0%8u!5sW4flz z*!m=i#tV=OByf~nZW3!o#b!@XnPvvL;Vf}=}W7v(IX zm`{vy?by%a$j4j(r0ByD3D2F*c^Elw@bB@g#P@4)Fbniy;bu=;7-XpNi@`PR#+`KS#a zq7xXwxCGfAeWfT6@)$N%x4{7vA#nC3!k_m#+XumF0`&}a>3kn1`tAa%7C!!eiU$+` zMkZ7Q@HFEUjKZ~#+YE;@4gNT4qh6oOp*45+R_~Hlh1n1^BqM#*6Lq`yCip+uvwPRr zg?laU(su)>XblX!*yMstYbaKbFei9&%3=cX>=z|MIVCR+$=Y-Cs_Tn8DaLw??d z(QX1$1MCAq*M{_0?;7aco7AS!8R*@ufnf|xd~d_a)80e|n8G{?8%!{d^0RK37Hh9` zx_2&%dAEAUIah%nJ|-`|7N1`y9 z63^!P(H1bIV7MEZ7=`$#dyAM*N#`E$rD_?(mGKxJAL$>fhDD891(8b++ z{dnQX&DIdkXu#`t`wgBO#D=}gRC`LcQw2@Se(V(Uf`g|?PSxuJDSZj`!-E5HPMwrCIzRay# zz|b=6MKyMkxzX|+L(HYEu(SnYTn?KcptYj7oP|^CEZGXZCQ$i;E{O%A;h7=(NtY=d z=veL|_MK5$xX9T7_PJ3}1u4^wT^@GWh3WFpWP`&^jGlK;)485YqflUTMnj`)etgt1 zmqnT_>Sz&K4a3m%vkPJ2acT%Y;pf1lT2nPH^wV_iV;Xp1TVLUU6oi%_gj5-Xt9QYb z4#0m5}e5rdy{aq z*_)if(lkm|V-OeSSkE}(sHI5|6er=$mnZYRv|4%pYm0-p+1zMv>_B#CG~5g0Snra& zpq3u<9_j-aYH4ZHNm$%cJjlsHfeJ@aiN-lI(ObwE&_TWc{hwxwcwWdA`hT;Tf(>&| zI3I;IQV+}Z6HkV9)6QMmklbuwA_~$^+ckRhLgn_IlBKG&VrUSBJP-rpXZtMpRi>eE zyTfxwo{;^jGGa)iysp-hvdLV@3#>7orqXX>7>kyo{zDB?N_L!!8T2^W9M%l+L6ht5 zeE~BIQls7C1vF)1JJ5@1Hm1PT;N&oq8%B4;AYgCKMj$+lf)AY>l>1P_L+L>^H`YRR z*}(6-^-kcww}q&f!#WsL|5?m{pwAl_?}wYA?qNW9!AY>6Jxc{(UNK-vJSsWq{u-ZJ z>aKl%7+x z4~g!ZL^H0T$8O5_+p6{=JwEdf(6u%de=RQ&>lUsGfc*4*4q;-65Oq z@pJpV$sP#R>W|L9bSJfLh)?#6P7Jcr+Vm{8-d#5J%7t9nn-r&;-i2x9v^az9TOB8> z@0XzZs69{QOoE@GClB@N)EY$TzIRx^d-(pnp$i@P_d3lPS`r`CZ#*u z!)VcE7&Ub_#BCS3-p4J_(9@_m_NbGiNytiYEaj>N{joBh$fFO3)^6<@&MA~{F?%Kd8qPc)4`AwaKns8go>x3`G4VG-|)`D@~Ky9Pkcae9>8Y!mlEp8;g@naOJn@?1&~H3a(S}_pzhZ%fFOHW zaeQqmuG};)Q?qG&Gr3B>o6XWf6rwb<^VCivjis^#b^Zn!>SMgF&j-r1q?_>dpgAio zf1ms)t~XnRbbRCTE8itDO2NE;tsn~>3e*WFc>HtS{)bhyj1z<x%4k8V2 z-ND7X^Z&2iON9QWgBIl1!QSDA#}h6jCfzy_csI=5;y@cYe`5!*UO;7> zgz@CGXFcc4nK-TzZrQjN0!vTVGJ=$#((|6>LJLDExV%9SDnrRR)Ejz=H8<2P9?D$5 zky27{Otk$>n9TcYym*-GpPm+h8ntB%Oq_I;xr8FMyz`nrHXAuq}Pt1_cBS|pX3I|a=|!KB=%e6iX?W* zYH>!Jcl-wZX*i>KGMYjl%|%lR*vG+?%LNOmsP_%SLI0F!A{f)M{jqscl6sYC%ZaIK zb@Qn&@=H^n%5R$b6sM^#1aq^gFA9gLFL?19Q(q8|iwmCSHEC2$-@>vCnT<^Pl}@iq$%(V+XLmvp3jq zf_qAAW09T+^A)-E>1uQ6{ejln9}we)Anr3M82H_UviHPN#5TwC5q{+3Yz6~*2+N%v zV+QL+AMBv&;fWcqJ;n|v#Ih$3FA?g6bLeGpg#)f^8I!|S0cFPL^Vm6s>vV?3Mjg(> zoX^7Gkn6#ECU#9^# z7C`K*RO^B6p;7FV!rc@kEUzv=r*kgn{HJWzbLp8&;fJxCZ(M|)lUS=f)|6(qcU#Ea z8)dh7c!--Od{Nk$8mx+7xdR<9;yjif=)kEVe;f)opztVN4x3zYENTRqjXe|CHHOR= zDm6Tk8XhrDRzfuuQhdTF+>P~Poaw?S?Re;5jAbMQPsaI!XMRxgt2wSx=F4M8Lhr~BFEy&(ojjD-SnVPv2;*~2n` z;8X36(m?@SRg{A#fWI6Woi-OYzBLp<&-9OoFc+bl%Vzx$>xb5bpZ=9m2Do$C`8j+`$@%%Oy7~iy9>6-lTRjx4tgGocs@7Ur@j4=vhjZ?i%fw9frSp z0;MqCGija9THfL;R?suiZY_u>`2mJX5I!`Jm7Cp`#}yUvMYbJ6hXLW+i{xDST+QVSu5!(elkQ$b2Xo`=O|< zE)Mct1Mgwn_eOrOVTV4^H~xx!!yboq)AKGwAKqIQ6-BdvOGsBPFLpWKH%By7KL2g_w+Kt&64|3QrhAR$=%?oEDC|khg z@R+|rL8W}1jlvxdfG2x!bqR_xHr<`+z|A60x8n}5w$lfzF-z74WRuxo?i#pH2eBge z2Lku&^x%3|CcKN}OPcuV6byt>>ilG!(}DHIK}|I#w3sR2&?D|OWvC7-{DXR$*&i+k z14;!KDeyp;?hVe$RVt8XFqzfkKsczzZFHRGsMk_doLv_gWF?f4B`ZPtGo<~)atKsR zik*2Q=z)0CN3j)Z0xoaG^ErcuI3~kyOs~e}1gOIVejv|dZye;Hj>UxCe~MxNA2?3o z1RZAK+{!8Y23>Ct5cj2G#LvmSoY;4W7IokV&Nc}@!_&;*xmV2$PKSlDj%T3gLXO!L z1*ySd;s$A}7a`LYm##9%(Gi^7;$)FGuX29^D!CAtE#UMV&d~LDU%*u(*pw~4%UM=l zQG#1p8C#Z%#9J!1F9+`2#p1}BGaYTbm+ed|FIy`%lPltI9a&`RZ!&sE1MgibYt_`) z+{zo!iY=SkJ8-XBOM7#vReST<4qWAT23LWdDe*M5#Pvoco~D*eLpj&YO$}`w$8cra z4QzP>Q;F{w2~b;@jjRT8zc4x{_8UI?{ozU}3Ff^J-1{yB3tb58epg})Y7i|#8S4w4 z>rwJ?9FBxDd~mx!fuaxIjJ|{N9{C!=+KH|w*FD5rmAx6Or~(9hU#s_0a1h{bs^W z3;~a)vJ;oB{q(YS@}WsPw#N;HxGvh(K}^s}r;Yw(7PJgtDkKtpvyCy(UinR*Xse|w ziz@etQc?1o2L zYX+oQQ#ha%#r{amn7?cxjsM}B^H`7A#U7{e4LxS;eD-Q{K|NH;_aeO$*#0reIjO&r zU8)9RM298ShLbD=BS#R~OzgB@Au8*+Q%v- zv5qD+7%$=#|4?!0y`{VGSAI6R7d_Vm+j_{VmA70QFV|4%R9jy;Ctp@hAZ_JF8L zQ8Lp$)fZ!F2je#^EDDUxroW!%v7n{IZJ1I5jbo(Fpbpqt@i3bF;EC>Kz--{-=Z zkbVtCxpuCE=PZ3QUbD4X_+>p?qv@t;j+?HZ^wBFGk+``{6FhJ)dnStVrrhR<;;4pm zV6WLs2Wp%nel7FhGG+BIwdcp8Ec3deZA8!t#(RH^xhNyb?g6@Sk6?bihU!Eo|3YmS zWmB|*SvtL^z6a_@U9R(|Ez4=-l_5}Cvo{*6>2Zv%%9J!R4Y=1X6xQ=XJDGhIFV%(C zrX+}0=%7z4Sitqwu4ESJl3SOU`(a8XgMj_ zzdvb{rI7>&+id+Qk@Y8eY^BE0|H4i?TMR0U7&kl;%XqA%@!X|*2rUnSwN4v7kwZ6; ziMkD(>!CR+Bh5qVkIFToaAuJ5>XDOyF&=o}xd+=1B}avXEgmcPq>gRNk7q075A)Bj z`-h4;7JQU;(b~jH&Jvz9WrYyR`E{cO;mF^Do{iC!T8RVC78zn)d*Q<>7?^RT9M*@? zKntq2)FwBoYBoAU;p5C%k%)t}Pk17t0(9yr1Enx8KNK-IMu@*6(M=YO=?!k&3Fks; zWV0cgL!^O}PIoMg3_=xq&;iI%N_^33tjU|{Zt;wFx%Q40m%)8>fFxDhDmrm`r^Fs0 z%vjSEYFTfrecUg?GjzWO3NB2gpj%7!*zzRj3GnCO6Kt)=&$K5z%$neQdV+?L98CQF z#*seyaDKc$=|!Q@P7I<7OZUc4~FtXWRxjhov@1~lzrB}ULzY0xNwo|-@{N6 z98Mm+ob1^zv0zM!YBlGvh45`!!oZC#nU>tZ51XJ^3*=;_tRM7e9ns8Ug|cLc`ewIl z9FQGp@dj3U#UGnLz2yG8u$6gRZ_lpewQOiLw_X$t<-4NItjucJ$d>ltxo}6TwsR=d zq@Cj%v~x3Er=8P5*v^Ry?Hs72om;$p8!uE{@a}sGhCwA~wvlb0HUFa6(r3QY1C8bB z_NOgdy@;Zdh&}0(WVW4IX29w0^gZQ|=%%jpAv2V8+Nc<()ZY7AW?U`hLi;Lxx{c$U zh!F$+(mG3obSL)STJ^5t@Q_Q`%%<5CTY1?&+z%de6mJ1%X~Z05Ce_j}79=R&++%mX z)nku}a0@EWD2hd8BVC>=5GRcEjA`yn$kmVQ<`2_X)Un8LX-kOVcxh%fVA7?TrMr6| zz}mBWXeVLO`KT2+O2yz}SE+FsC%$lWdp7Vu#8`pY2b`RoHEQ-Z;Fl) zqyb|c23rB6qZKISK&UR`XZd=xz8hbMq;B{zuZ+Ki>QhswJ4H=|)&5^f!9@RuvmIe%+=!Eq<_!Y>1s^&~iE!@62JyN@19l>P<(S#;MLO4b`j zX!orQA&g-0xd=}1Z+OVSqJj==jgt^QKNHCIGT*cw`L*}B<`KW8{c5>cO|btzY@%xp zzt!b*8f!$faN;RUS2#k1@rB35k53lw%78e?eWlv_m(KV?udH&^;PlGy2paW1NEC(E z5wiL$_xt>?PQ)VSUN>CQ&TZGZ(HC;nyL>Ms16V;Sl_Yt0P{-Tuo6u_(zR%>reLleuTA#d3;7 zMyKW`y1Bx|8I}NX8Fs}{&s^%Fv{FdR*XX^LI>E5Z_b}^JQ|)Nd;MNvf>HW<&baMay z*ODwQMe4qCjh~F+uQa!dym&3y?d!eHlxzog7?v>QwI9MD(k%{Bbk$dKao-Cm+sg^aF{3W)4x>j!PPh z2{wUP>?0CHrDO)qlu*oKII!gOk+UsAKMItaQ2xueK}Msf(Zuae;|Xm|A);ZYU*x!~ zj$ZO9o?tM8BBu<%Hxqx5BF*2hIj-%-N+ER?7022x3)Libt46-AFbmc$m$m)1(L8lq zT=l+%p-gH^lt)^FO2?v_*EDi{Ya?VBp`vUQ3pFVdwVihNt!i*;kLMzCpEkCh7x*WIq+4!7N|VS{UNee4hT+tQ=x>eVsneUl|pwoY2weB zibEpryPQq+B&r=k=^ev2+dIK0tGM%SxLdwsLxXtJ1CJ%h5i~cbk7fB?nj=^drYkOX z;(E&=q+tvX9f_Gm5HA<{M-TXpm*1hRZy7QQ`cwo%yfk<~LgcG2d@xFHLLS1|S^t2T zH_*pk=>6E(ct1i!b3(bIFU6&%cq;-gxM1feZaRg_C{hl|lgQ~^lWu&F&rHga7B1r* z9l=XlGMNhio=Nc*@^Y3xnS;kE<;rekTOT$VkKmOt*)EKyRSE`tmCK*g85qOiFk}-B zCg#o;7w)@mL|QL&b*I@qX;J9>kVrls*!09_7y4qva)_zELqJZQ0h1m)&@q zH2&ncp%50OBEWY+iVg7Cr8#4sAT5Yz4{|?E8*`^0k6cRaVs*t!7m#CdYbn7csS$j< zl1LuO(t;xPPg}Y%o*lsGK=R%e7#TW z7OWVKm`Z^1D3zMp(?bTaWk2BbZAPAw^M2&NWB!z+@h=SWt^+)ychFJ%k#}51 z@@Qb^tdoanPd^@9<^CKjl**}ldAEsKq_5(!mqYfj&Py-M)+AYlQo{ubw5AcVfb>PY zPzA-8!!5$Ty1V=!ABW}f3NaiQ?i(reKUnw=0N+YNcY@MKf0B+;%={63co5s`E+DQr z&>~cKPfrdPKKN&U#6(^qlfY7V(4S2a%uHf65)jl4Uv;l z^amd2nPls28BH7oMs9n{Zd5m;C(xx80qHNqPdqiuH&K00NI#GfP~Bq?@z&jX@W2pH ziVUD{c`tiT4HI%5OPZaC8BvYFg*W3WBwRhV7c0d9ALhe&>0PsXCi?*TEwM#4IS0ug z%|uKOA~i79%-?SyURl>tS@@1z+w=frFwnH_pR9siZ2T z>{WCVcxVleg?JP0IPs(;n-2Jb6UH&}40%=-5MK-RvIJfqfe3^x7psQNUf z;zWF9M0xSHoZv;~Vata@x9X)YY4Pl{m_u+pa)~eE_6?$b$!o2=r9({3KmZQ;;%P!9 z`SP!lgNHcu8It$P)P`@cD2Z28@j9pi*)(CmN6FZ7J;+%Fd_YslaoqZjD?AJi;r`x% zd^c|5mbNHNIM0B0S_g4N4d<2l&f2*g-k27v!){`5z>`^0%xu=TA!HIdCGmL(4_yoM z5%~;upMzi6BQ61;AHmz(=!8*kv^y9byKqrzJ>Izh)hiEs`VNCa2fP}Az}JnJ)Oy`z z90EV@`Ls*nZTm$A^4_^SGZwhA6ye zhE8S>9jKJJABuA5;(5NCT`c>6G2BOktHU{r7>%02lWcfnOE~?UfTKE%=#?L0C=H27 zYJ;?wh`7p`o`ed4X!JEX^jQ#51mS81T#f@tUdBEVSs>uzF>vG`S{nO7$XG&P zEaVP8H!flsYC8JwU@|f8X^fH@JHx(ZjzLmTiUZ6T-apiy!+-D+xQ~RpBnPXAB~JXJ zZSsTIdrR?1N%}M~d|{Yxs^a9IjM#dA5VIG5DoXXs!?U4NFh3g=C+QO(@kyIV$;TRb!{D~iD8zIB;p)9YEB!` z-LPz=KKL%J3=F&*vGDYt3Q8`%7TOBH>>NsnRbbM@P z9MrML3;)~nl792I7BjX^jz_C{q1MG~oaiexHx~-~wi(*m>Zejw5A_oml0>B($Bpq@ zFVLI3lMZ@P3<3~TjKD$Af`-=(%C{{HHf59nfvsr( z;86B6;k!4u)`uqz_fqvQ5yM64xEIGUxy&Hjst7m17ABygElj%T8NFa8`ISDN#vKNz zSK}kPFd`Ie&y)RN=t3Kw;%!@$`&z&@@8t$9hIvGVgk*_dSn4 z)LUc!u#kk4%jR4Li+9zc6X1!xXA?Yq3$(^zDPi9C)bP3D(DlNh)?@8WZO=6w&*C_LQ`?D##-{eL8|)hy zl}BF&P`_%QNCx0)4gX;I$RnXsX$+8sl)q?M5%&?L`(U|o+4eI-luQf23Suqy>E2g* zkb*DoK(le4` zwagiy%rrALCG(ZWUXfO--vj#Pqj*%yR zkbtYXp}qNZLneFTRO>t1v&Y+7Ga1~HlA1QOoXVcf9B=4o%3{UaooG3QCWymm%bX)7$Ov~}?>6Z4joLTs3EMtG3Zf!m8!cO7@ zy=zA@c+Xd3>sfXi?V1mdQ2@izg6M~Qj^bWRB@URSv?Vh=s5Os;%WLavviS84K~o_W zGB&Q^lc|{9rB8(F%^<0>b!}@7uJ5|$&<*Sl-@yLS8`vMYf&JTVU|)9w`^RozkJ4B_ zgK+KN4H#~eg=jK2@Zm<8h#Pco;KPlw@xYDp@j%@g`vcN?RDM^0S=StROe<({?`8Ju zTGkw_HT&@1HM-S`FBhw=b?HqSMl6u6YeApOIe>Z1K{QRaD80%w^{1R+&B23ZnQIOn zTEpC{lw;3p4nDdD{}IU?Y&+lx!ljq-G(siPQEF3j4hq8>Y^ucnqa(6_V zc;K+lsn@A8QCFvBHGmo_zp8+Rd#nLqNg+3s?U5@&aU(h7pr7m|F1;6Y+kSC@I>Afb zSRTL)DsnqFku1#c_NFXWXP_X%eOsx1w`U@NB%zEYzbux>LXE7>otuyZ zrUnPIp$Ye;1S@`7T{&YkZQ-ma%9=ZRlNKZW6MwzICC>kLZg7r&J3jAR?e9AG;x^|h zVD(C+b1;@)7ykeFi2~jai-(#E_$csrO94L({P)20hrbr!Yj->M-S{q@cJ2zkbFI$( zYkaFmockku`^TL7ulQyrocj{K)9-cezv25U;KxUPCqZmGQ^2Qz+XCDQ{JjBw7C3XZ z!2b^5=3D{41ibQr0-gpwHdVkM2L6Ene*_rWB6(A}QKIBN1%v-Y!;fu{^b&8{?%dWn zpT{9amI?m@u-`Yo!A(YZCc?9d|M5=ec71w-yQ=u{H#xU^VS`&x{O!P7|6qe#Qv3?= ztxFr+b;Z8~ybYOJf%r2%J0Af43gV}D82F*DZEzXIp8(#HcWzSg9|PYxg)&hLZ{^2w zq<{Ye`yJEH%|;kmAohD6bneYpoI{jd2k1WhZTaLT=a7fQ_N!3*BQV?X=}oRK!p#wX zM)B`~|L%oNt}DX*ieLW_%5`y*n~dB~1@>EDKdbly;J@?po7}aCe@XGDVE@){Y;xBl zyc+R4B$4Tp^sH`jiQ<2N`>oeDx#q||qxdbmkUws-%PT$r+*rBUO)369;H|fAcC(5t z|K9l!{Hx^OvDqPs5}*G;T(#LPNA}kv`xV76J`Dbyn;oJg?w5#@%??2buB~>i zs(Q1lRV?v)aNmUo$UYy~Z-xD=;_KkwdVI5M-s1g#`)=Uo&2C1q+0RAx zE0Mi>U9tNr#UF-$Rhi8$0cQREIPjKv)OWSF{G3w!dDti8o84T5=Og|F#Zumro87et zFDu@@2jNX`cB_hy0w24w*;TyW$JfHIR80FVu&-9U0=#Wzv#V3Q{SoJGN9NTl-VeO( z<;^amxQ+I&Y<69W&HsMIgRtN7G1M=`)4)6DHoIwH=FcwyAG~#gn^SE0wW|E)A3H$S zcge3+#5clqijBWsvEd%fXu3vFK@RnP*xGBZv-*mvg1^jc0e;E8b ztGBqTivJt%ww+ttf?~yoJM&n{*(RAy=7{Pn-B0Ezzd2u)x!QIl&50z-@PFy&$=zHI>L2| zjlW*8r0>ZsE)(HS#k&#S)2C2h6-)Y#Z*h}~&A+LDe+&3$6@M?>@9ac+6@QuW&mg@4 zz5{q(@umZ???8Hi!}45=@HORs0Q_4QH@fQqPJmYe`~Yyptv-K@zY4e=Zm|d0ZFyyr zt5-Zj|C*i4EB~j7>ztcXZ0Vg=`~}#*`ANtNigz3Yf4y^871t7^ZpyIjBrNr2f=>_gssj1 zZv*aE{L8T4_9e(m5xx@PdBuMV{(F|4TTp!GVfep-^apqw@RH)Au-~?d_$#*juXv-6 z|7F^DL7oR@fBYHXt;bP5inl)M-2D(Hu7vzA!GFb;pDT(_ga082ixrjLf3r^%{}k-E zKe)kFEB*{|^#)fP;ZDVW5BoRo-Qc^ZRhW^TiFWGQc&!Nr2x5Tpi$M;MxE`3tSiAEO5Qz+PATP z+TfZ4`#WKuQT#60A9`tn>kROdz+C}u0`3p+w*luB|2o{?3*me+u)hoTQ;PpP?C<)> z1~(Jo*$6KwuBn565bl>1XMlHp9`lI+*8r~s_-(+e0d59%xBL91`)7eG0-Ob|RQw6p zzvbEnR~6Xb3HwCxmtcPg^PB1bKM7nL;3nX@0Dl{Bz2YYyLwYbDY7Xr0f_+Bu3$VZI zOUT~{=Oa9)Sn_8X^D)K$4(@mE-00>5{0Q(ufDZ#N2KX58wE&+4UJCGYz{`qX|2Xm| zL4O_C-wFE_#rt7j``|{m8sNu(-5oyvY2OZ95#V7`0p9pskay`Nocl-F5JW{FH ziNwLWz%Yi-Rk?V?09&tN;{u{1{aH81qr&h7aBXt3$JW?NE$|KDIraY1f zFy)cX08<|6Qf%@_e_&5}B(K=yk;wp49+?U-<&o(CQy#gZ*yNF!08<{BQ*83c)c{i- zSy24g6J8!!ituuT-90{kE&nPMn>aBi$xZ~~U&nq^$YQ?*Ow>`MYbt<;`e7|A~ zFR%Cu=z}<)pH^)1`5DDF|6EmU{#D%T!#Dpb6`Oz6ip{?|#pd6nV$&DQ0f+jJtBOy) z-MKgJ#QZSAi;72K|0L$OONuQ%%ZmSR*zc}|X;SQeh2neaAfOpqn_*VQP z@P5p{s}=t;G4v(1ioXhc82XNS#Sb?)w+H#zsrWhIYVb@d{t)nnRrGI)zX!Og4*lzW zK7Pax0M{x0dEh&mF~5oIry~0+ik<%E6#u6N=ibnT{!H{amd?>E&OK1mjC^VEx+@Mnct5fzo&qy@38tXqxPRa#`yu} zYXRO4Jg@klV849|{Vy=bQ_?lvO9Oe5e>PLiEB3$*5PrsDsRn%|Ar{VtaH_#pfd=$7oz&nAP6~6-hLulWb z06z)bulS!~f7drRxTy$FNBF8@iI2m4MDfWc=MFSuJ`&)^fv*R6C-92mm&tz$^*_Lm z16SHRy}XHfqG{5Wv6;>-!ew*&G=gqtJWuUO*S33))VmFG-=S)Q{2W_ivjw(`6h zV3y~CVk^(32royt@?oDoE5E7$v;2|(v;3+RTlv)nnB`Zm*vhXn!d(%bR&3>UCBQ7N z*#NV=<`i3bT@5hHYeBJ<*J6NKUR>8@`?c~~iSTNKxhLfH+FAcL=s&@qdkOtKK8Cjd zL+vW~{-?Q50P}{(K8frzir)qPTVIA=G~(yplg%*WkKsH6yanZ76b{N8#$qr2d=l*` z;^&@~jr0V+e+BxZ_}kL#{UQDw@u>~6m*tMv75M%U=5BL=ujLtxhqt1=t3SkV0>+Re z{u18}TpwVrr!syF$LyI-!?m#Q3NZceSNwzUkNWt$;sxN{kZ-0G<0HRm{7?V>4)(Xs zW4%Q2=9A1XtT!nB1p4tUuR`CVxEA(XuVQ^cv4r3=DYo$P5uQ|R`n#)& zO@BA9*z|YTBD@sgWU~+7^mnxZrv9#8vFY!+BHSNgY(bFpnf`88vFY!yWkBqSslUS# zxnR@ZVaZvrmB)%=(|2OYy=c9vOR?qeBrx;W^q~uiEkBnOn|^2|vadiJrhC&5RVp_9 z5ch}B-f+EQ(+@Q(HvLd0z|;?Q2AKMxykgT2%_uhg(A5afNBEjzOCR@-Fn;DAJ6~ec z7gYq9`XcThF?;HZssc=XQ4(P4i>d=meNnAq(-(2SiTOu;QN3c*7c~c%`XcT>AwTV@ zFX{|1^+jEZO<$A`?5QuBRBZa9D-oWF@VsKnuWO1;U$hip>Wh{GOnuSy08?MI5@70! zRs&3Z5eGV^&-6tViWwgDMU{$8UsM%f>Wh*9Q(sgaVCsu%6`Q`OKCq|0s9CY;hq@x% zAK_`mmOrzKO^;(i>)hy2tRxvd_XzNjL=)E8ALHhobNVCswN6q~+?`*Y~O;m!z8Dz^Na zQEd7m?#H2fV(N>yABWiVMOOn%eG&KL(BAY#*A$z+=z4@#BAndf-J8CM`*Y}@>5J+j zoKbA?=YAaW+k7`4V9s|Z72AB5`*Fx`^W7_oZNAI>IkY!?HNwk^ZN9sr*yg+3pF{V= zobS3fcx?0C$^dh|Tcz0MyR{Lni*UbUo9}Wz4#Ttg?o@y|-26#L0 zoMM~rE<|`S!mEmHKJ0XVi_M2C1I+nwVi>w0t}oU{xH-a;ifw(7`)!y$8*k?n+jwjH zYivBtNBd`Nzm3(G>1aQV?XOAYlW0H9wFoaoxJvi0n0%51nDR-jVv|p7|BYeWe`9!3 z`At5t{Wm6`*!~-nPiB?h$4KU@8ImIS_Tn+3gf6Oa3`C~D_ls~QonDWO`fGK}0D>nJ# zdSFlaV@0va9~Iku{u!=}aJ6E~uR6shf7Az<@<(%kDSu=FO!=cTz?46_0!;a%U$My_ z`M{p?$E0GDKc)gq`C~f3ls~QnnDWPrVv|2+1AEFJbBay=ScvdqgqIat{;ViA`C~P} zls{as--Yr=MSv-PR0f#xM^%6+e3vSO1zt_PU%$BJT;KUNi+ z{81V0m#KVvGNzVv|3n0!;a1TCvF=GXbW)eO9r_8}kufi14yv zlRvI2Hu+;Ez?45$6`TA~q5E@)DSuQdHu=N$6B(|J>@$i@{^(R}@<&&IWxs}ElRqW{ zO!;Fr;j9PsOj-0vj*9fYV~kNvQUKXVxPIM&3lKPc4a)G0Rq>J^)R zor+DL)34b4n^SE1oq1sD&+aX{088D z#g-r3&qV$V__w}<{nv_RJrT;fIbh~zntou)kEVZL2r%{Uivgzo-S#_~{(V{PiK%~I zQEdA6iYo8F;mQctDmMLlU4Ui%B*3zMqS*BBwjYXE)=$*l^zTyG|2`jJ z>fdcY6z!>hzoz!4e_skP_3zgeoBn+@z|_B2+~xDb^zTW8t0SCIY~|A#V3to;fLT8M zimiO|0cQD3DYo*MiSTTM7Zh9hEC!h6b1lFuAKRa0<+H5zRz53=E&pwQmSNkUWw=iF zD_Qx}2bkrP2{6m2Q?Zp#e}Gv&lZvf;rUK0JxuV$0XD-55BYX|`+j2M>ia+-e$eW74 z3Vh2Izu$`X#9M(K_Wuyy(ue-y73hZod^d1)fZqyS8{i|rbpfV*bAS&6X97(BI~801 zFs1legn#F&=noXjdcZu^OBKud!2-%x@h2X@{1o!$s^V{l`!_*8bUS@|h<5;2Dz@;d z6#v~b{=90U_*3Nn8q%v+)*F_QUd6H=@fGMF6`Oxuik~@&{6u}@{v+n6VeU5~{$2QA zSLyc~8Lk25ek1mOw*J8VMTWWlun=IbKX8AM*~@tvVD^``{$TruY(Cj}kLS1XuV1mn zKd;!vEAIE9|2AIDDo*=nV1{Sw4VBnmlj2T{CyLGgx(L@Rw)KWd#WtUxQf%uD+|NV* z4bMjSy5bKW!g#fW@i4%g&%1lQdz-H(5$1j$`fv8lifulhQEc=1t^jkrA+Olx^V5ng z|7R3mhWxOt3+rFN%wHS-D-w@wy`dVI^`rJY>eCMNClT%fW_-oJmvE+CvD4pzVq1?` zitJYun?7JwvCaS8ecpe=iDJ_SaK8`3Z$

IED5Q;JbmF6@LKs+cFprBFz0jbZ_?D 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%0AJ$?;jdubvLWLBGzK3Zc=fJQQf zMlwZQxf^9A_uwtKJ5I)qDC1~gcDbL!M`m+BY{1a%=`&_gVc8b)xvr&rx|+0nuzN3S zAfNCykWYMDnh$v2#6`0DI2F1^IStGwyvv;Ny);-XYbhH*1KC?Xll2)F$OOJ>$&M11 zwUh^`f!WNqMke%`tOjzsG%(v+uR-pXMl!Gl%jMH1Nf0+zt)Q{*Iey zBzMTyW#c**$z0l6Zkh&ii8e4FDDJ~f1GxyBkf~ga+3_|dGiV^AXdt~^Be`Y1kqI7h z1nh8f{4;)T7s;fWlAG%4WOj|rInm~F?Hb9oO7P&h&ID_be3QN84#|>Ptb9LV*X&B! zb(X$7t(G(6S})sDKKQlWk_+VMxCS}jA{#exk=!9o$+h~{p&L$1c{BJ?d_~R&Sq;pm zphhyBOUVt_Xt{jGji;rYbZgn6ITx9SZFA;n+rT_!-)hNav^3p(CaZzGHngoA9vjGO z!*|vo;}YgQ;+tlDTNl_6KA@)bE3 z$x3{k3(T2wQ@Ox=z?g?GSFYX7@=d~g;MiRu2R)8*8p$vk$c4H(xy2Ig{h2WSmM89` z<4I>5NMB7z*LWshm5Wm@GH1`WlJ2ff`e|fN;nG8nf$zMKaiiokFt1FF%=z*&XdqV@ zH*%3VaSxlyAGOnZUu_}pBQ0eMnY8R6cXMqiN6nUU#56BQ%m(svi7n+Zxf*#sahq%$ zg|4-hveh(@ry6HmBsbF6Wi>Eo%1v^{mU2%tkaw9)NFNR4=4&9gMgy~}T_o=;cNJQi ztz{EtZ|T5hbNLZ{UDnl^ZQxtENbZu)(I)v86eSHjvkvEoB^^aDh3CzO9eUsdU|3An$scke9qRmYe@@2i1)Z23e^BeRnagX+7v zNWPWw84ct#y0$qD%o)@sa$Oq9?ur}PDl?VcHS&CIV5W451sBOtjO#RzVSL5}2Ol#X z#$34>Pi~SXD#?XX3Hyg;U@`(lCBBr44I0V4^TCpBEWI_5trKTlBpX9ha~i1Ku(JfvKmNh6CHd47TlJ}+JWW1#TVuF zkS6TKx!t50S(xjxpn**6Yg}L^_9+uQc=KvY^V64KV@@Mkb)3rjlnEX@o?ltcUbfsQ zTb|ZZF4j=af-U9lX&^U11G8Wk$trxSPzRBnqmeY%K+bwx=OVd5zV3|eCf~NX$+8-l zIb0-jXe93g*GNlg;{w_DwnkRso4CO2WM7x{buKW^z^6{z{-(7?a$_}+Ll)P$NUmN} z@=|aYq@}!-t<9&hjwh?|DHoVYeQOuUcNlIMEoEIUFnifN3po(3MJ{gQBALtAW#c*@ z$y}N4o%53jq7|Qb4c#s6O{8ONC!0C?WCrU z3FLEE1GxopRZb&$0=_OQ!Gkxn>ui29@>i^Z*+(vtNi~v5C3x_F@s*p)l-EJlUbnms zY#^@#O~~uO269{D%x;v`oXqE2g|@Z4DSUSgsNO#0ZgH0LQEFb;g1TwLcO z8Cg?u&AyQf%;EKQIX8!vazw1nuGP778pz~6k`I@-kp|{KxaKA}*$j=OS67Msg$K z%B)6mm2oQ*>A$GpzuY+G7n?ClGzZHCSq)_I8knQ4kqoSXIcc`FJgCrj(?F_xCU?fS zagjU*P01TZtK`jMgGE=GqY-z~NUkGp>>~N2Yu{Z1`Nql(lheTLem{3Tx9mP zP0596ApKk;S+qv7Xy0hTHa6cL*j-_MJT-xNHTYqCldP|Dfh^2-(!jhJG-EbyT&I!T zL<#h{?f;AQ-9I|Z_`T|<)-hx$HjtHQA`WClHeFLMPZm)Mt; z|9;20czu6GazBHU;upxTJo1meO0R14JzDVtQkega#`k~Jwf}%z|3UM&+`Q?uYv>B! z-)G+|{STUdQquV&sW)F{esf2Be?R}L4w>Ko|Iurv^PVr?-=}`~kok+R*ZEVfp_$*@ zW8dG;f9a6!}*^*Wd6?k_6v2TzkZ)yI%NLd z0rP+N0rP+Ckoo=pZ~kHPfAo;~2M5e=?zz8yfB!!t5C5R&|L8|`g_S4#O11R;efCq* z`Jm@Na`Sg&f0{4z{J&Rz`Tl;WEn|A`e);}B^S(pok5<3^{J&T_`Tl=lAoN^}j@Z`Tjotu0!UZe~0tG{gC-*2h9K2 z0rMX_Wd6qzy8g6Zs4M;T`}C1R<_~`A+t>en2h9J5L*~zahx2bAGXJ9o%>VcS^FJ&5 z)2vj6+4og*^M6HOqj4P={H=5}_e574Hw(fS>HQn-rfkIfcV7lHEf4F@`E=CXLBHwl zAN%Ls{3UeY{9kkH-yKn-w)u~OlnEn4!`Q_*L`~T&V z+dqROKB^oiVY|L$G0`VRN8DVOBeLGzC`^p50Re>4Bfc~(s7wC zAfjMP*{oXv2*nLVr7l0oSQJ4~aQlIRS`-x(6+saf=>PjY=iGTOlT2DbfByXc|M!zO z=X=jP_ug~QJ$HR?GViQfG%p^Dc`n4fzj$HHaXl}6U%VK}2+DXyZ7$h zn@c^smz-Uud@l8Z#B-@lpw6RI=PaCfpH?jf< zy^TgYl``MSxaz!Lntik$xhvJq&DK868@@01R}9l~4nsLGkMNjN^`ZPk{t^3$J*~XM z=tPmw8)$^}MwLD4@j6@y?+21+Zt7DnQKFYjgk4te_A6CSr(f<$^`G38<_}kzKU`_; zZ|#t~@QTD{Db>6A%C`wWdz;ofd#l=~ zRR7+O(u(N2sN~zIkF~$^zup$TPyH_G<9~tZ)!3uu)Wy&-5ZM0F(0Gu>no}z0#*MC> zT90XCULyjuGhC=&e{%V|@gpg%(Z3w#%MgrLn(*q)ZV!vSO7)^VRdw>=IHPtfmG`Y4 z$=Iz@K;t%T=dN3|{j*I+3jZ)QgDQc~Y^B0+GwDT$H&0MHSBRG!68BC7OvYnEFR0uh zH~glfgeK!xdn~#xex1jWw(Dl~=j4#>a=&+`5N{aja|qzHFM`#ZiQEXa zXLjfF>W{bosZYP^)oOUX??z$-$jkl5G5*2jy!Kg#NZfB!djzSm5|8?E1@*j1l8YVw z^wQqFkE1VT!1_AqbWrNgu=?6tL@&RYxugAOjuPrOD-C8IXmO>%%-336X<&Bso7KL- zO!Z&CS!pnHgvl!nW{!Qa7uJ!htbRG}J zTm73}Z}+YKP4p7>FROo(4%oqXtAEpBcHipXq!UFj-s<0^3y{F(DZeRc@>c&QdOP#C z`ZpbHajSomI&?7J>ffXt*!A~p;{=g!Pdy{!L$>iqi$5#zs6Raee~R{tr{Hg;;{*MR zC9!`{gVOP&w7 zemNefSIy=1s+mP!!d#p7(}bt(7mhP37#(NWg44!mM$DJ->48}5ali)f1B2u>qVw(ex1g z?sXc^ZsRC`^@uOT>$*wj^Y+&%KljEda>MV@bwlvF<0amlJwa%+{0qU!-uhi>i>{qo zzq+AX|6VKCjf<|Gld-F)rngJo-D}>U^LDU7=j;8oPtt1_eUd|UJZNu_sF&^0by)jo zdLQPA9$ly9MzeKb*RpzT5WRxDj)w{FQi*r<=)BpU`jhmB+?B(nzRs`PQ~wZtd+KjS zUoiT-QBUOCQ!h!p+4@4R! z+A*=1j`i%iS=ULbu)SVe*LK~m@^#*MQciAzrN2q#xc(TlUt9jkVegj& zjXSMhTYq%@I=4dmVe`AR-vu{lKWy|%`um~Q-+k@hT{r1^a@2U$CwHjzdtdu^*G;N# zwcT$&RQYb7l<>Bwe{JY6y3%Na(Q}Q~7+qjAWAqfG(~V9ss(zl^VE(&dwDGk+nZR1fx>m5_1!A?mdmSDmL5RjGWjKgJ%CoO%EL5<79d z@9dKBz9Dj5Jv*g6n@6kvyLqE|^f7k7+wP|&9^OCF?%!zl)$hamx=!or*=qN-{^5P= zM?F{AeYJ0RU)OtGJ$bt?#TCyJnn&xn+SQ}}nj5YCs;kHRdGsl!pZWRdjK$6WM=!9r z^^4Ip7PtN~`do{rrTpCJ28p}%6x)Y^_S}Li;f)lzT^PjZKh15r-)L@oO88N~#-UzqHtZYH;70dJM_AnLlMc7I+b7vRp}0@7eL``cWc!5T zKFRh8#eI_P6N>vJ_2+P(Wc!5TKFRh8#eI_P6N>vJ_3v<>Wc!5TK1nD1aGzxRgqcz; z&u`NH67G|1pE%y_lWdnl438J5ab!QilxpNk>Y4;XaApi+y=&;C)hQ ze{lVYe$JATZhv8Zk8xZ2r8|GfP1SiV>c<1EkC-oO;?BL?KBIky&68KU^|`JK65d+z z>w6oJ2qEFUOX8*a4%C0gs0k&VTSu{cT0ZQruXLQz_Kwz9&RuSn;=Ey~ z;rrKUzvH@}JvYE5n{t)u6klFxNoziOQhJ^y+n;C&P)`CKQ>;W1yyr&Vry z)mpq)U1{<0O8skeoGRA$S{%1aRDC4>j6}Waw9@7gCG9`U+W-8A zwOyfp9-?l3&Q0wuwl{N5csdU6vz@k?-pEhva*gR-te5Ex^NHTuO>bx4iK=h47Uwn3 z3iV5yer(yOezdH6UK91l2M6&-w|{c|BbWMo(GG0cT&f`Prsee!y`lx~>|?FWh-E>&f~hhy4;3hh6!BkR0|TPX1-R zCH!P;h^$|ev75bF;5$9)V!P%1-`}Kq`x}`mY;V`jNgK!gO_H7GZ?^FPQTChaiINP@ z8*JUN35G}TH{1ACB3C!W?r*Yn$L4U{>YLv;M4{|8M@oL<+`49Cnf$FEj+iE(4}y*GDzZ=UvR$-=yQdztQFcFr|Lu zaT6i5tIh}hW}62}>=oM8)`6RC+$xa^?W*IJzd0PQ`r7pgv+D%WBeZLo{QKFpO#Vf? z>cRN_*!2O?KtJ~1uDXu)H|qM@jZgjkRTc6#>pGqDVqZHrf7NxpzggG&rE;NNb${S* z=B$N&(l5WSt6jI7U1w-Jh5oDU>u<60Hd=YkFJ`M9#?4T_9p|1`Y_W1TTDkq?!9ciR z{If#$$L`{|BCYc%HQkp#yK%#fdv&o{I!|oU{#l&=H%^qCi|d`ulO#@i(IfqhI&PM( zcf$5NPUO38()HB^;~$au{?zLjHHFC2pXed(`FgRRcI*5}D^olnPcNvK?hjo(lQG?Y z`qxaB{4N-OpV0l$N$16In)5D!d z4TD0*fS-`v5T2o<{g~~vlQi>$cfRQ3&N)Z9b*pwaFIn+dakKrg*W)Gn(&Njuo4-wp z_3CVV?!89iT|K%Ebm#JJy)+D!u{_a4b88}EA6 z{k>6EZ-1_cdH#t?$5s7B>_C5H$W2xMEB8Du8SfIggs0gCRSLF!R_Pim^}ucPY~x37AR2D89=GYhU;(xB{zpT?E&-ipui>%C-5=Og-$AIUEv zqt0OI!g;$Xl8$=NqNUF#dmE^Qz9T|$f0Ldoh2xo?D~02konT`|X$Fou5Nu}-Y zn;%{<{!}S{fBH$jq&{@Peb#5Aj$d4NGPr)>_7Pn@H%hxw|1|EeH=2y;xU)ZcZ7K5M*bLAw5 z>3CYcKF9!p_ji`mhb`>-UAcO>dNlizO>z7xS6-LBKjof7M%SD7m6XqwLT|I?+q+Jw zo6lN@o+KknSI?c&j>*`;axQWhx&gKm!effM*o-(AK>oJSUlH~EYt)~M_Pyo^DWGWI z?P-l;{1^L9l&H7weXr`n_vp~|(ch;_LjM|V=VJfbrt@yGe{I+PR_tHftUtmgQvM7r z-@n$@Psm*Av0c|y;rWQJo5J%ETR*va)LK4U#|T(~Ps!&x?I+>+hz|7O`G~D2F>i`K zt(s5y^AWQ*T1oQ1*6cmU%D>j^je3YbZ%xY$>LdAQB>F1ON5Xbs{xAFdL5I_R<3@7m zW8$T~R1~3{pC=>l?*%F+xWAA6f2U;U z`92Jb;Oy`0Ufid4!q5nQz}`I2{>S!Ho#+?{exQ!Se$4iC=LE(5RHu%&e!#l}<@YU7 zEZjd?{(hPKwVQgy{l8x(f0Mgl;%3Reyx*$+yuV#E)DQYCM~K|{y577Dn37!|)p&9L z-)Z}QU-d3;SKI#w``G_?+WtJyd91u$ZGRrnI|j1rXUwkJe~SBmzfAu9>{=%OqFvA3 zZ@Uh>|KFEgb$s@H8@ExK_}6%;Zg{TJsS5dljn^f9SUgwhwEcKs^GS(Z=&!a955jpQ z>etC3`d(^wU;F=cR-SL=IsIp={{8m<>#SURAEoF=MR{a^aKZRD3fLciE-ng?j{dCs z|H19<#+QEk|IQ<&{NjA>Pn39ZJ`X18eb`mTZT~2ZLtB~OW=PZv$D8AX5$^vF-0yn5 zs{Oyeul@gvqSyY|ci{d1!1i@^0+!+7-vZC1=*wWg2FUz=?HD$&P{8_D?M61}v4 zzS-X25B>L8(|6iF^qpPQ_qCdpC`^61B2Rd;iuWVc@xtee|E6=B&XRK*zvSE|7$@o$ z_m%$P8b=)mo`?R;=QjRi(eFRz+{Q0Cx9OZB`n!4E?<_gDxx~(GFwcnnby?t5>$0eL zev%yeD$i}2MUArWAs5eW8dc7n7nK{||5@iY$)UIZoh2rR?fg5s7O1WZ-T7SIutQ`$ zz&P)}`uAGW$OY#}HwlsNGrf}M&F&nXdT|DQ^?K?4=+)}AORI(PN%x2MHYg+H(~6#V zZv#KE?!|>Fc-Jw4kc=&qanTQKUC>!>U7+KBIIezCmebQFenDtCze&bUD~`JZuM19; z`^i|d>0$FxXSw<4LXmU(jcGG(H$8UlLyvQcdJH@tRm=V2{1V$}`q+Hbxv%*sSE3iK zjOQo)=A-SV?=}0-SKqIrT?d|zR%&?%tDTm!`LNMQ4$=0L=UGUbJ;d&l4OghE(0xXB zuyl~?lMeaRRp_`jXgZY9CmrH-72|0JdEXn^^t~_n>ik4~>8X9vi@v%);eGC-`rHSj zuENF-+-DX0+?Voo-^}z}=k~b|MqP!@+q|DHy$?oRg`Q{dex~$37|GLpuoJa9oIy)Xr1oysMyKd);{jpc46VLs>05>k;dob!RG*TqE@3ST2DU^is znUq^E?h*N%y-(=A|DQ|UZ~TH#=D!u`-1kO{>*^jYWEk$B0=>BoqJ1yJ<>PAXIYrXr z`!P~(GBzSckZYS>%okC-*E(0?&8dvgTuRfi+yd^q@57AJZH*WG9_kBLF5AsLhj8UH z{oUkm#|MJbyKARDuNx>In$D%q_Nd$_J=XAgZ*UMTn=?mpc+9)}$Ki7=>dE}cmvrV= zT{mm~$@rV)P2sxu4@7QMGlUWNz9>U;+X8K$HfyIg)9ZGUSp7YOyh0pe?i;VEqVHu@E#-!S@s(MOFwV)Va_ z>i;(g+VnljpzV9c*Y}u%w(nT{M@D}rw9(#6?KS(YM?L8x!PJN4ew5GgD46vr|GuG_S~)x~z$`S&?e9@~Q< zmpWI{>_@q$06RR@lu@UkJ0nzV5+vWZ~xCEn5ymV zk4cDNFjd>#x0k_#soMU&eGfL6s(#>)p;yz+>JR=HtynNs{ldS7TJXO5hd)NoX#F6ytLUDR(wyQu$$c2PeL?V|o1+C}|3w2S(;e~k`o!BqA0&@SqCp3V%VbYPOnpicor>%sg=_Xo5)(;Mz1iMH+rej4x=lLHW=N%@iNz@ z=}PMvJ(r{XOY2?wJ!JR2J3ik?qu%R{CS%%9%e^nf|05Os{{`cG9fy)}9e-KwBy~NS zQ=WHB04;u>RK=zL(4Ttq_&`{JD~)Tt(F;0sek-kKX}!Ys)bh)gQ)vZ&xorW9x^6^8Jjpb3*xk#@aifd_QCDo3L|@jJ0z@`F_UQ zJE43(W9^<$zMrx7PblBdm>(pR?`O;(63X{8<`)U&`x*0(g!28l&QFx@w^;e+KeP+m zqrY989ke|{JEb9wJz>!f+D@UJteuK>Q2!6@r2QhagZiCcw3GT{Xb1J{&`#>_p&iuE zLp!PehjviE5ACG=!Eexff`s;i&`#PvvMo|g?{Szl14w_PKP?A612ptIZI|8?z(nY+ zRmypDG9c~CknoNa>f(X5cVO)tSo;Rnu7R~@VC@(rT)SF(n!h?f4a`3S^UJ{eF)%+2 z%>M%OyCC7}ul5ZRHf|(r+(_8Ck+5+iVdI9`D@dfJK0(6zYeL&SNT@#q2^;?s+WtYp z#+ih+cY8wZ(Vm!K`5YzmI{C!&c!xZKAf@zS5W0Ga<9#K>67? zW_AlE(TmaFZ6D^|OODn<^|0}%OuAsw6v-!di29vt=iZZr?e%Iid%b$Q_#R&SSiR9c z*8F9xwqN_$v?OdFtM+RjtNzwLR{gAftY*|cR_)V1R{gnstSZ<(R_CSmu{zGRkJWm& zkJWLyeXNd??PG^pITc3X7zpi}t(Qz3E%EF|&9At=H$Af(Rqv3W7WrhwGCiNE$jUs% z_3mEW3C7xdVtNE)t^ZiP+`2dzYx9cf8I0BWA~1b}u{LjvRlS3;HcyOI{e!VKj#xc{ zu{I8vy@Ihe4w&77u{I8v{erQ!elR-*W3^ugW_PEjJ4bWpb#8yd`I#-o{WCSZ3>PWW zv858;RD5Ec*3W+0{{8Kp7WrhwOtb6h|JT};_IV|CrGW-Z#~$F?BY~Y7!~V1*J)h}F z`?sU^BiF8jm0vC&>QOFTX}QiX+Aq<57ufi5n5x07B!u5*)&9TS`XBx;6T6|8ZAyz= zZmRCfvQ6rD#rHA>_+H4Pw*Q-@T}{$cKaPC6;M~lS_W3j}e`8-2GSR#eNm)rSnXv zm+m7%z0@B=y>x%_uh5GP73!t)SE!ec@1b5gZ-#p5d@z_^UHjp01GQsc|I&Fo)Jw;u zP%oXpLcMez`&a1I*S~aq5$dJ$U#OR^LqffD9)GoZl|L`h_To6(*WYwq6zZw#^H5J+ zKZSbgdj8ew>DG6*&b8{|_sMfaj+3;nTUU;nNbf}aCZ$}D^L(wi9v`oKmyY8X zhbq>eEz`C06d8Z|%^N+Mj_VKRSDL=@BDELuq5Dp2ybB2V*>kmE$H|f}?=vKa=y=9B zdq{De(<8U#dzB|!IZQ%5>EC{j=95buR?KfJ_@(;hc042Zb31fA&F#=}7XN?H_zxSs zUugRdea;d+-*xq5xz0}E^W5vDCdt@!_B?lr5F<7pX1uPwf8pMMBw*$#XoGmV!LuAb?=WlyJy$y_)9%Li~G4N zM@zZI=fXYAO}`K8?8fq4yEyyp>v==h&1w%P&+<6qB3dyZOszOCbb zXczUX&@Sdr#pk%{Z{c%XeGVBu$JPEDKF8I56F$e){^M`d0i`u|jQDfcP8~0kv8(kQ z4zmU&65hAO4jeb`q8&F&binyAI<7{?$HD;V_BGDB^lpA;`3&Wri3$@Z8~2kyiFn)+IOO!BgQKA91(Wj0*Qpz zEpq>EJ3Bju|BpK(^~r6}b;4lwWzS{1v8S*etXI(<{hpuqwRghP_3Hn&`tMJ@IpRg@ z%@zCp*1LFqm{LDW$gfeT{r;W(t<(=*i5+-O?(E>sJ%ZF9#Gm{|?a&EN_bvZ7v^#6G zulfe|J561;q{R+=4#o9EbbWn4$Cpkp5xQ>Hbz$_qjlW{5S&n-wuTFjiNd2V)@xj)+ z?3Zr*cH^siekIdP#7pJfdl<ksL#BvYn^|Mp4-mzUGM|~@`s`ANo z;B+9q55@GZz6tyN0JrY%8n20xFw1arr$mFVk0ZV1;Ip0hT#$k50zL}f zC9&{(8eL=3!s$9l`$00M=M4X>{8>*1md|>Yme2dtaIpK)^wg61kjGH$mnHd>lPh;V z)MdXj(Dk~s8@OPpZk_V{W>xSw1CHoyczuCQ~j^?98 zb6Y{`67}za`knLdIX{h}BApBo!UB}kRsTkXZPtZBP=sf%X>h~Vp zJTO@M&`{34``W*iwg=mjJNNzlzJq&T&+Y$`@lz$e^T)dQr@?{%b$-8a-KNw z`Iwz={ilBa!7q0{rsqIzzFUt*#Z-aw8awAJ_x%T-Qs`%qb1;r$fjvi!@-;s@=S!9O z{)7KdIv*RPT{(WxUpby~-ji{{&XN0{kKHfxLU<1JFZ!NCC$*s6{+E5vp{!jVEwPI` zw@X+(+_{}jc;UI7E|h}ext$ENsJA<}(}^W;=XRYs|NpP~o`bIgN^9(B=^x41R$bo} z&&3u={W%`VK7G4H2c6fW<0sP;KW`};~VSVlF-YYDAKg7yU$glkAe*fR; zccpg8?a+1AVD{k1R~(Pw{|6!N>i2TLU(@fL?BCS?{uy@Ab22;UZxpwOUFrp$q_XXVdFN^1H zJ9R%0Jul-77u^RAwC|&TvwlfW%bPUpYFT&qu~VeLNwN3J`v?9IwtD#g?fm$gB<}vt zpkHyS-bbNaPx%DxGo|}|lIoel_WU8I>wQeS>}P((nHHx}HN9)^_}LN<^{>_YMg5m)ysZA`^v$oLPV+13&l6|( ztIIEOuEt-s{`#E9y$?it;m_-ZUJUN{x81(aeg9%T$~^`5gE<*|LjD9H^8JnJfWaK~ z?q=`Dx*6|A_M0uE8AbXHmZFXXa>sjPlvff;rlcgPGcY-8uJi3<9iIV88Rn zbqwWS{rLl18FuNyAq5Y4=I7i~d9BwHKtF$4z>V(Eq%7&FLSQ{{Lz7n$!O+rvHE1yyo<;6#e%- zuciPvSnC(r+v&(MD5PhL{`xX|+TJVk2f*7dnI{eAUZ+x?O**H$q4d82n4-6@py z;{5E+n+H0--h=O1X>P+6a^L;_T=6;j4Y-LA{eLQtBR}_l zK{y_>0{!OEZIVpJ>w)gKx4l*D*c^FI%oMrQjaI*!V!IW<@4bX~L02j*>er)jj_;3h ze}ux=1W|o_#97a~$!}J9XD9rAxs(%~7hOKon|5OQY>&#h^Q!3kxiy?uD1^ZB<^5dS zpE^5dyYxJodVCggPLJHItx{j7PgD=)>+D<9<2JR+Kym}syZ2gAOX@GrA1eC3pUdaV ztY;E@Nw2T_%lCunS6w%2dAS|kqG$2|{r^kOU+WHdR?_Fryj1HEXnDK z^*-Oz6}xTJIO}-`ptBe4#D)n{pOt)r)Mt!-)#$xS+q6FfZFgAwQ${~&^bz$?k z?N4OyWP0^;f1=KR!7TMp-`>LrrmCNY|DQ_zHGFQPejC2mto|GRA13wV@c%HWKZpN^ zN&VV=FFKg2{_Pjv-&H>k-)mOC3*X;We+%E=H9sr9zpH*2zQ3#eIedRt`*ryKuJ)(! z{ax)>?)}~Dtvaqej^@w6e)QjyK$nA_0oodyY0ob{D(m;ITXdXq^Gve%JmWk_>pXE6 zXxC01m)$(FukpF~J$j^d^GyM`I8W)e!E^fV@A&P;U)TSd%k?*#*P`doGQKuK353$| zwf}kZgEAiUfB*Lz!jJBce!}_R^6kA|^XL0CeBR;yZvfw)WseLtd|UIqUDrbiPZK0# z$Juj_v*o$RK<%;x=@Z^jQUL2O?Q)y7i;XY)Y?lS5A4s2eIaK+*``a#7o|}hVySVdj zX9xGbR`ZT?b$r}m^WJS*9>331x?bSO;Ko7sf2y+fdoJPovDQAe&ItM1KD4*mOUE&% zN7rpPiv3+XB)p46kymO@SAV82ASd^Jid&cM)4%s+$IC@M&*`7r5BqW6aQ1s8b~^~^ z6W(ko`2SYBxbLF|sfWZLeEU(pAoZ}s=|4QlOL*!3=j{O3E{t6QU0GS;_M$Buexs5{o+95FZYMckJ%Ud z@R! zWsg2r3{tu-TMzx&bU{kjZP^}u?i`d^Z)bb#dv~_~2-EAjE!(q4$_rAuE(`DLx-Hvd z-}6i9x-`76>(*?KeeW-&>(cPPu3NJ`_C3Iqu1mxFx^8v*(jcYl((t~nTeCg-eVibr z>%#DULFeTj{T@n?(sf~YU)PP<9{pZMkkWNwcwg6z*`BAY{<=lL@4)O=>PQdfT$fl#(vgl`fbql!9MGE zlgjh^>a^oPXX&|r*KIa_dFs!-Hhz}2NAdh`c>nkJU!z+#DS+e4aX@Z;&UPG% zt8VzW`@O$ESi5tak>?GbzVGJRe>s4RPi80ge6H(ev)4LN!*jn==={KqTM6&W;+NEu zf%j`c2YVmA-2G^J?uF5Ok~jH9e?vLWADK@%Ii?vf?A_bi*}1ke-O*7QYdFJ6PR zjm_(_YuBV#H?C`5+1fHo@@om!)vWDY=a?frW7Mu|1h;WbOWGJ!fR=KE7j!oFO=XNQ zl`;CH>gZDtW1&1_eT3IFcg$PWxFQG(%{H&@Sk~3i+Lu$gwk5)WvI}cM0ca78wq!e7 z``7^0rKvBehZx+i2=>W~LZmpQCvo*MQ)jFEb-DksOJJM^`u1jxd z?OdDAcD!X$%LTKHy*eA1;c#Py-4Wqd|Ki3~%r@IGvzS6#xN{xK>x4Umeo$=FQi;Jm zK&98Tu3NvhvpwBv6EW#Pn>!nwkpxs(!#bbnzvkqozMucdF{okTGmWnmxe2}c3#p7 zof?~4)7drYbt_xboe*rg_@ZOebKzSZE|v9MD{StPTG6*(S-9akc^^x(tO?R+xlUS9 z534Yc%&%EA;BfN)nFCwkBfpKw*vz|cz?luNogXa9#yQ2=(m{TCH(iX%<7HV>^Ca{2 zxNIrxAxiC>P|gS;Z-!{H+|eF~b;O zsXOoyz;6Jh4JR9J06q?w_3g%WGBCeYT)_2a!yYJqSCV|%hp$yK&phY~T&(X_(A9=- z1ntBnd4lF};je-=c{c#-7zyG-&SqSPT?HA0;q;kphK~TgL9u+hFoQS)YaR9|{@u;uD3)M<1WJek3xJ@cED? z8h#Y;&w!~P{qZlrlPQG|N25;xE#MjnOuN#SNnqNc06Ybldfg9vGVsyB4};Ff1v^Ur zS_aH^U~p|hUs?{nv=y*xpFD6q_|R9=XMKB)cUco}2wrAZe#AzFcXF60eKDtcV2DAnBKGtNZ zH|vtYMV}?kC?Y2e;$&LxyNuxqiyJoro)gi}gPlG>?n* z=XqiQSGj(glG=F(o(h?0{ZB{SLZAAhd>7&whf3N9^NWON`@GqBgS8LmsRFKO`y6Td z%?3ZJ-(18k^wE#wm4)~`fD>>RO;o|TVm7ezuSLMLeHxdA_yT}sDpPS9uxkh2Zw8-j z$o|=3nB!s2F#T|gVfw{YhMDIM!{-8j)bL8+PZ_=xn9o?5{}s5tV)#bj2Mq57e#r3W zfqwu@AGsgbPYgc{d^WCyxE{szEAY<(eF4|+f%!Ht_xgV^dCu3IOlXq~@N0l+lLlbs zgE0I|d>jZqk_-j$Qv5)e017ehjiBrTCo6wASEBq`0ViLleDAHGly3&5{3XgCz63ZA zjCPa!-)nN$ncRm#@#o!!kKv$qg0dfd0W=M|8#Dv@P0&2(_d!|E6Qn5U_oTcu#A_TX z@mc1{0RJwIg_X*ZK2-&r!Noo`A2g4P{jM5U0av;H^>;1%K-!b_w-8?jFcckx<)wks zz;$->NZ@mTGq{d1oCl^q(vJ(cP6U5B=pJ0B0iOrT0xE$~WCd--agp*2oYz=KUe%Bx zJq*_cz%Y}S#$|y~kN;}*t=1+!FvDe_tiv^y=1x$k2pJ~&35 z0!n@OJeXqxzt%Pa^xdHBuQ!2moq7)_*Qmb)rEl}+N4Q=b2TFZU1EqhS1IoSv@(Gz&Tr^lH!}LHWFF66kk8j{^N8=w#5>pt4gyr+~f@bS~&rQ10N4 z2E785bLA&Mr-42IdMxNupqw*Dz(~_UCxgxaT>v^0v=x-|)@7h4fOdnP2>L}(&R>s$ zaxQod^c2uhFf!*Uz6Qa0;dD@r`xk<8yyL$wf}Gr$XhSzX{*jp086pJVvhAzu6f!+!$5#qghj*BE{txXUo+kk}T(FCc%0_56Ub zt_T0UfCUT&A27TJ_#?nqQ3n0{7Q-3f+kvHyz;^*(4Uul(&jVk>e1I8{wf(XLd{$ZB zy^v`({0-n%!w&(kFiZj!Wxf6g`1Qtr+;GO?4WN0$AaRU;63`^_iyBWrzR`HU0A?FS zLi{`k{twN;`;Yu?0Q+{Q5pD6C^fjp%?XF$HqWaemD(G>CR7IX5okXdEC^MN}IuLMRIz8W7L zhSvbEGrSgfgJNfwSaffS+YB&M*x#lzf&gZM^=Al_cw3N{Yv&t)n~YBaUBzBK5&kEE z*Wq4<0vh5M8-Tqq3TbeDftcvR{sNyX2HJt+D8r>nyw4-=Erv;sL6kBD@Y(kmz6&fv z4f1`=FbatM!Z6B+{naqKNqh)8HsyzbKN6VvU|jOX8J}a+biRxV(&8y8^>-i4A+T$#4yx~-Dwyk_9erZZ)3X+W6q5|Y zB!U^I3@+~|@bhFKoCs`vMB@LyAN}k4(Pgl32G{=fqjy2JfQ#YXxc1;G?MGLFmxiA+ zya!hX_+QbFn7{L}(!O&!Z(4xNEAB5>xJ*D@KIQrdMV&tX>V8p)K7uej(%<6j`%8`g zKHv+0VS1_iYT&I*fzW9(+ca8~$$=03qanTqjAiJ&SYvH@0r))NYfYjRco%R6gV$PM zrp*Iy1m>924SWso=Yb2rJAkPJ*Mc{jJlBGE0N)3`Hx&Cm!v)}nfWHBD9+TgXOg@7N z@3+9rzXAB~z_dXgcqjmIH}F9K)TaRadc%8wrviTye0#mbdk`>#iSq>T{|KB1J{@=$ zWiW}J1x%eYz~=!o&j#RT!+GFNU|FXE=Yg9bQvhaomLHgauL7TS%m9B7_)p|xGTsTy zJk!8m07iAZ4DiFiQb*t?fd34B9{6{_j{p~dp9iKqH^^~Js>EsF5x~?T1I({M5$A!A z0e&910DJ=Q3zWe?I|rCL0CU5BGe{nIH1NZ~1>o_( z)Sm|eQw*npPXMM3Gr*OG8-ULN{u}st;0u6Rmu}#!;hn&52krv@PT+08Uj!}ye;Al$ z?E(H6@Qc7afVdm@CBO{uy};65zz+eh0-tNZM}fCe9t(;m45xvA11x$1{~4J2Gyum^ zidO=UG>o-d>`22t@M(rS5B7#G27VH0FNOSt!0gz0;FZAVAX)&v*f0-CHUe{_%eB(g z!2DN{dEgs>@%1CG0DPNa9;STGa0d9RhV#JR2Odg!;Ga8rILjY^@w4$>26!(p|0QA` z_&_Z5enWkLlfWY=1E)&^cY{xSEHF&5i*cO~++g?w@Db!$AOYlMpLhoNu#<#^hSP{G zH+eLd1m@3TF9e@s1;Yy99SYs2Xb+d8x-3J2OM5ZoKWID>w1b3A;3M=~mtF;aUT(oZ zftfGc)xrS|Gk@ZbK&IPnelmi4fgyvTNcYh_Ci4yOZvxI(93q1Snv%D6~N2D(X z<`~PcF@hO)@>?VP4@B@MBAD_B@s&{UOW-36|AG+7ry>pf0Qg@t-b26;^~nDL@K-@I zxE{5%UjqI)Fnz<>=)b^o0eq>;(~$YHF`tdd?*+cc_|~C^_ac7S;eGQgm<$Q@kv#d{ zfU^ntU*U%Z$cR1@kWZKK-UxgzF#XN^QQqOO+tSv%5n(-$-kS+|gyCPq$6R3MiRoP4 zrEvD)IbbVz8C=UCgG@vQQSa;gKxhP?V^1Cz-@{=Dz+h@bkbAga0`50sbNI9`X}7 z-v@qzco^0uz&|6#fbwhLp96F4{d?di$;a9lbH1#9t^npU%iV}?1?Dp=;v0cqggh~y zaU_ngbsF$U;9r7Y08Rq`8rZ`+`EcNFVmRLnV6Hv#z$XI#o_rMgCSZi&-w_gyhwNY9 zHQpSP`5xjmz;U#N8)Lt3GUtMS4{+MzkdeOD1iteb-ui*vCt*JDEpG*6STBaP!2b>E z@&|-9^gd-7xfC+M6;psW19yWmyc@U)G>>Z=@S~swT(sdkKs`_k@gEuh3&(*Pe&hgD zqi^g$9@LS#+yd;@0k;}XgTE6Prj~c5_zudC!DHaNDa3hPdV#z{pB`{8`|i0(XP|7hr_pKM^9flQCmx z8vbOw1AsqncqH&`hDQS<$Ub{~TH2!`1IF>da6<`|hBJuO8qNc^8ZH2@H|#;5t%g~z z+YRS|cN;DMKL%WZKM;AB$d$!+jEFP1ewS992Y%jg0eCMk>>y*+*zw`{cnWwo?&onG z0Sq6iSO7c&_&!jE(|~0>0G|ANU=>4Z!PxcLUQFZ!>%a@Fv4sf!|}8@55~eX4-Dx9fk|QJ%;xH z?*wK&(cR_UDCd`Vg3q?k<8nUK4Qzqk%lj2BR&FS+&q5y6Db6Fm1&?7j_)mjo7|{^t z_+lacI|H#u|6e>Co$3H%pIB2)u&9LeB1$8ZC%g*e}f9)ta>e|9S`AuMsvj`Or8HQZNBZk@bj{)aFnFsqg zaT?dpjn8tQHu(%NpN}w4jy2Da4?Syu8Aby)fIbgCLZ9agEQ{eFtJh1A;k&mkplI<$ zjxBB+=iEb_HlcmVym^ZDLl9Z>3{>|j+&l#3QlBNjdC)Yj^MNVP`ZgIp1(+cT`HUd> z5SvpLwq$>h0NoO4!}c@j9_x50(z-zX(}=K+ZcbtyiSxJ^_9ZiAsvM0;`yL0JmsEH! z#4y|ORA6VfGYn_IpAXDAxB+@BGTZ`uw&9iNDs_glz~>om1HQm;J8+}nRlu!=R|97a zuK`|dcrCCGoJYAGxSY>0eyQ=d0xvm6>{&4qxLm!?fsCuyTYyv6E-k%*JDKOB69PXhD3 za)w>NX~PBJ@rJ(+Ji+jHfF~N(RO(`^cLlDZv^zl!o`62S8UlIQTIB$~A z7-n7m3Y@?kMj7r6ZC#icew_IxXyJn$+f58UD8fiH3LBk)|@ z$pgRB$pc^Jvqv!hb|*%mNWvA#_AUS|hJ5S)y& z19{s9kV*3f!U@)1*Foka!{oD1q(MIrN&6AQ8SoiSq@JK3H+}(_!Rc^kB<<%SSfz9v za&5u(U_h2d|2-O!FCZPr$dmD5AwCQE^ph~gLB|4^9Di+mk#}f_)41Hb1sPzz??!$D zF0MI<^SBnAq_`WH?=+BKz{Tgd#CveL=igMM&g9d;+*48}1I+hPh#P?UzTT;zd0ZLe zr(u*Tp{%_;wfqx3jv9cTZx4@E* z$%74Tv>q%nWcTHpIv%nYAO92bIUSKmh_6N68JrB?OUsnVbc8bEM=v3tH$f(Tvii|% zlZRNJ``kAzMBaJGA&jgvIgmbb{;8TzRhj$u+5P!t?vFf8(=RN!&+(f6eyZI+3;6WY zWep(bCee2m-E)LI6kP|t2yXzU z>C(6+8_ob94-7MV4Y+0j-|!IN%M9Z= zV#RxbtDzTlyAhcB?!soi6OWDOUPR{vmkAE2ORgj06 z_{c|r?=tyM054~`h~H&0Q-Hq)%(F3u2Y{P_yMez2%yOZ+_Y>grOy&vTw^%+u2W|r1 z3YlL6C-6soc#gy|h=Jb?aciIFA@gx%dw&By-(*In!~M#O;DasoP0S0^js(WKPu~Ax z{&~x1BKU8$d?o{5VEAa@3k^>Pt~Y!laD(Alz&r_aQ5cl^ScuBRYjOW#(?`Zq6^d^_f_H*H6#kh3kG2XR%RpOQVwk?#Wtet;n_=4U z?S`)b=D8Kahk)7c>{B~|*O|;GfoUJ|KVz7E|Gx~UfxiZPF=R5p7Nm|$=j!-9$RNm> z*^hx;S?}O3@o(07c-#ci5oIL?akowTCU44$keUvTV z!8;Z>XLWG)${_A+v;g>c$j}~~Q%*I^v2Y$R$Lj`M)rRxH=Nj$?ZUpAoSHRT<%zPfk zb&26efj0u9KGJWu0W(jA8x5y{Z!(+#{)FKM;JbmDXC9dLCB6dKg4BHjc&_ffkY{u_ z1RelxGQsZw!{);OF|hM3&UwUXlSA4*>zY%SNPZ*Vfg23SqtE@b!Q=ef4LO97d6O&6 zXKAzMv#HGeo9zCUGWVac`E^JARzDuxknKKKYD zudwvM@xvmRvJ9*r>7$q63l8-_W&;kW?B65Sd-xl@EViJ19utj2Ht460Q_#ldw{Ps%rBpP z$Z#6?4#OGX`wTY#KLp&0V)MX{8s-<)erqy$;O7i?1OMG{0eI*JwaFgf(T3U3;|!;P zrvmRr{u$s?fWHX)=Yii0jI6xO47_7tGBv=phR>bh#hVSEKSS50%;zmLyu@1Y*%l3u ze;e?Zm?!WRCcg)1uQmKLr2VMjp99}*_(|Xg4F3Z75yQVk+NTXaHN&g;li{Z!^P=J3 z0Uwaldi@@FwBbJhCk;OXeI^)w0eK#6_-~Lo!SLUKXB++p@KVDs0yi0c3D`Hh7kDGE z_~A^fOAV)iKLFf8djj8XI1l^ic9=a(NF45xwH4QGHm zfqS7t18|pHL}2Eb&tR+rjx!(N(}D5l?EzkF*qe>@oZ&QZi{T7#2Qbq%0KXlWcFP05 z$7Bk??>D>$xCi)9$neXncN$Iu7l4^h2Kav9-M|gNKQX*=ju-nAF#WIt{2}kOwgVnz zxEpu^@Hb+}5BON%Zvtm3aZUmJAo;+RCeJU-E-{=2UJm>%$^*9m?*z^R`@r93THqXT z8uL*HCeN+F*MQHk1Nb(|9FDaI@W+8O<1w}Ye*!oU{7v8{$QFPf1%8AHCt%JpoSBGt zUe9y#M`E33xEpw^;R5hchW7xU4E#yt&o4b!0^b3g0j>uAG;kjHt-$9%qyXFo{29t0 zg}MNLj`G0o1|9`={wObTgW=1L@?sx1d^zwvhTjGJ9m7{3?avHv1^$EK8-f2}xEuJj z8#Vu(z~g`q_R#*o#{%zy4h7(ofjq?4HB!0sb=hwAE96#K=u`& z$3l*6z%auw*k+?~@!a@ah@^peUdp;m z2VRe~9D_2zJfo%$<$*240~B}}WWcIu0F!4h9}4e#aHRzK?}5yRjei4hk71s>+-mp( z;EzN;(;>eTI1bA28N+GddkklQ9|Rr?+JNg(VCiqbKR0{@@H2+D0>5aOb{w%;({=+N z3j8$KDQqDX7Cu^4t$H@&A`;1;XS|~H9q6WR{XH|ZW?&*eKhBXl)>e} z^~F{oa-KoE4QB)aSynLHsLcCN)==;pz>n68b-4{Z)~onjAH3^L&pfcJV>fU&_-wBN z@J?WqSy6-dmw>+r%J4Pd-Joe)j{wu(GPoKs53mgzaQzB=;ykY30drm{0Ka6Il^C@J zI)P?zS%|ly+}DB6x?s5TrT{Z7!%2oS!0!At56p6rO#0MZ$PgEB@eG{jHZ03Rd^K-s zh+iDRmqhTVLirJ^BK$ie{Phw3T@gP2=a$R=v&IJt!-a-6qqLcY_}vjXHI~B_-eQ=3)MA+OZNO~LG%oJhn?N(T))+qzydIciNjI*`4BrXNkic}p zJg)-ZRqg$T)8O9%Z0&!<9fs>+@m+=+AY)+&X$P(fTr|knAp_mFP|t^fd5_@{OPc}y ziQxv|UmDH>{~35UXg97Qmnq%}bq_ZDN$7C6;ZKDgAUaUr3Z}y~88R@x*!Ec9d#o*{ z1Ean&mYfdk+Uu4h6sM8ag5>#SW&#Ey8OR@G^{Uf+M6}iNNh7w_a0a-`a0BpW;4aWS z)VkX6M&KI_Zvy_X;myE14Z|Em?lk-^@OK%$0&49x{9fR10n=_44+QBN#_#5)zgl`~M@j|FQRB4FmcW*p2nz^K{ZXz<(0-Zcv1gKMeC4@py<2pf7c5 z{J_UR!&}~npN5eGc0=w{*D@>bz@M1hmrLUJm&CtU68}|6Tyn#b>X(snIL^Fea=);0 zhFvF;#d4>V#Lp~=TfVTco`a(exIXmSOzyXquWxbj1qy4Bbmsyy9j~{W-0v-&ih1!r zhI)@!0_No=_e_c0pCWQ+Lhfpld#*(8FA=#EY`Vxc4OFMqtUt_WPTr@kU>-X{LZe z#5)O;jXf8XapnB3um$Q=T?jLD@3k;8h#YcRP9gUC&ST;Al4G`a4QbcK@pNW##kp6us) zOm4~`R!N4kE{KHqFHe>~@UFWlG|WC2^51(Ti*6O(r+p^0~PrK2SQYkH2bi z#}A@s5^}#Vxf2JGI~;OD-!CN{c=8}}V<9rxlM#Ga1Rn&Q zF^;pFaZZqM7(T}v=J+=)f=@8a@$<9@e@=wIG{Qd=`J=5R{~ueuIR5T2O!7no|15%k z9>GsW@UINB8c#*|zmDMFMDWvwIYz%8iCzy%{l@`Ug0hZB00*Fy84vtUP>$6TfwzNl zJe~x63n{LnfFCgaWZ)ke|Bb+VfjOQY4a{>7j+xVdj{)Ymcr5VghK~cTF+2mf37E#3 z3G5p_0hseU$F!4xd2Y;c>l9#~wQy{j12BQXEGzz^uar;5nf4 zadAAD3(B(<_W60B-MCH#=KaTT(LM`7`I|myOYcnJS-`a6S-?%eENc;Pm*K_0TY;(1 z65v~bCji#~-w(`wcsB5hz^uzs;4yFv%5!})1$aF05%3?VFaGlf00#QcWbhHV1o8Mj zB!b|X5&i{Suo(a32>;9|o)F4xi{Q6LWcc2m%V$M|zb1k&jbJ{Daq^c%_#cYk+aj3% zcgV?qHp0I*g8w^$e;dKiMR4qcVLl@wI2pl5M(}YFe0l^|M{r{VzdeHA9l;-tU@yC7 zomXE!d+E~I=hfFPJin@b*?Bcp_4VF5{1lJ3y7AI_{wzthHSq9LCu{I)C!YSwPCb85 zCGhx(A8v89ex2RMPrdM0gzB>${KX*>#`uda5*Hvp3qw@zepklhPrcMj$%2~k<3C>Z zqWbKbmexzXi%)@~__%mYkX^B+wI$uWva!>lfz$!S+f?oG{X?~>qA~s$3^u4tXeO{UedVAyZEFNs4_l_Dz93L->%_@ z*WTLYLFi((N(ao3A5ZccSFGr4UD3F%wZ+S}cNrLiCp z{mCsC!Ea$XIKzRN>?1XBUHRE87onu_XE-p^W4BQ;BFd1?kk6T73;vXr0RDoO{Wh5A zes#;KsO>Hu31ReA_X}E3d*PD#ORH*Yy(%S(XP;X?cj3~i%4G|ym$>x$16qA!NIJW+ zvZ`j8x3ua^hliT?E(d} zE6-9;w{*UOs>&(_mCKhZVDh3IGc87#Uom3Mh~7kZYi?C{ukUPJU*CRFXKQPH(B6dp z4A*OK61PJ?l^?P4@Y8Jp2Do}{ZcEHxZ-V!Odg1JlkWrZ6{YqYF>_v)4`telNDMw>61S--e$(K3nmlRJ0b z(#7>P)r%HZp4aal@?TP2v$T3yb-!C?o28ZK%&D6%en)DKi4 z-dsHQL^#E~>bfQU9l-9_EvY&eZm?_sCoqY5vllL^TUymmFDbox(EMkk#CMi4xGcn zCFjguv~WL#IBpG^8%FB^h5=f)Sk8G%1~gISqUzd#HJpduR9#awa5B~pS`C;bN1nm% zvo>{0YO9uDBrMmk)$^+BVZFMl`kJM1&jHJ!%zz^fx^Z>gvL)3^@mbZsedg56tFN4o zn>F<|!Iiq@!kTkVn!B)e_MAln^tdHe3+FGWuf!0&tcq^mPd63dt+J`5YV+y_7@Rfn z+^X3F4F=`(t*xr8Te@)BdG!mbtNXXf*{Dk8z?Q14sjDy7H_x5he=J{C35U`}L8;B^ zmMoaPWG^&cNtNL^)h&3X0nW@AL}XX?3C=L|Tml8*+O z+kc3s(d(C@68-X8g8trr_{OMRzYH!|*-w7iY>Zv9wi)o&vUAJaTv)ld+`MOF!oUWU zS#kEv0-S*LePf;kKO*L*H|!n~zie3cB(WXf7(as9G|i>uI`1{PtD zpEtYzd@YmH!X?X=_3tF?VsO2=^;PFC8)#;f`%A=g2UIO`e*qRuixw_k*k8Gb5R0m; zp4)#UDUqqJ;Uae+>q1}EXGv{+`8ACVT3Dj?FABY<5*>75RlPJ}KU>ydWUN{yi@Gur z%wfT7EO7>zj?rM1i)Po>E}VB>{i5mt7GzkI_ba-#Zcgoawe^c<*Pi9c-ny|9d(3bx zEDPO^wb(@;_kUP>7w|f-v(9()U7zQj=yCn$;CD9ufY-BvUq zTe7rm3Cq&9F0s;v2QdwxGVLJR0Afx~D@qtNrF{@3hY=744TPc@!c=p};fNAIlrTpO zfe~#61Sj;I|NmX@`|WoxUF;OTMBd+T-S2C?>-J$(duv&vuI^U+4|(?1Oqi_exxw~`bNv6C2Q9}T^O5-_0WDY6najzLqvrXM-fiMImr9+ z+u6}4zvl*vgGI~+$VXo>_-}_;4*9qD)G2&DI7A9Py)Yh5358Ozc&6A9I*Va= zhtjFD#j|bQ5F|pWL|OFN_U0Evox^iYA^qq|63kAHD+WH{wKz8Zw z?W0a#*XhmyzH}E)!D+Z(U{v4F!R{YCdluQ#+uK{{J=69q+=^2 znPMMgeN6E{axJuBKC1`wF8#=-b_5SDwRgAm_jjFo7LwuFb~sB1x_gmS0`0x{-gI#Q z0_FLr(2a?eZq$#SVqZ4Z6sNtq4;4Dw`a47a`S^Rj>r_{PUk&dlU^)TfWLW`4t#Ar+ zSeR#NE8&yXQ8X1Qu*lNu=v}ml==ZlvuE_+Oq%J;}jRfeyJQQP5jFIZ+oZjiaUdArY zyh({Iw3h}^q`G?hx(1$=-0kW*6=GT7$U3G9 z%d909oKcBdp>RHnA&MDh{4C{J9iQoL>nR}I@kJ(e;_EO!cvh{ie07XthORD8Gu;~lvSB2@~^SjQVVl-1HEUv+M%oS zNo>>ZtgmR*Fb&Bj&9`Wxlr(3k8Ennakkw-=CR)v0v1jlsR4Qg1a&h7Tj<(`Ol ziFr1&s(nu`?fB8X6tam2YnbWFU_%ZGK2U^{_0b)w(k%oAjdVY!Q46fXDEX*EC@h7( zp#p1g_Etc_mRa4hN_%hbnXV#@$b=|i*Ryc|3 z(%pNSdZ&8(&bRfUQIQsxKE)4uV~VzTRy^u1pgC>lYgQPYf-nV0Bm+r~L zAKyy7-Cda8q!F|&?QQLy67XKQTlTHLr$gO2Pjv}0Cxi-uS)c~`&*@|swNSfUWY~kS zF%es$rR|t`oi=L>TU$FDI%d(J1RLRC+to`ueCgwhtI6ooP?Z71>ddD=Tu?CU8=$pN5g zLyET3JoPf{6J!s_A|ifUY&*NqN6`ljM>dZOHHJ^ZRK$1&+>P`p_DOpVqRE1MjUD|8 zxE(=eAmivB}h2KwXVJJk9+ z2M0QO&r99JV5R+x1()s=I?%f!kucif$bxPSiF#jA+I6Xdl9H-E*n>Qgkl+{1CTv(q zVV1^dG27ydDg7_D4{AqJXg}SjGw0AiO=*|PD@_cFK^yXlL6C778mkV8N~|aS$bHd_ zjY13_4Qt-8;SjqzaNv7i5do2CVAw~aT!tCw#Q;WJ>T4eiSRCM37e!JGAO{ZUa0iho zH)`#LQ*CFvx)~mf17szGZ{mTdWnKw&m7Y1=+oQ(Oxp7p}F4N2Hg_BrY=s>bRgLY92 zvrx(l49f2_hmitY0-+ZG#0-`=~?t~r@NTH=xc^zC-c12MEI1tzepWTCe{ECH66K`gQfVI48PaOE(*A;7V7 zK70sP85pZB5CkyfEn>VT$^+-oHN`N-`hjuPV0U+aMVQJ8bg8QceW8p$G0LC<)9SpY zEZigZV9YLB)=0J&&ZF#MG=}k|jHr>7=L=}gqfx0@(oitC(qN!QqaL0=7r3xU73%0~ zkVZ3beWR=d5Q}Yn?VXu2ES<}YP#bPq*BQ>Ybq#27;>ZnV6BWck#HuJPoTE%-Don-D zSJ6o_tmyX6aor^ho$5Pled|z(d5D!(jvG!s%SA}7Fv#P;=BO{6F7}|^iUSF*6QiIO zyU|;tA@4>*jV6Xa=i9o^pkQ>Li;kh*b@iYv8i?NYKwQ&mY;BSR;~9(##B=0baR@72 zQU(IshoO$%(05*wS5hvcbMY;viKHy5cz+PXNX0^-J2n&&{^%kX*q? zY6K|;IoNh6v>j&sKmgeh7cnmC>Nt1+THoQK2Gc;6H?3i8lL#-ky&B=-5gcVuQWQiZ)i#NJ2i?$F<=o#nCw96Jr+# za|IR?+3oObzz6`sCgeA9L-pg3v$MCmLkFAk8Ve%-#gHhR?CtFih5PugSRH`m7bP_7 zEBcD(P)uXLij*sc-cnq!r>AY*T-3+EDB;EUgV6{{Tx0nzb%ktz!ulr#CTg?$Fu{}W z)`y|f>}KB*R1-~dPY325C|;wAL8l9=pJp1hkpfYyy%f#+tox8TfnM}W7~7+*lwAoW zbelT2!44EYQ2LU=Uv#=~s)%tY${EVi=~EE&!xR`V zCgD)h;KN=U<@#h1wYjY$zgub*q#?|Z^q$HOHtgA#!@s$`dv^Dqx#b=wjMTA(71NNL z#3}sKS40qda!i7vOej$Du<0Up?3A-0Y(-f~1g--N)4?dWp|=}^Xn?I8Xxb3}{O+!f zeYyH9I9(lk)HC#fx!BrJc-ohf4yG(eVYdq8s3>(qwQ}}K#l4dS$ldB3Wv;S$xR`tH zIp@ILx&4&K%F}a$16|$yn3`j}mj@aUJMSRN}c8=CWxSgq7jw8R+fo&qJe5wOll#E#@qJN5MVc+jmB1HCB#lr5TMb^D^=J z?%Xk~8Dssf*~IVu^Ie$4%jIJkGF4`0np$0@a`7vM_t?KG{&kU9t02B}HO2+ctZQl%5l?}jbyke#h^T38+<01r0D ztv*=VjIMClht|KV1kE^cg%K7caX1a>ElwLk_>1EL@y^B)`*Oaw*_V41OVjFonv?zQ z0|=mICBfw-@!~U+iN3r{Mfd9~y|~zLq=g0}JTrjBE=dSZ(L?CrWB`3#p4GJC z^IGzzqA-YwitJ2NX0W52FnD+A0{Z7Bi#T3R6}o@1iGtm7cZC>)Rbmg#wIfdhYsQ@$ zr7>)?UWw%5Pu*3T^K!|KEt17*dBIRG%4r}9W}cO^?A8jkgnJ!6boegWj4IuQ1S(F{ z#@D#dn?WsLRu?5EDs#qfum>xaGWUlPq;Imc}K zGSThofQ$|Km(w>zh;cn=i|7UP%~~%;4t+3(77jD}n1jcR2j{r45UOhiaa(P)0{5dX z#)(BNf??jj0PzQtdA$RjuyeMp2M8x90Y}kU3INlJ9!um=$obw`7h}tb>)4uPrkE~? zDJp53lSn|~)|v(3-PMGP%Ga2ya2TsuNIc}0BsjOEpT~--Oafy^dz>CVJ21FLDqJZ3 z<(S8nrmj-#Z4Zl^*fgKRU=OLag3tsFt+E*KCHv!ZdofPwYqRb0+VXIVeK*#lAeCZ5 z>1=+tv*@>#V~j$HCx?fjs&wkwyJK^XK>-c$sW5QMJ>~5Zem^|IAOdQ1_hPJ-ch19Z z6jCqVvdN(GdlA;+L{5M1W{8&;VO)+%&@gi0E?ket__);6V+y&RB05U+mWaT|#0<^V zl@rK(g{S*OA2Pekticjm3rr5JomnE6?>4XYNm+UHv12U{9zWr7kuD?eWWxzV!H2nv zVuI;`vzRhN3xu)!Mm<0<&2hvq>o1OPElAuV+r8 zbYNFM&f4_L{u}pZ%BM@1Ov4e1v;BPmTO>{wpl~p>V~C4|v@>A{y+V6C`X5Z5%JCK) zw!rD7j{Yu~M;9~L&Fw8vDT1-71rvK%(7>!PCfilJtL%Wz6TAabsQTIzbc|gtn4siarg%70JZy@xE)?JhdQtwJ#8q9CcpowC}xXj#J!KAeOpJoXUgq*k&T>ITqJ@OarkS9=Z%IaqtX659nZLRf>c&0=Eq@)n zxEu2;suAst1qg*D`}DGpb{en;67Xx!Xl$3 z`@GnKvAjm1GZsSTzZC!ul&~%)JN>w7fs|qP$NhOM1U>zEEv=l5j%E5d>Jl>zDtq#l zSh-sy-CW1%3?IQ5h6%!Z?t`@ZP#foObyOYqwCFCu0*g0m&N9g)Ih~42dw95dmd2X zE8Yj%MG2L;w>^7}`)p}6s_T|r4k~dLT8TU93T^$ec-eNctDBo?RX*m*Ja!k!E=cz- zLmL#-ID>XpX4et^%5*%7mM5`;q=YS0Ok7La4I@5{y5RivdRg*b-V zjg2U|BNBO>dHwKXPdpS8;W$T9nl|YCeBxLtm`UB0lTjg& z(ltJnu3^C~nPW&D?-+vf7TtIgx0o>Y* zODftRoN{Y}^~~7xU#VW+CBWelZ1(iWGX*N-s4xzD+!CGJi^Dv~{8V*M^9h`_dEhus z#Xj-KfjlM&G(%06ccQzqpY_WX_V+vcYc%Y71q7T+M#xl&+03N7Ry+43dT}xWV-{9Z zjUD862t?TKhf6u=dKehQ368jvF>b4d0i-^T5O6D$u8I}p5D^AqklA%347O--4w=%N zIxShkNrVc8g81T%6vWH8d$O}fwm*tWrM0Mpr7fOusnkM_;|`QC7`hL#ONQH!A_rve zBM!fCw--A&R6yut))Ht6k(a@_=G+)-`zAI6p* zF;CAlC758E5)}ExU<0@Q(1z?TtMF32!|QX zkZrJO3|q%K+s@#G4b~#Xb=ktnlQ{!8`Gn9iQzYC{dSfPV&5HLfJbK~@9!GxkF`hB5 zRFjj@IE9<2#shpGzL&=hSJXOof74?;_*BCw}mF({iojO&>gg6YP)T1ni^B z9L+Rws&AR2nI_|~lI^Br_daprKAcp(fG!UnE^{3n1WF5&k;S0Dh*=iM4Qw1@^2a@e zk`qjOdEt_;yfD+{1&hA=(vPVgUigA6lzzVKxbC1Hz@9)@!w)vqm*40@RHN&7iw?yS z!qSQMrPy|sSMWqN7Ee>t&3SA?lYV7)R2u>Z$lCTxC^-57i5)FJtIO$XzgD~{zpl)tV8?fjiNseRl)a$|>XORFEcamaS7 zL6Nr?*&MYQ&cxlgAqg`nFjS5t8er>4FhdvDQ`q&ZyupdMiZyYWIFc*#-Dk42cBl&0*S;m)T77)(1?*5{Nj7wW?I{(qI!CYpe?xI7=xTE~T3)VTxzZK%D3!Y5uLXzX%UR;?& z@+|Xrr9~h5z-RfOEzVYCg&14Q-pxSJ1x-WsFSgnk1ALLIj%N5@wgf@QwTXU7_?70e zmd~2gXn$RMV3@R3i`f?Ej^ZG;JZtXtr2ns+5ck?P7ER~Dv2Qh-hP5({;X_?E3)-(m zE13h$-Fj>837OQ(VNu^EO>;77iX+7R19cLK^2)Q#VCs-_nc#_o2`E5Omoq+biq;)+ zx6$gm5|vR!$f^W8;{9(IKs6RPGn>T%6&wIfxw_< zTmQ^8Y0u*F42R9=Nqusv_=7=|?83k=3Z0c$Q{5vz^9*>0E)~!xkzHs3LCf1x3pv}1 zx)+2lKU>C-iRSt{<4O&kh?Czig^mr9Np7#rOLIaW?i{#_h5hKG$8+2Vlf%BY9LDas z1G%_(-+PKKoF3@Rwc!Q_)CDdvKoahE4 zs`4#cVy+R$Zc+(EY#7R3plt_a!!5jXe*H-09Ek{xyeUy@cpN#wY^*U_9VGl1LeX)V zqNML-quHoU%whRtz?@4Oj6ef)gsl>b7<`Rx#yFO>Z1@BNEQrgCPLe2bnF6CiTs!i3 zyyZ?-r8ps!yLB&p$zfkp-?O>Bw@N4&l4awRvi~gDvZGoDLVT~-Q%n1N)^NkdEmo6O zb%XA#(SKX0keAF+OvjzW+W?Tmlgiy0bczp43Y|=MX++(q&nDsB?A9>5%Lf4!J2jZp zvfIIi!U%^eM_SJzkw`tqFY7|0x<);x1z*p}<$4ZUR?jWmv5uFEF3iT|x5~0aW4BoK zuLu`i=KX#U`5rm`fHhvRhmB(@+|gnej@n+Ge5L*#`oC<6BD1B}lp=q#O2w?q^rNdQ z?3=O?pKeDHbBQ%Liq>Wyn-q-p;}xCR0(MLT29D<%<;WxUbX7zKiG__1nw6iy75ci& z33iv>i8$Z8q9byv(Hgy7R@Z$~h%#z^t=8)?H&^TNsQ2ykcFTJ@*0vQl`&k~% zdEvFKR5S--NmZ6xvp(9==VJHFW-}|R56mnws}?QF7%T2`HJcY-x@hBHzJIWA@Rwn! zXeimO$q5~|rO7N<4X(2W^cK|Da@%Rf_#5j*EEt%$WnyvD3@!`eUe99RGsXPwIAtN_ zye#EN103yPV!7UpJI#3p`C2uxLLh03Mk<>N-@Tbb_Um&Jdpf#1dTtuPa9%>0llxb4 zT{t-np-`hxmph8>%@}3HO~co%5Xcxlm5^+EpLxh%Gf=Kvmb%Lm)Tdtm;7Qy_fQB+| z#Yz(h8N#i;t7i=T_7Prfk=7!I{n{>i%laU8zsxds09L0RRuz`kaKj5+Ccv#Iv@sT( zmD-C9DTB7bZ`q*S0_Wr|7ZUQ^Ok&GiNKLxtt-oDjb z%y$0;hI6@N<@r?Z6x2O_t2^exx7@8PU~=dr9yW<*{bW}MX6wXG9QmQ5B(t_Mx4G6C zNwJL_+{^jY#XaiuY4hwsuSf>fLfr z{0ap7Ms6q4&j9GB9=xke5AU+tJIi}Xiye1n;{xYs(jx6uD>&rj43!(1a+u09Y^zPN zv4BKZyxC=2tZbfl<$1a^dJKSt@$Ovw4hB6ct6eyWm`rp>Qy0yCGbW~wQ&x(CHV+<2 z^i}H^cht-7uq;Zdvp-sR?zuom)2G6b17b9dk69@vY(;S3t4;se$HhC+8qlpK#Y;7VY zQs)116T#w`{#Mw`lGoh6*yL58FFJWyELJMIR9_)sseCc1N^=*Rq~#ziPc3T!vQWP3 z@)|?Drpw<(Er{`3)72~sQR1a|Tx=H7?F;AM%IzI%rMvxLH80D}1=gJ2FAFf}9hSAN zzKE`11%AmWZ#7@cy08A3e{0r%v&r9hx-Q)hN}Y0$c((ck&Szg_8<`o`3?$1Lw6$X5 zW05&aHLUHyfR7W;a!D5bp~ z1tgAw%pY9ki=D>Uv(kkr!uq@Lb3_&ob6q#zY-TLBT_tRxUNMptp(^EidIxg!78lJt zd1J@-+^G{2T^N_qiDdA>fJ$FxAIXx+py&HmkhR4;=EKho%IQWIG3ya=U&zfl8}#|u zGA8z{?F`%RHJuUbrTv;BU8MtzSQ6SKS6kS8a9JAjmF#FyU$$ptwOC{Z*N(~Z zT3Ys8N9Gi7vQHqGcQobXo)ydWvQ**$^XTZxfuf@_O<&}(g>1qe$+gn-Rz;rKxBNa+jq(f4?tR#NI*I9q1TyrE!gFacHwvD_hR`3b$}@#M%bwrI9xk4E>5x zGQ3Gkv=6vX-3ouO2NOFrMXq2-S8SKfp=GhxA>c}}SFMYWeT7>Zd#J_XuEsv&EcRt@ zE;jZR{xJ4sC*Ec3nJ+6vo$418Z*8K=&Rle?)rUQhCxc~9`n#Iz$n1(V%{WU_bNymd zv>X8@r`ldQEm_#n!MkapVh4Ista`-?ooym^&0OViJ#6#QW+(0$L!(uZ1SX_w1A*>s z0N>ECtG&c112KTz*4QV;CXcT;k7TiRg*-8Y1Kk%kgw237RDWlK_?5V}x)W=LU=?pO zzwTJcFI>5{iap%8wu%m}W{aWUA8+hTf{$Cv^_8veVKkb^Efr6jjx#Otl(6eVtJ;<_t8oh$n_FqbG_kKn!0r?Hbk zzy4!jmvZAe^)6VHi|%-B_aKfNV2_5}*G+pk@)<9-5R0Vfx?F}4Us3FE3ra^nehVFg z{A>cZ!S}SuZ~xhD+$)U>d;8_fIo;#nd6o(_Yc*A>&p^WFG}EPrvtf*&o=+xX7nvX1x>i>RO%j??-6{((;Ti0XuV z#k?x+*1|4U+#-%+7`Si?Hj_XFL{9=|-!~cP=A5nUal<@uAHSB2c;fo)GGy=a^@eyv z79U8GYa@|tr*K@P7hk%Nvpd*DTUOwgA>x5qG%%95xY(e0x@@4myNfBng&ce^2e)$J z^vOUcw*cXM5po|9IE{Sg4Tf?X{i!}t=es3a8@?{W8x8R%*A>W%1*rmfH+7`~KDcDo zm?nq|!r6}0&*H|^>BNVYq;#spj1yEcy#lU*>+Z$5IegM9%MaPv%}mh5Et^&a zDV>=rDgtk@;fJ9yIWOtV76MVxFI3=A6vRxahFGA$Cu~ZCybwv!lAcT8SaPApa3bkh z%UIiasai#KkBVZ8n`2Ro`MDvfSy=Xz4YQ&Kcd!w+Aeo@0m>;>4Q&+Ia8j4Hq7;t)w zwvTt_Gyg!$Jyv_XYDr`1#0?wKtay&hiJr$)&zgv=99wycd4r_`et)Hp-_wwHYYnUo zj%@?(>qQEh9xn)GgIg|K(g2nbk$Ns2E{e%X+*Y3@A~t}?_tY>y6AiGO zh)JXePsJh@YDfETQIgvbDsltKh5GVL%y-5B-v>uV^CWIIQkB>ES(ib4>;o58M-`5* z~{WJ`m8X#?e>SW-*0ex%WK3%66(7>D&)f5D9+Xg<5qp$q>oW6D+WY=dT z-^@@Q-UF_$_>vdCP^BQFNP`$8GgfRz$|~?9PWn24%SW+jYIqhi5?!S>tO8426hk

xP8RWQACBl!L!8ex_+SzC4Vq4{l-yr0A>+GGz?8o@Y}#o;J609LVn`jCr)H4#>^p!#7Q>P z6dTdpFmI$h#6DFsx`;kjTrD#)64EtlQw|S$V=Mx2a_j!=)2=)(qT^sW{Cu!H`%I~^ zVi(^n_pq9=Q^z6#{x$KEZu42qFecvyk{x}1OAz+`VUdEaqIJV8Lw0P0zS-<3x|(Ea zR3;`?JFBv6UX$Tl%Tw9Y$?Y#|U*3tWQgNVSFSwPVe7qoZ%MrA|ZCPl@;_fU8&3w~+ zUi_LyfbD>3X1h#pg~)Nm3_d2TfkAS26{Ccq$tGgMsf2wwl@{E+VI)!rKKf{at$IklaN{#{CGEODtsF_*%%R-ilQA zS2r^3lCwB^DFsRGu9$e`WY_3j_+t<&x>L>sjnswRNuqoBpAlXC7=@25YfME*Wiwk` zxRe6Jjl)@9=>9Q&U&H5!R6E_O%ApD}#vRPDV!N`A4DDnvX_*mi`^pg;jhLT-p7HVZ z9KA)kFva7on5nj#C({Ny2@u=ISl{6cvRA%Yp@kuO1IxTH8Sci|` zp{DX$PWvb}tww9hKMf-N#z1Dxe6i)A zjw4uB$=5z`R5Ug&(Ujh9gr-5?qNZQIHzU{_5vu_&WRhxx7y9yGhlv;!ZgOo^4xrGi zfmke`3-kW;xA#5RtXq5PZtRHvV-u}x>`|v!G@q&^&>Ji~-Beax%L$NQGuMI2Vu zu?uL;35*N;<%#7W#43!BWW~t?h6=N6?L~ZwRxg09*Wdm6%Madgtpk_%$uB06woV+9;-3A(HQiDMr)cK->ZxWC=#(Z?RS_r(28q4HYP!m%fwSV5`q zz!Q&su=&BGg-0GdzM3`jKMQ5*&I6AizC(X;PkT%u+=8nw z2SO}E%qDI(s4L((brusjQnXU#I)2p*^OD(DyfER$ufk;3*3_*#u(s{GgBQ?0bOHU_ zE}(z-0{XXKK)>Mv`gdGF9~rQA0wH5AVBkVYxc@?Fxc@?lh%XvkAPg5u#{IW*qD(ii zW<>)^w)c~2EMzNhjmT`QtzEajK}%_6W0YBsMR;Y+y8U;UWq%v21q@c@y4Tfi>C61+ z7{myBs613O2Ubz9JAe|fvX#06`(wMMx5j5)NNr0L>kb@P(Qw^?gR7{=iFaNuz$@v^ z@wx-INitv)2D*p1%x!w1?j$Bj>u@{@|MvCDqLnq!NK{O)^E=4_(|R32Cs1`oURFRj z0*Wgs*sOqc4=ke;&+4a*@!1zFPGQkoe(<$(Ogfk6^W%aF=RxI5>i7%{mKFLi+DD&> zSuuVcTt5GdO<5|H zG)6yweK5Lk8hCwV0V`5iy~OdfY)%`WJ1-+&F#*j0$O4fpPRWYo$w7%=rf>kCL@ujv zFOFN~Ea++>gK3L}6+zb2(W^We=+FJtx{wR;*|jbN{%vdxA=ehdYnOyj4Xu4OAwXH4 zC-LtihswMc8Z)<*xdD9n?Pb0X{1afh!{;b?e0>N%fZy56L-+)KTki?sQ~0fK4Bc>O)8h(H9uClxD2fyLC34HC5vi=9aEsh@sf8+kL{uAKGA1(9u zgHN}Y`QzYUar}ee@8~G&|1cQIB5CslMhwp}C_G8U(RC7E@@Me3>4liao}1MCFG2s7 zm)3=$gvSydSN_C~5Oz%z41KY}++uM4xv`z{ONl2_M-dFA`Sn`aPs z{Lk=w@jCGAx=^e9E%1$V>q4XQz1N3O)g3}f`3!i+b0G{X!&!Molz#;J+n*0%Ea7qG zUxohVpA2CN{3hQ24u4gj+z=L&Z@K~YU)T_ql+FEsGDGvGpHH|!*~~X8KMnV;7~2q< z6K+xdN$B49;8VJoKyP5MJf~1ipV^Ll{!NayRV1xgm@xTY4Z0l72M53FfDj zAEf!WHUtDg^naMVxFO6Z`t=(t^@o)&xe4aqhJEEu^3sNotBU5Q!L?yyXi%2$ZQmGL zmH!O-$7(l*QldZP^fy6&LU||;_jhd!)87%@|0+2L{?5o(?16vzjbR4N@_i?`>Sfeb zG(apr_S7mr1^wK^8$)Bl&58LIWyz1`jiEE)A?2T@f2|wCsPgZD@9W$c#+A+g38!BL z{b}Xly{M0+jbT>#r@>o?HikLn-=Kc?#;~CLb?Ogn3`@%9e%KV_`wsN0p4%8|m1}QC z8;{J(ftfz{fe%!#3k}MaUPEf$+#6Pw^g?D&Bs`UvpH`OidL8jecux5z;s3F>5Fh3L z1+ID%h3P$&`Bkk<^HngPSH6B9;uESuz496G=C_fb%94KXYz$4xpQ8Ta#xSIu#ZOt{ zH;VWrJe8QAR+jj^fcPamr~HfX@4hc0e#)2Jg7CkD{8Bdm!+T?VX}${PbIJ`cziS%t zRqg_Bei`*iS>pE!;;Z~4)SpCr!OUNKhE?BqL|Nk7SQRD{o=(iqC`){gR)x8Q=as(% z|C>%!g+=8{>kyxZQF$*(@>7}St6)B_d=Jd;LgP@c{Jpn^aAiwXXmGp@+^9TC{imuz zN!j8zq%85PsS4u>PbTK4lqG)KtHMmev&z2={~oxZD$FZO{B|L}%I5!)GhYSswVPx7 zFRMrV>Z?Ldxdgs4kN7*@2Ci2grT#v|AMEq9DdARS*5@s#&m+o{u)pb&bzwsJRq*?2 z*M*sc=MtV*{wtW@gTE!^_wR>$82^P!V|Y%3Z*4^Ts{C2-p(eDc%6~-tqaoy#w;l*# zZ$k);%J+iv7^k%;m%!`ZTo+2p*n${p>(_-P<(~j=JB0Dc`zq6;MfsPZ|6UCChLkTk zi10SA3&V-|5#=28H=kG+#vShhPbxQ4zhzyRQ~oJ(>$%y4hE#PtGzkvRh?sYO|N0%s1C-QHYd5A$B zx{Y951%@@@--iD70gMY1{am8oto$vQzhrn_Xi3adHb84G5B>RTaMfty&kO4Uij4Rx z?u@Ss=B}BiOo1VjJeU>;_u{V#`NHs$znA>fI*~QLgs}@Bs=tW8u)S>VE$}7?IrXYf zz6^{aDdx#nfEyhj05g1a&-58j<9g_~I;Q)b%7@_ajrAzc%I)Ai`%oU0@gvU&{-t|A z4*g4}Fn(74IdIiWAxtaZi!n^q7eiQ7{(b0gnne9n7XMxaVEjz?#J_3OPi5%HlUM$0 z+Mh*zOt?u|>LZ|8x#14f$2U=59d7}*Dz`v?>jLu9?1LNMj`9P;Qvx3b539a~XT+J` z0{sc)S7Clr1L~vlUxRBA=4s{HJCVNoLYP-R2Hy2>5P5?BkvD-CRsS@2^9iH}3KR8> zYn6Wz`d18vkW>B@@b+P}QBHpw^y`)1fc{p#t>5cqy8P>F~_%q#~p71PbmKo%m`jLr?On2Jut=E2v#si}*R-3T||KH5fxGu}||i zfmXa`bYCk;1T899!L2b#}tU;D)6{+EA$Udpnfa=Z{V$H&t{bW1iXC; zb3=~b2VPKad;)VWjqAdq<2%4hj;{b$Lq25q?5RJ@qu1?|)`O2q9UinFw-&R8TRsI5a3+gxJJ(~Xtc*hXx ztK%EMGs@qhKH7_F$TKwG^g-nB4BA)akAt_qhW1hUH^J|l3nHJ<{9k}K&!c^WKFhZ~ zoyu2z2<|N*eU-ltyy+d(FXhjH?+EL|nDSqOs}_--%G*AS`uR5c3+3CuS1yG>`HcR3 zm>iIv%ERDW-a&tn=u=*!dFt*Ko&sOH5%G6?1-M4}PoRHwHQHn4?`%Q%EHx7LS}^0VN}Fu63G=#MCW2Kv{(y*`X9|0Q_y()uu= zeCc;1J$E60mG^>o=g=N2KMk(G0sW8TJ>VJTG3X!2qkVRKGnn!r!~X}+-&T+M>Ua}) zNqG_adk!J}E{W!E{0P$X62wpW0r1X!>jULEx@Y>M$|dOEvi7n5Uito~k)HcD zgjVGrARpQgO3FV6z7>O?QRPhql%J!BkFwR5ab=c&miGx|))&@~NoA`~)5=yK<{Yy= z%qv@cSX90f{$Kav`mp3U2M$|eeA}RZ!%HZ?%G2N-6YE30@}DyNUtAxW5^h%B)C&Dc z)Gy^C`08nt$F0%*9|B+hD%uO>FN3$ttPgWw&ZqvXyIEh*-zW!t7L|Vz`j;QU`p>p# z{%bVfh%r2v?f;*_z3mTUyaHzaN_e{w-h`W#{}JYQmez+6u=jsVS-lVA%I5!+viU!w z{C5n`Q52u;F+4}xz@6Y7kw?hg;L9SL`wa;kj>GcA}56b(&d&V$+ za(n}L$nj0!VaL~jM;+7tm~tE4e-Z7o@{8bIlW3onr@=ch{+$Oiy-wbT_&kjM4b1fZ zI`pq<-VmxUujCr#ns(@)*bo}QKE0cjEj?P4Exk+1mfpk4mfq9K7M>X}!z1$M^H@(% z{q_#{FpKi0{A=J%Z>$fCj&op6R4{zhzaCucnCA1~zk=SzBKltl4^7JT;7y3%keavh zJfdvz8&$UWO(nEc%qIVtQD4X;Ho(`qx4D90D_a&HR}14?};~ zn;4flt^-dyz8yU8xCy-A_;GOc)zN*rR{+;2FMzLHz?jJC?|^=T@;0;`2j2>z(eV** zljCFHPRCD!OUnJQf6XG~C#Sy?`eVvpg8oj7XD1V$N_bA$%G09qe~0~D7;n{F6XQp& z1J^pf9o*o!3Eb%Tad4~S0=QH8fi9#^1IFu4e+TqOmHVK7@Ce#3$49{9j*o$-9X}18 zQT{(+|C&aO*PZ@O=r1Z?^1Vo(qZm)-V*HG260TRa^l4H)2K&37M|>RL3@$l71RiyK zA9&31L*OaL9|BJ+|L<`B$`Q23PJajV7nFY+`t_egd>r2aUUGaK9IlP=qxq-6)ymhO zLHeNo$veIc+@Sm{^-aWsr}9^!zmxq>!XpV!CtguHJHhqJ=fGFJiSnjAL0&+36K+j-RQbQd{Pl04JSkst7U{hmUUP!nWZ8zJaFT(saIrKNm|CJ2+qTcaNaD(zcLH{7+ zjYh{;ft!?%^dSC6AP*$mnedph#J>^oRsJaKUo(XGDZfNMg83H5Rp2@08R&0rM0=d@ zlJeK7e-!QE4KcpPwFx&VU(<^=dU$3_*F{U1trMA`hGNO&^g+TAg{-&4}@f5Ht3H!F|Q{0QXBgi8qzD_eb^Q2s60-}V~h z6UUpu)i=fPd=vV4jNfV+7fw2{$HOQvL|cUp|NOqC5cJ_BQ4}9B&4X zD*puZuUbNVaJ&UPrTnY(|DE+=HsQI1tMf5F;(vgAsr)}-fBP=Tm&%qt!-@Wg^3Fb# zC&;hk2~Q+Eulyv;Uk>?pN%>>oD#)w3Juy7S`Gi}Pe;MXCZNz>RWgG8~D8I(=bYnca zH@YW03VHtK$QGZmgvXU_d^)3S5yZNPe+t(d^(Zv zWWsaGHa@MtCHiOMQ|_~1`%UKfw9zrgr_IXQcvCqWZ#u4f6YY^>8E-n4@up)LZ`MWs zv+<^KHr{mlGTv0q#+#01yy;lRn~r6?sho{BoxY4Wm9z0?!cz&)DO-72RL;hmx5oHo z<4wmh-gGSEO~*3cbS&dd*SjL-5oQ*dR#PDb1P33I7sho{B z6K+j-R5=@ODre(O$1>hj&c>ULWxT1JjW-isNVxW3j88V+RL;hmj%B>5oQ*df%Xm{c z8*e7unedo$Hr`au#+%C7c+;_rH3=vJ?VI@;W%Iv2;f91;m90JKO!UW;w+-bJ^i(}5$wkm%&&A$wJ-0_{@A?5!-{VB-j zj_(AID(`p(;d=$^5eZKwJgaQ-!a~A}30F77_?f(rOE{l!gRqb zFzcA|!kn_n3yTRaC7iz_hS%hUdS#OrxDSQpmrQwq`vJW?TfoDPYr!Lqw}VF=)Bc$9 zhVv)`CG5v>TmznPTnnCZd<}To@s;2i$Fx7IoTvNGVgAW+4S3#hEqKxKHQ*)3SAxTL z#q^+iv|pqAINcw?@|WWpa4z9`gCo0Wf%=Et!9CF zr?LLi7}J|v1FlgH`s9_RJ;D4yJ(&BO?}hpB6z2bwUqe3b=*0L;`P0yU5Av_mG52qk zl|{cSv|RF+ZYg z=jX-}9#^*WbCZevDW}i#b92geelDP$_UoP1%EvIT$@6o$gzFRY4ayQ9Yz}Qvw)1nt ziT;SPou3<1{!j3a=jSGr?fl$~vZddwGtcvLi^>mT-jnC&!u>Hmc7Co#+4Nfz{Yhmz zKNpTh`*wb=S$P`skUT%v31<2F_b5M`rcs|%-_FxbDE}GE^E};DqCf5Qd7f@j+0N5d zzd!o_)jZtKZ4A{9M7HyEIk5LXuWaelqUPni&BHifmGDSnepK}(|C({$D&a|GJ3lwA z{L`4XOcpB_>^i12J~fc&j&?oBJpd7MU!&y>yo zIb}{0zdgr3w3o9p}K!$}ds>VXS|HS^gd!L5QBh zdW7=lz&kpyU(oR;@PzU#^#`zCq5Mza+7i|)68#y++hBfHS=ztnuwJQL`w6V~%_4u4 zkAXM64*6BN6I_M$)oP5H8Q#y6-@xQQ@Y=P_1QeSWFxE$B9*g`l z@bA)>A+I~W1iYZ!3-j-5#Qq`WPlIp4{!AV?^8Ha>`S+l|=_Rb^J|6YAeiHj_C$XNZ zypQ}vtY0a=ADqMfyGCWHKd)dtS6TA&4S1*gWz@A@^B7+#%lTWh7emS)hkH90F`jk2 z89b`|E70GC_F>%d72pZwx2TWyV#@Iq;A!QnK85`>@1T8gycryxi1D@Xql>dhM&!PM%U;U$q{|VF|$2>n6 zj>q(Bf&L9Gs85cs1lK740QDiy)hb(fd9HxvPs+;}(ii+5^wGZw^E^z}tbENV%6kd& zg7PEaO#_e@luv^%A42kDsTQY^rulD9Pa=RD@%B1 z(7!56cxO@ml_k8dqr4~jH6M!MGyNguBk(Ujhx+DtGk8+j@@ql)XJP)j38cT{&EWbE zNB6%){kM>wjyHolmCZfw+h%@$@H5!I5>VciKL*~m5#`)3{L^__I8X98WYA4P4quQc^u<~R>zyb!(g_*7M@XMcq0#* z2tCX@;@4%oU)}?tC~0WI+Z1TW;e=t z$Sl3UJpV|xXIxp*3-|9#B|NQc_wURq+x2diM_J;_`*@VI`*^^<{U26+^KV31;@emi zcz!X^0L9_8#l9%b`?$(fh?crK0M$?oG(F4aT6 zLu1SPY8XDU+{dFlN`2nP1NQmZqO_Idu2 z=KmM;t41;3pXkpk%Y4=tT zukrjK*`5Yv8$a^=AoXp$)~b9G?s2`i6U^{)e9Q6du(IXXsIs{~rfm5&mFQ0^TYk+c zTYk+eXZf`~`Y-dVQz$RWFCctZy^8YUxC%U_{D;ubVemPpY~fo}mif}xFs|Pb-Iw`S z3{Gp6W&ZVb%r`jR1#VP+2kvj4!+ebLPaOo$qkJoyf1}El9+Qdwl(MDAtg@xYoU*0I zd}4ng(O*=y@;Px?jGysj!kw2_>X#DEL!j~Hw?1K>=kxlD%2s}Bc1C?N%WqCu?q^!S z{Fvh{;6~-9`(geq%zr6QfNyO^`E$GpJP!8deNx%de@fZP`>e8+_iw=6pI5__V|U|k zALb=7OcS}b2)<=1%5~KLS^Vvo#<)cF$vJRd`Om@cLAhvjyb0W_d@t%+)ti{NSAMGr zjCd|4`b)~UJqZ1`Q7+fT@CYv<-N1~u$tfeMZ|;w(e(d*guVun0>JmRQk06SBCYK;9 zDtJ-ZPviPaV}oj#I^k048Wn0{_!WRp`$$|k2w zE1R5Ra*(YXEULcAEww7=nA~D=k?GeveabB+Cz;$bq;ibOEki2DnA|d~Z0iVPj=7F7 z4rcw3aXK=8N%bxLSfN-ROpd8fxKY{6Hz`YgH*XBB373>jt{G7_xn@k++#7fLlxs{b zGr4BQ+~c@>sC>_;$u;w;Z*t9I;=bK8YI03ZZ;&fg-?&NH$C#WY@ts2YC+-K8GbBEcTk;8;oMh?IsQMBg$T2MmwbK^J41bwTc(vwZkchs4RXvJ*q7JE zgahOZtIu0dpD7oSMXo{T)vWyXg9y)PyqAXh#zTodEB^|(svhf(iT&0@e^~i%VV>v2M;vbjk1E$Z1pOwgvpC)g9#_5<`c+uR z9IuJt>moN|-!+dBgFK7BOR#?p$u9SWkgLF_+bhjI2fk#YY>r$7=AHiDy;-WiQZ^^+Bd>0dyZ*ho zT^%roNoMm`%*{vU_Yrm@JbC<`z~3*>5S|kLp2FY9A*=A2#2@v)qP&3j&*1OhU59`0 z2p|hv?s>JiHNW3(((qQ`DbTZdJ~q zd87U-%A??I;BH0)59g3QPbmME>eplJLw)0EWsBb;nBje5k2n|d)sZbe)8JazxAdA* z{g|syoBew96}y~y z_GM&?PczutXJ6&RpWBSR0M0)960+H6+fVb;^)Wqo<_1|T&pw#@b1)wyTOc1gEGT#2 zeh{yn_`4J8w>Cs|mPhi_%9Oplet@3WM{^~7@Q!GIUfI%TG2vPSj`qzwWec*Ir)=Tf zZ&J4Kp?X%>=h)tx=Nbpg%hw){;aOCDv(K>{^Uvx7`*zk3^M4`X8l*4vExj8OZpB(5 z{j>NCD_ecx9&)eGJ>q1`FYW>N`rPA9e&l=%e+}01y!m=%bH7>H{4Xh+{ZZv#QTHa5 z{{+8$W|b$D7nR>T6!pg&WBIc7ruN>-^4X$n?adsR>1F9Vulm;Ba8IjmZ^F^Y*4}VW zt8Z`Sz`lKHJyyw!%GSONy}z=(seT}`wKw%(U*9^Ft-f+mn(1x%U8`*6qZN!UDg68o z#q{BxJRe`~dGqn(o;R|^k9*$8mOk9$=HojC_VFD@-{pBy+2T9#SY>>LYx7VrC@{!d^&IsB2WJY?!&r1Cb0hyjW5T`Jdye3nH7xHXD z{-RZqZ+%3S`0rzg7u9oSP&L1<=JRmRKZm!H@Qs^9{XF7Bbbd7KC>E+SJZvB5B~Yh8d98V^y%!HzH#(TQG&8n*6O@guS999 zd<(;?$8x+iOeE=3rQsRDTBm=GYxr|X)AWLxZ%EXCRm$tukWY%@zn6NkRp#8i`_D;z zK=>uzWu42--=t{$p=9CKz;S_phNS#%4ID4|=btp)8j~#kl!nund)lkfbmO?iKi5lq z5dI`Q?Hc~3#Qbp$5BmxKd|kuCxxyndorly;bzsmOUohG(*3hT{pFgxe+CeKx?}YmTcfjQLmC+9JS6UHmpR$Y zAYRzdV%M>Jqs6PgF6q8qz6I&kUy*d%9_EvB_+`o8?Xs88oBsuAKeo%-qgVgWl5X2& zjm@inT*^88P4f2(8h(zW{Bxb;_x7-ml+TAW{2cfA=l_!Y-7b6Vy!wBY^xqyh&hpQI zhI1lu=K)QJxy0Z1slW3{Ijlpw!~FUq&3EfZego;qcAIBr_;8Jo&(oR?+-u~YCpA2r ztM(7`pYFdG?KhuW2sCFt2(Kt z9k9%F%WL?rRmVQB?pG(}@Q~y?)-uGsvd_P${&HT{KW8+)>A2`Cnx5SI=AS1uoO6jg zAC>wAf0J_cZ(*6?AJu%foc<+se^Km}eRx{k;o6CR?vwI{{7uZ~P`>H@KdJlHoaNR0 zOj15OH63_IyMOj-I!q<*w`w}`4uAhVig?oB8TI!z)%=vki+8a5=dYw5;%?1E{W1;b zY!aStsrgcp4ig9`{rz|9?{(_QSEZccY--}p{TlwMME!jl-})pxpGLmY{jFNwyfxg+ z>7$grZwOap@BU>2b}y&Tn_7=@iBs>@ay53O(ngoGH(2{jyr|ZA%_Q!8L+fK}qW(+j z4)2op&u;a%_A0L$!o%u*OQQb!TEBS5ynpUi^`*R5#rmC=H{J>FpI-nlo%>bMs_}!G z@4VyPKk+-^SBLLcMQbLW)cEp_cmK3$c!rYjpVRU=ZUsjzJ+I|qEHVF84bQ~&-gV3~ zsym}ee!ZjWyz|{Zc?~D;a`(@VYkeO%X7|rST3;3t^_R6ient&jb^R&L z$JxYuwYtx{+x>G+!_!z6u|@kkwcPTqb^qL<;o+TV{`ntT-gtMqf9}-s)|m6E=wp#? zED!%#l`Z^V(DckF=D(`$Hzn%VSa=fkk7+qvNYpp0`P}WH;`xHQ&%4Y0!}&>$2&NMC zD`B4D|NqpmBp2R4rS6O;=HJou=iTQ1iQ^TVVN1&A3ouXjIcLYmn)Sa_cWRUJ`8W*F z{5^^JZ)!gBPH+G0M*7ga$&cp#)0+Og!`nYUq4And)Z4AT?DnRyM?ll9>4r-6H-Yr` z4GpI?$4gpHMiTSSNx(4PxUtfmEgBx)&F!DhYrW&0-u`(&-QnHV{<%)eKkvZy&sVg6 z;oaQ+`GTfrbK=f}h!5lSO^w$9weTjIW;fM5$yc6woAi_`M-xc&7Vxn zfA4qDqj-n4dMQ6YtL40OlUK$12=a^W468fV-Cm~oSd+BpM>YJsv)Vtuhy0>DpHX*g z9P+IC%R8t2a~}CZ^PD&4W6co1b;R)Vj%ojJuOQ8TMa^5k{Fdem@0jyXkCq?aJ?)<= zEf2hd+CN=zpZ@Z0JOAv|^vvz^s@NZ-`NF%N{qt3=FTB&)KR>GO4<+h+|DHG zySBu5jV9&iteWRtzW(_eHP1VC{qtEZKXZxte$B_}MEwCZ&$~DMGotZoO2#v_n*KE= zD5#}gZ6A2YtAECj4y^AlsiHNz9qN8_V*W2Rof{MN6Xt%>zyGeLLqjrddDY^ZxbxW> z1_bhN65lT(of*!rCE@%IO&{K^>YwK|oV-)jKmQHkq&u6neY0WH$JO7K#NW?Z_!IRX z)bR68QvZC@>QSP8P{TQssGnAUdDp0a=B!>M?c|)+>)E6oKBwWFOVr=iaz2u@KXG0U z@=l`Or~P&HJw7y8lhbhK67@H%nnhy03Rhr*x^*2%f1ueG^s5^CP?U${cf4tJ2@7DC>olO4u zUF&C?y(+#Tr|GuzSf%=RZD6c04pjFSwBG!VmMh*dphKWaX5KZ}31X*nE9)bG*owA<^O{IglZ$va#8 z^E&d2{yv-dd!L4rceeQFl!mAEDX)qL^v@w*wqhODo>?hR z_y#QM;g)c1Xi|-O{rzK6zdEy_)dg{)J5qSXWT%?{T{yipHcq0_s_Hn_19geCsN_`r zH;^t{T=*?yU&9N-Gojw)1;FSa_S!ENtr%U zETCrQ58$2ZmZI8>hF^yPrrWsMw|x8^Rj*CdCskdQvzf|ABs^xi9G>@x`W0q8OV8Uy zeb+MepVjbJtB!^LGbo1)zm*_U$7h5j{7Y)y!haK(=A~J|yP3ZW?HJXiT0-6O?Uxar zEg=V$_yFZ;MLpVrdST(Q--l5|sE!|bO#O9a6xA&yOnnL&PW4=3{yGGJ>iIj_LPKKyZ;|0N-O*fHmt zxId2%Uc*IFe5L)oCJ>qS zZNCXw%uD+n!_xu9ddIZi?3ng>MurdVKS}f31ck-CW18og7CvTvKH)}fTBy(TwF*mlkhv1@H?iy%~Q}k^&54*!R$9T()E}>XP{X9V40==`9LK%I;ML=j_Kc=W7_B0 zQ$BbV|4q&}Zg%>#KlWiUo|(4+2+fOrOIe?6@|wBVsPdSZpG&y(kxKj3Pge4H!VOPV z>YIFJ{>>-)Hh!W$$1l}7-gpm~YBruQo_FI1rdNv&NNJYLGrfGsOz%m@jQ^rznjd!K z37Q{wO!L}&ihB%Sv$&3RbM+&q3@r(Nld|bs{JvdQ=Q97bc@+K#Je_dl>%JF&dtB!}jvyPtyzv1|!;I|!fydMhX z_)xg5HhfXL%d=~kv)iLw8+cEoxA;%n_Kkv8|JnER^ z`4=5iKAUjN`u?(G*5_%*EdQ@L?gq~}W_f!v;l+gCNw~T-rYGY|``Z)FCA=@;hJ=qM z+??=J33nzuknnKApGgKPz5@KP)2FDY-M#2v1MYVEa4rla z{9MA%C;Z8TUr6}HgkMVdWych~UUf`S>UGELTi$d`QR!{R9ExpZB>0OzCe?PwBj6hx ze*%2S@sEJ5f2Mt=XN%J(i;R!o|G%~SkBuWe3pl>s9x#-E0;<52qcY`a=OE2_H+C|C zv`vp|nf5|4aKHd*H;%o@m^k)gJJ)FmBB&=cEkVj3l^8@QQCq|a1t}6m3?fKTb$<*Z z6%i_83IPlh7$88PMV&t)mFJyzp7HLt-dz7+Bxl~w`@HYG^StxJ&e}VxadS^Ji#mq& z`@6l!2XF{Sa11AK3TJQ*7jOwzuwxRJrOhAKzYEv6zW+w;qkRB} zu=)MQ_;@j#z$u);Ib6UcT*3PKs;M@o#%%NYs@jD;*oOl+gd;eH6F7x4IEM?kge%zo zo$A=}m)FhB(&i6)un*hchwt?d5s%;)PT&;I;2bXC60Tt9YbNuZh3((@@8#nm?!y5b z!sdO^X3_bL;RH_M49?*KF5wEcf9JlpKjwYe>=*M z`hF+vufK0nM`$0z_V4ia#!C^;;2bXC60Tt9>n8J^h4uYRy8j;HJ{-Uy9KkW1z$u); zIb6UG$83JS*I)dae2mR=49udQgXiIsu)fb;`-fw3^Z$nkj^PBpHD>ewjXSWuFVc)> zev~c8;>H#1G_N;m`&rn9J=li>IE3}}P8}~sJb_aPzfJ?Z7o#yp$-5>k+oMZVT?!i7Bz#*)^&)4x{#1lA$GdPC}xP&X%Xx0UW{+ z9K#8m!Wo>y1zf@vtgq*5zWTmswcEUYuh!p>sC~o(ID{iOh7&l2GdPC}xP&WMe;=Xw z%)Vyw_`0wM`)~ksB;Q}t<3U+3ZKkULD?85;Z!Vw(937o@ZQ?7==9z#$yLF`U3DoWVIBzTZXj^$`!?5RTv&PT&;I;2bXC60Tt9jmRH%VGs7<05+e6 zXcnEX2#(sB;Q}t<3fAWc>Hf{Sll$w!9_+&b9KsPC!wHguM3wy8+2XF{Sa11AK3TJQ*7jOwzuybfK-&xp&J=li>ID{iOh7&l2 zGdPC}xP&X%c@y%7UD$(tIDkV~pFgJOSB$tmZ%pGU;u)O71zf@v>>Nh^unX&R%yj>J z!~-~lBRGZ=IE6DfhYPrbE7*Ak`NJ;k!9EU zJ;e37Z5j^{58()oVSV14ZZAbVgLAlmOSpoa9`c7>*n@pIfI~QfV>p3RID>PzfJ?Z7 zoj&r1UD$(tIDkVqf@3&=Q#gZjxPVKzf}JDCA9i66*7uj|`5GXu?>EID{iOh7&l2 zGdPC}xP&X%Ig0#Y7uM%B>hbmw58x1v;22Ke6wcrrF5nWbVCNX}hh5l%eK>$aSf59! z^A{tYz$u);Ib6UcT*3Oh2;HAqZ*o5L`4JlT5clB#4&exn;RH_M49?*KF5wDxj!))0 z3%jrf`)~ksB;Q}t<3U=Pssh9Tn!!GQ>J{-Uy9KkW1z$u);Ib6UcT*1z>$RBoL z5BA{z*5_^O{6>h!Z~~`r2Ip`Amv99;-;exZ7xrKu4&V@u;22Ke6wcrrF5nWbVCOmH z54*4j`)~k$aID%t1fm1kx zbGU#@xPqM@M*gr1d$4}Kk^a08ARfZ{IY!z(Mm&L2ID>PzfJ?Z7ogYE|unT*z4+n4v zM{o@5=PK#^q=;v54i|62zTC#{NXux9v=TZ3G@A93Gp-V_~%EM_E!+U2H${h!FS+$@Gkri z9{+rZ`upEtaz5tZ@y~-W?N1`U1fPLN@D=zPd;`7(-+}MJyYNG}b7nH%gYXy_C--hqP z_u&WdBly4y@`n$>C*V`?X?PvJ3}1z>!=D`Ux67`+4BsE~jKm+nkKhBVd-+ogxDtsNj3EzhA!uR0^ z@FV!ZIphx?f=|Gw;M4Frd>Ot9Ux#nPx8b|+efRZ0Ujsh{FTl^iFTktt4*U}Q5%?4E zC*haj&%mF9zW_gR0r|sE!3*$n@C)!NyaT@kUmx@HvTHZt+wfiZKKuZF1Rq%6%l~;P zJ_#R!Pr#?()9^Zc8NLc%hi}5S;k)pC_yPO~K5!BF!-wD#@G1B-ybfQ6ufo^ioA7P; zE_@$;06&6@?q7HBcmJll+x`3QKXm`G`!C&p?fzHyVfVkgf7|`5?*Dc_-~G4l|8)Po z`?>BvcgyYR%%^AmeC97^{&MECGoPCI)0yAy{!Z6_{yoc|>b~6llkSTz&HTa#;+c)k&dO-8 zwesTN+;C%O>;0X>Tf_CkJHu$lmY#j#9fu8u8_Q?chl8!1ozCjU_F%NRwbR+zTHe@R zU)~uG);BjVTpA6QH&zFiMysag-1_GG4i98Gcd>4`a$!*STVA;^+?far2OGnk_ib)n z7z|&OUD$4eW)p*pn;UC8n_F$=>Sn#^!MU~do#9q9a2u69S{V*T7j_1#TbrY{dTo2~ zf#KHXU~R8zWqEz&QoZl>Fp}3mCZg@Jdgiiytq+DfVYs^0+5aptP0YzBgW1;W3u_zaHal|6 zCQoHOdu8JF0-D}nB^=5{VlJV{b9}6GeW;sL-&9M(`s5gEVlFb1^@XuIb3N#_D%tPF z53jGkcyS=JvbDW-UTy^KDPpH*w7j)FlxjWxleKzuCu^HSK3Tc9U2`^l*=ENp+pUgQ z>PGkK2J34p!wuQHdSio~OLC#KcQSi5p*qfkS zE%u%`+}@Gf-r9CJwBhE$-7h?h%so+(s|Ot|zkhvm*>~n z3&*rZwxiv9QnHujPr-OqfQRLT|6;h=%&MbbQdSYvefDg3M~aE%j_krp$KJ zg4a|?uO=e9ET#SLNPCm#y~5;q&Ey?3ljjZURqt4{UbO3lhP}4>xNRqKE%a?kX3f^f zWVNBT)N6x_ZLlr%Y)R&_jkTp-TRNhfw*@&fwW41aWK!Giwj?uXYuZAusgbEX_6pO} zbd|ZDf2F3!I%^}j?;mX@^r)FoISuQzOiN8&A8ov7*K$y8+*}uJ$#m&Py)-x*)S(ug$q# z7i7-swVb~7+T203MO)LC(&I1jy{7Z+W~B7^PI@F3%`P4v)GL{j=0Mo>vBrybE&FZj zW)CHL> zZQGO5{4&tX<1lZ@gev=A_j6o~NZ_ zwjgt)HGNx>+lYpmf^4oW_1aQ@K|A(rNe)R}BU7pyumzdXCScd~wQqJ%CbSNi^U!vY zp`^6`%=VjHdv#NpVcSK%PhJpX1g7EUQ0bGJ-$=BFZI03K|R*1OLBhM zf|)ZdEoiJMNX(XGrnF64=(nYwEy?WFjpSQYy_UJsPJJm&`QQ6t3E7{cd$zUAmo3O$ zRQub4xp1|nFQvz4E)DFDw0z~^unsui%)~KUkZjx1QH?bPb3?1EGi`qQ9L?(-*`Z{P>VjOgwnFBrF31ekYco|gVy7VP*Bn+|W3fT_{`2b+dxW&igZf2kSwo;GaSYyXCw_e%f$ z#xLJ&$G_1uG~+)ZU)oe*Q^t?qV#l9r8k+IV9BY3a|4mcI zkDKw&H2rm@{nbxT89&`;eA8F^>-h7soBPdw*^ED@12t>yuhoa7|9fUkPVvSKdnEm)ja! h;J$uP^0y;RHXNC6EVAh5-k5&xmVb17b1jP{*(1hy{Xl^yC|>Qz0~DC z){-Qz7yp+h>N`m`-xB2Ce2>dfZF)fI?bW9H0ZlDQQ?SoRhn6UP%Y#D|!OgRVs)GG< z^qnLdQv>By>yjgc71C4ECn==|q;ixu|IXE? zp6uUO|OqP(rbTJrL*!)jDu^9-e$?@v2>)cV)^K2 z?d8NQvG($$Gsm|+l&0R)u*KUg7d^c!*um}Ey1iogC6_;IzvsNfO5#syzsdQU8p(k_ zn%q$y=ldh8oiCSTdZFE>o{rE??DyJ^&=2Z)p31sh((_)?@a=K9TM)Z16NKOVzN?&^ zqjAvxKBY4LXAK!f`5%jpcEYGLL>K+PfB5_`!fvjII3G5R;{TVZ-j-zO53GKd139;e zj{VqJ7L~|fo)SX-RzYa%UoJl{ca?nWcTw)5U0lzlVtVE`Nn-ws-fVn0-wz~%F1Odz zXs`a4hV+RQgQc~zhCU>0?LwoI_B4#A?bgdAxnfT8IpwSFo$|l5gX`cVXy1 z@|zx@Z9eGo{y?{>&GxiuvLN&RJ%Y2RhIxVdj2~L0xSem(s`RpOp{!r5A}; zm+OB@^yApiq8(_@=EYopZ2rvk$L7mif6VjfPw4N-LwBpaTz`x|*B|50^=FIt$Jw9a zJT#vEFph0JNBc}Sx^5pEx4Hgwg#6Nf3bHjmDk5hh|^Q?TT?__Ety~cK9Kal4b6+jLfzsT_s(K$Khh#sdLzYwpk zOposibksv(d^SaSu;;PjbUB)^V@333slJn;oIEDy_~dD_v91bSo@ocNEBde*JMtk< z$;$h@-KgEocV_E*ZoXPu0*Uah}a{ z2NCDt0(bmNS2}L@vK54SE#4vywsxVff_-sUIe80kO1y7k-L-XZ4D9~pNQ_5aM{tWu0aOs_e)W1JP`E=ykIzV;yG9uZ%S zBKI?mrzA!`o@z6?9#5IxbMchvlm5jxxI_HJQ^8NCCa)AdPJ4`qql*2C@ly1A{OxqA z&&N%R)E@eLvEVq{eL}pt8jVB7&s^o>$Ilb=diM&~<>m5m(P>JLaS`P#K8o>B^k?L> zcx#+;?pB?;8p)Z9do&Ly{<63y*Pg{i<7{t4+*7cJ?&D*8qxMF`H}vmF$uYk6M#eRT z_DWeC^8wXr_Aoz-aa5yr4mFNx-?rcG=i00L75O!>KF?75as7(>U|m&NY9aX!et*#Bxo1H>vtx08(e2+7 ziimi5_%$y$iZnD@C(kyikyR$_E9} zOP|39hCVL1GUz9jf92!WrE8T-y>?f|ermPg z%Qm~(KGJ@1w3i19>*k;plPpFT`4$5 zd!}da=O}g<{127yzeL~G?i9hy4jV*~o(@?Y6YbFN={b8u`OHs|?-eSCd@mPlEZ>m% zyURD49c)}=&$E2|HL8#J!2GA9TdmeF#=Bi^Up?v}JR7C^6Qsj&42+yy+D}L^mb~${^;ZBD&hc-{a*XQ)z4!1enD(L-b+0r+( zLv-PJ+*Zmztn{7_=o`2oJTK#UpV_Oh&OBV0=f1n;-a(TuJU^RsPElW7NsHNV%Y%a^ zfA5{4f5i1QwO7%gGuz~epjH^&-1jwUE?3Y(l+B_@hfpy2$ zJDli3m9NkH$xB6V`RL$-f^oki_A9P)v47-m6(6+qGna4ub-AmwV|tAB=Jr|gd@1#e z(x0Ix8}+BZTdkuH*W31rkxg-ZXzwm9R7$aYv@`absQk6B8}Dd@umIeUK9b8)DD?TjGrmX8lUEI!IV-}uY=mOTbd zuZ)iY(LnPX{BD-*V^kC7LEG>8xborumY~}!#a{U5NWUtK#}RgMJ;ZU}wE3Pej-tP| zuW72PUZC!i^_*7s>(QSZ+G%@LT-t94{>yXhZK5gvW=o$H=Aqc{x*rajKjEi$i;w&P z!CZd6-&OKWPvad=4gD%f-miABi}}6t{Xl8D+^*SkuDIW_`DMYL_|d7x=YEYp9U;15 zd*$#vDCC!p7q2dF=eX#v#rk8r{jUl9+~0mu*xLDlZcqI_dQQ@>l-&N#+aOCZo}{0O z*R;>`G4YKd=cZi#Bf@pLoWy_0dePLU^;^%=ZUQcj?R1qBtrSywXB75z<_A3^uj#vY ze&KoA{P29NJ)Q6$l-KjLPYAMa5cp?g&(lJ@J0tLO|JWzKG5TZkhwI($mBjD;nbLok zsB9f)V3FccEYP=W5Yzrg!>f zvxNpk!d%|Gs6Emt+<}M*?fas`T1(E<<{%Z_LsK%ycFxB{0qd( zy2Sdzx^b?)t)FuQ*$1*UjsBe@dW`<%$CIsL;xG0u_A9m@$5U)Kdk!}vdk$y*j~t(} z`nKuY_UX(X0@$uah<--2Qst)w5`43_Q!4u zCD*||pQ9gndCpQDy4+s%=W;7TdW>tM{o;LI|La0N&+A?(j5vjQM|nm{E2xXKYfn$P6o7`v}3@)HmAIsa3F^>|=tkLY^5Fm_yfu<>df@3FtJ|LsZ1#z`Z) zZ|NKClU(TA)`8d`;(1G7TN+>d8ui7vvH7Oo$8ogB=1HNxC|8s-#<@M6A^s#DksJpT z-?mA9@85{{Hp(?Z4)=?mN@#a&c|_c6e(UyDd}sC_CGKtYxOcJnk2h4m4;c~v+Ik%C zzwif}F=G97f63y@t?J(|F}}1rX8a*PUmq~O?7v)6;@=);Mtft|F#m^hchOFPneXEL zQn2F~ai;rGY$w(q8Nd^^dd{&zTEJ>I-eDUHSr`ne^S|41mE z%}=Ann>WL=IJVPOPJSPHO0UOd)EDA2k28_i^xvBn;>|S1o6Y}AZH|aHJzk$3pC6XT z9dEX&KG*-qcyonvbMa=u4skq3JJ7G;ac5eHJJT@Vbj7$c4RK_9+We1dCl_}HJ^1{T z>sMKPtZO#n#;{YqUnAqqgYVbyxHB!pooR?0bN%wTv-xkVU-h`tvRHJz@j;o?Qqu=J@&I_onwWplLo#(6mgNQft z@;#xlx?H}g##S~}id1(^oA;y#G)BR#ZyjiS2_BZyQ`k2p|pZxh|>_7F+we))2 zdA8_r`rmHx>N?nd#`Y&xt#}E!juD1DHV$I^$#^(H>Eo2=7vj}*u<~T_r_Y=CL5x3j z-izm@VLt_V6pxNmo>Ah?@s7``TH#zt+2hT-jh23Fyu|ou481(7@g~nz?S8Ahvj5dc z(iHbc+bhX5Nfy`t7+=Kwtged1>AB~uhqf=DRYSuM%FU4q4WeSBrlMY_71 zJ{|Z&KQg(xn{1zq=L$QNzrCvOk@e;J^*hSvxrRmDJpX=Jbni)Fp6aNGs$acl1$_1i zzMu2_Bvnf9MIoK|TXD$Q?Wy(W>?_VnOd~G8_V4$K6S&8r&1ujBPFw%ip5*I7nye;$ zN>`d}1h#Ho9DWx?J2#2H-)5`emypwWUbRl?y(fftVPh&PnRHozFT5ncrpaC|KF>LR zj@YQrW^L;0wCB}N#^>qoKS#J7XZ4o@e|*mVl|ZMlpEt}Y87uck4~w(+x}hH!yfZvU z@Ot$8$@H=6!SLL4?a`s%>+c;L6#ww&QiI=G*{#&1^D7SH?^td)r*xMxu$$e7t(qDj z^btyjHVAET6|_NU^FU~W(6;VD8-$+Vj<4MN{1CS+b-O^@dax2ZaFu&s8utB{y8m7MvEWBnyC3E5d!AAO+O?LV zeUQs6dhAH8eD<~0q+vXx7tUM!-8L!<2I^+40{xwF&=RH?YPlr+_2DwUCuMPC(nZYk6A07C& ztPM2x)jN~|9md7X;D5y1HKj*C=J#^;Jc_vXF{Q6x8{$6JYb#GX=CM&O@86qRlG1YV zGfzJ(=<9`^Z<~ZbYZs_&Jtwny0=UQN-3|vF?h=gpihi{IqoF?bgUn9IRdaqT-#aTj zcgDYM++=d!J7n{P%T;3iwsu(`tY18b9>{oH!o) zZ8qk4M3S7QdW!NE+s%!m?W(EKIN`Z}u*aHV?Om~DbMX81n@0EN1C1yAucjI&`+OhA zRj-dD@~z$CI2t)l60?8wYxK8Y^&Uk3ZDezPW1*ER>zn(`#o_)UoX?oJvL#7=s`TjZ zUoMGKJT~}6LBCB&*7prroLkhl&wtm(_1N|QcI@?Hl`ryVeo-#nT+g3i_Yk7JzO$qK znJ?B_y35bJP!$c_~v^)qMp?04u{q<>1|F6G@O^R z`Lpnxzdqjt`7^s*XVuv}J~YJr#f(5R-|rL_e@El?I^#h0?>{G$A308wKUEI*HFFPg z9NF`kOkUH*2)T~Kj~-I}^#4J@!tZ3ttC~W5S4dAu4{=5*nXhsiL;anrN=Yi3`uYS5 z~HeKwM*&n%Ox&m^V3ZKITve725^B43C@ zOCe6p)o1=ieOnvUXY>0g_1U_Bd^S_&>Qgo7FRW8rN?{&=9#A@Try%rhr)@ky?{T^! z2))9HF%BdBH?_Y-#C0&V^bZGIE)C!pi~N{7lpw|RNZ(|(b z_W|VFMZVR$GBr~7D^~9)_bXPP^XY!Y+RNRqn7q0B73+yM0dyMfl`N{Dfr}6uxT@q}#AB>ETyx!)`cZT?Om7nit z9GTsTeRnxNkPTuI^yZezQLJmqEVN$9YOzVEY)uAD@*E;NWc)7!64wpErI6Ti`r^AH~Q->W6P2K~o->dEq^WORg!~H;Uz2=Pdd>xK{H8J=Ve*c*AqaP6uKPJ#D&Lbmr4WH`d3~x%-OIe(&(K^@H|oeAAw-H?%ij?ZoqF z@i_(Ue#qKC^XU%?j?wPydj4p?KY5xZ0e?DI-+Es3w9PlPAL7KAo<4oH@}nHN-#dhL z*!7W#vxi-kU8$Y=cx`6auTRXO)Net+_GD!RSA@A-ng+4JvxCRyDM`*tdS(V6?c zA{d|FHEuWWpCj!N{WCtVEgVj?@t5|Qoh?% zMwja)`(5%l$_-FDMn{QN0!idwx?PU-H_z?)l|Hewlo;pXW~~16BZ~E%%4}#Tf4)ui1lrSkpj^!#sZ{ag~Z^<8bn=Mi$%O?d`Yq z+bo>LD{H-;&&PQ>%Fll7ZmV~AKVm&iu^+^F#y9!h-tKh)PVBbl3~g~g#@jzC+m8us z6MEn8{u1oFWAa+BXL!3&f7!Xyto`eP9vkSpQGX}3Z_{%|-tQOMjq_hqNasA}oFE5w zH9K)%u~#YWX)+TqsVi-s1Zz8O z3GxjMVgH(F;A4WEyR~r!{ixH{9`xg)IsabAi%hfAOP*qJgQyAa}vf zV*mQ@6c_$nb-Nlj^`%Np7P>tqc>S5)qd)On)yB2omzLS5Z&ks#pWb_6crLiIqSPei zeF&!a?0(ut0rTvIq2JC|?tM+T|6lqNE0;jaF3HMeMyI{c^Ljds?p$io267vjbi{Kz zlLLR!yTaw{HimL7|~3U+@!t-*1vc|HU5^ zC$zeqK9|iO=Z138UJb@mHtxOr&NyDV-!^+SDAyL}7x$C3aaAn;5a%oH7qg!{=>2S6@9z-}bnCSZ=Giz;O(@Q@JpcQF z+UvP9=&4cs*fsq8tBTl_-Jh15Y-VJh*{clTQx5ky{IMYKGZjdf&yM4kR*?Gy=DTi7 z&cDyp?B;gR`wDi8qo9|zqP%WL?eC!}yAQlrFniy?J>GtI(+Z`xcQ-8u==X8KKJnbf zgW-OkeSn(yn7^!F8_S}Gz1PwFoqX$OF5mj=cB;0RDD=NjKkKc{la$Z%r_iJIx8eIE z`l}{aynoJq@6cXN9#KwFPj$P6{i5-|Uutkb^|_w2-(~jr`$Sovl|BC7WnOLU#2I0K z!Q~urZaucwb8V8U1oKCyAmuF1bv?^Y9ZF{&GD`u?kMJ{S-Yd0D&r9t0n2(DOep|1+ ze2Sf>E4}Dvh5PFfcGzA~sZ1~Y9y9YZlZX9-&nO>%dQ33Nne!KGm;9ZcZ}R8z^Kw=x zZ~ZFDS+uk3ZLIf%eqHUMM_UKIyv+$p_jPo{?6UFGn*!b5l;)IL?r z{?Q&m&imTRMSWqtsHdB}aXpUh$8wyryh`PZ`pEfxuD{Re`=Nd+Igo3wV6H#5Uz9U!fzP*%LmiH^*o9QMvvbKmA{*ddJy+duAzq@BdN7 z{_{Sg6O~W@!?@Ze%K9}RNPD)PjkCQcR7RJ#H)6cx-k&7>Wb-rQ#q>A6c1E5DF81r0 zzBdUym_33VW4!nAV(Vr${}aFMRtod#PXw921f*A6*GInpF@e8L&&#YF>)+$zXFeOY z{9M`s{A=SXH@`k5zTEt4ewWM7%cuF* zBi04C&uH&`{DRtR+`s?w>+(tJ-}bV;>+9Vp>oVg(>vHKVUzZ&Bno1{5==i7f4*V|G>?J+)b>rZ$GsL~tFAJ5@> zyF~5g=H>tD>#glW=hlu&qD zL5ok?yX`$`P3_&`y~%OD?drDsnB4DX!u`VbZd04yXEfUSHP-#K#gv8huI*s&i6s;H!Sfx+h8h5C0C*Y9k-?^dzwey|1m z&~@UF?yzsRc}8-c=ofV)ueJ1R0}YeyltnwTUOsI3_lEO#(0xwd?QomJtq!XWH#uD6 z@LGr64lj4O%%QCV)L(JhXdZEMAVTa(Vhg?4Yzc1|fl`X$-)ceyN1%DagZ+;)0 zokQ-o+D1Jevq-`el{ zrz=B&?DtMrwEB6)lS9Tt>fyP{0sR7hu=^zUmzFIf{lffki~B{<&*FV7{$g=T^jB!x zr)|Vvm~XBRQfKq%X&qP_`9ly-rpwoQmoql5cc@1!p8trm$N4!QkN>9fc&}o+VD7z& z7Vl^GeT&0=BJaEG6(8qI_6RPTI%peY$E&{jdlm=n+(54V zz1H5e!Pg7YexRogUM6~s_H*|wqn$q(v^az~_650mtZvcnhxs`69Hk?##nbWqjJ&6F zfzmnm?Q(|u^hoobOk9Ebw&~mWg8rrro^NzrpDz+UMt_d3=Z|(?VQ{+gk?*esbN2j- z=#lLYnV#$R96CmPW3>Opdj6>P+@XBh|0ltmJ-;S8*S_m%D8x^hJ%?-@j?upLBjk^2 z&o8MR+W($l&OYA}9qqyS0^47X^ceQ}Pb*iq&(B4VA)ocz<@3i!nIGwWrhl*Uo>7X= zohNoHH92b0RY_Gy@7gerY<`U>=JiVgY+s}I2yuV5CRwTbvx#L(pUZo9Hw*LmdT9M? z!+Zv``3Gor1zMcqdzp%JA{}49EIbb@q?buIf16w0YSo`0~VS)^adT}FuOrVInCdoqa5Z3&{0nF6XdXR)Mxe~ zKgwx-LcU$D=hn+AMxLM3x78QlE7^Z`;19p&NM^=?h&`;`T90a`zS zCO>@;HNJA3m*V@D!gJ22d*XA?_?{%%ovRYaaX4TKQ2JQxa@|J0jhlj8M<7@5qXWoA zdGn7#`8LW2KRR%Ev&Sgq&7aqL`Sq73^VARMk|6B{e;Te&wM&-q2_(gG(DRkP<$~ZZ z(T-7{9cz?Zzt-ApsrAaAtGq7g6Ms*|)q75`dst7JuZ$(PTW*rQ-!fN^&8NBhm0c>s zIS;$Ie;5z~ZT*Da?X>v=^d6^eo`>Emx^SPc%jJ2C@^ra8Gq+cajORT5xPe>~s5i=G z^8)mMN+Or(7dpyic7Tp@+4=Z{+>W=4sj;PzmI;cqk{Qt(Q4DZN5KLIkS25DwlIk@`u9ar8ciN$Mw72-_zyu zPSXGCz&~-B!FTo8Y{L9?b4Xvg#$dY9;T03ZI=HrFXrFRsH;4ZVOGfN_7QE1jTutK{RnEw0y-EvmtO!}ZY?*VFiWmRQc)jptQ6IJai= zcsy5jfOBhYv3$>bKObE-Ihz+vZT^L@_+FWKE^YloL$)5p^_I9NPfu;o-b9x-?yF7U z{SLmah3Bwd-~0IeeDH^JO^)o`Fz2=gOrD3rx&Zx{(>op31lbS#3&95G?IvXXt)Dag z7x8n>_*;OuU#q0*o*fE~t%g#F<@Oik3DD;io&OX6p`16ad3p1*peH+TZ2pE{>{5R2yz$>UZT>>O{7LIayf3bZ zj`F(RwJtAIIxuw@wfaN&DZ&S z<9cFvHkNpNzFRm?fyB#$QaLN=lSD#WaioLiX)yw zh8_@ISpWVa-iL?%jl(|g^632Wlj7(9z1Y0p;{SI%(^p;3^I)5TelG+rF6f*4_U2<% z&##NV<9Od*l~lx65BfUvps(*^>p8wxEzSeCWqR^+;EnW-{(e*KMLiV#rm((^SP#71 zA^Tgg|NOr+TYvkBbr|3G?Z6z_KpKNlrdyXyA?O`DY9degbCr$htyINU2(@Y5d?@62cWoBxNS z{Zitds<=3ZY0*N$|9kTIvfI+1$@z$A*QKf<_dJ$cCgO_+2X_g^^M&zuTpLrRCgoLE zh5g$?dP@2vF|6td`@9>2yq(ZC9^?78LOIoE`&@-|)n|8>l(+RTSD%`RdadH0RzAwj zIZcbN(9@4|d@1y9(S`M*@j1wC;?CM3?iw60x~lI)zjJ#+NF)DX{jkVl?d!w&f9G4T zGP<^>1{U+2&HRD)7n|O1w`9(#R}3lj_#GcCQonp|FHYt9x9-H)0?;ZMIAv?sm5Pmj6HXnE0@R#kJ^N zaz}fm*lUL9f*lU}d``A5SDQ{&eeKnzlK}dCOxTZfIq*BvD{`3p?nm+myKf`k&u z@E;xcp+kNC-XPAwFIPJ*w@|z4^KrPp3i%^{M-hLApFP(J#arX^oc>KAf%9p%p{w)#TIQv(eXQmuN{}|uH>^I%$ zy8UcC=lW;kjQ*_G5)p+qg~UNx3kxB`SSi|=W^ow9oMf$a`C>u0o6ghIr+x;eT8{r z{oEDj;ul%@HCp#Z`9D2tO3YaHd$zbP{8;=hpVozT(Q&>m!~=&CcbNW0sn7IRNFR6H z!FsS;@)p*ygN`SNBc4`0jqHLw4lR!8R_#eXj?nYCrtRHIPR0{QV46(6hH=Cw@xyg0 z7yS=?*?1l$et3n)4>!1f{H@Bte?+dl{9~DD;uCxR6UQa`nQ!SQhx?W*rVf2f^cecI z`8wp6%!cCkaWgfpR|h*^M0xytK?ynSxfJr*{K@}$_<`C%KJDX-S3cWY7yqHkH?g8x z*atn!V8Z-m`xwY4JvZ^b=r=28487&&1+$I#U9M>dnzzu$Lh-{lAjrAG8wJPNo;^Dg zzqi*O|1a6?N@Sjl@5PAvkL~dLnjSGQuj~|zewd5%Y&|2t=J{p8Tz=jUpUpV%Cbfh9 z^Ygg*h|;6IWB(?0D|O8HZ=D!;|B20a#DN;;#DOLCuS7dX0@*Jtodz6B?<;fpqs4z$ zDWCc*{$oGD+M^xKQ;WOGrMbW?{(~>XY2%LjN}E)Fj1yx0#091&;sWzS=wkeLsmhJv zPdPo0jQ@&ye&%sqcwg{A#C0z?2)ReZb)(4r4CA%ZwUXmmjMvhG=+}sNt=O+z{PhI& z=Hsu&)lM${vgh^V^aIspSEKRPk|Z{76vpYVJl^8})O=Bbw^#Rn0npT54RLf_Z@a1% zPsQhyP0V|3;@{q_Z+mayZXt#ErQ!W-SCahJX#9oe>AT~7c~Sq{D=MAEi+UgJ^F+J6 zhy42*_-;dwa!_ux$Fan+{mead@8U%fW`--h`9c0XsU|G%(M`TYNdRB-YP zeY0+?4Ro|$ziG36-ZJ_X@!P}3|7-p`AI|NYf3uIfSn{rVaOgb2c%Gl}aF*yT_xp3z z!ta5+zx@A&@Vla--3op+V%)gD$8!wX@95i;@H_JUZEAgt^=ezv%J~-k-vWk8#%D35 zXrHeZ#<<7*rnPI^&`y;r%6lL`!@q2O^m zvP;GNxt3)AyOe{R4+tWs*||O4f1lC5FNK_Tt_L~4rSxYg=WQyh>lw)TUX_dYWyt#( z(a5W~y`G-#|ForNa)*5}exDQe%j$anviRuFmjs_-f8sI1*q`I0-s5{&vU5Ndtus!2 zUlhIHqjuvs;`c`H7hU(0!S@-R$vgPZq8FVR{?F5)`bBJ)-xJ-TdTIZ|f_3{3e$ePl zkAr_Bn)bgc*tq>cvs1_)_4if3tMc*wi*_xhjdqN3@q4)Y#TVo3QQqhJUFGw8!W{W%weo9%8vdh)npZh-Bn?*rN_q7va+Yf)R0To%&f?<^8O zZ}IO@0BeLIxpqR_F*kd@WcymrRy#iKOb)G2ML9gb6n?MKFh48bf$XZsyPf^+q*zZQ zzRhQNoOP?mWpl#srZ=xmDyp-QJv&n6)~|RDv^{NMe+<2sEsy*8mQ})dE@=0`#Qzqz zcC88f&mOoUlrnm5%G(Uch1qaT%mS~{Dt^u#P5hb{)xZKCEjo8QavtL$GGEX zKY!UsFYE(opCi`W`YiPKeAUM~_nln5I_GJ7GsM5Uln#8%;ZBD&ho)ceXJ?!z$J<{o zw=ljJGTuKlxX&2zUdYS3B}FpS-W}$JdEK@?w6VX{rVQj3&~ps)7wlsDq0C!*l=tGsF+H?Pcl5i=m#IhYAD=te zap>iC#`E+C9GB;*wfa2tOE|CkO|_RhuewWgVI3XzzFfAj^5<3UeuV$;XzLF8dYj6l zzxe>2PrV4Z*!8L3lcvzWa(%|}n>$}0#`pN%<2~AW)S!p@dDKz$O8?)a{{IPw~ z-}vjO7v4{9^IhTmU-5nKqn%S7uRdP*->Ba@r)vGqol~{@_S`wu+5e6DtMjR2_Lux` ztG|uzBf5q^R}`yV^?kag-%&zbpNX5F5)Itr(AJZJfBu;B3asPyK5WMIb9z4Y)siFb zKekt!9}x|#0d&sqCei#3Y`0*1ejD#MH>OHGr1Pq_&W%!^?UNSL$9-;u`N+ygxu3Q7 zYKQnB{=es@IRCY8E44}yjr@f5!|uZmbWT8hu&ZXfh{Rs6PB^>ANl z`;oC-{Pr=WGww|8jV86dx82$$f2ZeLPA)$$=d*b(!S*uIlliIpjm036!}mY3^Qpys zSf0~{c}r0rS9==b*XWO&Q~j*ci3@ceL2==mf%$W)M?ot-{19*~zx_lm-{uC4! zOg;B0op!WOs`IKh0`uopbspys&MP#(kn%dOU~vii5i|*1Kc^7(XZ@UNriZCXZa+~a z!d0K2^XKqJo>z$eb9*S3ol~7yv4qkyKflmy&lBm-F4dIlkL)5k_Q(7&*PqSGA7h@$ z%|oU2;??E$nlg_5*iI$(v;D5PuZn+}pF+=2eO>Nv&^Dg*r9d-CTbyt{i87ACe5ZyuU{ssK4=fKpan9W&3~N`Ew8FS$%7) zTAhEedHIS1pA*j8;fYW>lWS_fTPE`>zpswxs!)!NZ0xXDWxfA<3-x5@PvJjXdGYyP z>=)%zOFwzY;<%h%JC#08y;`5e?|PluNUyQo*bn46M&*#ho~!fx&*G_^9QI6XoO1j^ zb?G{g91|E^+Ku}R@aOz!lyk!F zH~mYjzi}V9wQEf&jN@&7P8k2q@3V7`n0aQ{|GoIJ$z`)mqV>34bX+$JaoC}p6W*zM zN2$-|fkOJY<2}}O^U*^5aNu*oKCX$kzazOC*#kQqTKv|n+J7bIgHKe$2NAbndVXhQ z`yb{XkE%TS&BsCVkHeH6?+3<+t9E#K^Q>P&Ty?YB!(Qf3ZqJ5s)x>Ub+j-AoJZ0mQ zIO-!}h|lG7zx!FOa~Jh>ME-%EdpOG?R~iPE)(NxX0q~akl$}%Ib>ib+O%+`2N0fV)vI`?^topsj4r= zIgFE8Mtgh{{TaJ2Q2IFKw6#P0jpWS5F*XmzIEHqt{c*N4B7TYbh;sY*808$3-N%iy zKO^Im*pAnqonwmcr9zK3-#yoHN&A{`PKfig_oHr|r?ogEu1{T6+Xr|S&(oG{{1@Va zgWgx*JiqOGyPUti=V;9vd7j7YN4(d@dy)3YulsE@Fpd|8=hE&E6AF46alXL$vj10u zy|nHnYp+dgU%>NQwp7D&y?JXAotJ2v*PUDkY+k!Cxmf%wQ++3Gym#diA@Todu01b# ziRhJ@b=apM{~{s&e6S<_-`u4(>(cJRXYUV5mY!gA0)2t7tiB~l#c2CZ zI+k82iuSD*_$o%GORbc}Gd3^JzMzyUhxT42n3I30=$!nowEVjKuP_?@bB!jyJ&()k zJ1?<$JSYE4t$eI+N%%dg%Xu*JTR)Khbyi=hZ_~d$8O_PxrHo8p{{IKY(Ep{zpX%H6 z{~94V`ClzMt8Yp8J=wv_pX^aR$Zz8=(^p4wrP6cqUm-ecuOqxKWeoY>VEn1RO@7;7 z$jSeDWn}d&NiH|KqVI$8pJbN`#P{U5Jk9+JmCAYWIRO$so1M1I34R*q=gYb+zj^%~ zVVt!j$=@sGc1uoL;(W>e>%&R{KIpK|;oT0mIo#^7>Tr|8H4d+J*zM5zO})#UUgEIg z@H~f|4i`F19d-z2{|};Y?z?dQV@ad=iMZr5s%K(Z--({r7+svV3g@IooU__q3FTdX zP5mp4*5dOqVGY-B?sJ$&bw0eU&ewELD4oR%r)2*pqC4bxJFW3O)~xS)l*3@VL-iH< zzq@~aDEEx#=QW{x`2M+-5O@_o9>{?82amfeT= zIxvy_mo}@XTi^D(vmHVT^W=zm(c9ttX}G^=Nq+HZm5a}Vz5cdmq5hKUrGA@lv-*|D zbyooFd+htVP@XGH5NuEP{gcs)!*ic_f5PtxY<=SVy^WK&AKh5*`*y0HkU!f04cYf) z<&sYk!IOXy4-5akT%B;`jD%6Rykc&ih{W{hjEze~uhK5se(v zhoz_ceq`yskB~dpZu&ybZz?}0=kr7(=b3^BmNUO^HuC?wM87QlJ^}f^q59)}EWfWX zeb()`{}JU!`8ap)at)eXjqNr}9*f0QPt;qKC$`J)BK}1AwEtDXx*hkM{i7Xe{{-dp zdxW`yjoaT}tLKmQdxZUeuKc(^NV`vnj&_T3@q3u)$GeoDvs<(AyWNnhZ24ynP8Mt| z*D$?o7q2eYOZGdG*gksslJYm->gVOBg!A&eucWHsRjl z{1&BNX1&n7=P#J^6xyr z`R!dU?}+o|UVgOm+vY#R`#%)xX>z&O_Rb2=VJE*^QlUTHjdSV#g5_mlT<^U7qYA%o zoDk26_TDjUo!P@%=lUzy5yW@cS(2veL=_xZv9PAwG!b?KWDj&S8c4+x=e@AuIqy`p@qdA48cZfn4Y2o&;0N)(nE&5$lya8Z?9F_4L3lsc z%8K!)W@<{y#x_YLwqzZhEisU9Xx~pA-!oaJXBr5D$KfbGvJl&ORqQADlb4a}A@O zJGXJLy<6P2&#+6#@OgD;VNt%@#RNb53|fbD_|I0pxDNn*nbL`$mKl5~#B0d4O?2U0 z&>@^Z3hV1A^_gA^>Ek|sg#7%Cl)qE=4(HCFr~c*q`8?6Yy`2utA9Mao#A@f4&awN1 z4dT*!l0$rr-cJ=B?SRo{h%WkX;d#OcyKJwhR2I)P#rtQ@pMOy4K;3B)w>McF5cge> zvrqZRVg1-x7G>wq&k{oZ-Gby>|8n_xxvS(`zl(Ag{UG{JF+KAS|Njh(_x!x_1IeJv z*Yh#Xp@+CA_nzb?E4RjqC;tu4p!=U!}Ir=edBJGc5vJ%|1Zv&UlZPj(JHvzN_>xpP)#Kl*9@PkM*x!T&#V zuD@?o`Z)Xhka%_Z_&JDk=wUpu&M&5T{v4Lg7f~M0V=Ytt*kOs_IOTdmyt?AJj^~nn zo@kBxUlVQiN%S6M-QOr4kUX)Sy~1^QJqK|PJ;Z~tAINVljZ^;Jq1CM2LpX=-acG>U zriS=)oO1kPymCye80UZ4bLiOJ_8Wp;#((~t^Xu2D=bS@t7tF2CZCao8e`xibOL@9@ zpJ`d^HSc4va=G<-Slom^&Jcg(i|c72Zab9t(AM8k>N}+Pko9_(iM05zl3<}X0LJR9fJZT!dhisx5W ze{OxY`3TzLOxEi*^_z9%ErMgr-!^_j{&RXh{YuG^i>Itz{s;vuCm1o`MBsb$(@UbeofD(hqx#DGj?a6W!!e(EnZ!2_w0Tw+I{5t^bp_V z+OsE};7%bgIZUn^v+C96d(LHW}!_|Xsf5F7s@LhpG5h&!1({}@^YCxL0TThDSHP;|0sfZ5H#@w=VbI6h zlAE30;BcM8H4bldc)de=Vn)5!I&JX|^m3=Ka@g(gHbMMU@k`#{afxIK>%7U)JJtRC z)*wH07zek8e#CP(ZqM$^%sN9u+(&(#dM0rWaP%z)7UX@t*MBce{@O zwkaKG`$s@qUx1QJ=@T5<T>U zeUsCsZ)l4Jfu?t$wGihS?!T?xc&;ZKryV9nJWu~-?|*TePS4H_4d=f;^3&-ZswuX| zJocDq;7*4%hsH zw#eHY z>}h%kcDD7PPwAQ6?;os+?(fw%dT!)*vqHXp$HBJG$D<$J9+KnwFg^Nf|NBD*@oQCB z=D)-1d0(stf1Dz|LzL@ouP<8G%A&ZWQP7(c=`W%f385 z$^OqlKYG-aJ$EXH-!t^vY%|7v1)FT>U%zLuc`U3S&7GmPO#ajRJ*B@Ia@{cVBn zN|G0=o?<@^v>r)bYrks#oczzaBz@Ytr17V9N#}lfZaC~YW#e(>e&xT9T2u7D=)c)~ zK2z;wb}q;97RTYLJHr1rjpzTOzeYd1D-_RuAAp<|A8}sYem77*@4e5?eXyTk^IqKV z=iL68s)F-F{i5r3*>8G{?Q`CIhVnTF-!9m=-Tfb`=Z|KO{U1<1?L|L0!sv8= z^aIly?b!@Md%5{XoZ+h5Km7lQ#&+1>rxN`ahjO(0=fW~OEcf(u|1f{(_w<}SEMBYY zWB*esi5>o3a14Feyx!Oj;dkyn9{s)j&99FJi{r@i?S1+D)TdE?R$jxM`7?WN(x{$B zeCpGv*U-?4b?a8IOV{*Vy=ujVbosi~YtpONt?1d%d*jOV#uXdWYp!3tF`c)3QZkb7 zrZvk0U(b!{icP)itxU$h?xyQkq}Qyz>Bi+&>y=cxe)Wx1MU_1(*9%#``pPvcR;;`5 zr59a#<@KvquexcCwbXOeV-0zx>7p8`5if5vV6ru0C49^*uMNxn7hv-Me13s}c2l`T7mZRTa-Z1KL@K z&(xhIGkkEAI>*><61Z<%v0>xtb*s`9H?O#H!}@xqqj+F}weAnr&I;@?iZfn*eGffZ zvu^c<)mN{+UR?@K*tu!mCS2-<-s?9jaryeIg9{FGb~<|FdMc1pjy^VSS$*S*D|?r# ziuGne)#b>fWc}6aUb^g!^Oj$+c;52U;-7iZXvv}JVePEGYW<3JH?LTJW$%p}t_kBI zaP=%-F0aj0-$)seX;PAn1FWk$k+0B{>4s}pr0Zb3>ZWT>OE1D9*2Gdi^u4i* zUiBLKIVl;@78!At7$*Jl8`q~;b)7UkDT#fdNxbbEHGV_y`t>W8rwe=5t?SvGUfqL4 zy&E>COc)yfCozevOM5kLS8TE>n8+?!_KH!bv;Rqab~Ny>e_%HhT28p$H4r}iwx?t_ zjN$jGCBN;M08GVci>eS}Sw4z+j^Wc1`M^^?;ii*)9^u6@&Kr3wZYc6l%-Co^S&~!F zIbzY{z_~R{Dtu1nqnM-0=S&N-!ZTvy^}Z-(Io}!z`;V7UugWas^J+eJj|sfo@hVWy z`=)x6*E+7dv$cF^rj!D2<0D-4{I27=!@AqsQtbCZ$5pn^J0M`mxqeG@#IpUbPkEVX z(4TR9I`|GRuWqTns6)kiUva*f;Ez+0>Z|bi9v`=J@*j?qZvSsq=~eI}fwE%_T=63P zP6oi|I=%;dAvk)M1SR!RIIwgcIAu%Sd^Bi}2Uht=uS)OZ^9FF~sm5ou<2%7`a{Mvy zTU>tZT>34?*%c_==6zOD1^NS?cPx0+?QHOSoliPU`Q-gB>K1=2eF_G#3VZ=bJ>eoj z{;Iyo*W@2ulG*lTD&UWTOFvaU(Fbd!e-#>jlfeD4RDph64RfV@EVD^elANHgob8oN z^I;FidFD~%``*|2;Co@v-q6E*8rZZ+c3i-xif72S3q!L_bHSn2m!?y|kx{KQE#?ba zk~F=HuSJMafzN%Q1-$8U(&v_;4+eY)cTvq(G`4Tg5 zlDq)?HOM4gN+zGL#cj_du$9e`nulcPl+Wdk_fg}!!QGzCJ>ZCC^IB|6wp5?H^Zh4pl>UeIqfEcifM=4@ku`6h z^OZ&uHNG0z=K}JSALRpW-r(|G2$7fXV(5|f2|gR;TLQ;z$RTsFUNuX{=3n3+0*`ix z{4XQ@lOqKXZHy_@Lue zv?W`r{%zorOL!l+=6>N1gR_u8TbJFhl`27A3LA)BtGeg^cLxdA}wVgpBCvQ1X(8 zQaE#1%ijT|f|QRTf~0>9#jAemYWa>OB`xv+`p_zVKCLMb)3qv2fUi~aXA5vGkm9Ys z2gC-g4+8O()~^5$1FF7B!2bl|XA?D^jsTtpBu1GiU7@y#>wv__6MqMYyc5+=#^S`k z0#at;_khH}ZE_#_*`_hr4!j6B19&x%c(?5~AboASABaxc9tF+MALXC zRy^#*Kx})M^iJAg8e=K&1Hd`J9YFMX*#82a02~CKNS77>kzvvW!1=%)AZe4f02c!9 z1`=;f`YiBd;Nw8X$)vr&Q&9ynD8@Sc`9O4W_~pRUfoi`KsP@kQs{J#8Uk9>=9xl6_ zg$iZUvw_sD=PXAo0W#+tAw8T2d@GQ;k9aQ-n;r2f;0u6%4}2l;hd|byBb$Nf;7IzW z-=`i4Pf`JP0qNV3tAW1(yd8KU@DG6K{K(G(UjqCF@M7Tq173nDv7vsia1?#fSUu{M zz?T7gfiDNX4fqP+eL(V#`V#O}K+V}pfwIpsTmjo?d{3rr%^Q=i0Wyv!%RgQV{8Jz@ zPW~DYADXQ8FT-{45v}cIbffo2m8I7=0Iv@_s^zUE61a3fi=PggkFJ26pfp`ahC$Xu zS+%J;--F|-_?5Wk4Y!5+h27%ix+(zszLD>m(`!PJDK|mi3|{f{jSQ$y z`7Lnz-CPBKo8x`pzYR{mnrq;)r|`$XKj`=X_(S0MUh^LCKLej!3V6+N^fTqJgf}J4 zKL!6gPk#zrzA65nfq&ca{{a6#j{h7SK8?@jy+B=W4yu~k3jS`Uf&qpp<6F3rrpgcA z16~22?sygaXmI-2S_7X8PJdblz!!plfN>76iA8qkFoH+(0Zx4$@LI?5X?y=DU@Cr_ zTp!X+s%CJ?PQ@R?85D4Q&hQFQ*9tyWAx--7-=?<&62F-GYSON;oMb9~7GKX5`Adhv z(<5i#fDIZ*N3$O5r{MV7L zSV_%GR`K7Ud|loj(?_m9pC)UyF(gwzQ)kQg?^a%p|I3hTl}7zvf#pRKAwf@TCOiO=$HIeve@N%V4k$=Edfkh2$U`Dy3OWi&85>i zNnq^hn)VxfO%C-=d%19Q069%QB%C&;$rl)h>hd&nXX*598e_`pL6y@q=ZIf;pW}yt zYaUnnB=CO68F$nE!SN%&2ZU2UU7q%@o=*R!4LOdEr%RWr2i;9q--S;FpW*m4@Dm+p z{7%={6Hhxh>xI=1@AOxCI^%8n8y#niPhal%EO7ab${qtQ{Rux7{C$pNv+4IbejND2 zjvo*HdB;=mFFQU5{A=LIDBqd>O`zt^3Ljl><%&;N7S~^&vxP4Y=kt;Z^X{9N&iNd%$ley^r+s zJ)QowFLS&Gex>7&0rUHPauBsK0UnKkDxY}W8j$wYIEXIwM~spGW=QFWt6jXp%c631 z%E#WWG{0^OFu$)htj_n7PhWJk-^-WR+5QQa!P?8!|HtrXJaV;bO>%sg43Cm-vcvP& zbv)ytKkffadTjSc;PO|y5cmv`7a~e0@PEeOug@5~6MJ+Y#29=R`~!S+{VwALFk%e; z9_bY^aBTzc#y8~e_}#NQ2J>U2IPQL1jq5tZv8J(SSFWB0<0~5ru(m(PW2$|xk7XOH zQZ5(s#*B%c&YV4CDuT#BfEjavcZmsnf%B*z%8Wc3n_g8!n*Wj8wZm?+Sh|^FGmnDj z_f-y@H6!@~HB`V)1gGqTD)>3z%vTfoz%K#+B6tmaDL68;2)`U0{+0po<=|fl@#xI; zj@L-1+2n7CHLKwGl=#~!;Cxl3w_(Jgag7<-|?<>J;KwbZj zdqF_Qg?!P+!z(+F8I$#uYs$-+%HV7fbRuIhRIcK#V3HH&&hq@ z)4|D`TmzpAPFs@)z)uDLPRW+3qhIJadOG^0j#JmsvafiW!I35T&V-~)-A8W_j;pqT z%f7?|L znYIR8ag=cCo%K`Ut;w`?gl*_r&zYue0-p{(1YQL{4*ZSaHSkjcuIyvZ4MTr=1^gm# z`ZZlVuLP&AcJW-{xOi4MUIo9!aq-^?PB<|`{J#%A5nTMA3OqB!|9R9lm2~lc6&xkZ z6#xI?>;HgPzz0Z2u$eXRe$%A0sda*Rlu?Mi|Uz>0(CJD2D~N6-v-Z5N&lebhA;Z9>)7zJ>Y!iMrvAb|dlC?R z=$b8E3Qxi3lBw%heR=&9n|%`GY^4FD&p$AfFB~aea(oG_Hu7aFkoPLhua5>e`<3~& zTsF0(x#f1}xeBOyW#>4n8}71!&%TbV`;-sP*vRlZy-s-S-u!-JNoL;#e1K0yv88qDy6h=_KC{2+dj1Tw5?uZnosjF4rpskhzrGK- z(h`%|{};I0@qNJ020ZGm`8}d@?Me-5*DmT5O@EJT1>P4@k5gZy7p~)ugV}k^Mms{f z+33%}E271~Wn~;UK9`v)jys)v&pNIG{&qfG$Gw6t$Fn|)pZPMTA9qa--&n_Eh0Tn^ zBoJMgqZ$S(!T8J|KxQ(D!R^N=RKkxzUMsn*Kt3CN9i3@C!M&=wm+!xQ(@b^1s?Sa z9=mo1aQsxD=7VakY#($SmzKE?f4Uc z8pB++SF3)d)GxnM{S|QeoA4?h>o{GrGU!?SsOEV2%-<^?{A|7)&-mZ395Hh}2G98u zOb^W!@RyUux}fX$OZmEwPX+vP$7`;uuK|_*CerbvQWbm!_}jtzzV)0~oi6A8jA;9DH;X8nE?ob|Q2O8Twf-vqCL-wFP0tfO?TP5(Q@*vC_MGCefeT>d>`SJG`A{toz7G=46$@NLL9*YUe4t9eW5ec-HVilYvH7+iDO_rYu6 z_*}A^I2LgHKk#*5aI52KQ}IAYmGmEg|0Fbd{Esk*u7A`QdM*J-I!=D{PfCOT-<{`i zQSdYYNJ_;koGX>xzbu5m!{Omi&will%*KANZZF z*Kd)gG2INH-Bj_5))B7sLwr4KXp+ibKIwRz+h)V_S^B7|D&VsJ(at0N3a^kZn+vak z?{&P!Bfd!im+t4B;CKc6g^pLjyBx29-$+~hNw;=h$=kB?O5WC-D*4{loOe22qwISq zh#oYT%y|fS9UrbaTBpCmr^+XHUU1H5;FnI8!1E~ZD}1=-$gi=#d}j`0Pd=q;=X}@o z`6T!c)g!JFby%`EsE&1G&QC}?9HK(GcLRUOhb!}m8azKIVLHVtJpP2;=8bM}=?ht9 z%emOs@U7tOj&B1$&hfj!=Yzi;{yy+Uj@Q7?a(n<>KB|7Am%NY8y^u8dK^1jx1ggD0 zKE^D_CA&(#R_eI~MBT)PY|fYea?O?f{*_OKk1+t43o`u2!V6=KvUA^XTX-OqQs1j# zxkh}X%g_IfPX%0ZDP4FK=;M3t?}2{@VQN76g77b)hq;bF3jcfEUjLUg>x7^#DZ{US z0IGi!&(=MP&AktDxzfNt!`Dv@P3G2Mmg(V{x*FK)={vnG>Y4lZ?i+2u3iLlwMopr( zxr|La8w!~FUA{DrRKTS#;oW?KFiA6gpZjlK?@f9H5pXeg}gcsbFBp(TP7AIVc z{Gpr42`>jf9G)sX_-#pZcMbdsAikw;p0L943b^W4dKG-L<2CTNf?pRzJz=ZkRnp%R zaEW)qhaFe?g8`qQbomoyCse^7p>Dda=Ze5z2jBzH#=Sfzcb*60Z!DqLc51mz#nkD8|X3|Rwez@(2S46 zwt@eJ3!f|r@yR=ht#TUh4eY#XMk71PXWh|%Qf(G!Otf4Ou*@T33`h7Ur7S8O{s!k<~TN=*W)-c&+By@ zndjX=S@bxi4}4=tpDJ8_LOoOQg?aCG{9*79JH7+_A#m(6wFVAt_+#Mxjt_wEbbJrE z^g|wMN#=cUh3^h{yYQcazaZ@S%#+VxqZw6>+n_hY`@mK4 z_rm_q{Nvz%A$vO{&7TMUBJc`0Ixf8!yb69U`1#;9aA1l2js$!OUvC75o_{In=(nQ^ zjt)x~g4e*W1Aj?yi}~xpF9sJsepRCU(ccj;Vs*#l3yz#~YT%E6Bimf@(BD!IxOl!r!q@4a@P7qI zCkv{4egXb=U?1W15#ZQhK@D8v50#a!23Gl;5qJ#0fb`{U_IlHWFDLzb9LZ{f z2N_E%%E?J(@D-k(f^Q`K8h9$;?*P9Ryb3Nm;`b-j!0!S_|0e?$ei$Cc)yWkIt`f4H zTqXSz;H$xF;OhHYJNlI@{31Ahb4n$|6QvE{;@?R+{al=Yql41N?Wk6=@JHa-`vveX z+)F05cmez;wK(1fJ{A18NUwn(@AzZjr-F-r0Q|+&v)>+*CMPWczZ|?m`chMK@ zSHW+RKwNLvS14PuI_U^k^IP=o>9Uo_GtGZWS)Gs8WVJ)-*kyWvhU4E!CD0}DR2}aC z)*L^YG679Wv%o8!ehhfk@ngYjj?a#gkcRG>DxQwtG*ul>!E27sscWn>7rf%>CxBNS zKM}m<_`IM}QKk9d6;EFPUUhsSc+K&XLR=xLbTW9w(@z1f3U3JlqvDe_?p7)dybu0% zLz9#L$o2onqI3Lz4jK9Xs?I-*=bv&s-)g|~!yM0^20TyKc}_uuC|ka*Q}Dqk&ndEx z%Rh`~L5}Cl20R*+-mg<$)_~`-98XUJ9>#T6&!z@Ex951?-+%60u57@=Je}2p9!9N4bDi7b)CU{z z{8^6Y?;7xYFURxL=sb%i)_E4;JEO_7XkLzo`LNCt=AY*6nmKEH<=QXl%vrXf+!2z_I0lV=UOD+ zR(Go4n!|s}r^d(IZQh*2KbOO8esDeX=hAC+ymSF|UL{4x%lW@7I^d;?;JI-Wo=0;$ zmk1BK9k#ywWu2$_jyhf`6*XvDf#d8{8xd0xHaer6)pO7;8`RY zOVCdM5p~fIfu`CZceoez{xBcL{xt8*;h)Lj8naQSU&-NLt>YzZvFPUr!JmTYxW_7v z)0D<~lT=y1mmu2Z;C-YY4*n+a8u)bY)9b-I9Df7&adbqN0uozGUH899-ih`0;(2MY zp62mRlIG;7kd7ag*gd0+c2NXclIDax?Y8v&!Gzs}PU<+K;UAQ2JyH2Rj@&&RG@ zJ>4Xzo}Bzr=V`CXDkrnm{=|2hbi#F-<{j!jjXB5o?*UTnX`cd$?=OHYd{kCyQ5rFn zuG7B5m*jH0l~xKr($j=+MR*PTPIzbU_k+I&ybAsa@VnR_NWd9u zr4N9M=g&z%{=>vW-wdyT|1&&yhneK`{{xOMOsbIn@9nhOWW8FgtVPo9dUxf6K&z5apnpo!0}2U;$py6KYIBefK-^bp z>A_i`frdh%r57#G^Y{LIXXbfk56KR{{-2k$&u3=7bA9JK-?`^eAC@4J4V0C67LYJ!vsq1i#JWN$_1Bm%tzOcnbVE0#btW%qi_5Ov+b}t+|k9*_%8Z z2QNYY1!ykfALE9v@;<>oG#l>ceJ%fs;J@bm68@LK-%V^R(}(+pfA{#CY&m_n$KL|~ zyvO+4xZUFicn6t3Cj1EfxG_htr@T{|7YjR@0mJ>WNCsZ5^qfIrF!0*Am-lbUMUSJ= z7&732H)L3ONyDV<15Mw{B75W}*y~$H=V{*pe@TwGRKCcNo{i}FzLx{?;3D`}z=yzP z-s1BjIP63I2>2HX#HZQTLthIG&qkf~R`~E~<1M`9muKTU`3d3N?XbLWB&@zy^1lfF z^h2Cq{BQgsjyxN`!w-ZT|BZJ)$E3u<0p3r&-c6Ei06zzkU&WqhljNGQX_5o)@c5bF zePCozlMP3bA_Yxco5fQvhdSHS_uJU#Bl?>o ze0zrb#H%3Z;!j9)To+7+Rge_r+x6@7gC0ro?~(@VV8~97r$OJP_*Kwcz19KS9Ar1EklV$?!yH_|ome8c{{rDRtjX#V168LK9 z?sGI-Ccz&7=dphg_=Dgjuyi_Qq7b%R#}E3jKL@4`^`Q&;^I-I^==+zzZ%b@kNi4}0 zl@aMXBM*jFc{pQ{_gRUvU&8+5m_OpgWXm6658atL?7spg9cSjje*=bRXD;#fc^znB z|1ZQcfEDGr<==VZSI<@@R&taB{|s;OI}g^no0mt8#nLw7GLNB2+lWQ5XkL!rli)IM z(j%U1%@K~`Al|buhxN;?=YcEy=lS>P?EA1V0>(3N1i!vsx6QeIOscB&<(ie>G`-9ER_jRnqrq_ue{*`)9z5 z(2#b?gXD25Y3=(Q|9S9HEL47?K~IQpD$A`e$NuRqmaV^r-JgJS*#9>8dT<{67BFcY z5WWpeeIHl^zcaDD!Dk4Qx4v&88%toxFgo>2;g5nTJJ^!Sz(exb|1tF6!hR8Z)gfg4 zAxqf*Irt;43U2+H$GL>(%v4UcejDSQ?4bX9eyE#zw*H78@}g(k8SttfK>2QaIN^NO ztdnhz0!v2oGK+v<8~XLQnc+Utn3nr12*-~X700%x`SSWx@Y%k+THwvZtIXzzXCH6e z^_=-Re*TmHJT%Y4jeI7H;Jv)jk;zH0=!KWSm+@AT?iW1)lKq6Bw_VAbXWJA%6!JF8 zSajQdk@o=aU*#>j*YWcd@O!{F@utq}N#o0b-%1c)z%mcMjkn@H1pZxbzX%R#ItfM> z82u8M@;3VW!IYisNlvm2H}R)02ZrZ;U*SIw{!5P+!IYQTFM%mDVP*Av{tf5BkHkRP z^)G^-ggyTIm%ytXCacN$+da;MFYy?9+mD6J4M4B`K7Gg$+(^!ccYR+6i~bP!8{kFo z4EV3WONl*w_d9l<-*n~L_eEI~f-erWKhhKlTwC~H{MMtmvpZ^=)?^i|T{bFUh zn!4d0<(hP=ZW;%`)>rcOi;?}WM_6Sgfe;xyI{(eQotL&bkn?XRUPLF!L8J0I%s-FX zGOH(f>?u3Lhrl2Aco8hwCm+d4FnLq`PnP)i5%nF)u&reT`)|vhN=DQnP0Q-RzsbVr z`wsDZ6Hh;j-AUOK=Xc%v{C@<054;G?zk$CGUgDppkNU4-*^WT;i7pR*1QstMdf_Ky z_fOy@@LAx0wrY}WUy~R=21K(7`%hxO2)+<|FFV_xkNx9aR<>UQ{vlZOGvI#(FM?ZO z(sagB!gD4DUX+QRKJnQe@}=^@e)}tUA9l9eZ}2!Tvj|ATFG1t)Q|bFV+2B`UB0Jkp z^7eky@|XSFAo&4qJlo#`{s)JH?vi=?`yte0{(X9K*na{$@}p<_r}>fl68|ARzntN| ze-RdQN$1P->(hK)gs&%@R+MJdf9Yj=JiW=k!>-Tgv1C+A%s*O(G&v%;5LcgcXh?(U zXYcpFBl{1MhOgsEPP}Z+_7~-j?0<_NVJo93uK&SK@pRa0e_3Yl;u`o9>_Xl@9N}9c zd_2Sb4;A)&yEU?Zcx397W zDewn``%IVRKkRV@`;U7}S>>hQL^BIke@u7|tU4n+5B`G3RWQ2C>}%k!gO#>=Br}WH zKj7_e;F=npS>R7|g3IM=r_$r|wevIZ=vkQa`2BM)T*%X|KlR~YwOly1_Mr6SqV!Pi zyT6+G-Tl|NtBiSe|9~H1!rc86;+4$9=be2&N4!0SBDgU@xiP2QAm!cJgyo4xWOd&x~N`BZxL@*{WQ3EuL379{Hqxt_(E_?3w7<-ckUoLy@BfIc7$?>mp zkzfAzd>;lHjSedfp^VIv=Ub{9A&dDI)9g`Q@VtGN^t(?#A-ce& zAN~Ak8qyd%4)9Zthkdj0}C#9GhQU*|_S2mTx0K5bWj_Ig(?6x-E5B%GbN z@mx*+!saz{T=S+luOs7mF!F4e_^y!*Tn9ttNAfCs8TQX0Ocf%mxn>=2KSp-vK?sMq zu0d9krx7sWT_aggy+kivqjJ!pR^tzjSS!yaUt4kCiD&HkcVTbL;CB!9A0o1|uv(%? zv3f3d)V9)w-b!-*ypV7n8nrjVhbWz*$BTrcwn6qMp?|B#OW@aed_Pk!4>(LRl54)` zagHcn>Tw<#)gQv?J49Ryr128)BKH64?E7>0RXIS@pJ#6YZJ^;p*#DEqi^Th0k54k5 zMK+CQ2^y7;{NB&i1>!Xr?k5F!*uNK?15-YRPlBK2XwH!R29NV#<2OZh2s@tsVelg9 z`6vd;^o%8FhQNfcXbK}9=Xmq&p+yr?$WEO( zJjsFY@i-6uIG8>`atQoKyr0DXBBZbKcnSM2fgjyxaZNwqF%eHo_GM4FhX*|7efWvO zXC!@O?=bz@{uhwWJXrk;($lxd+m~nm3x#QH^*mZX-8y3SD$ld4>DJv$prZRR_;(5A zko*wlK7MFJl|MVXbR9Sk&7IH`!H2;2f=_@K;pInoA9f-;_c8E0zHjv&Nvglxnp4T)|pG#{~KxUODwYa0p7pG zKhOL_v6q>bwc*lpJbh>J^G*KIneMy~m~xrdWf$;TWjnu-_uc&S%wz5^0T#hKJk4q_ zGTc8U3NZ56Ujv*3Uj>cgMMurQ2>UXaXMP?GPb?g0`>Ws^uwOXSWt{Zre3^8Rp81#Y z^CpAI{L6X2$75utf7;>rY~B2;i8t`!w{Z`CZzBAMVkU2PeobNV%&Q%r@mTG6#bcEt z>DDu^e$%YS9|O;M{An=xagUFe@aI2=jSt@#uk@^7ANQ?Jhkm*6`*L=YwQjmEaU*aXP%Ua1@+95_0$SPx2-TOOFBX z;4G53Hz(XGAz$4&ahCVMpQ642DK9AKGdfrm5)oCnc zPnZ_|b@E3y@8g7XJs{`8H=T1R(mylUA0gvE0}cMGi@bTNs=Jg`75yvrRS8GQsD6vL z=>Cg0d8<8zH{NUHPxZTYC2x{dlYBj#_iK4Sg8wKFrW2G_!mYg>pt#{fP5ga@Xnh{Y zYhRwYJYRH9rsic!XF_T!C(#gR?K5EXb>AWIpL@IrR=tw_N$|J9=sVTZ+7H0;`+2bR zyYQEpBGBFl$-(2mk9U4CCH1FyoCB}&I1k?7@geYqV8Tfj3F|D6Ux_)&d;hOsBnsud zz6$`4#jpB)-iP_;sb7IT?q*-)?d8eZJmDPwQ5zciKi6LD+t6S2?h1qd;2yp)aP7^| z$?4VleUwW>MEBZn`EXv-+x>N$y!#EyxG#G5-;}!&!S7l2YuNfCiq|{60 zm)HF<{(1Uer(aJ8t@?^O52^elQ>e$Md%D+yKXiSP{5mY7JYWAQ{N5zL;6LLB9lVa0 z^@D{UgZ($LcoR4W{yQ*rXk8xsA7JXvx<#%OL*5Oa1mnl>68K3T-w!_9;d6Pt;T(^1 z;LRTA!O!*h5cv6E;yQN`e9+@1u*#Wu*YkSAoX0t^!Ja1@ zPJ)rke&X1$1U?HI_`FdxYryb&BWb*GyKsN9k@C86uW(HjEr2|O>F{$x`QjQ*70O~iAfWL@}du*zKcS>Shh{A}=j!uX}$-uS1&XC#|e zgTLZw5RMza?!}7q#s3dG58XXcYrVV_<7)IFnQmU2RA)F1YQI$V9)!e*Lb`HezU_8wVU3-4}Lf2 z!SD6>5cnRC7r`I*_$2sGJYE8S2|j-ezxRXx%Gqx@3I4vvOW+@Qe1DR>QF$k>t-Rj& z1b!&%tvT?|gW=Cs`13|z?pxu{8{v!5=fUW5!-v2JJYED}K^i`Z-;>~Loc*>#;8~9s z!7YzZf`8fLCGZU%-wzf~NSoOG#&>$01HaGXJopnH9|Hfe$BW=Edwdd1TVdfWfxqYR z{osECQx;?^(N=oHdGHg##JhbFta2AV306Xcm%x;<;rqeE4qw3QP2^qn7v#W`9_PV6 z?-v{bAB8{YwF?%(&&?978->+vD*ZD7LLxd>L7B4ayGf8`BK^9*nN-|4Z;9SY`J$@DiBt`bpy+(cb|6I#~3Y z!_LvAS_Hov`!_*edu*&fcH+}XN$>(9PXnq7HZD%bq41AQs zXD@+OH=oA2XkI6kN8ucJtH*h;G9mjzVDi;}CwLJ&3BDV=1g?Tf(<(?$Udzu5+_~G6 zufqQQVA0JR^e-!4N?!&l#tvO@B>vJ}M_mhSXf%9PHWyzN1lD8g$hB8>ah<(%Jli-&_ z^I`0lz`sdZz^{St`aXy17|&bZ2+f-qrsu)8U?IE+eiwb0tH3A0@JwlV(tE&5(7zeX z`>mhG{lnsM;sJ)QtR-Q$DcH6Fv8n~B@#(L*<1;PI8<5s%5+&B(UV`~rARnDiV1 zw>+K!|1!8A`$h1tdVCW6TVQzgu^ZcYI$wBi~=x+w+!QbF5 znnmz;cq{yqj0fRYav%Ro*#Cg{HwlkdSeNd5m@7xgK;L5+Iy`{m)!-a`PU&{!p${J4 zth%`X&ii@o>%fcHg*<+VYauoMP~eA%cOI8p<*w&UH;gz0&Cg(en^`8eJP{1<^k{yj z|D6us@>IfkB$#+_Sc3I9vrn~Canmz`VQiybt5dF(&w^9bK=`3q>?h8xcjCxgEQ z4Sz`<9OXBx&-X3j?*ZH?$G(%${4M5pfS163f2Q+`|6AaB|L;P_bIX5$f6w7t2YBOG z&#emo_Z>Em;tziN|B*L5)zkkyeuN(*lN@>JpR^jUcxm3luw?@pm81S6np?FG0G(%i zj`Q^ZcBH}bB{>8u_*!jKL@^=_jUZ|sfRzu`?dTZ!X7y^ya;X*=X)?Ofvn0RO=hwx*--}6}X{|Khc zRaQ0^a2TA&UTuQx7s3C&;VCDHF z_*KGZ+FiD{y+N2Xpwn)<)njC+Ee#4!X&_m*y%PYrrQr^;^$9S~ZFga>Jd(cKKE_*q zcyj0SBb?(u%2)r#F@`WdalPB`qI{{00^hz5_I_{sSC8}1{Ex?nINGUl{zVeB2!5Q$ zzYKnc$1ejv%VWa2eZBC2eGm5bZQlMB*o*(aNP=Do-s|zJ!Q)`@=Y}wbeyDvz=XT1> z`1yKhDx&BAB)H)*@^HJpyQ%WZgRduBp9b^XF8&{JY|N3i{?CB(v|XP9|1o&c&COXG zxCH&{p#LWJxZnOJk3SE-&EqeFRW9ON4oqBO&tgt8OI)hoj)33K3L{WttN)LLd4CRn zA3%vH41&5Hv!2`kiXZ5l1HYsp;DJ}-{trIhhk^eaCzTgZDu+3l;J1JJ{{(;+7iJH8 zxrsndk0G2O+Zb)nlfut&O)v48{O5T`^lu|uAq^|iE1!h%Hq}#w$@8|e`SIb0JobN4 zE{<0ko9OBPlKnai?}IK=KPmNR`qAsSuV?lH--xhyYYZp5zmehoCq(#us_9FWSt!2= z{uOv5;|9#~BmKkkcHt-SpNF+)@mAZii2WORzkvTG?4>Ur?O6ZzTfoq$FZK4{^*9Hn zPAi>-~X#Up#?6_!}r< zCJn*=@89PAJ%GLEMRJa?=Q-%zU&iHccz@l~e#g5H=uH|(OY$susQf>bH{mOe_YQjc zzs2m^oBqEOez<;DJYdOG<2hoALyKX7z^_*Wg~A9R?1(r&)v zj1KdY+RbVD=u4&XqEqfT&(r;zi}#N0?f&k#s>6J3yV+GFg-IS?$j=%4!Ium(M_eAJE>FH3vZFDC8o^BO%f8yz66^Ccmp6)r&eaX`yW^Htj#T?SN8aiLj z1Jsi?I<+-{4tc%fJ3c(=lQ>?|p3<#@?jJmz>Ud1|l!%Tr-SJ~jr+#fr_w5Bbyk4*Z9rfhyhx&LgT7eEZy!$zx?&1~bkb%1|@pR8~bax;2W}n`>U(w%ILD_#I%xaNrW~-C)8R z*bDw5SaA)5zw0q=sP4!#`+ekJGWUO=As#zhgM1Af04qP}w}CM*eiC%pzyx>>j9d&{ z4!#kLybN3k{x}$YGjJ9EK;y{^z~a|=ykE$F0jxY;!~aXc=nL8DE_K62@b7`q2LqG* z|0!5$DDnRtu+mVbiC3MWt`AIu;a#FM9|n(m`U;qT$>zW;_*cR3?B4exSAAd}OQQgC zb?-e76|(2vr3il|!`mK};d{Ro;qPX+FYPpNa4n zBOLMS{6mrb4>SCh8!~)fUxcH4-FJ3o|HS(DDge`SQHGrS>6 z+kLgn{=RD?{E7&_F2Zk(@Vhg-rWN5xPR^gn?C-lb!VwSei+Fh7w1|iF~ZfUXFnpdfA$k1{LBcS6XEkC zyfece_=60uvWpyD_#gOiX8(bRZ);x|*+=#61K)`3zZ2mfW%z^r5q?;NA0OdoM0jI_ zqq_OQk<5Pe_cHv!LWb9THp3r`c>clTk^N$Xqq_OQ--+yRj&M{@KX_kcAIJ5z$o>Zz z{!mn2ABxKBL#ra1Z7Hr)TS=iXI5swTRbhPi7lsNGR~;BC6q447dO4Xd9xs%utwyEX zOzM?twNgEtOjR1?QmZgMS3A~B^joM*g?FKqG#jNtrJhVRTYAY^TRP^; zq_pG{$k#rgVN#-~cH8k3Y8jcScRO7&!6+ZN@8-!w0C zwd&!Vev*aFo8-uE>ZpR6tWOu36hy(II$E4dX3HlM-U}+LI)$RN77rh8ln)nMFZpKTSU8nwFTW~0?gs^!+PT4T0QK8i>*6D!EM zG?t_`*(^7X5+@0r?jS})jwjX0LOV?s9dRq9YUxCRFr{&OYxt|A6iUT~X4wd_aaolw zvA@N;Ges(Tve`(c?AL@YnKB`KajjaG*tVrd3^3V-Q)&4o5u@6K%*je%m$DM-LWBu2 zmGWTSOb*Z0CMk+iZK2vKH{ft(j(35gH2U&%<#=HZd8*V4Q^i&>xLYwRk+KBN%EAmO7%S^ zay|=AVyp_3lc`#vUM@Fw4euU9UTd=pXobLEvN1ez$=J~NcrxT(`v>eH)+BGpe zIuf$%qw%3T6J7^*?HW2Tk&F#JAM!*#_YCiw7#b@Kn(uL?%L_<~@U~}oq_Ah-;3diU zRUV9uPdJ+c<9i(#+;yn~2gfdPU})En1G}ymb3ooxIt7{<6kclZsis~g;sa{Hidkmr zPO0oFQlU{iR+yb`l*@(Y>?E2AshyoPiKUVkjm?d6u?e>eP8_^v)ba_Wt6ZM1x121Y zqAAE6|IltT$gwasG&nvwV#MPI zhIS3_8Sd#?7$4nrsShOfci_^A!o=ukVSNAKzI|PxPV72R*hPe04lXobfL*Q!cQ4~@ zWN5;dxzf<(Z**es(AeJ5ahKOPnZwHji2d-$-rZweLE$iVz{S<&c5q~P*C1t%4D8!f z*ne=}gqgeOuG}-Wzi?o5-|()hy4(nVWc0w;=)`E3ljqIYuFH2G+_R_4**q2Y4|OwD z+#WnQvA57GLvq}|dn-b*XY}Amw*YwegCj#%A_fyZguqkm864hsaBQe6T^9T3is26u z^NPU_j$S%+)hU8lE`HCpoz%pAqtte!J(d6^PikPir_12Z(XojF^H5?3|`SY>56%L=(2-D zBfENsFg$Yk;J)G0B$6ImF*LMy4>cg}rtw@g(vwBI_KlABPT?ME)98Vr-rkfyQq?m^ zX`Yqbm79Yj<3l58!sQBfbkAr3?j0N|92i49d&VQ0o*IX0JbG|qWOR(*q3-h8d0wP(0y!<~+p@OjU=QW& zJntSF?4=BrOYiv5u7hL46IT`Xj*fPh$z^0^S8q=3I&iSCT;05KcegH|*o8p3PC_To z4vy>{9NA5lDY2dkR1ICvRtJYm#%ZjEy7hx1Ik;=|z*U7kgJ|?FR_`9Vyr*83Jq5J8 zTg8j%g)uVG71jv#y<2^wwF?u7;I1zEi9vLi^>unWOrl_Kw7$sx!o=|YA*xev64m%UgWc`5 zHBQ4L6BFH)L{$vY+g%vCa-vtuXzn8>xjmB>x$mXJv~PI-aChP&B1N@pba%HV>7W@s zpiXZu?vh@Yo{{mw@_ibwwCJ*SM@8+~MFkxmDp(PA@$vwgacIIib<0pFguR1waaL%K zDX?Ap2FJ&T_gq!jH`=2^Mkl>1>hXg+$FCYM>>nJzG_m1*vBBsy>kC^)w_amBc^9^>(Aql!SH$MP;vcC0$nbpS>0?k7D}z$vOVqGTE(^|cWsj6sZ8fqGhPXU_uR!7 z=QhY~!-X5o-G|nkEle&p4`Q`5J_si#?<`i*pMlL)rw(V&Ufe6Ttwg8yeFl} zq)?qMG3aHKry-sV_n20&_smqo-bWV73*`dC1qS?w>HL?N8DMx_o1Si#TZuCz)f(i< zw3#%_m@Q8wGvy*9|3>j}QlFkL&ll$yNF?>T#;PYub8hfD()JL98IR&f1z1w6kDa4Z2rRL zH5!wSzEA+wiw%Z5j9unxjRbR}a(JdCFjt-?Xu>ZjD?}n_@ib>`R9sf>0w-FG{^yx$ zV&F4xut1Jx-BeG~v{@GYW|J!#6SkU+Z{cRKT4DkzVeAEa7@i7|lJYd8Z1UpD9Rejp zd?*woa+<6P(Fb$FJXNhxE=)~p0M5|2Iz_pWyDC#e^GbGeVSb+Csnu$Q+HCOzVYx}E zQV7b7Q{}nJ(Q<>i04A##$rg&tq*a;GX;Mxll1E6Txni?fnLd#;%JU_HRRD7}SY?J% zjVY*divi^^XEDc=4byDZDx=UaAK@n4=C%}Oip`m%dCa|;Bb#OhjhUEYy}7{bibnZn zDo899ybF@a2nL&Ev01W`anpD8qfJFnFE?5zILKYF+L!pm6{e3d>sD;crWSLXGdtrx z6N@ltx>1`?vrH(K<+9_zRJqhRQ5RKHQ;&xmHJ6@hO%jJ?K#<7Kz`e{j5(wBU$rnpKBRqzt4I(S{o? z++qQgs|)kkv`t&&-0TH`Nr#@h!x=9!dg*HKyd&4yd!UUfq_Y=6yXSZow&!4Yt4xp^ zTsX2-SR@8b-_+!7L3)7dLq$Yb3XS6hseu#~D$`E3GMf?;Ta~g%-0bhHpEVUl=_n#v zH2=)|)*1!V=oVbLRHl+=7L&|8&(#jgZMxPtR&1b|Ol>QiP_pQ9i)gNZPA&SZ=gt z;R6d+))qq9s4b98sWydmxXFTmW;H#QM{Dsg8}ps^!_+$NG=}qo&MQvNNdwI?XWOV2 zOmr}yJmF|b^m0p$4Ku18m5f;2A-6LXS~|tx(-E|DTbjyRe?Y+C4~kW-0wz%wO4NfE ztrO-FNtP6)a)`*uo)-ypvB)`+G-bHMYQbg@$v~qVvP`Q!jiQ-cXr7P&%_-2-0Gc|C z=2C(*#~CWYB=w|FpD`gd2RAk8h)A_Dj|!5Our=HYrq$Gv2H?f4#TaNc{Spi^F|*K` zsvWb+NtdTI8tOxY;+#n#>j_YP8^){X&&8v6S#Gw2HU{Nl}ry zY^m7XyerOBy9M8p6iSC1etsSYsz%9bujv@Xph#IMD(l@*N>i2O#g!n%YSVdT^ZD3(pW zCq)i3RaYuZ7w0Q;N+ewjTTKzN2+S^x%1o8|(QUP=C#T6%hpA*U*QLTF%NkRZ#Zk1S z5ld1HsCibXN4LQiEzEcW*`?}i=L zDGf(mTzODr^`d%v8I*mNtSn7xcUgy%v#$~*tw0L1WGHKufDbK&7Me^(K?`SZs}{Z^ z>-;Gtu0Uq8UM_7kz36(4J|2puAO_p=8*TVDOR#|jmJrRvDyain7j=jPyC!?v7Q8Ak zp$;*|pf_EnD`?iOV>DPUjjqzrom-fjYqq5+vrtHtDlMdSZRvZ+LcBWWIZJplRv8YM zQ_!5H!ZBoz9vfX(>#S3h$E4#OsZ}@A9!joh5vna}&-kWw3$xzWZE4a$Ozc$GBT8a}0n7Vn4_Zj$5Ejrq{59=<;#i)e*NYCHLr0@s^g33Yo2B^Yj<~?6 zU6m?osO6%oGT!r*HK-#?#!>nN7P&gY$5|}1l1`)rj!)H+#xc)C<4ssjTZ%BZ*{DQ=UTQ%BXxmg)6WrZ#WF$s(SsOqWf&m!?s?G;js2;gfuH zB^`V^P?6c((YomLn4-|Y=t%iOL(9uF*?yHMUq3cIwxnZ!tLZLpm=; zjq(u$(KVWIuAJ2BZnuEOP{ldzDBu?vF1r_94Vf%7NpQWAq`eQ-FcTQ(tY#pLO@%{S zM2k45HXg2Dud$W&>|D@=X?jfy$QiP9c$&F@WERol<$l%nt97p}`1ajlW?VGrmK;}Vwx0oE zatUQnM#1UFsm;nXqvK*Tk={^~qc@Ez6?n2pF-yp`D~0~5cw#!ndh&)As%+kHmUM9- zH`}^RIY~Hb#WtF zHxt#O<4`V7F+U<(8%=t1I=W1wnmLw5d#uQg2IihZGHgJbnxJGVA#+6#*) zs8vBSQcK#I!aS)_SJmE_ql6mERVs(8t_y9YX1r}ORAn|sYz7t^>|tsYC{Y{0rWWc< zdMh^lw5TKn@nvrFyh=vUO>r3a(DlK#HP;N#Cr1>T_;BS)HWbpxj6i_Fi_ zT3G4prw}LHEY$KW)S;pjG-Jc?F~!v~vtt_nATXLWBzef9UKV_v0B9~7qZu+RlU{VwawmEoR#Xd zb}$vqrd6p!4GEK&s462am&@BXY}&YWiy5tuWj|kPxzIvV62{jFJtGaXU7~0&Dg1UT z$t=k^oKUn#^g?sS)TA_<)tM<9otOlZTSOYNbR;JOebp_Q4RJYD!;E7JUH=|gs~n;2 zbQ4Yf?e!|NP&175o2m0;gXy+XQN4rXnuIAdw6DXOvx4>H5{&|tm7uDcS?)5cBbq=< zg4s$IgWn)zMX3BwF3imyNsiZ>>h+>lETMivEKQj=TZpcw%G^U~W~z4B51-qNHP-~w z#ijzlcI_`|)tCZz+QxF^I?%2Ulj>rVYzxYfN?CbbR%y;t|Iy-&R&@?ns(^Em?x3b? zkBierPCrG{t5rI7h?Tm7h~@m833_<@s$FEfWwJgWz!ZHiDufOEPc)~SnhsomK}|CR zv2wOiqEuC-ZBj8|GB`7&E*f^HE;7iaU7Ds!ljPLYgi4x{q+83Z!to=@A)urZGi>jf z69|9Oq|IRjow%Z+yfvJ*!nSUal}U08RaCCJiH6pUMvzo*m_rNGLh(y4sBg*yBmERh z!UB@gT42(TD#To!F|^&z8USBdULP=|E+PZWwpV9esj7O0hBpL4d`cT; zd5 zZab&>bx=&UEuIC{M+c$vQvyclG0v%NhN0EowmM~C#K8bXfEIEvm?ky#z$Cx4s$o_- zC^TDfVL2x=5IQ>jFuP9EsJpDNsIe^2MiE=!UShLt96)5om8lK-C$W2*jVLP9wRVEY z0(Y7O=1bZr+O6P5anh};r15myVH4Wpn5x4Ls`m7BSYV{(ZL}uoKV(VjWs993d&beV zTZwzDnrQ41ia0V8LS(Xnj?7M_73kfht*@IVXAP~)3XYmcQrTdPV~ruA9=AOjT_Me+ zz&A`(E|y+259S>vK2ENE{km+wWzQtriSF$NGwm85tt+gep$JU-y8+0W! z$KPt0x@y`kYyG;-)xP2JD=O-J_~zP8S*QcVhD~}t8t(>uP*7K%U3z0fm$30>cw~5D zn7v28!0r@piNo+Xn>I6>gCoICTP0Gz!7?Kp8`{TS#mv0>;QswrC1VpK`&g47xs>f9 zS!_LQ6}m4p-_p1iX8%66kqlqXIyaktf??O-NHXWtk`@~2OftOJtFAWEW2e26+1lib z*hH>X%|x96X6K5 z5;~Bk=JmF*b*VOk0%idMuVEbO{dt^s9=GEC4j2IIGG_QB|u|wqFTaGV$p2g)|$nCCQ}mY z+s?W<^{HeQsq{WnB#bXu)(&AXp0M76C!huw7HosNMx2ZqEh1J~QMGLjfrw^JN<)(G zMi!d3YPdNk<4~=6#G7m?DVnjOf@`3S3Z;2)+xp#j9;RCFNxe-vMNQ(EqrumRrpoG} zkn8n|0hUC`myM@=himt~f_5W~Xs_BZTMiR%!6u)bl74S=j)k4J4br$Pj}>Rj?B^~j1*~f`8fBOZFQ@Qe{gR3ng3GE4*f#@-GgNEz)Z4AJk3X_u z>7+i-bVFnA1o1PW<2H_)7S_tPuT5c6bEdYy42Vxtb77Jab#;m{PC-F)uz-HqT$$>? z%=-~0FG%M+<)*0u>S}68tn3rbB`EvUJC}c74`r9u5*ak{;Af|tkze&=Okzx=DTiTp zkdF=RAH7_A`?QOuFn;jB0k)Z*An*{-w9&0eE%&wU_`$8DX zuo;B;CAU~Q6*i~LD`Q02EFXah%s+H6!&|W9Up%ZATQj^Wrb4Gt;utLIX#|=xAQ)W= zV7I0WG-KfPt3fQBR)JpiX&SZ856y}ClAv^1YPwKX;GQ2iIK~j2RZ2XT7F=^(sMJc6 zK3YrPJn5KnQ;pMJMCQ=GaT$B_w1$j+a{$YFuI<#qVOc+#i($3n!0>K6NX9$G6PHAW z1F>N|a?nmO%jSY=XL49!TEIdKJIKG8r<>-aDe&@S#U^>`@R&BS(lR+>otO2-2J^w% zE+SKTdYa~ecGyguS7OE;>*D-mMaup~wAZXTHW>OdEl;U(b}N_}nUy5i!R&@)sgWsE zwo94!LUDoOrkP@0r^#fBO4z0)n0zu_I!n4?tNTsW2S%IR_S!`0Vq`=LG=DEaqR_np zrcq)l(d%Aq(Za=5534cilT#O@y-{>WnQ@}>h62OLWt{xlEUCtubn;9~7Zur2T6z{Q z>2d_4Xf?oJ#hE*2C&jWTo3RlhMY>|b2%w+gDeq3tp3ks&T7Wo)0!CZ%cfRttjV z$OSfZpwH>DA;GIxRi@VEHl)d^Os(;eu}GP7GyK}~vMy&jCfokP;X<~*P)?j;#I}9s zqTi)s+ogPP+A5RL6JqWqFNp%UIJZ&TXtJ%D3$4mrlWm#GcXy(hZH-fnQOVwL;ik>z zLG09)Ac<1%#K|RN&X(=Y8(EgOY}-|D&zZZ=TxStm@_Yd+ZIrOz0*Z;9a1=KChJ54;M~ab(F16B`I4>yfpE23-$-u2dPd1h0iovSkNhNvqOPZPjL)t8rNGouX`>-b+UjktUxgh1@MD3OkbSdXVle>Qep0>dMr)J9Ok&o+|Y%tR6-Qlkt?kwJ~Z%-+3lP=MHX_%l~XY; zD=>CdrM}*FN<`Um7OwUvY`0-~*|1#(mkHbUKg401g$vt>p2A%l2`mW;rcA}1zI+_r zcDfRxEho^rliqWatb-MqGo_&s+qL~zjx(GRc7xvy7j6@uPnXvc7str;+GDY>K5VU6 zm*a?oPMGc+8nJq)VA=Y3sv^wfXua`pa2x)iJPJ6%sX~EN6~q{7QD-?DrI%TeWm*$c?}F}11<7#4Eb5!eGzCgW zn={8+20p^MVtOHrGBzfqV~vEJl*vNluw0WmJDD{N#i*1nQ#EmOd~&v>DDlX)DYPkC zVq32`eEy|ERCt=ShR*2KF!{}{-a6CM^6pX^1t1;dDQz=^FF{75)(Ed&g)iSAN4_#% zgfb=p!w1|kPmZ;?P_&*;F<0t1y6uK6oikBH&}^@9hm7gLx_*I07y1(Ga&c?3E;qul zBudt&ptCTWtk-jrTZwjZhDDV$)!>LPnEqecVu5E|QTV6J6b?&Yl(-};lY1Oj z&b$a#%)4#?pyw7ECYhrA%XJxzo(Z?>t%O{43xV;IS}P;*Y+J$SR7$ZP`9;E1i$915XF(ZHh=o9*L|d=NYfs|I zYvtB97Uoo_VPw|nyryUFJr!J8mut_rf{XL25i#pQBNLadKFgw-*3RafmUuN0z~DUh z>?uF026SI{g7XWjXRV8U_(p$SVtnC85~je<-QjLG$vyMpT=#`0akAtyPMY^;DMu|$Yex9;S;Ody0EIh7BWz;n*YqRPrWYgTDB zdN;W6#Ys<0YiDK^czD8~rFS5wosntIw3VlFty&HdTd3z87gc|I=S?~B)d~qZKv#ZT zbEc|X8*-~w`ILL7Au6>y@0;eyyKHnGUhi56>Qw;VsYd~Lm(wW#PkOoq z(3Tv}B4>RCQcZ7PnMJUgwF2CL?QAvu1 z{L4j|DHLWB_Go2fMg1dD?cs&EY=U69SmaGltRT|(R%~3HKli)5mWabm8!Z;h=BBF8 zY2|b{Bv*8dRFAt&+s9sA1nT*OrrLMBoC94+*Mj>-&=}!b=N;~rhd8yu8LKqRnb6ol zEyr?f>Ot-$N8W9ywVYSQ7H1`m@08qak93#DZY!m+J6q-@PN#-FE2XnnS}l;CY0c8- z_HMA4ssySBm0t7LE4G*$na@*1;rmePnx|KKD7oQj3lt(`OLy_DTuIeaNJ0pDht7#E+?49*ePvy-t8s6-E`rd3f)7BMn$QS#D6#8Fvw}cz{@Al1)0meG*_N$mZNs0t=k_G*VbcKU#*kTAvnDw zeHxEwp4-v!A2Eo>BWT*Q=6iU<3T^=d?u9Ap87Zh(v^GPr|s2E^-ias`?j!r z?$iF8&wXl6bDu?Xy18$QN4d{}c#yfzy2tGWFZ2fs7fY|AMxAT(Dr5zuiW@?)Q$nJGsu%%I8V^@W9_fye66RxHXd(QnO zU`~ifFIgQtx^S4Sc6Wm5fTy;XWESrHw{1BIxlw)7Z8ome(@2KKJT@{n)^%N&nCtiV zu*12e3zRsDiaz7SDyb~h36fZ6C(*Fn+RG^#4h?ecRe|kJo7nZXk=w0l`6g+9X5AJt zBeBh7fxgbIPLQ+3i%Xky0EiRUDEUUx(#1g9FpQRE7FcHw0owDO0(u+T+g6%k7afk~ z#)d8KQ)(23NBu5aj(F(Ypbn<7qe@p<=tvPhN_PC!ez=KD!LTV?tF=~UvrGg{mJ|2t zS!Tp&{i92@4S6Un9p@t}j8l~ki{9*>(eGw$u5e`+u1sR}gjEr=G<|>ePx}Mr>;Ma= zceS=-TgeI|Ie^r@D1j89!A2I1}ta9mPDM1CszIm5io%4c~1=;&NMUs!LUtZtlfIA&#Ofn*fSzm zuhPP>ip0Ekxb0i0tzP*%@^d?K8`Vm$RwJwqVx64}Y_-O6ot=qGDr&^hjtMHfiB3IY%qr0`9C@yB&*xR(t zSG&3HSr#g?g-X1HId1L6XkWw$*G@^XF#O1QpqGWf$$sqT_d%lTPX*} zb_X^-s9gZcigkxAv2oC06MzaR>+XtSQGX*XMv{@1X-EhkFvzh5*AAlS$^jUr((Kjg z*P@jZ(Q&GV$^e@+t3%#%=NcQL&SykSn`gzU!Bo_>R4Nr6ZiPD6l-Sa(6a181^vHqR zz@hrOKHJ9V0`+RbF~BI46RWwTGR|E@0#jAzA;^;HoZSfICCcBnEo(B@+;g9s+q}uq zgoLv}nN8dJqC$Zq&Gm(rOZ+P5ixxs(V@QX9tCTo2rP~%J!N zDJqq;UnyQTRjS~&pLV%Ug#tmKd0^VoQ2PubH_(iA5%YcWS7m0JCVXfg0H5_ZbNS0jzl`RmoF+>Nw-vkZX(qoBekaN zdJauGwWSSn_*z!fgjy+ucH$(mcUNkKZ;g19Zi(YA25rNgEKXMDv^m`GA+U~@zmO`z z*4Cp^+$N)W+k@D}$9bx4haXspFSkK6a>A=yBy2B;jsT)^2r+u0@x~oCxi)mU?l|AS zTSCzmNBi{6gK9rkZacyTvgIbUb76(hX+AgLPIuEg?yk$ZOti7g=U5WU8Y)+=z^IO? zl@2L{#zkUMPMwjb=Nex)PI|@Y*rf&I&$xOWo^7-&nv@KD3t}5WXlwMD&RyLecg;Grr<0m4_8CLY(N_Iu_uxv; z0tz!k>)Qi-!3N8?szR?qTgI1?5idC_?M@)jN$J#(k11#EV)JxohXNl?8D6%U>}JYN zV{%9OmrF-AbL*y*+L_@R?Rkz~q#ad}>4HwaJXNgf9+g?nrP>hbJg)3$x6ckus8fN@ zYLk&8Gv>Z~AI7cGFjZyQX}#va1m_Gd8RrWTWBWI*<^+tdL7tF!IYC;@t>s?q%zJ9v z=6zG-eFY8fKcqx(^n&A#rEHuyMeScl?%c3lGioa}e?EO2=wXP!*;+n&rC1a80nE8e zDsiDWxDG~lfcag+1-oFI{tIWi+>RoRlo{tT;DOX}!pcbF>^6&n1s{`etp;(qOI2p7 zc8t$#+Pyg|ripYyyxj>A;FDg-0v8LZ4JK>`R4uzNfXj7szYa~CS~nZWH{Gi(1%#jm zic8ZNZ)=mM?GH?*N|>}`l@`9tv2jMI3xwU;$PPc9aB9^QpJ#@yEcDD^l;a4uLuWqh z@L5}wK059!pno+*%yQ+lxuR@vnAXizNUm+tf{_7NrEy`}3}=IFqqc=>7ZB>oY9{oR zPW_k|I_7I5udXr}nHbY2I_&6uhn;;bgfCOHQ~FEouNc%7{5_q9cI_SI>}-eQ(D($$ zaEHhDb~}ylJvhNvT}JpS#7I}5sUtVtcLka{Di6JU?;RQ(o7l7jV@F8X%ApkT9ea}O=`p5;#H*d@5Zf*{R*(sGZ3Tlh}t{7lE*?uJo|H8DVq@`>(irjGg z*~h~vK5a7O%Yk8S#Of!v$fTn~cTkJT1c6tK?;ux7^e8T-e&mB}OFUdTAwlTm^$Y8{4*MjPLOu9lH?^RLd)z`jLsf7?rtfjmLq{KV2nd($mjNJ+>3Bl>zvu0S4{FF80 zl!2diwKK)oUhNckv~Pf!7=2e)i}U(uOxyO7Ym+!7!VjV-m*+}%HD0#1h4_00woKJc z^W0f=-4IVf>Da{SZKTlod)r6R#+zOnD%z78k9gg5Z`x36v(#zsiBOn5%Ibe>A5ciL zjpEwMo;kqI{Xl`ZjS)Tf1)W+Wgs>ijILXWZQr*=Isk&!jsj_=8uh|_Y8^cPYR7}sM zyY6K>kv7+t5+&F7Db2T^=yr1n*|J^iMsJ#VfwmR7*g4DybS}g(d)BpXqXK;5&gk@kVXg0Byx|AD!Qcd0{e9ob@ zb#YkYBoON=FoT{Fs2Aq?4{ZdA5~QcC>t<`i3WjTe;<1po3ZtPghDamn9`1xZDhfY~ z#~gqit>jJLGF16syT$^WI36}YXZDRwvR6lpr)pu9>|t++8(fk>rGEMbES)8#R9 z3L}3AdN+?9OmR~QOla^G$;;eF%xzDBmMC)PtyL^J&M7xeZ;tT7Dg%2_6@BHN{_0(g4BMzxQ01b z=Pot!U^ci0zpfh^_wCv`a$>b@ZcDXyIo{#w>o}8XR>yfqbv)RvP{-vVuH!OibsWUbu)(4M=4`V|Se*d|qQZm9lksa44OTsyOs`^PT{Y<1leKY&9kTQO{u#JwMU!UO-23kcVE!~;?58zthJZJ?=ta=%pnt|PPhgU zeNviTy{bJvxP+}|Q>T;b*Egg6;hhxiTf!wpofJI=)TS4+-jl2Do&H>{XB&!9o2fUU zO)7da;oekHS0X@1m~v;qKGU-zf0VyA#bQlmSS*a&%3v27OZg0T=?0#*vg@&zr_EE^ z1#b71TD#n|d2xl~x9iJAPnwF3^{&|1BdowQDs)HprU!A5o3>*GX~c{I*zIRu3sqm( z9krm8qYibCFni0<%6^;-nQXW=uSd9<_^i*QM~rGKXtf||2BiGCgUyx<&)wlJNn_^` z7my9QdzR!~&+wY~0iH_Y!R=Y>`K`X`j#gFNwzm{uCR%%A%_R};WN?`jr z2@UQ~dFUV{1qHUu$q2{K9Q}HYRKt|cPoZ%`KzeuU)m|f-=sbW8(7bkCw)tJ%Yd&L{ zrXf2473V8%A>#BBaG}P%pN*s17ZrALv~ zj+oT3+->D!jYvhT?QDEylirFYX7wtkg{%R~dZm^n=Z~rQu+JtAS_SY-PvQ4l#m>Ur zk{Ft`PD+_$`Abh?`c&rZR$q3HSts6SVSR45K8z4VwAW1oJ&IG@3o;lVa*C6*{xsBF zc9BM#&sY^xG_kSUN4HSeY@ScvgOQ2Az-|q*f|z?pq@``D zuUF+4Vf=J+yDf+Z!)_<{exwvOX~%H|f=tpvt?jO;ajoRo1Gfe8jos~%W8&}8W{e)6Ty>%4F@;);$N&R{&Co5vX^5wF8xS=&q{kDtV zPtlZ_v~=*uOHg-Pv_5XCPT6w(bS-3@pf)y|gSY9Cw5Y73ax+h6?)DNC#_6r2We1W^ zvn`Z7#%k7`D^?NFU)F47m>_SPVv#RBQLi-21)biBVR`P3wr!TDt&f>q$<;F*3QmtC zwtd79S6N5X{u?KvtBE21u35>>hFEv9*Wr-pV2E$qTxZ&yyl_*eJ&%Pf7h-yFBvFdH z1It#objZXX4_Q92D1F^wWeJ;MZ=Anjm3{UXSlq@{Hh8fnV5JM>2D`x7NCsN%L>wFx z5!-3ph2+aqGI_L2a6SyNpu_u$NmwSd<>TSnTbEXM33^9d+3<487e-;eka6c&|S(Tg0sa(q27^=XQ${ zipP5sPsj`DEWvMg7dd8eXGY&|l{`s6`Jx;>SMDs8;TW7^QyANMW#Xg1yNjXv16O3C8JYk+0htaxx1sp9xL;JfexKFCN447`s_&?Sm`kT{mXi*{gC1 zE?DK6EyKGxDvq6#D(j0^oJ{0nE3D!f#3Lu5C2`ahzFfz*t(>F>X_AxTF*1UK zE^B+u@|NaHOPGkUzN=?7i$SR^YnmP5uv}WOLhw>ttMUC-T_Au*)le=MR>BoA+D_k@ zSNUO5>8YXvy`)Jx?b035TI3Xti`;QNRSKyb2YGU3!_}zzh-!oH*Km3c9JE2ux=uIn zp#(S>+$3kJ5}9zB%FB#o{wUu;hFN7UNKl8zzRt}xPlfdJMY1i;94?f!8;7M)J4$a~ zvlojR?u>}^8tjqGo8DDzGFDM)CB6lWv#el&FkdHwvYhbAX(#S{w~r4&xu9g}?pfe_ zymhK*(wr|9W=Ii-&j~J3U#h0L`6%Z$b_2D2Rh7l=VKpD0fOw$-yiH`v3q{z%wpBJNTbq1BB z$SY_(b49===|!YWWGJb<7Iq}m2qa+!;D=7>kPGj}xAkUaM>E?>LsviWJtbG}R@h9c zmRmX*M6cF1GV0UZ_F)mVXHG4fqvcgpcCCk~wN*vmi8gYiQ@&I{_PJ@*ea1>^rIZ$$ z!!lpcLNSw%O0_h{r@A%AQ%|hQGGL%_m7TsmuftDv&$bB~V=X!gP5K|UImWaKAr~6c zr7hdHZ}Fcg3=O&}nLd_+nfSS*M0c-~C3k*>2vVSMEfxA^B9m}ZNxGs#*>c~s4ArAC zTbSnDe=@0$O-|2c*7~-h-3V?6hu!`YeKOdwEmfx~0{qpERgwa32=F}XYMhAK;%tM3 zk#M%SGVSb1YzE!u;)8>fV8F_*_u8aO>7!yRksamoE-p!dtX$G3&Xl53LEk;|kS{yy zYh%G^9~IVz+g#-~BLDSgPR4OeS|2K&EN}DK*pe*FRh-{~kQga}Mt|w#n1wt)1H%;W zHhaw#C;0?D{SwnAbG2lqLixJSoS71KS_h?d#3~nG-T=7|Q#!pQHAsLpeVVaRrShHN z0&RK=qVt+d-vVf}XsHhu)MKO@qsX*cpZSx?JgG}_gmO+oWj?Y{p(<)+qOMzSREzn_ zJ-TcTL9}vrZKXb7uEXULPpO(F-<{-Y8?|!*!xf#T;|pL$>4qulcF0OWxi(PUHS05n zUWDtiY2h_Jm=$#@%C&+ziL@B@!Bl7BLWriM-i;fqPel)0->szkUa3mm+85xJUALJp z;ZxW|jJ(rKMB^Ji!mY6m&A3lpFk4PrO}a83sReBEWm2!8+^bNdmv3E%V|LC^l?oy$fL zOeK}dOm`n!z4=BR-Dr`UB)Ace4**(nh{D@DHZi<^XpCJyV>;$HHj&x{vlwNWm{fb9 zkt_uF>}e&8Hn*sF|69WJX|{n-QS9zyzIEYqI+uwe84v)b04!=4|#*1KEyg zM^!fUI@or`Zy51vxZe4#U01l&Olg`PU?P5$c?}$3n%V|m>KTVl1Uz*@MVM|50QK!fJ zMC2MKCGcoltaz{MxE*MnRwFE7+~v+~Jc)`!3<^6Z@e}Q;!qm2_%CEzAd|%C`4AW1$ zY10F8)vEcm5)%cM6xQ0B1CeS~%L$L;f|ErAE~J6)|707x*bJLZd$)Orc69o5buA6W zyZDwpS0)zp^qDRvt@OFIo<7~;QTo);yY2rWyZ$p}R&9K4yTrxzdD-{*Tw1lC0bS`XGV=Qf_2o4s zUL_K<*Hv!E_e3GkH!m^JRt&}7PU0T$jFa^|p*0iH#v^()SX+ryGBP6x5Zd07Tx1%sa zWr|Ozgp;nEPj~01bx_@EmtTOB$8&dNC%nyQq&mBv9@&nnMjU*z)EGYSf@e=%ec`jG z)`vgVwz#c2c(=yl1shNTx{k*M>FhQ-yCg6z4j4^zs(?+Ib_DF~Lcl1j_AO<-nA}Cw zb5nqAlHf9(=)=62mN~m+#OLm)PPWJHZ#x>@IX*OY`OxkHpD!93+cUUpXgrjhI5Ayo z*p*WiBzeO{xeC6P2@l6}&WXLsyVQcGZ(Hf)GNg2CuJ%%gE!K1;6Zwmu<@~4HaTP#n zh*Qwh=Q7EU(~~AAtEmqzs5CWjEyZ1db(Tnc-BB!kfpa;VSDt3NF{dwgm#5gZr4Q8S z_yjo9#H|zb!nICAJEmd_n@E*aZ3dQfU(-1FfAb-;8*u;!mU2UFH>431Wpg7YRXc`97ptiQg%Gd<5t zg$ZP*_4o-v~Ripg5@-&=Ymg_fd z>PftQ)8=LD-NbTd;OjSSU50*}F^AK&yn>nE9yUC%yGej7DgCkicq zrl45{(|A!U5H@wk94Pn0*)(W!bhT5Tunqk+%dMLv@-!Rht{xHXPrN)_{=)hTv4 z5N4rd*RryP+Ne%zDTa&RH8M$ltQ1y7uHQ1QYB|x}k;XKy#0tsa26}gUzt2`IZS+rA zdq7xVNNJLkSaK98Q}nJ!Mv{ZaV|7+h73I7x+q1ZxRI@F^Eu^rLP$^tytAXyiGE3kBNNFD9Ad5==mswDmt~(mL(?_OgE$!o5(=@El5#7ru$NH}^w(&1I2!cajudADKt+@8h#^+~+{I!PLN-rr7=7JmA_n{$7%lzDfWg-mxT^+8CK9FdvP~mt%fs zWWF*hEz>jgf>F2HIF?aI+*`)7Q z8N@ftj~z(*-u`gRxeoJQZ$3Ned*8XZAMY@~zQcUdnV+yD>APg0hx2o{el-I|Cg_Kfp6@- z?mPbg$szcdA^05dIT(^NgAr#&(9@XFj08&>36e$CQjX(T~ULr=q&Y*V(JAhql; z@e7V$Y}eZ&jTAw?Vyaif-JN$$GnN<0MS#=Ci+Z|G$HK zaJ#$rqY?T2pL75JbI$)h&b|LbAoimp;AQeRoU8PJY2WGJcdj}PUiEVH9Bi=~_5aMd z)iKEH5nlIv2DaC5Jj5E#oxvDqo_1aDp#L~}5!NjZ`vUprUDvnKUpyD#LPTHsl7Ii$ zbv34-Uy5+q^G#i@YwK3X;ZMhSRU;RB>g12OuJ6L%_;y4e@s<5=`ljpp@f_qk5#H<6 z?}B6M&mR2gN>l&8xUOx?R~P*`1AhZK{W*KkbvxM8Rq^^~PrB~pZD87a_Gex9pzKe3 zF-)*^ts8xjH^{%~y2pgK$baIxQ^NG;tjb#vIsH4g;<{%`fw%T2DkAY6;c>k&Eay;=9C zy}JLtB=tW5(_rsD{FC$JmS1*m6Y<{1csp+UR;a(_x?fL2uHz|hczIiY(=+C?dj<2o zZ!5x0&-wkXdsW8UC7*WPH5{M4=*S+Qy$K_SelKhgdHzQT70%z@jOTZwzxoI`OI~u_ zUl4hYe4p$7ipUF|)!tt8CH=j-?7F`y{g=sax$bq`7kVo`KJWfD7aP15T`J}Z+aI0a%txVAP{@nob1#eNO>0j&ceTeOoX$Z z?^tv_7w&{S?^*o29rh2PZ+mT&y5@GZg=>MW~jkD0-^n4d?%;Nw41{tyYu5dHLtxi6WCS#l?_BoI-40{gb$ZtC* z=i7l|gi8@#CGR-bnuUJN^WDhZcBTI{!_wb6`FiK}glYesjQ@cq<%nwu@*(HrdG{vH zDfl;(_k0g-<<)sG?YSHJZ;3wp$8Nzk)bRb?bGwVBk3i1;y%fAl`CoUj#bNLsdDF!* z;3O0!{`V+n$bal&CouoXtmg~eF7_;rw`9&R{7>c$-w0kNUvjZB>`ktae+Ks_8Lt-M zwFqxU_HUAZ*Tvq%`IT%LJ_X)2{4VgG;R5n}`gcM0zX(nk`IF$J=X;O2m|TyBQ$~*b zayU)-11|Q~bzsKlUSS-s!&xIg56&6Jv&=B#bMJ4s*y=d8Cf^H1l}-=b9Q9YFz)Xo4Z}DoN45+<1l}h9m5Zkl zpOL1KOMF_Mmyf#mB77OyF?<@lYxoj)&+rxJMjiPr7tg?-(S+d}z$x+%T>ON{(}qQk zF(qCXvo4-R{6-5AUXJjZXB=Pg>!rVS%Aa@f*Jb|=!|-o(ll)6~bQ68X>!PseZ&Chx zF8(I2pQBCB5A?ZsRha&_d9PDGmLcEi;&0*lGnOM`{;$W$J(iDf(KEspY-1J5-*H{f z;(j<*i||^6Y3~F7H=ZwXJs#Wka=m_!(O$V8%k_Ia>E(KT9^dq=iuq_>E!`S|Im~1?&kgOARHCecpYSXBtMXR;9%CvFZHbg)3i@w#y} zc-b(Hr-McEOD_J7a3#XXy4_Ft}BT-OjW5bjQFH#?LoJ}Hn~N8<|C6W&lI~!+H(){5xf!#?9u#VDiPrfnfb_6*0bg#Q#r%%cPeif z`N&j}%zR{Oh0J_psutn32yaIAZ<3jhOwqp}zrg)=YRAam1>QAW0Ph*b{T8P{;D50H zlVJL<`N(wA$Z>v5r#uJw1CGyW#z*s!X~rjD+;69IMj!XvX~swMk!jc@=Zoee)5~P$ zBh%#wS0Y^V3^#&pdd>5F%txl{h7q6Xb;F3y^oC*BGQDY7;?poJ@!29XADP}Za*0oq z%zR|JW%w-QJBB4byM`q`d!98PnSoalpCG@%$upCnocYI0I>MO<=RKpFV4GQ{ocYL1 z(J=CnnUY~#Q)kMCk&nz&3?m&kJ(CuS0cPdWE>v(fD%3+5*&(E!U*5~=T zP0#xLc_>AF_ID`bS^GPbrJVg8DtOlZ4i!DO`&*-&?+XrLKe1Q0L)&;}`%U%Z_Wv#Cvd5iEqd{1=bjI^TW6oWVd@2q5MgGtYh?nT+ z$gkn~8~H{W{si*3@lHb+wg&v~@V*1*W4h$|VNBfFtH3Mdd+~k*W2M)~Z@SoC47@@9 zDHqG7oIA|^9u`JEaJWeM-*&MA=J)Wb(HD6=B1eBVeuuXx|7{m54M2a_a}n!D&%)os zd!98Oc%=~dQ#|3H&*x#2_!lrPcJuHd;43cnGLEl#+FSfPF7~=G{crbI_WBPp{`0h7 z<2_&V@*v*0zRlM=kB9k9j`urwKF7&Fzik-#$$XRipYePSUP$=!L-WUlq~USM;ZKnN zF@IcuKW)bOzmO#}KU^q8csarq&ze6jtWeJUaiMBh`iK9)c+4Lc)(peH1^6#=%^w#w zBix8^%d_T>3pP_bl&EHV#3*En={hVRZFOdJp#g|3C zY*^&d>-93aUf_Sg(9a~voUcsEu*ew?ou5qJ%iCP&g48h-JN1Lw6WI@&^z+2aVf{s$Mb2?# z+;th(^!twKH`pKgPp&~Hj(^ym{0;oWeXk(>!2W>$PZzrYE+N<1HxZ}>?WI{4>lUP5 z3HjO}?vF0(_X}9`bB3qDdBfL&5nmZ6&=+~pF#2*O!_t45{F^Q&@8?~G{6pkB$Uj`w zGk){is^_O*%cl4be`UOnm~CBllx{pV0+-)U!b;Hs>?bY{r z-Ly~N=XLK=zvAD2_N06~HQ(=nJraM7Zx8$s|MdN6Ps6k0*2DgF{i=ukt9)O=>+AcX zeMvIctM*}h>0jR;?aPz-zGz>;v%W9d2irtHV8nM{(J+qZeHAj_7wuak^L^32jR zc-wQ^{ubrzPcFs5_JoJl(@qVPYMCN){Z^g)wKlHAU`TnT47U8uBZ+b>pf~|Mk zv%Wv-Z5qb=qu!QbiO-HsN_Vgv$|L^$fFvEm5bO?~kM&Cg@KX z&sS0p)8^~JjPLy-zZKjta-5`zEyE9ix5<2elwkaW{UtsvFW2`+i5TE83C#Eh z`d3h|0x!hAWxhY^OBlWZa>jd^?~nS@lnaYI=ULwmN&SuV*XCk`S3G0bV3YcqK%eiA z`s#+^pVZd`a=t(6V?1>|tFJ*h-yiicUi$v1kMU?To0lM=imN{Vc6eKe=qU*SL$t~|A2A)Nxe3>^Z_Hupx9iV@@elk$y{#-wi zdK>Bg>HV&2Y!Tzt4G)9quRaeCG`K&Xj|a9QO#k%xSW>dUet90o{X^?(g6C!2KL^uZ zuJ7{(^ARpYnEvQ`;~?$V`|Tj@mHVfxHxAN1y`Sz!yV#@K{%VBTpRPCV-|%wHPxfz; z;fv%a`?n+9?BoL}GVBiOYtn{c-+?UoZPwQ;N4OYa^dt7)wd3=X1GHE3la6{D>A&vv zH9tAf@T~DVK>KyQ@xZQ^YkoJB^X#|{(LT*ThRP9n)wAXwL$puxjiDOl%twYc$jm>6 zHa%u9!*xczvLsh zzb01=vuH&7|wfnz=)65?*xqaX#GyW z1#r>mBR<0=!-$X8_h|kxTrqOQXLyCo{A0Lk82QKWs$s-uxMmpf8D8_O`NweG$Pu66 zb;`MZHQb2sR)kxg9XG893i1IQKUxnI@Dl1*peN^Zz{o$e9w=bsA0v!^!1sVtMj!dd zNSdtmG#MjDe6$`&^N*37mj`?r^1R_o;DTY~A0x|T<{u+P!#6-)CNuvSsTdY{)wAXs zBaC;O>k;{;XU9$Jhb}Vz(0ZYO#lIH!XZ|s=V;J){vP)+EF|y}b^NZ1Bgi{gDk(qyJ zJ&@)bql{0R84tC8bj9zl`NwG0Fzg>)B{TmRT{8^(N9$zfA6h@8`NwD@B5!%t{9}~y z(E1In9|~Cd-{bzwKgJS$<); z4u9qO{lT}kCFmG!m>^b;`lJ8{I+{6pMw8#KL{A(r}Bm|eyTwJykAdAAs&Ig zFvd@n$$#qCQ&QCkuSR&ov%Zf{F&+V*L4R9DF5_>L`940?G%Wf%WWJA2?HPuAGT~X@ zzfYzkoQd$VXPuwPqG7~mvSb+cO_s@=pUH}0#AlN6(DjkYHOe_(ll2HUJnQ^uy_U|; zB;ygVjNha_=V!8ISjOKabAF~6k4Kf05qZwD&d*fdFycA2Y#8HD70H~RDaJ$BOQu#R z=lo1n4NHGD&pJO->k;0F@HYPb^acFG-)nx#VSo4=F#M_YgZB*Me3bevk-s_aVqd}a zVmfVj3Y;;F^L;vN82P@`XSMeidBO1Y;AO+oKjIk@|t1f<1=gi z`lss;QlBLEn}A{4Ov5nl-!o0aGTx4#e_el=O_I6(Fk7TP?^m;B&yL${h4L+b|C_CO z*8A0Loy_~w?56KupGW67o<6V6WxQPbpUXu!&;7aHFt_4apXcYQWZZk?d46s!!muZJ z-c~vN59)={Hn&ST`jz_OLog)Jf7?ILA4*4<_THuP0_EtpHH-b1J?r!Qp^{-ZQ~{+=ei z?#FZ7(&%6O)%OAEW<o`G-v=Dddj9C6Sf@n159bZzdU3cw z{&_5|!M?+#2$v&VBmbU@UB+Y`X1qSS=VC?apZ@9lhr=6QU*A6*-ZYHs(cvxfB^Uht z&SCm{f$tyY6O=0_Bb@Ere}0+F^^W+Vi?cU^HtCH z^6z)%SB)Ik!}%KJ@_ykuFyo`^9rJY~KM(o3;U~ZwWWH~hXS}ptcD_M5-!IHJBi!m_ zT!Mn*13!XoA?-PMe}IecLdG!Svye56_$=fMBR&gx!-&rU+T{2P`a^scmdRZ2SST7f z;B_HzK_48DR=Gt&h_8 z4Y&md@zeJWM;O0geFN8zBT35n_d7?@WWH}WlJ%_b8;;QbHZMoyYh=D}I70jN{lbwA z%5i+i-}4;V^6ae#?|9bt4M+A2V}6d(pJ09CYH)&bdH;ap?+_f#3$r}y_v$;nn~I zD961~@}uL$2yc;B{QAc6ZNsqVc#F(@=PDRt^P{U05zdo$d_Hs)$Jc!5Dvlp8`oF5| z^>uyYs;Xy=*HvqtHDA1{5%QbZe~IJ6tYBM8d%5N_OF7RJyQO8yna?cI9$nv9DpAgS zW~oYMKC@K!toh8+x?$uqOB-b7GfP_$W_&+N`3V>%@%$+BnG^I!^O+MVFV}qLMA|Us z^hCxm@|hF#SJyvIlqhHZa$+UI)d<(g%!f`i$joO>(4Qb*!TtIK{n32pMAPUOAa5DQ z{rbd?Vcf4z?0VLG=ER7 zOJ+WE5;n_x==#aY_B?Ao1Cs;)_3wX9B`9Y;b1EI-OoYqa zpMQ^hszN#QnNur`b)T&|RGpA~X?*XqFMm}?@PG&xHYTd{YpHmy2HJ>@P zX&Cv;sfJIH-azB>8 zN4~m3IoD6FUNH>+uC9`~escAyVI1FA*T~FguC9C5{N-xKqs@&@dDfAc&tz%8<}=we z<;-WYdC%A_*s>+hn$KkEPr$H0OMf(<$yTY)d?rhOG+)WqDQ7;DU5_y5L-U#J9_6gx zxCU0q`K{|G*CfcyXRb*aMm}>5{ndQt8U#f4Z*wlf^hfiVYiPgbGuPCp&-#sP);w!I za}E8`eCC=4^_kCHv(?Gh(tgcnuBH9@_YBvjsn2}oTH3Gq%e4hBZ}W15VV}HT()E&S zH^^KsxpvpHu9sYg_=>)6*TKHv{S@q$^^)t-p7njvby?5)e&agCFVO#%UoW|C)pNVQ z8s*yGy61L(o1WYKH9HxXn4tdx-%nki?0jExeI~*=&p&m*#Z$;PuFsRN#q$}?&+AL% zM_oK~7+f}thmY&4hHnC|8kYXnJimDbrMx&Fu7~~d{^qBC-NoheXRhBN{{t7l48Fld zI04;1K&=ekKPHbu4u6Dy>d#y(bpV_)JOWM|o&&?bwmxEVL*6hZ^M-=qTfobPA-kdC z`KR+PwkY<&AL;L>SDdR)fa`{Pz#HUWa&8@yalr-0>-yE;BjeQ`zd`+`3;tg1#%<4k4Sm0f_`hqJ{19RU&Lunh%jF`h`hUa4ULS=%?fGke z}e*q)+_%ZfB13LnK1@CXM7;+{>{;YF9 zISEc1#>4s<_#f#1BNvm!lQUVvcsX_^XISI~@~(?@!zQ^F2Kx)+_&rnf{0Xc_Byjwk zDU)$L4#M6uH8SpxKSVsv(4SA>{bY+P4xF? zmt1@g_S}@9To~8Co08;5T-PA%zbQlhgp2RO-kY-Iue$h8mcaD)XMfo=cJC_`>|0!ScsQ4%oX6`q z+W&DLujeY1^LRX0^ZW@OKj+px|2)pG3a+>3=ug0i&pG<@^T>za#PM^E{(N}G#pUl+ z&(WWs$NBdb_~s;zsb&1V33R32;AYzU$>XkTWgeXM;{^=gZl?X8T*mqa&c~Zel>fTx zdJFNoxlI0Nu4@(c-CT|EDtXU!$>&Smyy^K((;)FI?AGVehT0 z{`&e^tdA~ZK5wmi`6m(20{XjkGs3k0v+s6Y7ev12=Tq~&+Y+7~x7(7GZ{gU+`FLA~ z^FIJvG5@#aJZpY-Tb1^F5`Q`d`R(XO?(d)d=gz$>-0;lq-R(OOM*Kv-Hj2N?!}aDo z#t-;m7h8kB=TqbrtXCfgrwwDi&cnVyU*tGO&m+EV#_@SRZ&>y(knub&^MAff{zDgg zX9isH{JCEIy)EK(zDEDiw;ccH>ps4p!}0%ZTwl(w8y5X0`61W!9n9Z(#9Pky&tZPI zpnr!W|8FiPpMQHtg8YBESQ@t9k@WlvnBPTQFYbWqjD|J?;K!4~~tl z9oTbcnff|@)V`XRf8k!&^%KnRog1E!4|O}?hG*nI-Q74}?`#^z@pR`7_y4-lB5!$i+zRkduIG1d`SbfOvZ zG%VxqkpI-zm)+wcoQQDNv(_)&gZN1QT3>cg!7#?ZXPNv-7yNzxJ&cFeFWpn7ob^lh ztQbCn{Z~C}{n9=42(L$Y%d^hUJ==ycKljl8KrZ&RDChj#vtt^e(o)hIe+&q8y0!lv(DeW^smkIug&XTU+k67 zSGc$7&&MzQYvcpC-`xv;X-*W-Kl48ynkoMGfQ_azKt|N9V+pufLFJ*vpD zPn#jTFKt-*%NmA#_vH-ZdFQ^oVcEan`OCN$yea)J8y0!du=HOxEd5suOaCi|W&c(3 zT`u^3gZpZRMZOl{b@DUFk;I-2!=k?#;Vtqb>HiFJy{{nOUZy{1_z(#4 zZ+OP%g9qPdv5fH~K5gEO={ri z+#bjqeazPbMKZsy;(-#G-)Hdv{n78Ucwi+WuX;Ym@3VNIM&|cfJW%(n-)Hf_x}Wd0 zuQ>M|8Nb2)`27|S(BGTo`zy{vzSk+goQue5 zzwUpT_P6(ky>fir!tb}ZyxD30W!ej~g6;Ay_3?cLucxu@kc=?eq(9vrqjp!vxjmKIsMoA z;D?I7KdldbsAL$=mk+HN#_{k_)!&b`KKLQ{EBT(*V?5NPKA#UB+VQOZJw$)>`QYJ% zm+Sh>!znWJ?T0g-k%tELtPd~y@w8s};f;{x^GP1w@~q=M412^r-5zdH{}*vRKkHmE z=~?SziWpz?wLYepjc_i)D`fnXzyB?+8iqZ^HS*iOUbwg!;YNgM-(5Q{s248cr`V(Q zF~wcO=>HKo7Ray1d<&;M>wG+tp}d0ojmVdMJmopzcFgA^wa)lHQV;c|-slmIk70uC zQT$)V)B2f5IUdFC(JbYxpLsM#X1&a#`3RTDte<(b>{;t^ABEjAUcflUA6+H0-sDl( zAIOFAKH$+c!|wvu4Hv-chA)CQ3_l6p^sMzJk2Z`P_vc5qD3^K@96ygX4dZ(HXv;9} z>5uM`Szq#)Gjcr7Kb9o3zT~k?gtHNb58|(Gj}<*@z3gKp!-&UYWy6TaV->^b>#-HX zh{t19!-&UYt7O)fJXSMu#N)9wvecI#9*?aXMm!$dFpPLS*6^(LB#&(yxx}MIIqC)E z^X(to>*Omg!YR*a4z?>9%2`ixC2M#I*TS4(oHJMQhHnKUCKBJEo)#CKE6awlW_G1W zWerDpgB=x>l&A0oM$j30d7hsax=FQVQdi+Ehw>*UAb zwdkw-@swvY2ixO}ht{(`&UonOcRZfw{;dCaoc?OP$K&*;%@wcT<{FvxACIqj)_R7= z>xOYXd3=-1dWFZgBixMeo@cFJz#$a)tMv;{Bn_kgC(@p^Ug3#cgz0ZvzCtGku84KJ7XGIITVg7#|t{}Vf2-sas-elp=1W(V7o>99Y!zCOwLQtY0jJ#DUfeXZww za^17uub!lRdcS&di*nqHq@MFh+N<(Xl5&hA_p1`^xl0)Kl(Lk+?eABm

ueOndcy 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

Fq@Vr;Eb^^L|J$B1UqPKn|86HE-R zhH>yp9gO6;?K%*Te)^~DGW+*B&S;np6_AZ%}|y7!A@D{8rt&gxDB;D>$=Sl`&W4~Nx9aA zq{vzql8$hJtaTyFo^{2sb@DZpj_W*3||Ci4dY$GaL%)?+YIN89QnD{xdiJp*MS)yUAGx7 za(`LZIS+ZsFxDl8%Ve(G46hjZB;-{x*KLN^B3zGf!?WWy-1MyLHp4B$cwW#tmq0G@ z*)?*B&z@n#2e+W$d+8DB2yBw`F_0rZBaFAM%ZxCdZLV;CuIp$W48zl|bGe`EHd^Nr@DlppfD>e` z3t{~Aa}-9?lylu?G-LP%?4S3n>o!^!)8#tn69WZN^p%V}8b} zWUkwc)ePhK)4CO{0~y<(oa;Dan-Sjed>`vV#`Y-Jx)2y9^Q+$zHJ%`AT}a9>-b;?B zJ?pxS)~&QTACXr)YhB1V{nNUT@m1=xE@Zq;=DN)|{n2%s@kT_x>si-r#_6A~+f2}( zc3lYl(RCTEOKEe?_t$2%pLHP=WemffRF3?%&o@%V2$v#UCGYtBBSrf)|47k( z%|B9gudj6>sfK5bSBmk`x{%bamuvnuN&6f(tt-*|VzTV@+w!VstqYl?efKcGn52De z-k?77i^)yTnqN#d3?qJ%TZV50x5&%~reKJiKl-^2Q>h52BOLLsU6-Q$(Z3*{zwZ_Q&;SYMpY{g-mT4#{F}u zVHo$%sV&3EFQ&H1%rB;zMvm*(REx~~Vrs9GwGQT9ts6;sx#OmFEt+3wT}!}-&vee~ z2aNbk=M5u1)A$$M&+o*#8R9d&Y#8y;Iv33^rb|YS_-LI=kPlo3=KKVV_)M=*U-A#c zXS!+_@tI!rtog+>=STC4={3rkKTK~#cr(J=o*ABYolB4p;P}xxmw=I9Xq`*I$Stoeo3xoCbdlQr^7(9apZ0?w1Q zE`;-?`Nd3;a;*y~8NLDgS3GMzp>;29u0`bQp5b<|X&sAxul7uX`jT&me_LeMg=ig% z<`*+f%2^kpbu5}c;1(Lhx6O$NXUJL?!uYi7K=PC`-_Sahzrynom}NY)E@XDa z?;q5eV$ooB)iBOaty|IjVs@Q!<`=UY5#IK!`Nb^#*Se6|7WG*dGP^@&elfde7{Qr? z4|0BLJ~5Yya5};h>Bazn)i+qdxw*TCcdHVCZFysq~PWeL8^9Q{U2_${m% z#>4zV-SY?WIU<)uzHV6L8=j>u2DK?}f&RAb+4geOjl@dFA>Z|kx{=tkn4g6`_IDHh zE(r2P>?rf`!PoG)3m9)P=~<7TMT{@!gB~x79Pfj_?A)6;9u_%Xz_Ndn{rxK}eTuwg zSmZmNKQ!oKFJtUQ+9Su$r(oX^_@u|j7cd`3s^m|jE(&~<_I~Iw)J0{$v^QXpqaWG- zLz}3R5_#UR$cvs=#_|3KV;$Wyd;)bcXp{Zbf2orZUbz+D3x@mKvE|Nq9IJS_#^czE zVfcHD_J5G^IJQc;u*hqk;a0F6t9#aX9NQw}e35u$=-+Ff_VLJYJdH<&{cAij4Zpv} zBeQK7{T)wwUU?rr3uYdiHZ1ZY`R}7nOStSgFc$wiUh%Bw$8p;80iF-XYZ3Xn=Qjpi ztUiGKo1Sqj$K-R7j<-Cw``@Ab1nM9#{#6jjd`KPEI+C%gX#X4d+>)=0yg)hXuEgG} zX#X2HA2zQ6uX;JYr!e;IVKD9c@Oc+&hyJ;)kJRVWW|4|S6D|r9(esu!zlYB$#SWc7-pMyU9ZObtqC*W_utYbM*HH>@G z3HTStweDy=!W$9Z_N;X*Cz^(3{FY%Ee~0{e)*bB`#`q@_WY)2qOh-5q;bqTS$8wVK z&^nfrWh2Mei&@G4pBj@Ar|eBHCwshn&?cq_uYo^^gs(%*m)A3XAP z%+IL=ne%fhX&CW2#dv64(WxBeoUc>)2$wwT{G2Kqmhl;nK#usFVmuz@{G6&%Us%Sk zkvTu77!R!r(>kFxH@&{j JS#Pby66Ub$J#z*Unu4X*6&gkkC_vidvoi>dAuFiVa z`MJ6f;pI;L2%h0w9RIM%=LdZR>&}%yK+-VIyD$DZ+Kk?p23_}CMlWFKed(@x;HhszVF9r_R%b1nPd^fk|2JCI{O z&WRn^y7tK5^(?h6BEMPe#@1a0&w^!KY~5R(+ygz4--72l*?Q2g<$X!d>fgQslwi*- zxVFkBwI{;rPj4FfxMym-df~tDyRr5vTkj_RXZG)f{dWJv8uS;!{S)h+b^k=8bN@tS z|GpaZkA(a8)jjL}eUb6|c00%Khd*)5yXyCgJz({xANE-L`*%9`AE-hf7Z}}tK$Gj5}wn7FW@Vq{SK7WZTNOM9s~Zj+y3Vy0!YJ zm%*4XJ>E~(ytNWY{ht%L;ajSmoTq=P ze=q&{5`M~d?;iBw-+OQ!lF=edZ0$;_3DATXSL@NbnW%(QYpd>&w9PO414YM>hij0J>D)u-=41z z0)^F|2iKsF`O)L!!41!Pd_5@h`#12J*vMOCdo>3({=PR4hRu3Ces9FT_qM!Tz zoC%@vQP^zv1wJhkw{Qu6GGCuXlR=d+q_R>m*J&e0E;Z zb4(cbU5#s8`g=4y4@Ea%*e_eWiT{~-@5258H}Df%*BW%pymr;mXpZA<>~H6}Tl_*F z=k&h2=UL~qrwlgt-5!aPVZE>FalEhS<;uMnUi5Wddo$i1z3=vxJnL~R_fdNsCnTQc zI7qB??w^1?HXeP;&^PzpKJ;&o6S=R7zK-9w)wzGa=$rd)f5o#NM{-}a`}a3G_a6}d z&2cqQ_N>RvK*aumi2Z{F=$qqiQ2I0XU8!w%H{l<)|KHtRF=e=&F%<9LaGfay^c^#2&C7=iOG* zn%^n+P_Fr3Ps8i$aV5v0ofpmT^tjsBg1)&vO6{*bu6kEG_wU{CtotYO&^O0bV%f7E z7n0xE@e{4i{iW8_9#?%B&t9MUBK!A6_V1Vd&2iN)`-Ank`tS0&$o|1`XpSp64()N3 zu7aNq`#YQieJq( z68mHS^6tmRV@dtv{!6=^`@8?otqY3(Z$h+p|M%@(|3?f99g%i4jlGOE>ZjqGZsU@d zvpts4R;1~_7q)l7SKSu>wrNMqbeq0EZ0}BKD{3-+Cv4wm+WY@a*xp+;`nj+@IA$r@ z|4+mA;M`?<{3i$w<0Cn%Y_TmoRy>bi=+{79TKzWrXZXqXM1zg^F(ua}wg=Bn6dk@T zZ13GLH6TBx7?<4}Ll%-8HM zoAzp`KYBTAm-<%ShW;pQAIfPfYS1JvVI20C!}j6NhV5gOu)Y7zu>C+PYy%&3xXp8~p>PLpx*Vs0{-qUo!d)w&Tah|6)v z+mDpm&2Ih|!*;22)otdIX>L>~?Z(c-X5M4J!hUe3GxCqe$XSY=wf5SCx+P6%*T-(+Dy|8`3 zobU2EQ@RcQG=8K0QDe{KzYp7`o=&&X9@AdaR{RY~)wHjL?S1C_o!$)F=UYbKj643% z!uDe&{LXFi%lL(MO8uH{Ls`>a&{kY;|G8<;hwXz`OuO-G-)BsFCDcFktES!fJO3MD z`?2j%f6!c)W?EtUz86FN*>u=GZ{k0j3EM}mGx{c;1J8x+dN|8oiOZ(l#AoV1hVAop z{Lbz0@8B24^N{I(SoURmdR?_qQ&=+X*|7cKe>UwVK8s6X`}}gKAB%_QqmyG;Hu!ze z%**_SZrEjA{n-i7<*FLusz5vRo@)9GoLj5n0Y^Bj;ln~^z*3E zuZQg;ziHYVVf)~1ro9!mk31N*r`E&vNi*+#=J**eh5CJ~p?*s84f@qr3EM~H;LvvC z*AZNvwY@(b>W}@gX>Wz?3F(vl$U9Hn#>57;YdS2llz{5*NsHeS`|(rtSF{y1;=dNQ zkLSbosok)Ba4T#-_-fd`-}t-mgRp&UC)D3>&btH2uzlgLLj42c3%B(DgkNaq(5ANH zxxmch0kMtSK{H>;gtp@O#hgd>eUa4AYyYE#P=DciAYT7el`@V0P_FUM0$n-y44BICquh9Ni!uCGn*JLAXA2RV7UJu(xB!AO> zcEa}Yw@rI1Y(MaQ({BCEhwUTDP=Ee|rrpG$FA=ue=j#I-Vf#oGzjHeGSp?><8 z!gl#POWkHKoA#8pVjb?wVf(@LuzmFTuwDM1Qnw*ch?Stj8JuNY0d$6WX(d?(f_F%1??Y*Ww zSi@)g#CJmd!4ezsW52xL({b0s_KE)xwjVaf*MwX*sDB_G>QCJmw%hfN1&N{dzZ>eO z-y62u^_o#R#;HFfzH>{=)Z>g$-S_B=yRq$ZQ9=*whtG=_QC%lY`6E{6i#3DcdQla&;L=_E}t8s z+vIxKKAhH8yq7ccHCzkZhlfLb`+oS)J7N3qMyNk_By5-OUC{0DkZIr4Ry^0=6}As= zhwUR@HSN1$`-JId$>{f84E0CMxHI>db~(nl&DZb?kCTzIwqhywb<CGBaO#g0LjCFYn|9OxqTDyB zKW^+f_*~c?ylY}t3x8_b>uki2-rqLuYhnArfw28x%Cuh!+YfDo?fp-M?FUO?d+$fW z_EaKlpEKu?d|tP1vybC9`emQvM&AhACyhN5vM=?gOx${phwYP9{LXFP@8cKMH*s4q zahu#yZ9IRO^JvzzPl+$uPd?NiGWY$da@d~E82x70KKw%1E`M*U+r;6pUH%SVw=sDi z!g1$JKSL&eu91fZIOjlGJ*QJl+caA%4=6$?n+BZY}p)u2L z?Cg8mwC{!bGpEA#Q>m~$c&E*Ar6yXp@h{^yZ8veA%$xQSe&;sw^Y}&ejbA|xgSMME z?0eYg8-El3Dr`UX|CDwwaCTgGf#?60(u!sL(rp2_#; zOuqlBl}}Cn*e;X5EjIc6*88y|p2;7yo;%0Y9Q14Zf0aPb)Bd@4?`PJHKEI(p7u>w$ zjq8>dO#NGHotMon>%MwxZt};!+UiHGp?ZC}{66BxWvj=%eZ0vwUk<46FS@+7K6|Y5 z|8{E~4!_IPKWXjnp_i<@bzJ(>tJe7mFHWz|;R(5Pz(uS1`ZgwCIsGKG7N zoBVa9$!|-n{EEqMRBNdFS-))Z2mgb~+wX^utM{L}e$!SrxkKcKVK{hLkwZPxl<|5qk&|9ou!Nt556 zntu9^n*8{p$?v^t^4ry%^=nMsC-r{W?~AtlsmYH|>B_R%_m@`Q8h87*Tlw15KQd$T z>hFAYud&}S`Q~?~y5QI=CckH1CuK9PzOT{q+&gaahyU8-cLXNCZ_&y}CV#!P4ku!h z-+qr(f8OMGK5yk$On%QVS^3iBxBa=5ADI00Z?p14lRui7{7&EGciwCA_WRp?+f07v zw5fmKkdiq4I$={^z z!#clf%H(hS?^b@nJ!_`^rpqS3H!=Bxs;;hoxNq|Nt@-b*On&c=oBHbSp>?lgUuE)#tomEk zvr+f&`(17MJ^q7MJ~R3LVUyoin*8>kHF@=S#=6(ucbokFE-BmQcNTiweW58hVBMDv zTKQw@{XkcL$<*Keq?I3-{Mb*Jy#0N|Uh6ri{(evQI`C<$zLnpv-k6x_r@P<@@gMHu>9YlOI#>L%RB_CV##4{Jp7f@>{I+x4$nKdzaMF z{oE9o`iIY2`N-t`zq9g*$$Qp)^5m?^Z~HN;es1!+f8EMk>+h?vy7{b_`a5Q={Hn=s zw(eu8b^bJ;>FxS2O#K_a&#GUV z{C+EMe=g_->pZtV4|ecA)6bzP)6We@t-LkvR#ipM=g^`;``Y)Lveo&+t2!y0y<=9s zHu>v+#pF+@W1(M1epCY8&xx?h%I~ed&gA>4$&ab;%XIxCfyu9X%)Ad*Z(*9(gnWME z`z7k?TgPSJ6)V5iR##uQS;x`-e9`sRb$6_9>TmgaiFNTP4!t-jZ}#`M&01E5Bg!&F@@v{b1GPciw2~zj4mw_ozN~{Wn_u zk6HC^jZFRC`>f+Tq4Rgh&rj|${n+0p?*17oKd-gUIb}Qe_r)ef<-(J(ci`L(6&Ik3mBK0~geeY1uWqqF9w5YP}Ymd7BboqIml#Q>h zmo6Wh{0(YuI{$V#&$^fQZ%qEcYL}Jww|{K%{l3W`x@z*xzU!i!zS`suE}8mAe!$9G z>#$dyKYBg~7ft28SmCsH69r?P^&q>y) zXT5qIlFx@{veolBqQ=s%z3Tf`oj+==r}vD>-&}XK<$c$GG5Mp@CcoKQpIbbW-?e1w z-@Ib-d)4);$GzE_&!&wge{{~&@84(T7fgP;dY`8IdHa;f@4eULk1m^h^PW@Jx9|T4 ztn2Qmbw2O;d(+RczUgPXb-f>(GWqMR^*lCf^7|f=xSOY16a6}Do&U$I<9JlX-8|R2 z+VXqzXRZ8-$se}!*8KOq!PIYl2B@3tw62%qq3Or}LsS19fyp1X?hnVU^*>~t=l1jN z=q;un^=~D+*G+$5<*j*c{$`WES?#-i-Sklj^g6sD>9X?s*4oNj{p|l+lfPxr)IX%2 z%etRitp2xtx5)?A{_eVD@~5o&M|_hH<|WpzgVy;I47#lR{`w(_^|+@dOn#U8eq86@ zxNPz_Sod@LdAjM#P5s*zP5r&dlV zsGq0l{B83lzr}hUolt9{U)z620$u-v)&JOETlui7Ex&hGb-VhDCco7>pC@Kbe&^pw z+|^$;`R3o^>HK77^80Tx^(UrH{-8P*y8eVUpDo{G@+VeJ{jnEK{&th@?fi9XL>1Q%E`Th$ge`?(1kA1t9x8}d)Uz+^sX;c6D z-?#GCdLBGz@^7;G@4v(3Pg}?F*a4G2BVqSCYCSj4R9#lS|9U`TeO%7OCO@`l<#UtY z**E!n=1hM3I+MTCn*V_(O#Ys}slRjH%3Jjhf86Bn9Gd!@)O&3`&-*fyKm0zEe{*W` zy-&%6Z_VM3BR|IAcd ze_bW_$$v2Qr{XrRzTWs@GoKCD>-?Sat=cb2towPJb-wNSMw5T*ysj^s@jo&7`&Lc< zrY)xb_3D|WUPtBUCx0qi-Tzw`nr!pMx84uDH8J^d>-qB56_fA(H;HvWUp;5?n|{Q~ zPnrC#UorWpZ}PiCGtUig()m5|d%y>+`pc$%|5GOawpo+k^j?#XGLzr(Hzxn~36tOZ zohJXb+T?q`Yv!~5Cv{%li|v26Re#acAOAs9f5X@7yqs5?zhLUW!&=X=ZC2iz=iz^D z^7l_ktY6pfkU+2V{i|J8j=ObUy)!cT&6`dAcg~vp@gr8gF!|>9lD_ROmhZ3aAKZ3n z^?OWpkHhQ0c1h@YzH8hR-uUAt|L%E{-*ejJ-(}5z+b68NRloTRt?vKb*7ZJay-$A3 zy1sV&uIcA%t@C#CZ&~?TV*NV)Jrd~tzpm`E^6zJ@_g(K_byv`>%4lOZ}PhzGWFkYt>@N1F!}dQnEIQn z_aX1AOx}CM)c;W5` z`GZ#e{Z{{5?=VM0ZS@o^`8oOfU6VuNY>wfsSnwx&@ zyk7#nUk|Q!S$Y5PeJ20GzRB;f?uQ?==DGPVtoqhG52F4NfE5Bg!+wL&= z51Djt$Hz_ngF{oW**f1oWX)O$hbDjQd6R$0TAzc~ee9vo)ZcoOsedsw`CZ>)@(<0M z{NA%xe%a*rThHZ(N|WDpk5#`i`7OU^-Bkf+T;(f zT6ycZAN_Y$J~QtY~@Rn-)?;$^zgvs_bi(FPoyS)z&iiWS@Ybt!PGxz z&GW$BR^FQDo{w62Yo23$lRs~*n`hkz)Ge@k`5%x-uiN>#E-T;vs(tM8iOKK&9V>6m z=Z2xlKT??boBr0yFPZ#}|Iy?xsJ8lb#CpCw8g*HD|G!gWJ)cJ_li&2yCVyepThu75(3 zI)8bpt*pK;^MBCPzg)L@_4Ux>CVypFW!l%aZ<1}-kJbMT*8S~jS6Q}Of5OziGBgFA z^*-=QWb!vITJb#75<9A#2 zt@RxLWs^@AOg}gLg2_JyU)$DdjG(&P`RwbI8+ z-MYHh#($7V=RdO4W##wC)_L*~tDklD_r>3#>%UoTj_qxuK|g zuJsC1>E-9-0oL_%y)Klc-}sW1SLc#?N&dP&ll+mEy%oI;q@RbZ{7~oR_^%(c`q`-S z($D%2n)>Ucee+WF_n3SyGWp&*ng5t}w@GB48zk>_3B8s4hF_BW4aoPU|39_n(-q6Q zY}{pyE9=s{0_o?^rJpTbMZN7y{>LQ04S7}n-%5V`i}UNBk-YrRe%+z=_xr5*bmOS? zKVs##>Q<6p_i^cDx7~~U{|L;dUylW7Y4@3w2!n(#m)1 zD*4{KtbDhwavra<&xb`litN|AHK~6@+qd%n-pcEAPs%rZugtTn*X8??f4Ah-dtCda z*7;e4=ni|rInX;Y+jPzHf!ZWlfTKH&y>k;{)|;W zGI{TZt^BmfZ(OzVvB~$wt^BOc%lUWw5i6gX`bWOi%FmnphWo61rt@dy)}xL~w?50J zeiO<1u0Jc096$A1C-YtZJ{2^S|C1@PnydD8eewH^*UP-ttM_}le0?c?!1Aj2J;ocR z-0}^HTfT8ZZ1ul!Ab!xa-?-+sAM@Sz>hGr5ZQuVEJPmZHq?qPoF z?_t>G*T-)A>sL^&=4|J%Mt}XE)}vyLQ{Fe=lo~ zzem-#u8%#duJ=yC^RCtBmDj8HgZg^CaZPN^*T;B%g7Qpkt%v&i19tm;0m{|*R{#4J zQI7HVWBmOKZu|X9Zu|YKV)gxw-k+N!Tz}TGIzPX`^1SNcp&B0@l^lj(cYi_ve>$w)X#M7{*I{rt?`aT zC{Iwn=9V8Fcgv5e@vQwhy6Tpz&)?YP$4a+ceeT6BKfdIa-#p=#-#m?S)PKXcTmKEJ zy|uq@SVXy+zg2#Vs&DPjEz>B+{@$|cmIrHM>v+FW9UrT|H)4I?sM=fQw|Z`WxAn!= z@w_c`>)$qu`b#KZam!Dr`qp?S=G}7jxeB}d_G!2Lq?(`A{$${m-_di+@93j^5#`Hn z`2^}uWN!V5!mU5)yXBK=eXQd-sp?zvovhq)_4y&Y{1o;7`47C+G&-9PSB`~ReIsOEFY@}k(ZBa%+6`IRLx;+a}!hZ<|H=Jj&Jj zSpB`-gXi4#Z&&lT=J$3rA8Y>aQ0=YqcVs9p-17T-Zu$LvlrN%u*)4x(;+DTtjc1Mj zZdG6X@Jc^#-#aC?o}cfX6~|Wjn%G*8_pOSp`)TZpt^JKvf7W<$j`C%<{QYXaR{yGN z`~La?^#1|$uYP}MkN?1g+y4WrZn?U3+w*%6yx3arnI*UW491(CaLZ?7x4+ri_1QVG^*lSP&KK)=o>k*n$MYdIAFKSK zMYml2p2aSISoLqUKZo*jEMIoppIdd?pAX#f^AXAyP_B-THU1-0V(WZ+WFA)QX_Y_P zht+(o`%kh2uZgYoxuE82jekL{uhm}tUcs*am4q1*oIxLbZTLb+;hjrY`?>!-2* zPcORV9}eLa*Qr`BtAF)#b9=tesQFptA5rtO&YzEDaOt-H2wdj?S=`l;s#_$s$KN_Hw(cKWRefu{x7K27{@X&geA}#BzTFpF`?p>7XWc)x z58U>$JWl`W-xAv6kLParj%l}i$DCWfbHXiG{|?)p|1Ok&(f9wD->#wCe)klt#<$jM zH|D!%Mar%9-K&nDRe!IVkF~yg=TTm`9Uv|rnV?M|GD4%uPAD>70&@I2&cgt^HMESB?{sy&v*8JbF z;FjMq?v^({53u(C7FFMBf6J2FUj2I)yF7^8a`pQV`+nP-?m73{FIn!P{{O7|7(Wz0 zs{52pPwkI&e)ZN|uao(%PfY!Fi*C6$q0991V~fh|YXC|AeJ+MnimU>&c0SkL`xJgfef`uT73Jg|=UO$%=O=6PV1A5iOI z_1`=Xtnz~xzj+?m z`)hjmkr?Qd1O$y8kY_-g?b^S9=^XW4DP*LTbJhHm+d3u5c|-Kg4I{oPo*^?lXeD)(pI z@_o}{>v-);-1_^}c-H*)_uTUReUz`dV*7c$O-h=J_I6Mt!Vr%~V{oS!h zc0m1XRo@Setw??Ae)>k4uU-De0_C;a|E+31*8bl*>(*EIQ@g(}c|Y~s{%;T5{%=?F zvG(uw$}KvHTYCM=h)QJ!@I6&GrApaw7gF%U8w!)bhMo{u_<|ocNn9=i+a%{AuyG zT2|}#G0QKCKWj;pgE`!=I7na*Rgfe^z|G<p3R zID>PzfJ?Z72XGA!U9b0G9}eIUj^G$h;1tf_94_DzuHXS&!$a2_JlKZ=ID{iOh7&l2 zGdPC}xP&Ws0N3!)^+pf&;Q$Wd2#(sB;Q}t<3Ld~UJaj$g!9E$aID%t1fm1kx zbGU#@xPk|84G&#k@4-GCz#$yLF`U3DoWVIID{iOh7&l2GdPC}xP&Ws0N3!)^%f8I;Q$Wd2#(sB z;Q}t<3Ld~UJaoO)gMB!FLpXwCIDu0*gLAlmOSpmua19S#Z}VUu4&V@u;22Ke6wcrr zF5nWb-~n92L)Yr}$M*MI>hng912}{uIEE8Ag)=yZ3%GID{iOh7&l2GdPC}xP&Ws0N3!)^)3(g;Q$Wd2#(sB;Q}t<3Ld~UJanx- zZ(?8nyL~u-LpXwCIDu0*gLAlmOSpmua19S#@9|(C4&V@u;22Ke6wcrrF5nWb-~n92 zL)Yr_qxSJvzkhZdz#$yLF`U3DoWVIQa1rOjF9=cYaueSGpzYhm+2uE-XCvXa9a1Ix630Lp{uHm8Un>^Tu12}{uIEE8A zg)=yZ3%GC za0o|m3@303XK)S|a0yrN0IuPoYxVCD?EOFF!vP$^5gfw_oWdEL!v$Qz6+D1zc)SlohXXi-BRGZ=IE6DfhYPrbD|i6c z@X+-M5BA{z4&exn;RH_M49?*KF5wCuz%@K{eY*$yZ~%vJ1jld!r*H=6Z~>Qa1rOjF z9=cY4ug!k{deVmjID{iOh7&l2GdPC}xP&Ws0N3!)^&KAU!vP$^5gfw_oWdEL!v$Qz z6+D1zc<6eID{iOh7&l2GdPC}xP&Ws z0N3!)b?Cu99KazQ!7-e`DV)JMT)-t^?P5RTv&PT&;I;2bXC60YC@ zT*E`xU*^F+9KazQ!7-e`DV)JMT)-t^?P5RTv&PT&;I;2bXC60YC@ zT*E`xZ}DIs4&V@u;22Ke6wcrrF5nWb-~n92L)UNhU>^?P5RTv&PT&;I;2bXC60YC@ zT*E`xU+uv@9KazQ!7-e`DV)JMT)-ty1zf@vJb-I>==yCQ?85;Z!Vw(937oy1zf@vJb-I>==vQV?85;Z!Vw(937oEH01n{@j^PAO;SA2<0xsbS9>6s`bp1{b_Tc~y;Ruf51Ww@$&fx+s;R+tW zH9U0vE)VwM01n{@j^PAO;SA2<0xsbS9>6s`bp37*_Tc~y;Ruf51Ww@$&fx+s;R+tW zH9T}Z?ZG}Az#$yLF`U3DoWVI$aID%t1fm1kxbGU#@xPk|8 z4G&#^od^4H0Ech{$8Z9ta0cga0he$E58xUey8e0(_Tc~y;Ruf51Ww@$&fx+s;R+tW zH9U0v9uM~601n{@j^PAO;SA2<0xsbS9>6s`bo~t;?85;Z!Vw(937oy1zf@vJb-I>==yyg?85;Z!Vw(937oID{iOh7&l2GdPC}xP&Ws0N3!)^#?uJhXXi-BRGZ=IE6DfhYPrbD|i6c z@X+;#JlKZ=ID{iOh7&l2GdPC}xP&Ws0N3!)^^6DmZ~%vJ1jld!r*H=6Z~>Qa1rOjF z9=e|OU>^?P5RTv&PT&;I;2bXC60YC@T*E`xXFb@512}{uIEE8Ag)=yZ3%G6s` zbbZc)eK>$aID%t1fm1kxbGU#@xPk|84G&$P_h26m;1G`B7*606&fpv_;1aIj0bIjF z*N=Fx4+n4vM{o=$a0+K|4i|6ID{iOh7&l2GdPC}xP&Ws0N3!) zb>hK39KazQ!7-e`DV)JMT)-t$aID%t1fm1kxbGU#@xPk|84G&#E z>A^l6z#$yLF`U3DoWVI%!vP$^5gfw_oWdEL!v$Qz6+D1zcy1zf@vJb-I>=sNXa z9}eIUj^G$h;1tf_94_DzuHXS&!$a54c(4x#a0o|m3@303XK)S|a0yrN0IuPo>yLP_ z4+n4vM{o=$a0+K|4i|6t{XK zhXXi-BRGZ=IE6DfhYPrbD|i6c@X+-?@n9bg;1G`B7*606&fpv_;1aIj0bIjF*Wcv9 zJ{-Uy9KkW1z$u);Ib6UcT)_jlhKH{IsR#RT0Ech{$8Z9ta0cga0he$E58xUex}Nu7 z9}eIUj^G$h;1tf_94_DzuHXS&!$a5K?7==9z#$yLF`U3DoWVI$aID%t1fm1kxbGU#@xPk|84G&#^s|WjV0Ech{$8Z9ta0cga0he$E58xUey8f64 z`)~k+kkp9}eIU zj^G$h;1tf_94_DzuHXS&!$a2#9_+&b9KsPC!wH;Kh*eK>$a zID%t1fm1kxbGU#@xPk|84G&#^(t~|CfI~QfV>p3RID>PzfJ?Z72XGA!UH@+$?85;Z z!Vw(937o^?P z5RTv&PT&;I;2bXC60YC@T*E`xxd;1j0Ech{$8Z9ta0cga0he$E58xUey8e_0`)~k< za0JJ20;g~W=Wqd+a0L(G8Xmg--#yre12}{uIEE8Ag)=yZ3%GQa1rOjF9=iTv5BA{z z4&exn;RH_M49?*KF5wCuz%@K{{b>*O;Q$Wd2#(sB;Q}t<3Ld~UJaqjd9_+&b z9KsPC!wH%xP5IDkVqf@642{5|ILGsQf-058Jo^F4O^Wq1W% zh1XpFcn=!0Ys<8U9IfT!STcov?6=ivo- z5nh6q;T3olUUU7EJ$M}M!xQinJPpsnbMQR8058Hz@G`stufl7tU+BT(a37w4r{HOL z7M_FW;RSdRUV@k56?he1bNw%R@HpIuC*Ub~8lHvc;CXlfUWAw6Wq1W%h1XpFR1Y49 z`|t!j1y94X@Ekl3FTjiN61)trz^m|@>!0qy<8U9IfT!STcov?6=ivo-5nh6q;T3ol zUUMzoInUFjakvjpz*F!vJPXgk^Y8+^2rt3Q@Cv*Nuets|d+<2ihbQ1Ecp9FC=iqsG z0bYcc;AMCPUWM0O|4a`ahx_mZJOxj~v+x`|4==!r@DjWXufVJDn(LqK!Q*fro`9#| zX?PZ%gXiG|coANLm*Ew76<%}wnI1e2_u&b63Z8~%;W>C7UVscQi1AD)1x;Awako`dJ%1$Yr&f|ubH zcoklA{c}Bd9PYyt@Dw}^&%$%?JiGue!b|WnyaKPnYp%;4JP!Ba33v*ghG*e9cphGW z7vUv%8D4=`;WgJk--E~DK0EDw_ybQ0vtMHoZ7kltH z+=nONDR>&5h3DXTcmZC7m*8c11zv^MT>nxJ9*6tz1Uv;#!?W-lJP$9xi|`V>46nee z@S5vi?!n`5AD)1x;Awako`dJ%1$Yr&f|ubHcoklA{eSh~akvjpz*F!vJPXgk^Y8+^ z2rt3Q@Cv*Nuep}y&iDVz<8U9IfT!STcov?6=ivo-5nh6q;T3olUUU5`J$M}M!xQin zJPpsnbMQR8058Hz@G`stufl7tf3*jX!+m%Ho`R?0S$GbfhZo>QcnMyHSKw86&GoPK z;BmMQPry^~G&~E>!SnC}ya+GB%kT=k3a`2TY!4oX`|t!j1y94X@Ekl3FTjiN61)tr zz^m|@>tFA|<8U9IfT!STcov?6=ivo-5nh6q;T3olUUU5$J$M}M!xQinJPpsnbMQR8 z058Hz@G`stufl7t|8)-@hx_mZJOxj~v+x`|4==!r@DjWXufVJDn(L|ukHdX<0-l1W z;aPYNo`)CUMR*BbhF9QKc+K^1_TX{24^O~T@H9LN&%yKX0=x(>!OQRpyb7~% z9PYyt@Dw}^&%$%?JiGue!b|WnyaKPnYp#E*2am&jcmke+r{P(64xWb>;6-=|UWQlT zRd~(yOFeiT?!y!C6g&;j!gKIEyZ|r4OYky0==H8U+#CIUpOP=HuJ_|o9W!G8d&%w{b>H`>def0ww+v)(>ei?oRe%1Bw zY=IBJC*XVG`{4)Si}17XbMW)<3-F8ZOYqC^EAXqXe|HOf06qcV3*Qev2w#Msg`b0; zhhKnSgkOR`FaDJLr_aCN{etV2E#h^ieB}Uq0=^f%AAS(N2tNxy2R{$L0KW*o1iuWw z0>A3|_qMTaTi^rm3HV<4e)vK7BK$1;9Q-`|0{kNU68tj!3jC_; z&uxJZz$f5);rrnS;fwII@N@9<@C)#Z@aN?AW&M4<&&mDHvE1)$|AE{G9q)#Z!)M^P z!0&<2!B^pr!JmXb4SxpyEc`k6^Y9m3|GN$FZumHS27U|t9{3!575*6fN%+(7XW-Am zpMyUSf5G)1Zh&{g$Kf-uobUGM$^TH!cgJ$RJC^g^v7GOY<$QN6=euJ$-yOdMzYMp$88AAnE5_rmwX55gDWXW{4I=iwLN7vY!Sm*H1Bua4DY z|9R~H8T&6|e>wJ7V{2o7J@)^Oy*l>yWB)Mr7h``j_NQb2IQE~${=cz585@rM*RlUL z_Jy%;-t>24|9$Mw$6gux+p+(9?DJ!PHukOSKECeokvoFump9z?+`6y$u61wu-gRH| z-uQtJzWpc1eroL7)_=$Pk8k+YhF=}~?AULP{rtus+W5l8V&l(l{KbvWZ~WX?@9M*I zGnXHJdghVyPhP$JOz)8k7q6bbJoEVZXL{$JdSY%Sy?FNO`ExUmT)gz*-pR}7FP^-5 zKE2vT_r2$$^6Wzw&(B=GdbM}%$tyE+mo8uJUA=tv$t$Yq%*9KW9)D_X=IoQ_ zW}ccmr!uOqlQZ&q4(o=eE6wm51Kw@?`CAF zM#X2(otwGz(3SI-pO)3R@Z{A;MkTMcM`};oah^PTb>@k)PhOZ)BdRuC(c?2tQM1I4 z&t1Os(D^%_eB|0?my?;fD`%gWlLMePbIo$~&Rw{C{^6_5j$dhxi`tDVy|a%#dingL zqhord8Ry}PXRlnj@W_Spm+!dxa4Neab*{Wd(X~s`nYoA0Uc319OVgS2*BbCz1?_m( zDs6`A3Lla^dGz9?ht6J{dHB*(Ps-UXd-lZHxhuUZ=hgb0ee{YxHc!Y-pMCVaEYi7i z7p`8o^rSRtPpI=(FJE~0O3yyK)Rl5^=KR$pId{4D+9ykI?z~(|`mB=?+a?#!TzK-4 zOFcPo?m66@wzB%&CG{mMG{;nrpxPy8uXN)zXM@Vg**}W)rK+x~=K8Y6QWt>anyXfJ z-ISlac=72cW@Je&U%Bw8S{nDf@9r2+pS}3hdAXa6PM>z^=FVQeqSD>D;byxd?`HMs z;3iGK>P-8hZtdi#S3B8tYH~9dFFbty$!2!#EwH`ZdhG=?BbU#m%jbI6JO(q5UcU6y z+=X+^71Z86YcoD^|JIY+h?9=wwEu-jrDAI*2o@?ZqU7_o_y-c`E&R5 z?!WK8duE!=N@wnxnH-hrXrfD#CpW25EzdnNi|&8=aXs)dtdIm(hV5zDu3%`Y}NpN&7aK=mOb~HX}W@fm&>J zj6%JYIkyREJnC0RQq)G$O&drzqcR;yS=&w>Jk_&I^>iD_7^5;1O}05%qBfA@Ai-}ngxJam~%q>W?jECq-0*B>N--Vx$f~)*aXr+8>q9Yjig;ycDL@k z-O54j5|eEpRlB0Qbk%k%N2g0nwt-Y_1DS)abJxtBO`|hH}j^seJ zDe0yS?wL8Ghi`hvK- z-SK84_w;rv_f?gan|iaATYj^Zn|oKT1G&rVlF2RzyDDuU7g3W?Yur`sN_0l{^X{hT zjNZzyy3MIJkR56Rsd`saG@-Y07`lWG)EVDYkrPix;mn9>LGbC)^QjoAk3 zoNh8Qk}2v^lcSW5q@y+^W3(N~$z`ets;4LP z0H@kOowr@jDti5H?(SWfllQrI>2viiHKluInvGnv%{J8Rws*FcQ@5>l*UUXlAn#9_ ztt>(t$U=7|I*@e@bzL1uoi?M+r8c@}=5F23sWy;vsSVWKvMZbH%5)&>s3YmJEmKRZ zd%COH${sXZ>8B0Ux!q-SBxh+?HrWQUplu-ibwzjT{@SgK-3D^Q@49OPb*k&CI*{3o z>gY)NZBue%Zz{`;T{k+_2I_=wGSa%Mq62k)>!Nn6PADD8aF8QdwvA;HO`z7Z8DJDhA6@^a+en7g zDRp^tg*uYK+mv)Ls-+`Ypf)8tD8cKW{9P}nCz=st&^C}YX#=&EZKR$L?KEVvZ6qT| z@cJWk*VUbBhvg>O?DySzD`$ZMj@$O(5S7G+VjenypM* z*N{WlMzSzn9UaK~v8J-TA8WR!1zf9oHx^ zicWQ9I#AbWS4&57WSflIrREfo)3FKU3K%8YNLsgn%vG1k4OODozB1d^cgnJ;ex?65 zQ0IFascWn$la5DaI#SozonPX_?;4+;Xor&JZ6kG&wJCLNbwjj)%)Jd{gf>vu*q0jW zPW|jUqjp8!G&d{NZSQP-N~iT^vfawTZ+HKmW-Aw#?&DM&s53}Ma^TxYT@6hwS)n#i z7ekYg)zgu>EZUTMs_9Pe?kcr`v~L4h;Wm(tMs>PKy$+elq7O&ys>8%WQiN;;Bn zJ#|0rR{CiJxi*>tIWM{zI#4HLS4RiZaaTzPYERpgOt}kAH9e}MH=0*-Qm7|dH&`3U z8jk98naMVg{v>$q%ct#M?Ph!awA)Ep$hJf-tR|2?+Jqd&CQvtvZYpi0uDv#;uDvFb z1#JUa&^C~f+CWC=>ZsuLA3j~%(-Td%a(`+AbqVT>4%AY&DfOId%G8zjr3N^oue{UE zE=m90uBoj&#~RCXtl7$QtSy)4SQE(Q)+XdzoF{%~lS38_0vK>#hxC@w(vdwyHd&bX%R6)CqZ7b#2=~U9C+vlL2J&3%dTj%B33pX=BcQtY6IDsHfS!~rmVR-N43;h zA?H_P>A$U^uE{2nl2K8YnH*Kpk?ftMUi+dvtB&{U%B`!SO_|!x@qPn`;NN!1OBtwi+Dti46yInig?0_7uW_xG5 zm4#E3>#W(zb*8tc+CUuy9m!sFg<(@kt`Xh%R2#@aYy)-o)RD9w<#Z(P>U8^dD^u!% z$u>}<>PS7qn%a`Ps}1CeXaaQsbQvAVnbD?XiFBECHL9f}xhk4=GH@HH`L>Z`#JjRCrEcF%2Xgeg>ZjXz%bUG6P$#lF4su;ITXm*4fjR@* zD$=u#q{B8+Ct*`4JECj1TbV{1$a=J`)c~Waqq=RGs@z2CD(X^`qlPMa?ThAAchR(s zWX;<^Cfx=y(=|~o< zE4y0{-)`kJ9R;V_NSf=E?06fgXG_ye9w~aV?N-i`E};W;-gjk_U6~G~n=W%_w-=+} zR2#{%cfn*E$b&2@{w1GT0x?b8q-amJV(_NKQqm+(h5?yT_s53|%8#xEs=5h^< z`e_2WhDM35?x|5qN9wxjYUxN_O-)MHsoBawZnkokHCuJ2>eJ$sj%5AXNS*tWulYF# z`PKhPDQbU3H`#U22C{o?LeAADPD50VH-)mZ6LjMl|tR9-O4H02J$q~ z1*f{iD7d>TX#;iI>PVgSO`#0X)w-)m$Ryf8-bv{i?N(g|U4L!RTn0@_4r5nY2hz=* zy699J$m!4q>g?}YwSk;fZ6H1BNS+=|9ck4DYOpqv_Bthd(bdv{>`t4JGoop)?s?70 zr;cO0>ZjU3dTs;huMK1`x;i?LbhwIImu0?jijG8P$#t>O9kz@;Qp%I{Jd_W zJH?w8(zG3?3uI~9#3)cFpV|?1?y0Rh;nY?=ESf-F3_3W~2I`7zGSWtZFLB;CHDzZe zx+W6*|9@@#jP$YoHT&7{?I+v(&FcSy+kUBk)6l)tBs!0ENxhwFw;%P8w|zp&)c*&# zdQCN7yD#fMG2ezeR%CmN{HOlyje2$M$9uhv-!Hz#_#cg$+Pxrcx1+CJdr55kXY%D5 zV~b8smRDkTUgpz40HC@@tL1sv66yFaN3WyK%d%jDOwxC4a5)7o<$R`psAK zrE4#l>%Kw0Tx0wn>{`e;&G_AU*tJ*VS5kJZ@t1T5eZB2AU3+o!@5in+z8Y7(y79NP z9Ib;I|H~wIt?^fM{XlQKjXnNdlDyXVechlNf17sKUX9=U(P*9T&JWE`4|VW*qqBD?ZxZVAN{-5_)~3zjf=8X=ig5G zPrdB%e?WYV_5a*-Q@eM^T)Q28?b@rR>fdi&WBeapZCi}4fB8In^Xl5mdR*6+%xjOo zZvApoyVp~7>{r)ba@QS@FV`6V$MyV2=igr4N!MPDum1k}wZ>o7_4|6;ZMyd2>%LRI zTxO&yl&8qua1>^S>tc~thgJ$dpTgs>vNy~(T6e#C#@R1xJ{$i~3a+*O3vHtfOR`nh|IyZ?^-{;hzW?fCy}9na z>e$HZkJK93FKhhX>)d~TYN~DYM{}}O;~#HrkH6vQrGLD?S@(HeINEH;)V$T}o7&Cj gtF>MmUzDtS-gMR0PcFCNd(>9itbcFo(fI!V09hiX_y7O^ literal 200920 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
  • !9J7k|{Ao`F3@`^D3+x6<)} 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 diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/gen.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/gen.go index 3ec45b49c5..a95d9ba481 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/gen.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/gen.go @@ -1,4 +1,4 @@ package ebpf // $BPF_CLANG and $BPF_CFLAGS are set by the Makefile. -//go:generate bpf2go -cc $BPF_CLANG -cflags $BPF_CFLAGS -target amd64,arm64,ppc64le,s390x -type flow_metrics_t -type flow_id_t -type flow_record_t -type pkt_drops_t -type dns_record_t -type global_counters_key_t -type direction_t -type filter_action_t -type tcp_flags_t -type translated_flow_t Bpf ../../bpf/flows.c -- -I../../bpf/headers +//go:generate bpf2go -cc $BPF_CLANG -cflags $BPF_CFLAGS -target amd64,arm64,ppc64le,s390x -type flow_metrics_t -type flow_id_t -type flow_record_t -type pkt_drops_t -type dns_record_t -type global_counters_key_t -type direction_t -type filter_action_t -type tcp_flags_t -type translated_flow_t -type observed_intf_t Bpf ../../bpf/flows.c -- -I../../bpf/headers diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/grpc_proto.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/grpc_proto.go index 761f0053c9..9680a95ba6 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/grpc_proto.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/grpc_proto.go @@ -9,7 +9,6 @@ import ( "github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow" "github.com/netobserv/netobserv-ebpf-agent/pkg/utils" - ovnobserv "github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder" "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" ) @@ -31,10 +30,9 @@ type GRPCProto struct { maxFlowsPerMessage int metrics *metrics.Metrics batchCounter prometheus.Counter - sampler *ovnobserv.SampleDecoder } -func StartGRPCProto(hostIP string, hostPort int, maxFlowsPerMessage int, m *metrics.Metrics, s *ovnobserv.SampleDecoder) (*GRPCProto, error) { +func StartGRPCProto(hostIP string, hostPort int, maxFlowsPerMessage int, m *metrics.Metrics) (*GRPCProto, error) { clientConn, err := grpc.ConnectClient(hostIP, hostPort) if err != nil { return nil, err @@ -46,7 +44,6 @@ func StartGRPCProto(hostIP string, hostPort int, maxFlowsPerMessage int, m *metr maxFlowsPerMessage: maxFlowsPerMessage, metrics: m, batchCounter: m.CreateBatchCounter(componentGRPC), - sampler: s, }, nil } @@ -57,7 +54,7 @@ func (g *GRPCProto) ExportFlows(input <-chan []*model.Record) { log := glog.WithField("collector", socket) for inputRecords := range input { g.metrics.EvictionCounter.WithSource(componentGRPC).Inc() - for _, pbRecords := range pbflow.FlowsToPB(inputRecords, g.maxFlowsPerMessage, g.sampler) { + for _, pbRecords := range pbflow.FlowsToPB(inputRecords, g.maxFlowsPerMessage) { log.Debugf("sending %d records", len(pbRecords.Entries)) if _, err := g.clientConn.Client().Send(context.TODO(), pbRecords); err != nil { g.metrics.Errors.WithErrorName(componentGRPC, "CannotWriteMessage").Inc() diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/ipfix.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/ipfix.go index 379401ccf0..36c2a88890 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/ipfix.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/ipfix.go @@ -287,7 +287,7 @@ func setIERecordValue(record *model.Record, ieValPtr *entities.InfoElementWithVa case "packetDeltaCount": ieVal.SetUnsigned64Value(uint64(record.Metrics.Packets)) case "interfaceName": - ieVal.SetStringValue(record.Interface) + ieVal.SetStringValue(record.Interfaces[0].Interface) } } func setIEValue(record *model.Record, ieValPtr *entities.InfoElementWithValue) { @@ -296,7 +296,7 @@ func setIEValue(record *model.Record, ieValPtr *entities.InfoElementWithValue) { case "ethernetType": ieVal.SetUnsigned16Value(record.Metrics.EthProtocol) case "flowDirection": - ieVal.SetUnsigned8Value(record.ID.Direction) + ieVal.SetUnsigned8Value(uint8(record.Interfaces[0].Direction)) case "sourceMacAddress": ieVal.SetMacAddressValue(record.Metrics.SrcMac[:]) case "destinationMacAddress": diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/kafka_proto.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/kafka_proto.go index 50b5ee3f1d..169562c578 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/kafka_proto.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/exporter/kafka_proto.go @@ -7,7 +7,6 @@ import ( "github.com/netobserv/netobserv-ebpf-agent/pkg/model" "github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow" - ovnobserv "github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder" kafkago "github.com/segmentio/kafka-go" "github.com/sirupsen/logrus" "google.golang.org/protobuf/proto" @@ -24,9 +23,8 @@ type kafkaWriter interface { // KafkaProto exports flows over Kafka, encoded as a protobuf that is understandable by the // Flowlogs-Pipeline collector type KafkaProto struct { - Writer kafkaWriter - Metrics *metrics.Metrics - SampleDecoder *ovnobserv.SampleDecoder + Writer kafkaWriter + Metrics *metrics.Metrics } func (kp *KafkaProto) ExportFlows(input <-chan []*model.Record) { @@ -52,7 +50,7 @@ func (kp *KafkaProto) batchAndSubmit(records []*model.Record) { klog.Debugf("sending %d records", len(records)) msgs := make([]kafkago.Message, 0, len(records)) for _, record := range records { - pbBytes, err := proto.Marshal(pbflow.FlowToPB(record, kp.SampleDecoder)) + pbBytes, err := proto.Marshal(pbflow.FlowToPB(record)) if err != nil { klog.WithError(err).Debug("can't encode protobuf message. Ignoring") kp.Metrics.Errors.WithErrorName(componentKafka, "CannotEncodeMessage").Inc() diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/account.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/account.go index f850f960d9..6d87806bbd 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/account.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/account.go @@ -7,6 +7,7 @@ import ( "github.com/netobserv/netobserv-ebpf-agent/pkg/metrics" "github.com/netobserv/netobserv-ebpf-agent/pkg/model" + ovnobserv "github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder" "github.com/sirupsen/logrus" ) @@ -21,6 +22,7 @@ type Accounter struct { clock func() time.Time monoClock func() time.Duration metrics *metrics.Metrics + s *ovnobserv.SampleDecoder } var alog = logrus.WithField("component", "flow/Accounter") @@ -32,6 +34,7 @@ func NewAccounter( clock func() time.Time, monoClock func() time.Duration, m *metrics.Metrics, + s *ovnobserv.SampleDecoder, ) *Accounter { acc := Accounter{ maxEntries: maxEntries, @@ -40,6 +43,7 @@ func NewAccounter( clock: clock, monoClock: monoClock, metrics: m, + s: s, } return &acc } @@ -96,7 +100,8 @@ func (c *Accounter) evict(entries map[ebpf.BpfFlowId]*ebpf.BpfFlowMetrics, evict monotonicNow := uint64(c.monoClock()) records := make([]*model.Record, 0, len(entries)) for key, metrics := range entries { - records = append(records, model.NewRecord(key, &model.BpfFlowContent{BpfFlowMetrics: metrics}, now, monotonicNow)) + flowContent := model.NewBpfFlowContent(*metrics) + records = append(records, model.NewRecord(key, &flowContent, now, monotonicNow, c.s)) } c.metrics.EvictionCounter.WithSourceAndReason("accounter", reason).Inc() c.metrics.EvictedFlowsCounter.WithSourceAndReason("accounter", reason).Add(float64(len(records))) diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/decorator.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/decorator.go deleted file mode 100644 index 75d90bdd32..0000000000 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/decorator.go +++ /dev/null @@ -1,24 +0,0 @@ -package flow - -import ( - "net" - - "github.com/netobserv/netobserv-ebpf-agent/pkg/model" -) - -type InterfaceNamer func(ifIndex int) string - -// Decorate adds to the flows extra metadata fields that are not directly fetched by eBPF: -// - The interface name (corresponding to the interface index in the flow). -// - The IP address of the agent host. -func Decorate(agentIP net.IP, ifaceNamer InterfaceNamer) func(in <-chan []*model.Record, out chan<- []*model.Record) { - return func(in <-chan []*model.Record, out chan<- []*model.Record) { - for flows := range in { - for _, flow := range flows { - flow.Interface = ifaceNamer(int(flow.ID.IfIndex)) - flow.AgentIP = agentIP - } - out <- flows - } - } -} diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/deduper.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/deduper.go deleted file mode 100644 index 06f7b07f5b..0000000000 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/deduper.go +++ /dev/null @@ -1,177 +0,0 @@ -package flow - -import ( - "container/list" - "reflect" - "time" - - "github.com/sirupsen/logrus" - - "github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf" - "github.com/netobserv/netobserv-ebpf-agent/pkg/metrics" - "github.com/netobserv/netobserv-ebpf-agent/pkg/model" -) - -var dlog = logrus.WithField("component", "flow/Deduper") -var timeNow = time.Now - -// deduperCache implement a LRU cache whose elements are evicted if they haven't been accessed -// during the expire duration. -// It is not safe for concurrent access. -type deduperCache struct { - expire time.Duration - // key: ebpf.BpfFlowId with the interface and MACs erased, to detect duplicates - // value: listElement pointing to a struct entry - ifaces map[ebpf.BpfFlowId]*list.Element - // element: entry structs of the ifaces map ordered by expiry time - entries *list.List -} - -type entry struct { - key *ebpf.BpfFlowId - dnsRecord *ebpf.BpfDnsRecordT - flowRTT *uint64 - networkEvents *[model.MaxNetworkEvents][model.NetworkEventsMaxEventsMD]uint8 - ifIndex uint32 - expiryTime time.Time - dupList *[]map[string]uint8 -} - -// Dedupe receives flows and filters these belonging to duplicate interfaces. It will forward -// the flows from the first interface coming to it, until that flow expires in the cache -// (no activity for it during the expiration time) -// The justMark argument tells that the deduper should not drop the duplicate flows but -// set their Duplicate field. -func Dedupe(expireTime time.Duration, justMark, mergeDup bool, ifaceNamer InterfaceNamer, m *metrics.Metrics) func(in <-chan []*model.Record, out chan<- []*model.Record) { - cache := &deduperCache{ - expire: expireTime, - entries: list.New(), - ifaces: map[ebpf.BpfFlowId]*list.Element{}, - } - return func(in <-chan []*model.Record, out chan<- []*model.Record) { - for records := range in { - cache.removeExpired() - fwd := make([]*model.Record, 0, len(records)) - for _, record := range records { - cache.checkDupe(record, justMark, mergeDup, &fwd, ifaceNamer) - } - if len(fwd) > 0 { - out <- fwd - m.EvictionCounter.WithSource("deduper").Inc() - m.EvictedFlowsCounter.WithSource("deduper").Add(float64(len(fwd))) - } - m.BufferSizeGauge.WithBufferName("deduper-list").Set(float64(cache.entries.Len())) - m.BufferSizeGauge.WithBufferName("deduper-map").Set(float64(len(cache.ifaces))) - } - } -} - -// checkDupe check current record if its already available nad if not added to fwd records list -func (c *deduperCache) checkDupe(r *model.Record, justMark, mergeDup bool, fwd *[]*model.Record, ifaceNamer InterfaceNamer) { - mergeEntry := make(map[string]uint8) - rk := r.ID - // zeroes fields from key that should be ignored from the flow comparison - rk.IfIndex = 0 - rk.Direction = 0 - if r.Metrics.AdditionalMetrics == nil { - r.Metrics.AdditionalMetrics = &ebpf.BpfAdditionalMetrics{} - } - // If a flow has been accounted previously, whatever its interface was, - // it updates the expiry time for that flow - if ele, ok := c.ifaces[rk]; ok { - fEntry := ele.Value.(*entry) - fEntry.expiryTime = timeNow().Add(c.expire) - c.entries.MoveToFront(ele) - // The input flow is duplicate if its interface is different to the interface - // of the non-duplicate flow that was first registered in the cache - // except if the new flow has DNS enrichment in this case will enrich the flow in the cache - // with DNS info and mark the current flow as duplicate - if r.Metrics.AdditionalMetrics.DnsRecord.Latency != 0 && fEntry.dnsRecord.Latency == 0 { - // copy DNS record to the cached entry and mark it as duplicate - fEntry.dnsRecord.Flags = r.Metrics.AdditionalMetrics.DnsRecord.Flags - fEntry.dnsRecord.Id = r.Metrics.AdditionalMetrics.DnsRecord.Id - fEntry.dnsRecord.Latency = r.Metrics.AdditionalMetrics.DnsRecord.Latency - fEntry.dnsRecord.Errno = r.Metrics.AdditionalMetrics.DnsRecord.Errno - } - // If the new flow has flowRTT then enrich the flow in the case with the same RTT and mark it duplicate - if r.Metrics.AdditionalMetrics.FlowRtt != 0 && *fEntry.flowRTT == 0 { - *fEntry.flowRTT = r.Metrics.AdditionalMetrics.FlowRtt - } - // If the new flows have network events, then enrich the flow in the cache and mark the flow as duplicate - for i, md := range r.Metrics.AdditionalMetrics.NetworkEvents { - if !model.AllZerosMetaData(md) && model.AllZerosMetaData(fEntry.networkEvents[i]) { - copy(fEntry.networkEvents[i][:], md[:]) - } - } - if fEntry.ifIndex != r.ID.IfIndex { - if justMark { - r.Duplicate = true - *fwd = append(*fwd, r) - } - if mergeDup { - ifName := ifaceNamer(int(r.ID.IfIndex)) - mergeEntry[ifName] = r.ID.Direction - if dupEntryNew(*fEntry.dupList, mergeEntry) { - *fEntry.dupList = append(*fEntry.dupList, mergeEntry) - dlog.Debugf("merge list entries dump:") - for _, entry := range *fEntry.dupList { - for k, v := range entry { - dlog.Debugf("interface %s dir %d", k, v) - } - } - } - } - return - } - *fwd = append(*fwd, r) - return - } - // The flow has not been accounted previously (or was forgotten after expiration) - // so we register it for that concrete interface - e := entry{ - key: &rk, - dnsRecord: &r.Metrics.AdditionalMetrics.DnsRecord, - flowRTT: &r.Metrics.AdditionalMetrics.FlowRtt, - networkEvents: &r.Metrics.AdditionalMetrics.NetworkEvents, - ifIndex: r.ID.IfIndex, - expiryTime: timeNow().Add(c.expire), - } - if mergeDup { - ifName := ifaceNamer(int(r.ID.IfIndex)) - mergeEntry[ifName] = r.ID.Direction - r.DupList = append(r.DupList, mergeEntry) - e.dupList = &r.DupList - } - c.ifaces[rk] = c.entries.PushFront(&e) - *fwd = append(*fwd, r) -} - -func dupEntryNew(dupList []map[string]uint8, mergeEntry map[string]uint8) bool { - for _, entry := range dupList { - if reflect.DeepEqual(entry, mergeEntry) { - return false - } - } - return true -} - -func (c *deduperCache) removeExpired() { - now := timeNow() - ele := c.entries.Back() - evicted := 0 - for ele != nil && now.After(ele.Value.(*entry).expiryTime) { - evicted++ - c.entries.Remove(ele) - fEntry := ele.Value.(*entry) - fEntry.dupList = nil - delete(c.ifaces, *fEntry.key) - ele = c.entries.Back() - } - if evicted > 0 { - dlog.WithFields(logrus.Fields{ - "current": c.entries.Len(), - "evicted": evicted, - "expiryTime": c.expire, - }).Debug("entries evicted from the deduper cache") - } -} diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/tracer_map.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/tracer_map.go index fe9d711ec4..7fa12bd075 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/tracer_map.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/flow/tracer_map.go @@ -12,6 +12,7 @@ import ( "github.com/gavv/monotime" "github.com/netobserv/gopipes/pkg/node" + ovnobserv "github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder" "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" ) @@ -28,6 +29,7 @@ type MapTracer struct { evictionCond *sync.Cond metrics *metrics.Metrics timeSpentinLookupAndDelete prometheus.Histogram + s *ovnobserv.SampleDecoder } type mapFetcher interface { @@ -35,7 +37,8 @@ type mapFetcher interface { DeleteMapsStaleEntries(timeOut time.Duration) } -func NewMapTracer(fetcher mapFetcher, evictionTimeout, staleEntriesEvictTimeout time.Duration, m *metrics.Metrics) *MapTracer { +func NewMapTracer(fetcher mapFetcher, evictionTimeout, staleEntriesEvictTimeout time.Duration, m *metrics.Metrics, + s *ovnobserv.SampleDecoder) *MapTracer { return &MapTracer{ mapFetcher: fetcher, evictionTimeout: evictionTimeout, @@ -43,6 +46,7 @@ func NewMapTracer(fetcher mapFetcher, evictionTimeout, staleEntriesEvictTimeout staleEntriesEvictTimeout: staleEntriesEvictTimeout, metrics: m, timeSpentinLookupAndDelete: m.CreateTimeSpendInLookupAndDelete(), + s: s, } } @@ -107,6 +111,7 @@ func (m *MapTracer) evictFlows(ctx context.Context, forceGC bool, forwardFlows c &flowMetrics, currentTime, uint64(monotonicTimeNow), + m.s, )) } m.mapFetcher.DeleteMapsStaleEntries(m.staleEntriesEvictTimeout) diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/metrics/metrics.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/metrics/metrics.go index 77e3ac28d1..413a8dd510 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/metrics/metrics.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/metrics/metrics.go @@ -2,6 +2,7 @@ package metrics import ( "errors" + "strconv" "github.com/prometheus/client_golang/prometheus" "github.com/sirupsen/logrus" @@ -118,11 +119,21 @@ var ( ) errorsCounter = defineMetric( "errors_total", - "errors counter", + "Errors counter", TypeCounter, "component", "error", ) + flowEnrichmentCounterCounter = defineMetric( + "flows_enrichment_total", + "Statistics on flows enrichment", + TypeCounter, + "hasDNS", + "hasRTT", + "hasDrops", + "hasNetEvents", + "hasXlat", + ) ) func (def *MetricDefinition) mapLabels(labels []string) prometheus.Labels { @@ -154,6 +165,7 @@ type Metrics struct { NetworkEventsCounter *EvictionCounter BufferSizeGauge *BufferSizeGauge Errors *ErrorCounter + FlowEnrichmentCounter *FlowEnrichmentCounter } func NewMetrics(settings *Settings) *Metrics { @@ -168,6 +180,7 @@ func NewMetrics(settings *Settings) *Metrics { m.NetworkEventsCounter = &EvictionCounter{vec: m.NewCounterVec(&networkEvents)} m.BufferSizeGauge = &BufferSizeGauge{vec: m.NewGaugeVec(&bufferSize)} m.Errors = &ErrorCounter{vec: m.NewCounterVec(&errorsCounter)} + m.FlowEnrichmentCounter = &FlowEnrichmentCounter{vec: m.NewCounterVec(&flowEnrichmentCounterCounter)} return m } @@ -255,6 +268,20 @@ func (c *EvictionCounter) WithSource(source string) prometheus.Counter { return c.vec.WithLabelValues(source, "") } +type FlowEnrichmentCounter struct { + vec *prometheus.CounterVec +} + +func (c *FlowEnrichmentCounter) Increase(hasDNS, hasRTT, hasDrops, hasNetEvents, hasXlat bool) { + c.vec.WithLabelValues( + strconv.FormatBool(hasDNS), + strconv.FormatBool(hasRTT), + strconv.FormatBool(hasDrops), + strconv.FormatBool(hasNetEvents), + strconv.FormatBool(hasXlat), + ).Inc() +} + func (m *Metrics) CreateTimeSpendInLookupAndDelete() prometheus.Histogram { return m.NewHistogram(&lookupAndDeleteMapDurationSeconds, []float64{.001, .01, .1, 1, 10, 100, 1000, 10000}) } diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/model/flow_content.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/model/flow_content.go index 111303565c..155926f37a 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/model/flow_content.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/model/flow_content.go @@ -1,21 +1,16 @@ package model -import "github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf" +import ( + "github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf" +) type BpfFlowContent struct { *ebpf.BpfFlowMetrics AdditionalMetrics *ebpf.BpfAdditionalMetrics } -type BpfFlowContents []BpfFlowContent - -func (a *BpfFlowContents) Accumulate() BpfFlowContent { - res := BpfFlowContent{} - for _, p := range *a { - res.AccumulateBase(p.BpfFlowMetrics) - res.AccumulateAdditional(p.AdditionalMetrics) - } - return res +func NewBpfFlowContent(metrics ebpf.BpfFlowMetrics) BpfFlowContent { + return BpfFlowContent{BpfFlowMetrics: &metrics} } func (p *BpfFlowContent) AccumulateBase(other *ebpf.BpfFlowMetrics) { @@ -57,10 +52,30 @@ func AccumulateBase(p *ebpf.BpfFlowMetrics, other *ebpf.BpfFlowMetrics) *ebpf.Bp return p } +func (p *BpfFlowContent) buildBaseFromAdditional(add *ebpf.BpfAdditionalMetrics) { + if add == nil { + return + } + // Accumulate time into base metrics if unset + if p.BpfFlowMetrics.StartMonoTimeTs == 0 || (p.BpfFlowMetrics.StartMonoTimeTs > add.StartMonoTimeTs && add.StartMonoTimeTs != 0) { + p.BpfFlowMetrics.StartMonoTimeTs = add.StartMonoTimeTs + } + if p.BpfFlowMetrics.EndMonoTimeTs == 0 || p.BpfFlowMetrics.EndMonoTimeTs < add.EndMonoTimeTs { + p.BpfFlowMetrics.EndMonoTimeTs = add.EndMonoTimeTs + } + if p.BpfFlowMetrics.EthProtocol == 0 { + p.BpfFlowMetrics.EthProtocol = add.EthProtocol + } + if p.BpfFlowMetrics.Flags == 0 && add.PktDrops.LatestFlags != 0 { + p.BpfFlowMetrics.Flags = add.PktDrops.LatestFlags + } +} + func (p *BpfFlowContent) AccumulateAdditional(other *ebpf.BpfAdditionalMetrics) { if other == nil { return } + p.buildBaseFromAdditional(other) if p.AdditionalMetrics == nil { p.AdditionalMetrics = other return @@ -83,6 +98,9 @@ func (p *BpfFlowContent) AccumulateAdditional(other *ebpf.BpfAdditionalMetrics) if other.PktDrops.LatestDropCause != 0 { p.AdditionalMetrics.PktDrops.LatestDropCause = other.PktDrops.LatestDropCause } + if other.PktDrops.LatestState != 0 { + p.AdditionalMetrics.PktDrops.LatestState = other.PktDrops.LatestState + } // RTT if p.AdditionalMetrics.FlowRtt < other.FlowRtt { p.AdditionalMetrics.FlowRtt = other.FlowRtt @@ -98,6 +116,26 @@ func (p *BpfFlowContent) AccumulateAdditional(other *ebpf.BpfAdditionalMetrics) if !AllZeroIP(IP(other.TranslatedFlow.Saddr)) && !AllZeroIP(IP(other.TranslatedFlow.Daddr)) { p.AdditionalMetrics.TranslatedFlow = other.TranslatedFlow } + // Accumulate interfaces + directions + accumulateInterfaces(&p.AdditionalMetrics.NbObservedIntf, &p.AdditionalMetrics.ObservedIntf, other.NbObservedIntf, other.ObservedIntf) +} + +func accumulateInterfaces(dstSize *uint8, dstIntf *[MaxObservedInterfaces]ebpf.BpfObservedIntfT, srcSize uint8, srcIntf [MaxObservedInterfaces]ebpf.BpfObservedIntfT) { + iObs := uint8(0) +outer: + for *dstSize < uint8(len(dstIntf)) && iObs < srcSize { + for u := uint8(0); u < *dstSize; u++ { + if dstIntf[u].Direction == srcIntf[iObs].Direction && + dstIntf[u].IfIndex == srcIntf[iObs].IfIndex { + // Ignore if already exists + iObs++ + continue outer + } + } + dstIntf[*dstSize] = srcIntf[iObs] + *dstSize++ + iObs++ + } } func allZerosMac(s [6]uint8) bool { diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/model/record.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/model/record.go index 8f6b832309..9bf54d1a5b 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/model/record.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/model/record.go @@ -8,22 +8,22 @@ import ( "reflect" "time" - "github.com/netobserv/flowlogs-pipeline/pkg/config" "github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf" -) -// Values according to field 61 in https://www.iana.org/assignments/ipfix/ipfix.xhtml -const ( - DirectionIngress = uint8(0) - DirectionEgress = uint8(1) + ovnmodel "github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/model" + ovnobserv "github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder" ) -const MacLen = 6 -// IPv4Type / IPv6Type value as defined in IEEE 802: https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml +// Values according to field 61 in https://www.iana.org/assignments/ipfix/ipfix.xhtml const ( + DirectionIngress = 0 + DirectionEgress = 1 + MacLen = 6 + // IPv4Type / IPv6Type value as defined in IEEE 802: https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml IPv6Type = 0x86DD NetworkEventsMaxEventsMD = 8 MaxNetworkEvents = 4 + MaxObservedInterfaces = 4 ) type HumanBytes uint64 @@ -36,6 +36,18 @@ type Direction uint8 // (same behavior as Go's net.IP type) type IPAddr [net.IPv6len]uint8 +type InterfaceNamer func(ifIndex int) string + +var ( + agentIP net.IP + interfaceNamer InterfaceNamer = func(ifIndex int) string { return fmt.Sprintf("[namer unset] %d", ifIndex) } +) + +func SetGlobals(ip net.IP, ifaceNamer InterfaceNamer) { + agentIP = ip + interfaceNamer = ifaceNamer +} + // record structure as parsed from eBPF type RawRecord ebpf.BpfFlowRecordT @@ -48,29 +60,24 @@ type Record struct { TimeFlowStart time.Time TimeFlowEnd time.Time DNSLatency time.Duration - Interface string - // Duplicate tells whether this flow has another duplicate so it has to be excluded from - // any metrics' aggregation (e.g. bytes/second rates between two pods). - // The reason for this field is that the same flow can be observed from multiple interfaces, - // so the agent needs to choose only a view of the same flow and mark the others as - // "exclude from aggregation". Otherwise rates, sums, etc... values would be multiplied by the - // number of interfaces this flow is observed from. - Duplicate bool - + Interfaces []IntfDirUdn // AgentIP provides information about the source of the flow (the Agent that traced it) AgentIP net.IP // Calculated RTT which is set when record is created by calling NewRecord TimeFlowRtt time.Duration - DupList []map[string]uint8 - NetworkMonitorEventsMD []config.GenericMap + NetworkMonitorEventsMD []map[string]string } +var udnsCache map[string]string + func NewRecord( key ebpf.BpfFlowId, metrics *BpfFlowContent, currentTime time.Time, monotonicCurrentTime uint64, + s *ovnobserv.SampleDecoder, ) *Record { + udnsCache = make(map[string]string) startDelta := time.Duration(monotonicCurrentTime - metrics.StartMonoTimeTs) endDelta := time.Duration(monotonicCurrentTime - metrics.EndMonoTimeTs) @@ -79,8 +86,20 @@ func NewRecord( Metrics: *metrics, TimeFlowStart: currentTime.Add(-startDelta), TimeFlowEnd: currentTime.Add(-endDelta), + AgentIP: agentIP, + Interfaces: []IntfDirUdn{NewIntfDirUdn( + interfaceNamer(int(metrics.IfIndexFirstSeen)), + int(metrics.DirectionFirstSeen), + s)}, } if metrics.AdditionalMetrics != nil { + for i := uint8(0); i < record.Metrics.AdditionalMetrics.NbObservedIntf; i++ { + record.Interfaces = append(record.Interfaces, NewIntfDirUdn( + interfaceNamer(int(metrics.AdditionalMetrics.ObservedIntf[i].IfIndex)), + int(metrics.AdditionalMetrics.ObservedIntf[i].Direction), + s, + )) + } if metrics.AdditionalMetrics.FlowRtt != 0 { record.TimeFlowRtt = time.Duration(metrics.AdditionalMetrics.FlowRtt) } @@ -88,11 +107,73 @@ func NewRecord( record.DNSLatency = time.Duration(metrics.AdditionalMetrics.DnsRecord.Latency) } } - record.DupList = make([]map[string]uint8, 0) - record.NetworkMonitorEventsMD = make([]config.GenericMap, 0) + if s != nil && metrics.AdditionalMetrics != nil { + seen := make(map[string]bool) + record.NetworkMonitorEventsMD = make([]map[string]string, 0) + for _, metadata := range metrics.AdditionalMetrics.NetworkEvents { + if !AllZerosMetaData(metadata) { + var cm map[string]string + if md, err := s.DecodeCookie8Bytes(metadata); err == nil { + acl, ok := md.(*ovnmodel.ACLEvent) + mdStr := md.String() + if !seen[mdStr] { + if ok { + cm = map[string]string{ + "Action": acl.Action, + "Type": acl.Actor, + "Feature": "acl", + "Name": acl.Name, + "Namespace": acl.Namespace, + "Direction": acl.Direction, + } + } else { + cm = map[string]string{ + "Message": mdStr, + } + } + record.NetworkMonitorEventsMD = append(record.NetworkMonitorEventsMD, cm) + seen[mdStr] = true + } + } + } + } + } return &record } +type IntfDirUdn struct { + Interface string + Direction int + Udn string +} + +func NewIntfDirUdn(intf string, dir int, s *ovnobserv.SampleDecoder) IntfDirUdn { + var udn string + if s == nil { + return IntfDirUdn{Interface: intf, Direction: dir, Udn: ""} + } + + // Load UDN cache if empty + if len(udnsCache) == 0 { + m, err := s.GetInterfaceUDNs() + if err != nil { + return IntfDirUdn{Interface: intf, Direction: dir, Udn: ""} + } + udnsCache = m + } + + // Look up the interface in the cache + if v, ok := udnsCache[intf]; ok { + if v != "" { + udn = v + } else { + udn = "default" + } + } + + return IntfDirUdn{Interface: intf, Direction: dir, Udn: udn} +} + func networkEventsMDExist(events [MaxNetworkEvents][NetworkEventsMaxEventsMD]uint8, md [NetworkEventsMaxEventsMD]uint8) bool { for _, e := range events { if reflect.DeepEqual(e, md) { diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow/flow.pb.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow/flow.pb.go index c1ce04bb8d..c15908885d 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow/flow.pb.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow/flow.pb.go @@ -159,6 +159,7 @@ type DupMapEntry struct { Interface string `protobuf:"bytes,1,opt,name=interface,proto3" json:"interface,omitempty"` Direction Direction `protobuf:"varint,2,opt,name=direction,proto3,enum=pbflow.Direction" json:"direction,omitempty"` + Udn string `protobuf:"bytes,3,opt,name=udn,proto3" json:"udn,omitempty"` } func (x *DupMapEntry) Reset() { @@ -205,6 +206,13 @@ func (x *DupMapEntry) GetDirection() Direction { return Direction_INGRESS } +func (x *DupMapEntry) GetUdn() string { + if x != nil { + return x.Udn + } + return "" +} + type NetworkEvent struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -791,7 +799,6 @@ type Xlat struct { SrcPort uint32 `protobuf:"varint,3,opt,name=src_port,json=srcPort,proto3" json:"src_port,omitempty"` DstPort uint32 `protobuf:"varint,4,opt,name=dst_port,json=dstPort,proto3" json:"dst_port,omitempty"` ZoneId uint32 `protobuf:"varint,5,opt,name=zone_id,json=zoneId,proto3" json:"zone_id,omitempty"` - IcmpId uint32 `protobuf:"varint,7,opt,name=icmp_id,json=icmpId,proto3" json:"icmp_id,omitempty"` } func (x *Xlat) Reset() { @@ -859,13 +866,6 @@ func (x *Xlat) GetZoneId() uint32 { return 0 } -func (x *Xlat) GetIcmpId() uint32 { - if x != nil { - return x.IcmpId - } - return 0 -} - var File_proto_flow_proto protoreflect.FileDescriptor var file_proto_flow_proto_rawDesc = []byte{ @@ -879,138 +879,137 @@ var file_proto_flow_proto_rawDesc = []byte{ 0x07, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x22, 0x5c, 0x0a, 0x0b, 0x44, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, + 0x65, 0x73, 0x22, 0x6e, 0x0a, 0x0b, 0x44, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x22, 0x83, 0x01, 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x38, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc8, 0x09, 0x0a, 0x06, 0x52, 0x65, 0x63, 0x6f, 0x72, - 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x65, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2f, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, - 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x3e, 0x0a, 0x0d, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x12, 0x10, 0x0a, 0x03, 0x75, 0x64, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, + 0x64, 0x6e, 0x22, 0x83, 0x01, 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x4e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x39, 0x0a, + 0x0b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc8, 0x09, 0x0a, 0x06, 0x52, 0x65, 0x63, + 0x6f, 0x72, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x65, 0x74, 0x68, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2f, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x62, 0x66, 0x6c, + 0x6f, 0x77, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x5f, + 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x74, 0x69, - 0x6d, 0x65, 0x46, 0x6c, 0x6f, 0x77, 0x45, 0x6e, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x64, 0x61, 0x74, - 0x61, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, - 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x08, - 0x64, 0x61, 0x74, 0x61, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x29, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x66, 0x6c, - 0x6f, 0x77, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x12, 0x2f, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, - 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x70, 0x61, 0x63, - 0x6b, 0x65, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x12, 0x25, 0x0a, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, 0x07, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, - 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x1b, 0x0a, - 0x09, 0x69, 0x63, 0x6d, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x08, 0x69, 0x63, 0x6d, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x63, - 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x69, - 0x63, 0x6d, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x6b, 0x74, 0x5f, 0x64, - 0x72, 0x6f, 0x70, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0c, 0x70, 0x6b, 0x74, 0x44, 0x72, 0x6f, 0x70, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x28, 0x0a, - 0x10, 0x70, 0x6b, 0x74, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, - 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x70, 0x6b, 0x74, 0x44, 0x72, 0x6f, 0x70, - 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x70, 0x6b, 0x74, 0x5f, 0x64, - 0x72, 0x6f, 0x70, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, - 0x18, 0x12, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x70, 0x6b, 0x74, 0x44, 0x72, 0x6f, 0x70, 0x4c, - 0x61, 0x74, 0x65, 0x73, 0x74, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x70, 0x6b, - 0x74, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x70, 0x6b, 0x74, 0x44, 0x72, - 0x6f, 0x70, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3a, 0x0a, - 0x1a, 0x70, 0x6b, 0x74, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, - 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x16, 0x70, 0x6b, 0x74, 0x44, 0x72, 0x6f, 0x70, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, - 0x44, 0x72, 0x6f, 0x70, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x6e, 0x73, - 0x5f, 0x69, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x6e, 0x73, 0x49, 0x64, - 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6e, 0x73, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x16, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x08, 0x64, 0x6e, 0x73, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x3a, 0x0a, - 0x0b, 0x64, 0x6e, 0x73, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x17, 0x20, 0x01, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x74, 0x69, + 0x6d, 0x65, 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x3e, 0x0a, 0x0d, 0x74, + 0x69, 0x6d, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, + 0x74, 0x69, 0x6d, 0x65, 0x46, 0x6c, 0x6f, 0x77, 0x45, 0x6e, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x64, + 0x61, 0x74, 0x61, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, + 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x4c, 0x69, 0x6e, 0x6b, + 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x29, 0x0a, 0x07, 0x6e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, + 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07, 0x6e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x2f, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, + 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, + 0x77, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x09, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, + 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x70, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, + 0x61, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x12, 0x25, 0x0a, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, + 0x52, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, + 0x67, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, + 0x1b, 0x0a, 0x09, 0x69, 0x63, 0x6d, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0e, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x08, 0x69, 0x63, 0x6d, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, + 0x69, 0x63, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x08, 0x69, 0x63, 0x6d, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x6b, 0x74, + 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0c, 0x70, 0x6b, 0x74, 0x44, 0x72, 0x6f, 0x70, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, + 0x28, 0x0a, 0x10, 0x70, 0x6b, 0x74, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x70, 0x61, 0x63, 0x6b, + 0x65, 0x74, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x70, 0x6b, 0x74, 0x44, 0x72, + 0x6f, 0x70, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x70, 0x6b, 0x74, + 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x66, 0x6c, 0x61, + 0x67, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x70, 0x6b, 0x74, 0x44, 0x72, 0x6f, + 0x70, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x31, 0x0a, 0x15, + 0x70, 0x6b, 0x74, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x70, 0x6b, 0x74, + 0x44, 0x72, 0x6f, 0x70, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x3a, 0x0a, 0x1a, 0x70, 0x6b, 0x74, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x6c, 0x61, 0x74, 0x65, + 0x73, 0x74, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x14, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x16, 0x70, 0x6b, 0x74, 0x44, 0x72, 0x6f, 0x70, 0x4c, 0x61, 0x74, 0x65, + 0x73, 0x74, 0x44, 0x72, 0x6f, 0x70, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, + 0x6e, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x6e, 0x73, + 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6e, 0x73, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, + 0x16, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x64, 0x6e, 0x73, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, + 0x3a, 0x0a, 0x0b, 0x64, 0x6e, 0x73, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x17, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0a, 0x64, 0x6e, 0x73, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x3d, 0x0a, 0x0d, 0x74, + 0x69, 0x6d, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x74, 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x64, - 0x6e, 0x73, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x3d, 0x0a, 0x0d, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x74, 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x69, 0x6d, - 0x65, 0x46, 0x6c, 0x6f, 0x77, 0x52, 0x74, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6e, 0x73, 0x5f, - 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x64, 0x6e, 0x73, - 0x45, 0x72, 0x72, 0x6e, 0x6f, 0x12, 0x2e, 0x0a, 0x08, 0x64, 0x75, 0x70, 0x5f, 0x6c, 0x69, 0x73, - 0x74, 0x18, 0x1a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, - 0x2e, 0x44, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x64, 0x75, - 0x70, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x4c, 0x0a, 0x17, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x1b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x15, 0x6e, 0x65, - 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x04, 0x78, 0x6c, 0x61, 0x74, 0x18, 0x1c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x58, 0x6c, 0x61, 0x74, 0x52, - 0x04, 0x78, 0x6c, 0x61, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, - 0x67, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, - 0x67, 0x22, 0x3c, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x17, 0x0a, - 0x07, 0x73, 0x72, 0x63, 0x5f, 0x6d, 0x61, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, - 0x73, 0x72, 0x63, 0x4d, 0x61, 0x63, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x73, 0x74, 0x5f, 0x6d, 0x61, - 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x64, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x22, - 0x6b, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x25, 0x0a, 0x08, 0x73, 0x72, - 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, - 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, 0x07, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, - 0x72, 0x12, 0x25, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, - 0x07, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x73, 0x63, 0x70, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x64, 0x73, 0x63, 0x70, 0x22, 0x3d, 0x0a, 0x02, - 0x49, 0x50, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, 0x07, - 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x36, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x36, 0x42, 0x0b, - 0x0a, 0x09, 0x69, 0x70, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, 0x5d, 0x0a, 0x09, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, - 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x72, 0x63, 0x50, - 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x64, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0xbc, 0x01, 0x0a, 0x04, 0x58, - 0x6c, 0x61, 0x74, 0x12, 0x25, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, - 0x50, 0x52, 0x07, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x12, 0x25, 0x0a, 0x08, 0x64, 0x73, - 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, - 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, 0x07, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x72, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, - 0x64, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, - 0x64, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x7a, 0x6f, 0x6e, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x7a, 0x6f, 0x6e, 0x65, 0x49, 0x64, - 0x12, 0x17, 0x0a, 0x07, 0x69, 0x63, 0x6d, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x06, 0x69, 0x63, 0x6d, 0x70, 0x49, 0x64, 0x2a, 0x24, 0x0a, 0x09, 0x44, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53, - 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x01, 0x32, - 0x3e, 0x0a, 0x09, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x31, 0x0a, 0x04, - 0x53, 0x65, 0x6e, 0x64, 0x12, 0x0f, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x52, 0x65, - 0x63, 0x6f, 0x72, 0x64, 0x73, 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x43, - 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, - 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, + 0x69, 0x6d, 0x65, 0x46, 0x6c, 0x6f, 0x77, 0x52, 0x74, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6e, + 0x73, 0x5f, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x64, + 0x6e, 0x73, 0x45, 0x72, 0x72, 0x6e, 0x6f, 0x12, 0x2e, 0x0a, 0x08, 0x64, 0x75, 0x70, 0x5f, 0x6c, + 0x69, 0x73, 0x74, 0x18, 0x1a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x62, 0x66, 0x6c, + 0x6f, 0x77, 0x2e, 0x44, 0x75, 0x70, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, + 0x64, 0x75, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x4c, 0x0a, 0x17, 0x6e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x1b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, + 0x77, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x15, + 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x04, 0x78, 0x6c, 0x61, 0x74, 0x18, 0x1c, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x58, 0x6c, 0x61, + 0x74, 0x52, 0x04, 0x78, 0x6c, 0x61, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x61, 0x6d, 0x70, 0x6c, + 0x69, 0x6e, 0x67, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x61, 0x6d, 0x70, 0x6c, + 0x69, 0x6e, 0x67, 0x22, 0x3c, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x4c, 0x69, 0x6e, 0x6b, 0x12, + 0x17, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x5f, 0x6d, 0x61, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x06, 0x73, 0x72, 0x63, 0x4d, 0x61, 0x63, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x73, 0x74, 0x5f, + 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x64, 0x73, 0x74, 0x4d, 0x61, + 0x63, 0x22, 0x6b, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x25, 0x0a, 0x08, + 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, + 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, 0x07, 0x73, 0x72, 0x63, 0x41, + 0x64, 0x64, 0x72, 0x12, 0x25, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, + 0x50, 0x52, 0x07, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x73, + 0x63, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x64, 0x73, 0x63, 0x70, 0x22, 0x3d, + 0x0a, 0x02, 0x49, 0x50, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x07, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, + 0x76, 0x36, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x36, + 0x42, 0x0b, 0x0a, 0x09, 0x69, 0x70, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, 0x5d, 0x0a, + 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, + 0x63, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x72, + 0x63, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x72, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x64, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, + 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0xa3, 0x01, 0x0a, + 0x04, 0x58, 0x6c, 0x61, 0x74, 0x12, 0x25, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, + 0x2e, 0x49, 0x50, 0x52, 0x07, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x12, 0x25, 0x0a, 0x08, + 0x64, 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, + 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, 0x07, 0x64, 0x73, 0x74, 0x41, + 0x64, 0x64, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x72, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x19, + 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x64, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x7a, 0x6f, 0x6e, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x7a, 0x6f, 0x6e, 0x65, + 0x49, 0x64, 0x2a, 0x24, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, + 0x45, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x01, 0x32, 0x3e, 0x0a, 0x09, 0x43, 0x6f, 0x6c, 0x6c, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x31, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x0f, 0x2e, + 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x1a, 0x16, + 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x62, + 0x66, 0x6c, 0x6f, 0x77, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow/proto.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow/proto.go index 27b7e57c08..781881ebd7 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow/proto.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow/proto.go @@ -4,11 +4,8 @@ import ( "encoding/binary" "net" - "github.com/netobserv/flowlogs-pipeline/pkg/config" "github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf" "github.com/netobserv/netobserv-ebpf-agent/pkg/model" - ovnmodel "github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/model" - ovnobserv "github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder" "github.com/sirupsen/logrus" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" @@ -18,10 +15,10 @@ var protoLog = logrus.WithField("component", "pbflow") // FlowsToPB is an auxiliary function to convert flow records, as returned by the eBPF agent, // into protobuf-encoded messages ready to be sent to the collector via GRPC -func FlowsToPB(inputRecords []*model.Record, maxLen int, s *ovnobserv.SampleDecoder) []*Records { +func FlowsToPB(inputRecords []*model.Record, maxLen int) []*Records { entries := make([]*Record, 0, len(inputRecords)) for _, record := range inputRecords { - entries = append(entries, FlowToPB(record, s)) + entries = append(entries, FlowToPB(record)) } var records []*Records for len(entries) > 0 { @@ -37,10 +34,10 @@ func FlowsToPB(inputRecords []*model.Record, maxLen int, s *ovnobserv.SampleDeco // FlowToPB is an auxiliary function to convert a single flow record, as returned by the eBPF agent, // into a protobuf-encoded message ready to be sent to the collector via kafka -func FlowToPB(fr *model.Record, s *ovnobserv.SampleDecoder) *Record { +func FlowToPB(fr *model.Record) *Record { var pbflowRecord = Record{ EthProtocol: uint32(fr.Metrics.EthProtocol), - Direction: Direction(fr.ID.Direction), + Direction: Direction(fr.Metrics.DirectionFirstSeen), DataLink: &DataLink{ SrcMac: macToUint64(&fr.Metrics.SrcMac), DstMac: macToUint64(&fr.Metrics.DstMac), @@ -65,10 +62,8 @@ func FlowToPB(fr *model.Record, s *ovnobserv.SampleDecoder) *Record { Nanos: int32(fr.TimeFlowEnd.Nanosecond()), }, Packets: uint64(fr.Metrics.Packets), - Duplicate: fr.Duplicate, AgentIp: agentIP(fr.AgentIP), Flags: uint32(fr.Metrics.Flags), - Interface: fr.Interface, TimeFlowRtt: durationpb.New(fr.TimeFlowRtt), Sampling: fr.Metrics.Sampling, } @@ -88,19 +83,15 @@ func FlowToPB(fr *model.Record, s *ovnobserv.SampleDecoder) *Record { SrcPort: uint32(fr.Metrics.AdditionalMetrics.TranslatedFlow.Sport), DstPort: uint32(fr.Metrics.AdditionalMetrics.TranslatedFlow.Dport), ZoneId: uint32(fr.Metrics.AdditionalMetrics.TranslatedFlow.ZoneId), - IcmpId: uint32(fr.Metrics.AdditionalMetrics.TranslatedFlow.IcmpId), } } - if len(fr.DupList) != 0 { - pbflowRecord.DupList = make([]*DupMapEntry, 0) - for _, m := range fr.DupList { - for key, value := range m { - pbflowRecord.DupList = append(pbflowRecord.DupList, &DupMapEntry{ - Interface: key, - Direction: Direction(value), - }) - } - } + pbflowRecord.DupList = make([]*DupMapEntry, 0) + for _, intf := range fr.Interfaces { + pbflowRecord.DupList = append(pbflowRecord.DupList, &DupMapEntry{ + Interface: intf.Interface, + Direction: Direction(intf.Direction), + Udn: intf.Udn, + }) } if fr.Metrics.EthProtocol == model.IPv6Type { pbflowRecord.Network.SrcAddr = &IP{IpFamily: &IP_Ipv6{Ipv6: fr.ID.SrcIp[:]}} @@ -117,42 +108,13 @@ func FlowToPB(fr *model.Record, s *ovnobserv.SampleDecoder) *Record { pbflowRecord.Xlat.DstAddr = &IP{IpFamily: &IP_Ipv4{Ipv4: model.IntEncodeV4(fr.Metrics.AdditionalMetrics.TranslatedFlow.Daddr)}} } } - if s != nil && fr.Metrics.AdditionalMetrics != nil { - seen := make(map[string]bool) + + if len(fr.NetworkMonitorEventsMD) != 0 { pbflowRecord.NetworkEventsMetadata = make([]*NetworkEvent, 0) - for _, metadata := range fr.Metrics.AdditionalMetrics.NetworkEvents { - var pbEvent NetworkEvent - if !model.AllZerosMetaData(metadata) { - if md, err := s.DecodeCookie8Bytes(metadata); err == nil { - acl, ok := md.(*ovnmodel.ACLEvent) - mdStr := md.String() - protoLog.Debugf("Network Events Metadata %v decoded Cookie: %v decoded string: %s", metadata, md, mdStr) - if !seen[mdStr] { - if ok { - pbEvent = NetworkEvent{ - Events: map[string]string{ - "Action": acl.Action, - "Type": acl.Actor, - "Feature": "acl", - "Name": acl.Name, - "Namespace": acl.Namespace, - "Direction": acl.Direction, - }, - } - } else { - pbEvent = NetworkEvent{ - Events: map[string]string{ - "Message": mdStr, - }, - } - } - pbflowRecord.NetworkEventsMetadata = append(pbflowRecord.NetworkEventsMetadata, &pbEvent) - seen[mdStr] = true - } - } else { - protoLog.Errorf("unable to decode Network events cookie: %v", err) - } - } + for _, networkEvent := range fr.NetworkMonitorEventsMD { + pbflowRecord.NetworkEventsMetadata = append(pbflowRecord.NetworkEventsMetadata, &NetworkEvent{ + Events: networkEvent, + }) } } return &pbflowRecord @@ -164,7 +126,6 @@ func PBToFlow(pb *Record) *model.Record { } out := model.Record{ ID: ebpf.BpfFlowId{ - Direction: uint8(pb.Direction), TransportProtocol: uint8(pb.Transport.Protocol), SrcIp: ipToIPAddr(pb.Network.GetSrcAddr()), DstIp: ipToIPAddr(pb.Network.GetDstAddr()), @@ -204,35 +165,35 @@ func PBToFlow(pb *Record) *model.Record { Sport: uint16(pb.Xlat.GetSrcPort()), Dport: uint16(pb.Xlat.GetDstPort()), ZoneId: uint16(pb.Xlat.GetZoneId()), - IcmpId: uint8(pb.Xlat.GetIcmpId()), }, }, }, TimeFlowStart: pb.TimeFlowStart.AsTime(), TimeFlowEnd: pb.TimeFlowEnd.AsTime(), AgentIP: pbIPToNetIP(pb.AgentIp), - Duplicate: pb.Duplicate, - Interface: pb.Interface, TimeFlowRtt: pb.TimeFlowRtt.AsDuration(), DNSLatency: pb.DnsLatency.AsDuration(), } if len(pb.GetDupList()) != 0 { for _, entry := range pb.GetDupList() { - intf := entry.Interface - dir := uint8(entry.Direction) - out.DupList = append(out.DupList, map[string]uint8{intf: dir}) + out.Interfaces = append(out.Interfaces, model.IntfDirUdn{ + Interface: entry.Interface, + Direction: int(entry.Direction), + Udn: entry.Udn, + }) } } + if len(pb.GetNetworkEventsMetadata()) != 0 { for _, e := range pb.GetNetworkEventsMetadata() { - m := config.GenericMap{} + m := map[string]string{} for k, v := range e.Events { m[k] = v } out.NetworkMonitorEventsMD = append(out.NetworkMonitorEventsMD, m) } - protoLog.Debugf("decoded Network events monitor metadata: %v", out.NetworkMonitorEventsMD) + protoLog.Tracef("decoded Network events monitor metadata: %v", out.NetworkMonitorEventsMD) } return &out diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/flow_filter.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/flow_filter.go index b29e2dcfb5..0fb15e14f5 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/flow_filter.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/flow_filter.go @@ -22,6 +22,7 @@ type FilterConfig struct { FilterIcmpType int FilterIcmpCode int FilterPeerIP string + FilterPeerCIDR string FilterAction string FilterTCPFlags string FilterDrops bool @@ -29,20 +30,14 @@ type FilterConfig struct { } type Filter struct { - // eBPF objs to create/update eBPF maps - objects *ebpf.BpfObjects - config []*FilterConfig + config []*FilterConfig } -func NewFilter(objects *ebpf.BpfObjects, cfg []*FilterConfig) *Filter { - return &Filter{ - objects: objects, - config: cfg, - } +func NewFilter(cfg []*FilterConfig) *Filter { + return &Filter{config: cfg} } -func (f *Filter) ProgramFilter() error { - +func (f *Filter) ProgramFilter(objects *ebpf.BpfObjects) error { for _, config := range f.config { log.Infof("Flow filter config: %v", f.config) key, err := f.getFilterKey(config) @@ -55,7 +50,19 @@ func (f *Filter) ProgramFilter() error { return fmt.Errorf("failed to get filter value: %w", err) } - err = f.objects.FilterMap.Update(key, val, cilium.UpdateAny) + if val.DoPeerCIDR_lookup == 1 { + peerVal := uint8(1) + peerKey, err := f.getPeerFilterKey(config) + if err != nil { + return fmt.Errorf("failed to get peer filter key: %w", err) + } + err = objects.PeerFilterMap.Update(peerKey, peerVal, cilium.UpdateAny) + if err != nil { + return fmt.Errorf("failed to update peer filter map: %w", err) + } + log.Infof("Programmed filter with PeerCIDR: %v", peerKey) + } + err = objects.FilterMap.Update(key, val, cilium.UpdateAny) if err != nil { return fmt.Errorf("failed to update filter map: %w", err) } @@ -65,24 +72,42 @@ func (f *Filter) ProgramFilter() error { return nil } -func (f *Filter) getFilterKey(config *FilterConfig) (ebpf.BpfFilterKeyT, error) { +func (f *Filter) buildFilterKey(cidr, ipStr string) (ebpf.BpfFilterKeyT, error) { key := ebpf.BpfFilterKeyT{} + if cidr != "" { + ip, ipNet, err := net.ParseCIDR(cidr) + if err != nil { + return key, fmt.Errorf("failed to parse CIDR: %w", err) + } + if ip.To4() != nil { + copy(key.IpData[:], ip.To4()) + } else { + copy(key.IpData[:], ip.To16()) + } + pfLen, _ := ipNet.Mask.Size() + key.PrefixLen = uint32(pfLen) + } else if ipStr != "" { + ip := net.ParseIP(ipStr) + if ip.To4() != nil { + copy(key.IpData[:], ip.To4()) + key.PrefixLen = 32 + } else { + copy(key.IpData[:], ip.To16()) + key.PrefixLen = 128 + } + } + return key, nil +} + +func (f *Filter) getFilterKey(config *FilterConfig) (ebpf.BpfFilterKeyT, error) { if config.FilterIPCIDR == "" { config.FilterIPCIDR = "0.0.0.0/0" } - ip, ipNet, err := net.ParseCIDR(config.FilterIPCIDR) - if err != nil { - return key, fmt.Errorf("failed to parse FlowFilterIPCIDR: %w", err) - } - if ip.To4() != nil { - copy(key.IpData[:], ip.To4()) - } else { - copy(key.IpData[:], ip.To16()) - } - pfLen, _ := ipNet.Mask.Size() - key.PrefixLen = uint32(pfLen) + return f.buildFilterKey(config.FilterIPCIDR, "") +} - return key, nil +func (f *Filter) getPeerFilterKey(config *FilterConfig) (ebpf.BpfFilterKeyT, error) { + return f.buildFilterKey(config.FilterPeerCIDR, config.FilterPeerIP) } // nolint:cyclop @@ -129,15 +154,6 @@ func (f *Filter) getFilterValue(config *FilterConfig) (ebpf.BpfFilterValueT, err val.IcmpType = uint8(config.FilterIcmpType) val.IcmpCode = uint8(config.FilterIcmpCode) - if config.FilterPeerIP != "" { - ip := net.ParseIP(config.FilterPeerIP) - if ip.To4() != nil { - copy(val.Ip[:], ip.To4()) - } else { - copy(val.Ip[:], ip.To16()) - } - } - switch config.FilterTCPFlags { case "SYN": val.TcpFlags = ebpf.BpfTcpFlagsTSYN_FLAG @@ -170,6 +186,9 @@ func (f *Filter) getFilterValue(config *FilterConfig) (ebpf.BpfFilterValueT, err if config.FilterSample != 0 { val.Sample = config.FilterSample } + if config.FilterPeerCIDR != "" || config.FilterPeerIP != "" { + val.DoPeerCIDR_lookup = 1 + } return val, nil } @@ -264,3 +283,12 @@ func ConvertFilterPortsToInstr(intPort int32, rangePorts, ports string) intstr.I } return intstr.FromInt32(intPort) } + +func (f *Filter) hasSampling() uint8 { + for _, r := range f.config { + if r.FilterSample > 0 { + return 1 + } + } + return 0 +} diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/tracer.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/tracer.go index 6b9ab6cc34..da2cac8bcd 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/tracer.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/tracer.go @@ -36,8 +36,11 @@ const ( aggregatedFlowsMap = "aggregated_flows" additionalFlowMetrics = "additional_flow_metrics" dnsLatencyMap = "dns_flows" + flowFilterMap = "filter_map" + flowPeerFilterMap = "peer_filter_map" // constants defined in flows.c as "volatile const" constSampling = "sampling" + constHasFilterSampling = "has_filter_sampling" constTraceMessages = "trace_messages" constEnableRtt = "enable_rtt" constEnableDNSTracking = "enable_dns_tracking" @@ -114,6 +117,10 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { var err error objects := ebpf.BpfObjects{} var pinDir string + var filter *Filter + if cfg.EnableFlowFilter { + filter = NewFilter(cfg.FilterConfig) + } if !cfg.UseEbpfManager { if err := rlimit.RemoveMemlock(); err != nil { @@ -127,13 +134,10 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { // Resize maps according to user-provided configuration spec.Maps[aggregatedFlowsMap].MaxEntries = uint32(cfg.CacheMaxSize) - if isEBPFFeaturesEnabled(cfg) { - spec.Maps[additionalFlowMetrics].MaxEntries = uint32(cfg.CacheMaxSize) - } else { - spec.Maps[additionalFlowMetrics].MaxEntries = 1 - } + spec.Maps[additionalFlowMetrics].MaxEntries = uint32(cfg.CacheMaxSize) + // remove pinning from all maps - maps2Name := []string{"aggregated_flows", "additional_flow_metrics", "direct_flows", "dns_flows", "filter_map", "global_counters", "packet_record"} + maps2Name := []string{"aggregated_flows", "additional_flow_metrics", "direct_flows", "dns_flows", "filter_map", "peer_filter_map", "global_counters", "packet_record"} for _, m := range maps2Name { spec.Maps[m].Pinning = 0 } @@ -162,8 +166,13 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { } enableFlowFiltering := 0 - if cfg.EnableFlowFilter { + hasFilterSampling := uint8(0) + if filter != nil { enableFlowFiltering = 1 + hasFilterSampling = filter.hasSampling() + } else { + spec.Maps[flowFilterMap].MaxEntries = 1 + spec.Maps[flowPeerFilterMap].MaxEntries = 1 } enableNetworkEventsMonitoring := 0 if cfg.EnableNetworkEventsMonitoring { @@ -178,7 +187,9 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { enablePktTranslation = 1 } if err := spec.RewriteConstants(map[string]interface{}{ + // When adding constants here, remember to delete them in NewPacketFetcher constSampling: uint32(cfg.Sampling), + constHasFilterSampling: hasFilterSampling, constTraceMessages: uint8(traceMsgs), constEnableRtt: uint8(enableRtt), constEnableDNSTracking: uint8(enableDNSTracking), @@ -312,6 +323,10 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { if err != nil { return nil, fmt.Errorf("failed to load %s: %w", mPath, err) } + objects.BpfMaps.PeerFilterMap, err = cilium.LoadPinnedMap(mPath, opts) + if err != nil { + return nil, fmt.Errorf("failed to load %s: %w", mPath, err) + } log.Infof("BPFManager mode: loading global counters pinned maps") mPath = path.Join(pinDir, "global_counters") objects.BpfMaps.GlobalCounters, err = cilium.LoadPinnedMap(mPath, opts) @@ -326,9 +341,8 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { } } - if cfg.EnableFlowFilter { - f := NewFilter(&objects, cfg.FilterConfig) - if err := f.ProgramFilter(); err != nil { + if filter != nil { + if err := filter.ProgramFilter(&objects); err != nil { return nil, fmt.Errorf("programming flow filter: %w", err) } } @@ -360,13 +374,6 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { }, nil } -func isEBPFFeaturesEnabled(cfg *FlowFetcherConfig) bool { - if cfg.EnableNetworkEventsMonitoring || cfg.EnableRTT || cfg.EnablePktDrops || cfg.EnableDNSTracker || cfg.EnablePktTranslation { - return true - } - return false -} - func (m *FlowFetcher) AttachTCX(iface ifaces.Interface) error { ilog := log.WithField("iface", iface) if iface.NetNS != netns.None() { @@ -724,6 +731,9 @@ func (m *FlowFetcher) Close() error { if err := m.objects.AggregatedFlows.Close(); err != nil { errs = append(errs, err) } + if err := m.objects.AdditionalFlowMetrics.Close(); err != nil { + errs = append(errs, err) + } if err := m.objects.DirectFlows.Close(); err != nil { errs = append(errs, err) } @@ -736,6 +746,9 @@ func (m *FlowFetcher) Close() error { if err := m.objects.FilterMap.Close(); err != nil { errs = append(errs, err) } + if err := m.objects.PeerFilterMap.Close(); err != nil { + errs = append(errs, err) + } if len(errs) == 0 { m.objects = nil } @@ -852,23 +865,21 @@ func (m *FlowFetcher) LookupAndDeleteMap(met *metrics.Metrics) map[ebpf.BpfFlowI } flowMap := m.objects.AggregatedFlows - - iterator := flowMap.Iterate() var flows = make(map[ebpf.BpfFlowId]model.BpfFlowContent, m.cacheMaxSize) var ids []ebpf.BpfFlowId var id ebpf.BpfFlowId var baseMetrics ebpf.BpfFlowMetrics - var additionalMetrics []ebpf.BpfAdditionalMetrics // First, get all ids and don't care about metrics (we need lookup+delete to be atomic) + iterator := flowMap.Iterate() for iterator.Next(&id, &baseMetrics) { ids = append(ids, id) } - count := 0 + countMain := 0 // Run the atomic Lookup+Delete; if new ids have been inserted in the meantime, they'll be fetched next time for i, id := range ids { - count++ + countMain++ if err := flowMap.LookupAndDelete(&id, &baseMetrics); err != nil { if i == 0 && errors.Is(err, cilium.ErrNotSupported) { log.WithError(err).Warnf("switching to legacy mode") @@ -879,32 +890,62 @@ func (m *FlowFetcher) LookupAndDeleteMap(met *metrics.Metrics) map[ebpf.BpfFlowI met.Errors.WithErrorName("flow-fetcher", "CannotDeleteFlows").Inc() continue } - flowPayload := model.BpfFlowContent{BpfFlowMetrics: &ebpf.BpfFlowMetrics{}} - flowPayload.AccumulateBase(&baseMetrics) - - // Fetch additional metrics; ids are without direction and interface - shorterID := id - shorterID.Direction = 0 - shorterID.IfIndex = 0 - if err := m.objects.AdditionalFlowMetrics.LookupAndDelete(&shorterID, &additionalMetrics); err != nil { - if !errors.Is(err, cilium.ErrKeyNotExist) { - log.WithError(err).WithField("flowId", id).Warnf("couldn't lookup/delete additional metrics entry") - met.Errors.WithErrorName("flow-fetcher", "CannotDeleteAdditionalMetric").Inc() - } - } else { - for i := range additionalMetrics { - flowPayload.AccumulateAdditional(&additionalMetrics[i]) + flows[id] = model.NewBpfFlowContent(baseMetrics) + } + + // Reiterate on additional metrics + var additionalMetrics []ebpf.BpfAdditionalMetrics + ids = []ebpf.BpfFlowId{} + addtlIterator := m.objects.AdditionalFlowMetrics.Iterate() + for addtlIterator.Next(&id, &additionalMetrics) { + ids = append(ids, id) + } + + countAdditional := 0 + for i, id := range ids { + countAdditional++ + if err := m.objects.AdditionalFlowMetrics.LookupAndDelete(&id, &additionalMetrics); err != nil { + if i == 0 && errors.Is(err, cilium.ErrNotSupported) { + log.WithError(err).Warnf("switching to legacy mode") + m.lookupAndDeleteSupported = false + return m.legacyLookupAndDeleteMap(met) } + log.WithError(err).WithField("flowId", id).Warnf("couldn't lookup/delete additional metrics entry") + met.Errors.WithErrorName("flow-fetcher", "CannotDeleteAdditionalMetric").Inc() + continue + } + flow, found := flows[id] + if !found { + flow = model.BpfFlowContent{BpfFlowMetrics: &ebpf.BpfFlowMetrics{}} } - flows[id] = flowPayload + for iMet := range additionalMetrics { + flow.AccumulateAdditional(&additionalMetrics[iMet]) + } + m.increaseEnrichmentStats(met, &flow) + flows[id] = flow } - met.BufferSizeGauge.WithBufferName("hashmap-total").Set(float64(count)) - met.BufferSizeGauge.WithBufferName("hashmap-unique").Set(float64(len(flows))) + met.BufferSizeGauge.WithBufferName("additionalmap").Set(float64(countAdditional)) + met.BufferSizeGauge.WithBufferName("flowmap").Set(float64(countMain)) + met.BufferSizeGauge.WithBufferName("merged-maps").Set(float64(len(flows))) m.ReadGlobalCounter(met) return flows } +func (m *FlowFetcher) increaseEnrichmentStats(met *metrics.Metrics, flow *model.BpfFlowContent) { + if flow.AdditionalMetrics != nil { + met.FlowEnrichmentCounter.Increase( + flow.AdditionalMetrics.DnsRecord.Id != 0, + flow.AdditionalMetrics.FlowRtt != 0, + flow.AdditionalMetrics.PktDrops.Packets != 0, + !model.AllZerosMetaData(flow.AdditionalMetrics.NetworkEvents[0]), + !model.AllZeroIP(model.IP(flow.AdditionalMetrics.TranslatedFlow.Daddr)), + ) + } else { + met.FlowEnrichmentCounter.Increase(false, false, false, false, false) + } +} + // ReadGlobalCounter reads the global counter and updates drop flows counter metrics func (m *FlowFetcher) ReadGlobalCounter(met *metrics.Metrics) { var allCPUValue []uint32 @@ -918,6 +959,7 @@ func (m *FlowFetcher) ReadGlobalCounter(met *metrics.Metrics) { ebpf.BpfGlobalCountersKeyTNETWORK_EVENTS_ERR_GROUPID_MISMATCH: met.NetworkEventsCounter.WithSourceAndReason("network-events", "NetworkEventsErrorsGroupIDMismatch"), ebpf.BpfGlobalCountersKeyTNETWORK_EVENTS_ERR_UPDATE_MAP_FLOWS: met.NetworkEventsCounter.WithSourceAndReason("network-events", "NetworkEventsErrorsFlowMapUpdate"), ebpf.BpfGlobalCountersKeyTNETWORK_EVENTS_GOOD: met.NetworkEventsCounter.WithSourceAndReason("network-events", "NetworkEventsGoodEvent"), + ebpf.BpfGlobalCountersKeyTOBSERVED_INTF_MISSED: met.Errors.WithErrorName("flow-fetcher", "MaxObservedInterfacesReached"), } zeroCounters := make([]uint32, cilium.MustPossibleCPU()) for key := ebpf.BpfGlobalCountersKeyT(0); key < ebpf.BpfGlobalCountersKeyTMAX_COUNTERS; key++ { @@ -1037,11 +1079,13 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, RhNetworkEventsMonitoring: nil, }, BpfMaps: ebpf.BpfMaps{ - DirectFlows: newObjects.DirectFlows, - AggregatedFlows: newObjects.AggregatedFlows, - DnsFlows: newObjects.DnsFlows, - FilterMap: newObjects.FilterMap, - GlobalCounters: newObjects.GlobalCounters, + DirectFlows: newObjects.DirectFlows, + AggregatedFlows: newObjects.AggregatedFlows, + AdditionalFlowMetrics: newObjects.AdditionalFlowMetrics, + DnsFlows: newObjects.DnsFlows, + FilterMap: newObjects.FilterMap, + PeerFilterMap: newObjects.PeerFilterMap, + GlobalCounters: newObjects.GlobalCounters, }, } @@ -1087,11 +1131,13 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, RhNetworkEventsMonitoring: nil, }, BpfMaps: ebpf.BpfMaps{ - DirectFlows: newObjects.DirectFlows, - AggregatedFlows: newObjects.AggregatedFlows, - DnsFlows: newObjects.DnsFlows, - FilterMap: newObjects.FilterMap, - GlobalCounters: newObjects.GlobalCounters, + DirectFlows: newObjects.DirectFlows, + AggregatedFlows: newObjects.AggregatedFlows, + AdditionalFlowMetrics: newObjects.AdditionalFlowMetrics, + DnsFlows: newObjects.DnsFlows, + FilterMap: newObjects.FilterMap, + PeerFilterMap: newObjects.PeerFilterMap, + GlobalCounters: newObjects.GlobalCounters, }, } @@ -1137,11 +1183,13 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, RhNetworkEventsMonitoring: nil, }, BpfMaps: ebpf.BpfMaps{ - DirectFlows: newObjects.DirectFlows, - AggregatedFlows: newObjects.AggregatedFlows, - DnsFlows: newObjects.DnsFlows, - FilterMap: newObjects.FilterMap, - GlobalCounters: newObjects.GlobalCounters, + DirectFlows: newObjects.DirectFlows, + AggregatedFlows: newObjects.AggregatedFlows, + AdditionalFlowMetrics: newObjects.AdditionalFlowMetrics, + DnsFlows: newObjects.DnsFlows, + FilterMap: newObjects.FilterMap, + PeerFilterMap: newObjects.PeerFilterMap, + GlobalCounters: newObjects.GlobalCounters, }, } @@ -1188,11 +1236,13 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, RhNetworkEventsMonitoring: nil, }, BpfMaps: ebpf.BpfMaps{ - DirectFlows: newObjects.DirectFlows, - AggregatedFlows: newObjects.AggregatedFlows, - DnsFlows: newObjects.DnsFlows, - FilterMap: newObjects.FilterMap, - GlobalCounters: newObjects.GlobalCounters, + DirectFlows: newObjects.DirectFlows, + AggregatedFlows: newObjects.AggregatedFlows, + AdditionalFlowMetrics: newObjects.AdditionalFlowMetrics, + DnsFlows: newObjects.DnsFlows, + FilterMap: newObjects.FilterMap, + PeerFilterMap: newObjects.PeerFilterMap, + GlobalCounters: newObjects.GlobalCounters, }, } @@ -1246,6 +1296,12 @@ func NewPacketFetcher(cfg *FlowFetcherConfig) (*PacketFetcher, error) { return nil, fmt.Errorf("rewriting BPF constants definition: %w", err) } + // remove pinning from all maps + maps2Name := []string{"aggregated_flows", "additional_flow_metrics", "direct_flows", "dns_flows", "filter_map", "global_counters", "packet_record"} + for _, m := range maps2Name { + spec.Maps[m].Pinning = 0 + } + type pcaBpfPrograms struct { TcEgressPcaParse *cilium.Program `ebpf:"tc_egress_pca_parse"` TcIngressPcaParse *cilium.Program `ebpf:"tc_ingress_pca_parse"` @@ -1264,6 +1320,7 @@ func NewPacketFetcher(cfg *FlowFetcherConfig) (*PacketFetcher, error) { delete(spec.Programs, aggregatedFlowsMap) delete(spec.Programs, additionalFlowMetrics) delete(spec.Programs, constSampling) + delete(spec.Programs, constHasFilterSampling) delete(spec.Programs, constTraceMessages) delete(spec.Programs, constEnableDNSTracking) delete(spec.Programs, constDNSTrackingPort) @@ -1272,7 +1329,7 @@ func NewPacketFetcher(cfg *FlowFetcherConfig) (*PacketFetcher, error) { delete(spec.Programs, constEnableNetworkEventsMonitoring) delete(spec.Programs, constNetworkEventsMonitoringGroupID) - if err := spec.LoadAndAssign(&newObjects, nil); err != nil { + if err := spec.LoadAndAssign(&newObjects, &cilium.CollectionOptions{Maps: cilium.MapOptions{PinPath: ""}}); err != nil { var ve *cilium.VerifierError if errors.As(err, &ve) { // Using %+v will print the whole verifier error, not just the last @@ -1298,13 +1355,14 @@ func NewPacketFetcher(cfg *FlowFetcherConfig) (*PacketFetcher, error) { RhNetworkEventsMonitoring: nil, }, BpfMaps: ebpf.BpfMaps{ - PacketRecord: newObjects.PacketRecord, - FilterMap: newObjects.FilterMap, + PacketRecord: newObjects.PacketRecord, + FilterMap: newObjects.FilterMap, + PeerFilterMap: newObjects.PeerFilterMap, }, } - f := NewFilter(&objects, cfg.FilterConfig) - if err := f.ProgramFilter(); err != nil { + f := NewFilter(cfg.FilterConfig) + if err := f.ProgramFilter(&objects); err != nil { return nil, fmt.Errorf("programming flow filter: %w", err) } diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/tracer_legacy.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/tracer_legacy.go index d573146a58..51681d7a6f 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/tracer_legacy.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/tracer/tracer_legacy.go @@ -14,24 +14,18 @@ func (m *FlowFetcher) legacyLookupAndDeleteMap(met *metrics.Metrics) map[ebpf.Bp iterator := flowMap.Iterate() var flows = make(map[ebpf.BpfFlowId]model.BpfFlowContent, m.cacheMaxSize) var id ebpf.BpfFlowId - var metrics []ebpf.BpfFlowMetrics + var baseMetrics ebpf.BpfFlowMetrics count := 0 // Deleting while iterating is really bad for performance (like, really!) as it causes seeing multiple times the same key // This is solved in >=4.20 kernels with LookupAndDelete - for iterator.Next(&id, &metrics) { + for iterator.Next(&id, &baseMetrics) { count++ if err := flowMap.Delete(id); err != nil { log.WithError(err).WithField("flowId", id).Warnf("couldn't delete flow entry") met.Errors.WithErrorName("flow-fetcher-legacy", "CannotDeleteFlows").Inc() } - // We observed that eBFP PerCPU map might insert multiple times the same key in the map - // (probably due to race conditions) so we need to re-join metrics again at userspace - aggr := model.BpfFlowContent{} - for i := range metrics { - aggr.AccumulateBase(&metrics[i]) - } - flows[id] = aggr + flows[id] = model.NewBpfFlowContent(baseMetrics) } met.BufferSizeGauge.WithBufferName("hashmap-legacy-total").Set(float64(count)) met.BufferSizeGauge.WithBufferName("hashmap-legacy-unique").Set(float64(len(flows))) diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/ovsdb/interface.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/ovsdb/interface.go new file mode 100644 index 0000000000..e9f350995c --- /dev/null +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/ovsdb/interface.go @@ -0,0 +1,903 @@ +// Code generated by "libovsdb.modelgen" +// DO NOT EDIT. + +package ovsdb + +import "github.com/ovn-org/libovsdb/model" + +const InterfaceTable = "Interface" + +type ( + InterfaceAdminState = string + InterfaceCFMRemoteOpstate = string + InterfaceDuplex = string + InterfaceLinkState = string +) + +var ( + InterfaceAdminStateUp InterfaceAdminState = "up" + InterfaceAdminStateDown InterfaceAdminState = "down" + InterfaceCFMRemoteOpstateUp InterfaceCFMRemoteOpstate = "up" + InterfaceCFMRemoteOpstateDown InterfaceCFMRemoteOpstate = "down" + InterfaceDuplexHalf InterfaceDuplex = "half" + InterfaceDuplexFull InterfaceDuplex = "full" + InterfaceLinkStateUp InterfaceLinkState = "up" + InterfaceLinkStateDown InterfaceLinkState = "down" +) + +// Interface defines an object in Interface table +type Interface struct { + UUID string `ovsdb:"_uuid"` + AdminState *InterfaceAdminState `ovsdb:"admin_state"` + BFD map[string]string `ovsdb:"bfd"` + BFDStatus map[string]string `ovsdb:"bfd_status"` + CFMFault *bool `ovsdb:"cfm_fault"` + CFMFaultStatus []string `ovsdb:"cfm_fault_status"` + CFMFlapCount *int `ovsdb:"cfm_flap_count"` + CFMHealth *int `ovsdb:"cfm_health"` + CFMMpid *int `ovsdb:"cfm_mpid"` + CFMRemoteMpids []int `ovsdb:"cfm_remote_mpids"` + CFMRemoteOpstate *InterfaceCFMRemoteOpstate `ovsdb:"cfm_remote_opstate"` + Duplex *InterfaceDuplex `ovsdb:"duplex"` + Error *string `ovsdb:"error"` + ExternalIDs map[string]string `ovsdb:"external_ids"` + Ifindex *int `ovsdb:"ifindex"` + IngressPolicingBurst int `ovsdb:"ingress_policing_burst"` + IngressPolicingKpktsBurst int `ovsdb:"ingress_policing_kpkts_burst"` + IngressPolicingKpktsRate int `ovsdb:"ingress_policing_kpkts_rate"` + IngressPolicingRate int `ovsdb:"ingress_policing_rate"` + LACPCurrent *bool `ovsdb:"lacp_current"` + LinkResets *int `ovsdb:"link_resets"` + LinkSpeed *int `ovsdb:"link_speed"` + LinkState *InterfaceLinkState `ovsdb:"link_state"` + LLDP map[string]string `ovsdb:"lldp"` + MAC *string `ovsdb:"mac"` + MACInUse *string `ovsdb:"mac_in_use"` + MTU *int `ovsdb:"mtu"` + MTURequest *int `ovsdb:"mtu_request"` + Name string `ovsdb:"name"` + Ofport *int `ovsdb:"ofport"` + OfportRequest *int `ovsdb:"ofport_request"` + Options map[string]string `ovsdb:"options"` + OtherConfig map[string]string `ovsdb:"other_config"` + Statistics map[string]int `ovsdb:"statistics"` + Status map[string]string `ovsdb:"status"` + Type string `ovsdb:"type"` +} + +func (a *Interface) GetUUID() string { + return a.UUID +} + +func (a *Interface) GetAdminState() *InterfaceAdminState { + return a.AdminState +} + +func copyInterfaceAdminState(a *InterfaceAdminState) *InterfaceAdminState { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceAdminState(a, b *InterfaceAdminState) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetBFD() map[string]string { + return a.BFD +} + +func copyInterfaceBFD(a map[string]string) map[string]string { + if a == nil { + return nil + } + b := make(map[string]string, len(a)) + for k, v := range a { + b[k] = v + } + return b +} + +func equalInterfaceBFD(a, b map[string]string) bool { + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for k, v := range a { + if w, ok := b[k]; !ok || v != w { + return false + } + } + return true +} + +func (a *Interface) GetBFDStatus() map[string]string { + return a.BFDStatus +} + +func copyInterfaceBFDStatus(a map[string]string) map[string]string { + if a == nil { + return nil + } + b := make(map[string]string, len(a)) + for k, v := range a { + b[k] = v + } + return b +} + +func equalInterfaceBFDStatus(a, b map[string]string) bool { + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for k, v := range a { + if w, ok := b[k]; !ok || v != w { + return false + } + } + return true +} + +func (a *Interface) GetCFMFault() *bool { + return a.CFMFault +} + +func copyInterfaceCFMFault(a *bool) *bool { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceCFMFault(a, b *bool) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetCFMFaultStatus() []string { + return a.CFMFaultStatus +} + +func copyInterfaceCFMFaultStatus(a []string) []string { + if a == nil { + return nil + } + b := make([]string, len(a)) + copy(b, a) + return b +} + +func equalInterfaceCFMFaultStatus(a, b []string) bool { + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for i, v := range a { + if b[i] != v { + return false + } + } + return true +} + +func (a *Interface) GetCFMFlapCount() *int { + return a.CFMFlapCount +} + +func copyInterfaceCFMFlapCount(a *int) *int { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceCFMFlapCount(a, b *int) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetCFMHealth() *int { + return a.CFMHealth +} + +func copyInterfaceCFMHealth(a *int) *int { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceCFMHealth(a, b *int) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetCFMMpid() *int { + return a.CFMMpid +} + +func copyInterfaceCFMMpid(a *int) *int { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceCFMMpid(a, b *int) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetCFMRemoteMpids() []int { + return a.CFMRemoteMpids +} + +func copyInterfaceCFMRemoteMpids(a []int) []int { + if a == nil { + return nil + } + b := make([]int, len(a)) + copy(b, a) + return b +} + +func equalInterfaceCFMRemoteMpids(a, b []int) bool { + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for i, v := range a { + if b[i] != v { + return false + } + } + return true +} + +func (a *Interface) GetCFMRemoteOpstate() *InterfaceCFMRemoteOpstate { + return a.CFMRemoteOpstate +} + +func copyInterfaceCFMRemoteOpstate(a *InterfaceCFMRemoteOpstate) *InterfaceCFMRemoteOpstate { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceCFMRemoteOpstate(a, b *InterfaceCFMRemoteOpstate) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetDuplex() *InterfaceDuplex { + return a.Duplex +} + +func copyInterfaceDuplex(a *InterfaceDuplex) *InterfaceDuplex { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceDuplex(a, b *InterfaceDuplex) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetError() *string { + return a.Error +} + +func copyInterfaceError(a *string) *string { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceError(a, b *string) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetExternalIDs() map[string]string { + return a.ExternalIDs +} + +func copyInterfaceExternalIDs(a map[string]string) map[string]string { + if a == nil { + return nil + } + b := make(map[string]string, len(a)) + for k, v := range a { + b[k] = v + } + return b +} + +func equalInterfaceExternalIDs(a, b map[string]string) bool { + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for k, v := range a { + if w, ok := b[k]; !ok || v != w { + return false + } + } + return true +} + +func (a *Interface) GetIfindex() *int { + return a.Ifindex +} + +func copyInterfaceIfindex(a *int) *int { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceIfindex(a, b *int) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetIngressPolicingBurst() int { + return a.IngressPolicingBurst +} + +func (a *Interface) GetIngressPolicingKpktsBurst() int { + return a.IngressPolicingKpktsBurst +} + +func (a *Interface) GetIngressPolicingKpktsRate() int { + return a.IngressPolicingKpktsRate +} + +func (a *Interface) GetIngressPolicingRate() int { + return a.IngressPolicingRate +} + +func (a *Interface) GetLACPCurrent() *bool { + return a.LACPCurrent +} + +func copyInterfaceLACPCurrent(a *bool) *bool { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceLACPCurrent(a, b *bool) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetLinkResets() *int { + return a.LinkResets +} + +func copyInterfaceLinkResets(a *int) *int { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceLinkResets(a, b *int) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetLinkSpeed() *int { + return a.LinkSpeed +} + +func copyInterfaceLinkSpeed(a *int) *int { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceLinkSpeed(a, b *int) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetLinkState() *InterfaceLinkState { + return a.LinkState +} + +func copyInterfaceLinkState(a *InterfaceLinkState) *InterfaceLinkState { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceLinkState(a, b *InterfaceLinkState) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetLLDP() map[string]string { + return a.LLDP +} + +func copyInterfaceLLDP(a map[string]string) map[string]string { + if a == nil { + return nil + } + b := make(map[string]string, len(a)) + for k, v := range a { + b[k] = v + } + return b +} + +func equalInterfaceLLDP(a, b map[string]string) bool { + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for k, v := range a { + if w, ok := b[k]; !ok || v != w { + return false + } + } + return true +} + +func (a *Interface) GetMAC() *string { + return a.MAC +} + +func copyInterfaceMAC(a *string) *string { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceMAC(a, b *string) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetMACInUse() *string { + return a.MACInUse +} + +func copyInterfaceMACInUse(a *string) *string { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceMACInUse(a, b *string) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetMTU() *int { + return a.MTU +} + +func copyInterfaceMTU(a *int) *int { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceMTU(a, b *int) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetMTURequest() *int { + return a.MTURequest +} + +func copyInterfaceMTURequest(a *int) *int { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceMTURequest(a, b *int) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetName() string { + return a.Name +} + +func (a *Interface) GetOfport() *int { + return a.Ofport +} + +func copyInterfaceOfport(a *int) *int { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceOfport(a, b *int) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetOfportRequest() *int { + return a.OfportRequest +} + +func copyInterfaceOfportRequest(a *int) *int { + if a == nil { + return nil + } + b := *a + return &b +} + +func equalInterfaceOfportRequest(a, b *int) bool { + if (a == nil) != (b == nil) { + return false + } + if a == b { + return true + } + return *a == *b +} + +func (a *Interface) GetOptions() map[string]string { + return a.Options +} + +func copyInterfaceOptions(a map[string]string) map[string]string { + if a == nil { + return nil + } + b := make(map[string]string, len(a)) + for k, v := range a { + b[k] = v + } + return b +} + +func equalInterfaceOptions(a, b map[string]string) bool { + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for k, v := range a { + if w, ok := b[k]; !ok || v != w { + return false + } + } + return true +} + +func (a *Interface) GetOtherConfig() map[string]string { + return a.OtherConfig +} + +func copyInterfaceOtherConfig(a map[string]string) map[string]string { + if a == nil { + return nil + } + b := make(map[string]string, len(a)) + for k, v := range a { + b[k] = v + } + return b +} + +func equalInterfaceOtherConfig(a, b map[string]string) bool { + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for k, v := range a { + if w, ok := b[k]; !ok || v != w { + return false + } + } + return true +} + +func (a *Interface) GetStatistics() map[string]int { + return a.Statistics +} + +func copyInterfaceStatistics(a map[string]int) map[string]int { + if a == nil { + return nil + } + b := make(map[string]int, len(a)) + for k, v := range a { + b[k] = v + } + return b +} + +func equalInterfaceStatistics(a, b map[string]int) bool { + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for k, v := range a { + if w, ok := b[k]; !ok || v != w { + return false + } + } + return true +} + +func (a *Interface) GetStatus() map[string]string { + return a.Status +} + +func copyInterfaceStatus(a map[string]string) map[string]string { + if a == nil { + return nil + } + b := make(map[string]string, len(a)) + for k, v := range a { + b[k] = v + } + return b +} + +func equalInterfaceStatus(a, b map[string]string) bool { + if (a == nil) != (b == nil) { + return false + } + if len(a) != len(b) { + return false + } + for k, v := range a { + if w, ok := b[k]; !ok || v != w { + return false + } + } + return true +} + +func (a *Interface) GetType() string { + return a.Type +} + +func (a *Interface) DeepCopyInto(b *Interface) { + *b = *a + b.AdminState = copyInterfaceAdminState(a.AdminState) + b.BFD = copyInterfaceBFD(a.BFD) + b.BFDStatus = copyInterfaceBFDStatus(a.BFDStatus) + b.CFMFault = copyInterfaceCFMFault(a.CFMFault) + b.CFMFaultStatus = copyInterfaceCFMFaultStatus(a.CFMFaultStatus) + b.CFMFlapCount = copyInterfaceCFMFlapCount(a.CFMFlapCount) + b.CFMHealth = copyInterfaceCFMHealth(a.CFMHealth) + b.CFMMpid = copyInterfaceCFMMpid(a.CFMMpid) + b.CFMRemoteMpids = copyInterfaceCFMRemoteMpids(a.CFMRemoteMpids) + b.CFMRemoteOpstate = copyInterfaceCFMRemoteOpstate(a.CFMRemoteOpstate) + b.Duplex = copyInterfaceDuplex(a.Duplex) + b.Error = copyInterfaceError(a.Error) + b.ExternalIDs = copyInterfaceExternalIDs(a.ExternalIDs) + b.Ifindex = copyInterfaceIfindex(a.Ifindex) + b.LACPCurrent = copyInterfaceLACPCurrent(a.LACPCurrent) + b.LinkResets = copyInterfaceLinkResets(a.LinkResets) + b.LinkSpeed = copyInterfaceLinkSpeed(a.LinkSpeed) + b.LinkState = copyInterfaceLinkState(a.LinkState) + b.LLDP = copyInterfaceLLDP(a.LLDP) + b.MAC = copyInterfaceMAC(a.MAC) + b.MACInUse = copyInterfaceMACInUse(a.MACInUse) + b.MTU = copyInterfaceMTU(a.MTU) + b.MTURequest = copyInterfaceMTURequest(a.MTURequest) + b.Ofport = copyInterfaceOfport(a.Ofport) + b.OfportRequest = copyInterfaceOfportRequest(a.OfportRequest) + b.Options = copyInterfaceOptions(a.Options) + b.OtherConfig = copyInterfaceOtherConfig(a.OtherConfig) + b.Statistics = copyInterfaceStatistics(a.Statistics) + b.Status = copyInterfaceStatus(a.Status) +} + +func (a *Interface) DeepCopy() *Interface { + b := new(Interface) + a.DeepCopyInto(b) + return b +} + +func (a *Interface) CloneModelInto(b model.Model) { + c := b.(*Interface) + a.DeepCopyInto(c) +} + +func (a *Interface) CloneModel() model.Model { + return a.DeepCopy() +} + +func (a *Interface) Equals(b *Interface) bool { + return a.UUID == b.UUID && + equalInterfaceAdminState(a.AdminState, b.AdminState) && + equalInterfaceBFD(a.BFD, b.BFD) && + equalInterfaceBFDStatus(a.BFDStatus, b.BFDStatus) && + equalInterfaceCFMFault(a.CFMFault, b.CFMFault) && + equalInterfaceCFMFaultStatus(a.CFMFaultStatus, b.CFMFaultStatus) && + equalInterfaceCFMFlapCount(a.CFMFlapCount, b.CFMFlapCount) && + equalInterfaceCFMHealth(a.CFMHealth, b.CFMHealth) && + equalInterfaceCFMMpid(a.CFMMpid, b.CFMMpid) && + equalInterfaceCFMRemoteMpids(a.CFMRemoteMpids, b.CFMRemoteMpids) && + equalInterfaceCFMRemoteOpstate(a.CFMRemoteOpstate, b.CFMRemoteOpstate) && + equalInterfaceDuplex(a.Duplex, b.Duplex) && + equalInterfaceError(a.Error, b.Error) && + equalInterfaceExternalIDs(a.ExternalIDs, b.ExternalIDs) && + equalInterfaceIfindex(a.Ifindex, b.Ifindex) && + a.IngressPolicingBurst == b.IngressPolicingBurst && + a.IngressPolicingKpktsBurst == b.IngressPolicingKpktsBurst && + a.IngressPolicingKpktsRate == b.IngressPolicingKpktsRate && + a.IngressPolicingRate == b.IngressPolicingRate && + equalInterfaceLACPCurrent(a.LACPCurrent, b.LACPCurrent) && + equalInterfaceLinkResets(a.LinkResets, b.LinkResets) && + equalInterfaceLinkSpeed(a.LinkSpeed, b.LinkSpeed) && + equalInterfaceLinkState(a.LinkState, b.LinkState) && + equalInterfaceLLDP(a.LLDP, b.LLDP) && + equalInterfaceMAC(a.MAC, b.MAC) && + equalInterfaceMACInUse(a.MACInUse, b.MACInUse) && + equalInterfaceMTU(a.MTU, b.MTU) && + equalInterfaceMTURequest(a.MTURequest, b.MTURequest) && + a.Name == b.Name && + equalInterfaceOfport(a.Ofport, b.Ofport) && + equalInterfaceOfportRequest(a.OfportRequest, b.OfportRequest) && + equalInterfaceOptions(a.Options, b.Options) && + equalInterfaceOtherConfig(a.OtherConfig, b.OtherConfig) && + equalInterfaceStatistics(a.Statistics, b.Statistics) && + equalInterfaceStatus(a.Status, b.Status) && + a.Type == b.Type +} + +func (a *Interface) EqualsModel(b model.Model) bool { + c := b.(*Interface) + return a.Equals(c) +} + +var _ model.CloneableModel = &Interface{} +var _ model.ComparableModel = &Interface{} diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/ovsdb/observ_model.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/ovsdb/observ_model.go index 7ba2329e34..22547a3f8c 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/ovsdb/observ_model.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/ovsdb/observ_model.go @@ -7,5 +7,6 @@ func ObservDatabaseModel() (model.ClientDBModel, error) { return model.NewClientDBModel("Open_vSwitch", map[string]model.Model{ "Bridge": &Bridge{}, "Flow_Sample_Collector_Set": &FlowSampleCollectorSet{}, + "Interface": &Interface{}, }) } diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/db_client.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/db_client.go index 5ff1587a6f..8b58e3608e 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/db_client.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/db_client.go @@ -65,6 +65,7 @@ func NewOVSDBClientWithConfig(ctx context.Context, cfg dbConfig) (client.Client, c.NewMonitor( client.WithTable(&ovsdb.FlowSampleCollectorSet{}), client.WithTable(&ovsdb.Bridge{}), + client.WithTable(&ovsdb.Interface{}), ), ) if err != nil { diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/sample_decoder.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/sample_decoder.go index d691fd9cca..0642e795b8 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/sample_decoder.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/sample_decoder.go @@ -291,3 +291,49 @@ func (d *SampleDecoder) DeleteCollector(collectorID int) error { fmt.Println("res: ", res) return err } + +// This is a copy of the ParseNetworkName function from go-controller/pkg/clustermanager/userdefinednetwork/template/net-attach-def-template.go +// We need to copy it to optimize dependencies of observability-lib. +func ParseNetworkName(networkName string) (udnNamespace, udnName string) { + parts := strings.Split(networkName, ".") + if len(parts) == 2 { + return parts[0], parts[1] + } + return "", "" +} + +func networkNameToUDNNamespacedName(networkName string) string { + namespace, name := ParseNetworkName(networkName) + if name == "" { + return "" + } + namespacedName := name + if namespace != "" { + namespacedName = namespace + "/" + name + } + return namespacedName +} + +// GetInterfaceUDNs returns a map of all pod interface names to their corresponding (C)UDN namespaced names. +// default network or NAD that is not created by (C)UDN is represented by an empty string. +// UDN namespace+name are joined by "/", CUDN will just have a name. +func (d *SampleDecoder) GetInterfaceUDNs() (map[string]string, error) { + res := map[string]string{} + ifaces := []*ovsdb.Interface{} + err := d.ovsdbClient.List(context.Background(), &ifaces) + if err != nil { + return nil, fmt.Errorf("failed listing interfaces: %w", err) + } + for _, iface := range ifaces { + if iface.ExternalIDs["iface-id-ver"] == "" || iface.ExternalIDs["iface-id"] == "" { + // not a pod interface + continue + } + if iface.ExternalIDs["k8s.ovn.org/network"] == "" { + res[iface.Name] = "" + continue + } + res[iface.Name] = networkNameToUDNNamespacedName(iface.ExternalIDs["k8s.ovn.org/network"]) + } + return res, nil +} diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/config.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/config.go index 3b129624b9..1f601153fe 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/config.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/config.go @@ -232,9 +232,11 @@ type DefaultConfig struct { // EncapType value defines the encapsulation protocol to use to transmit packets between // hypervisors. By default the value is 'geneve' EncapType string `gcfg:"encap-type"` - // The IP address of the encapsulation endpoint. If not specified, the IP address the - // NodeName resolves to will be used + // Configured IP address of the encapsulation endpoint. EncapIP string `gcfg:"encap-ip"` + // Effective encap IP. It may be different from EncapIP if EncapIP meant to be + // the node's primary IP which can be updated when node's primary IP changes. + EffectiveEncapIP string // The UDP Port of the encapsulation endpoint. If not specified, the IP default port // of 6081 will be used EncapPort uint `gcfg:"encap-port"` @@ -417,14 +419,18 @@ type OVNKubernetesFeatureConfig struct { EgressIPNodeHealthCheckPort int `gcfg:"egressip-node-healthcheck-port"` EnableMultiNetwork bool `gcfg:"enable-multi-network"` EnableNetworkSegmentation bool `gcfg:"enable-network-segmentation"` - EnableMultiNetworkPolicy bool `gcfg:"enable-multi-networkpolicy"` - EnableStatelessNetPol bool `gcfg:"enable-stateless-netpol"` - EnableInterconnect bool `gcfg:"enable-interconnect"` - EnableMultiExternalGateway bool `gcfg:"enable-multi-external-gateway"` - EnablePersistentIPs bool `gcfg:"enable-persistent-ips"` - EnableDNSNameResolver bool `gcfg:"enable-dns-name-resolver"` - EnableServiceTemplateSupport bool `gcfg:"enable-svc-template-support"` - EnableObservability bool `gcfg:"enable-observability"` + EnableRouteAdvertisements bool `gcfg:"enable-route-advertisements"` + // This feature requires a kernel fix https://github.com/torvalds/linux/commit/7f3287db654395f9c5ddd246325ff7889f550286 + // to work on a kind cluster. Flag allows to disable it for current CI, will be turned on when github runners have this fix. + DisableUDNHostIsolation bool `gcfg:"disable-udn-host-isolation"` + EnableMultiNetworkPolicy bool `gcfg:"enable-multi-networkpolicy"` + EnableStatelessNetPol bool `gcfg:"enable-stateless-netpol"` + EnableInterconnect bool `gcfg:"enable-interconnect"` + EnableMultiExternalGateway bool `gcfg:"enable-multi-external-gateway"` + EnablePersistentIPs bool `gcfg:"enable-persistent-ips"` + EnableDNSNameResolver bool `gcfg:"enable-dns-name-resolver"` + EnableServiceTemplateSupport bool `gcfg:"enable-svc-template-support"` + EnableObservability bool `gcfg:"enable-observability"` } // GatewayMode holds the node gateway mode @@ -1056,12 +1062,24 @@ var OVNK8sFeatureFlags = []cli.Flag{ Destination: &cliConfig.OVNKubernetesFeature.EnableMultiNetworkPolicy, Value: OVNKubernetesFeature.EnableMultiNetworkPolicy, }, + &cli.BoolFlag{ + Name: "disable-udn-host-isolation", + Usage: "Configure to disable UDN host isolation with ovn-kubernetes.", + Destination: &cliConfig.OVNKubernetesFeature.DisableUDNHostIsolation, + Value: OVNKubernetesFeature.DisableUDNHostIsolation, + }, &cli.BoolFlag{ Name: "enable-network-segmentation", Usage: "Configure to use network segmentation feature with ovn-kubernetes.", Destination: &cliConfig.OVNKubernetesFeature.EnableNetworkSegmentation, Value: OVNKubernetesFeature.EnableNetworkSegmentation, }, + &cli.BoolFlag{ + Name: "enable-route-advertisements", + Usage: "Configure to use route advertisements feature with ovn-kubernetes.", + Destination: &cliConfig.OVNKubernetesFeature.EnableRouteAdvertisements, + Value: OVNKubernetesFeature.EnableRouteAdvertisements, + }, &cli.BoolFlag{ Name: "enable-stateless-netpol", Usage: "Configure to use stateless network policy feature with ovn-kubernetes.", diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/db_object_types.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/db_object_types.go index 9f0e8dfe87..bb2afeea11 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/db_object_types.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/db_object_types.go @@ -9,6 +9,7 @@ const ( portGroup logicalRouterPolicy qos + nat ) const ( @@ -33,6 +34,7 @@ const ( NetpolNodeOwnerType ownerType = "NetpolNode" NetpolNamespaceOwnerType ownerType = "NetpolNamespace" VirtualMachineOwnerType ownerType = "VirtualMachine" + UDNEnabledServiceOwnerType ownerType = "UDNEnabledService" // NetworkPolicyPortIndexOwnerType is the old version of NetworkPolicyOwnerType, kept for sync only NetworkPolicyPortIndexOwnerType ownerType = "NetworkPolicyPortIndexOwnerType" // ClusterOwnerType means the object is cluster-scoped and doesn't belong to any k8s objects @@ -45,6 +47,7 @@ const ( PolicyDirectionKey ExternalIDKey = "direction" GressIdxKey ExternalIDKey = "gress-index" IPFamilyKey ExternalIDKey = "ip-family" + NetworkKey ExternalIDKey = "network" TypeKey ExternalIDKey = "type" IpKey ExternalIDKey = "ip" PortPolicyIndexKey ExternalIDKey = "port-policy-index" @@ -123,6 +126,7 @@ var AddressSetEgressIP = newObjectIDsType(addressSet, EgressIPOwnerType, []Exter // cluster-wide address set name ObjectNameKey, IPFamilyKey, + NetworkKey, }) var AddressSetEgressService = newObjectIDsType(addressSet, EgressServiceOwnerType, []ExternalIDKey{ @@ -131,6 +135,12 @@ var AddressSetEgressService = newObjectIDsType(addressSet, EgressServiceOwnerTyp IPFamilyKey, }) +var AddressSetUDNEnabledService = newObjectIDsType(addressSet, UDNEnabledServiceOwnerType, []ExternalIDKey{ + // cluster-wide address set name + ObjectNameKey, + IPFamilyKey, +}) + var ACLAdminNetworkPolicy = newObjectIDsType(acl, AdminNetworkPolicyOwnerType, []ExternalIDKey{ // anp name ObjectNameKey, @@ -308,6 +318,14 @@ var LogicalRouterPolicyEgressIP = newObjectIDsType(logicalRouterPolicy, EgressIP ObjectNameKey, // the IP Family for this policy, ip4 or ip6 or ip(dualstack) IPFamilyKey, + NetworkKey, +}) + +var NATEgressIP = newObjectIDsType(nat, EgressIPOwnerType, []ExternalIDKey{ + // for the NAT policy, it should be the "EIPName_Namespace/podName" + ObjectNameKey, + // the IP Family for this policy, ip4 or ip6 or ip(dualstack) + IPFamilyKey, }) var QoSEgressQoS = newObjectIDsType(qos, EgressQoSOwnerType, []ExternalIDKey{ diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/model.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/model.go index b40dd4104d..76b525fa48 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/model.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/model.go @@ -7,6 +7,7 @@ import ( "github.com/ovn-org/libovsdb/client" "github.com/ovn-org/libovsdb/model" "github.com/ovn-org/libovsdb/ovsdb" + "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/nbdb" "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/sbdb" "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types" @@ -470,7 +471,12 @@ func buildFailOnDuplicateOps(c client.Client, m model.Model) ([]ovsdb.Operation, Function: ovsdb.ConditionEqual, Value: t.Match, } - return c.WhereAll(t, condPriority, condMatch).Wait( + condExtID := model.Condition{ + Field: &t.ExternalIDs, + Function: ovsdb.ConditionIncludes, + Value: t.ExternalIDs, + } + return c.WhereAll(t, condPriority, condMatch, condExtID).Wait( ovsdb.WaitConditionNotEqual, &timeout, t, @@ -489,6 +495,64 @@ func buildFailOnDuplicateOps(c client.Client, m model.Model) ([]ovsdb.Operation, return c.WhereAny(m, cond).Wait(ovsdb.WaitConditionNotEqual, &timeout, m, field) } +// ModelUpdateField enumeration represents fields that can be updated on the supported models +type ModelUpdateField int + +const ( + LogicalSwitchPortAddresses ModelUpdateField = iota + LogicalSwitchPortType + LogicalSwitchPortTagRequest + LogicalSwitchPortOptions + LogicalSwitchPortPortSecurity + LogicalSwitchPortEnabled + + PortGroupACLs + PortGroupPorts + PortGroupExternalIDs +) + +// getFieldsToUpdate gets a model and a list of ModelUpdateField and returns a list of their related interface{} fields. +func getFieldsToUpdate(model model.Model, fieldNames []ModelUpdateField) []interface{} { + var fields []interface{} + switch t := model.(type) { + case *nbdb.LogicalSwitchPort: + for _, field := range fieldNames { + switch field { + case LogicalSwitchPortAddresses: + fields = append(fields, &t.Addresses) + case LogicalSwitchPortType: + fields = append(fields, &t.Type) + case LogicalSwitchPortTagRequest: + fields = append(fields, &t.TagRequest) + case LogicalSwitchPortOptions: + fields = append(fields, &t.Options) + case LogicalSwitchPortPortSecurity: + fields = append(fields, &t.PortSecurity) + case LogicalSwitchPortEnabled: + fields = append(fields, &t.Enabled) + default: + panic(fmt.Sprintf("getFieldsToUpdate: unknown or unsupported field %q for LogicalSwitchPort", field)) + } + } + case *nbdb.PortGroup: + for _, field := range fieldNames { + switch field { + case PortGroupACLs: + fields = append(fields, &t.ACLs) + case PortGroupPorts: + fields = append(fields, &t.Ports) + case PortGroupExternalIDs: + fields = append(fields, &t.ExternalIDs) + default: + panic(fmt.Sprintf("getFieldsToUpdate: unknown or unsupported field %q for PortGroup", field)) + } + } + default: + panic(fmt.Sprintf("getFieldsToUpdate: unknown model type %T", t)) + } + return fields +} + // getAllUpdatableFields returns a list of all of the columns/fields that can be updated for a model func getAllUpdatableFields(model model.Model) []interface{} { switch t := model.(type) { diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/router.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/router.go index 9aeb42123e..3c95230a74 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/router.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/router.go @@ -257,6 +257,27 @@ func FindLogicalRouterPoliciesWithPredicate(nbClient libovsdbclient.Client, p lo return found, err } +// FindALogicalRouterPoliciesWithPredicate looks up a logical router policies from +// the cache based on a given predicate +func FindALogicalRouterPoliciesWithPredicate(nbClient libovsdbclient.Client, routerName string, p logicalRouterPolicyPredicate) ([]*nbdb.LogicalRouterPolicy, error) { + lr := &nbdb.LogicalRouter{Name: routerName} + router, err := GetLogicalRouter(nbClient, lr) + if err != nil { + return nil, err + } + + newPredicate := func(item *nbdb.LogicalRouterPolicy) bool { + for _, policyUUID := range router.Policies { + if policyUUID == item.UUID && p(item) { + return true + } + } + return false + } + + return FindLogicalRouterPoliciesWithPredicate(nbClient, newPredicate) +} + // GetLogicalRouterPolicy looks up a logical router policy from the cache func GetLogicalRouterPolicy(nbClient libovsdbclient.Client, policy *nbdb.LogicalRouterPolicy) (*nbdb.LogicalRouterPolicy, error) { found := []*nbdb.LogicalRouterPolicy{} @@ -581,6 +602,30 @@ func FindLogicalRouterStaticRoutesWithPredicate(nbClient libovsdbclient.Client, return found, err } +// GetRouterLogicalRouterStaticRoutesWithPredicate looks up logical router +// static routes associated to the provided logical router from the cache based +// on a given predicate +func GetRouterLogicalRouterStaticRoutesWithPredicate(nbClient libovsdbclient.Client, router *nbdb.LogicalRouter, p logicalRouterStaticRoutePredicate) ([]*nbdb.LogicalRouterStaticRoute, error) { + r, err := GetLogicalRouter(nbClient, router) + if err != nil { + return nil, fmt.Errorf("failed to get router: %s, error: %w", router.Name, err) + } + + lrsrs := []*nbdb.LogicalRouterStaticRoute{} + for _, uuid := range r.StaticRoutes { + lrsr := &nbdb.LogicalRouterStaticRoute{UUID: uuid} + err := nbClient.Get(context.Background(), lrsr) + if err != nil { + return nil, err + } + if p(lrsr) { + lrsrs = append(lrsrs, lrsr) + } + } + + return lrsrs, nil +} + // CreateOrUpdateLogicalRouterStaticRoutesWithPredicateOps looks up a logical // router static route from the cache based on a given predicate. If it does not // exist, it creates the provided logical router static route. If it does, it @@ -643,25 +688,12 @@ func CreateOrReplaceLogicalRouterStaticRouteWithPredicate(nbClient libovsdbclien lrsr *nbdb.LogicalRouterStaticRoute, p logicalRouterStaticRoutePredicate, fields ...interface{}) error { lr := &nbdb.LogicalRouter{Name: routerName} - router, err := GetLogicalRouter(nbClient, lr) - if err != nil { - return fmt.Errorf("unable to get logical router %s: %w", routerName, err) - } - newPredicate := func(item *nbdb.LogicalRouterStaticRoute) bool { - for _, routeUUID := range router.StaticRoutes { - if routeUUID == item.UUID && p(item) { - return true - } - } - return false - } - routes, err := FindLogicalRouterStaticRoutesWithPredicate(nbClient, newPredicate) + routes, err := GetRouterLogicalRouterStaticRoutesWithPredicate(nbClient, lr, p) if err != nil { return fmt.Errorf("unable to get logical router static routes with predicate on router %s: %w", routerName, err) } var ops []libovsdb.Operation - m := newModelClient(nbClient) if len(routes) > 0 { lrsr.UUID = routes[0].UUID @@ -670,27 +702,7 @@ func CreateOrReplaceLogicalRouterStaticRouteWithPredicate(nbClient libovsdbclien if len(routes) > 1 { // should only be a single route remove all except the first routes = routes[1:] - opModels := make([]operationModel, 0, len(routes)+1) - router.StaticRoutes = []string{} - for _, route := range routes { - route := route - router.StaticRoutes = append(router.StaticRoutes, route.UUID) - opModel := operationModel{ - Model: route, - ErrNotFound: false, - BulkOp: false, - } - opModels = append(opModels, opModel) - } - opModel := operationModel{ - Model: router, - OnModelMutations: []interface{}{&router.StaticRoutes}, - ErrNotFound: true, - BulkOp: false, - } - opModels = append(opModels, opModel) - - ops, err = m.DeleteOps(nil, opModels...) + ops, err = DeleteLogicalRouterStaticRoutesOps(nbClient, ops, routerName, routes...) if err != nil { return err } @@ -747,9 +759,9 @@ func DeleteLogicalRouterStaticRoutesWithPredicateOps(nbClient libovsdbclient.Cli return m.DeleteOps(ops, opModels...) } -// DeleteLogicalRouterStaticRoutes deletes the logical router static routes and -// removes them from the provided logical router -func DeleteLogicalRouterStaticRoutes(nbClient libovsdbclient.Client, routerName string, lrsrs ...*nbdb.LogicalRouterStaticRoute) error { +// DeleteLogicalRouterStaticRoutesOps deletes the logical router static routes and +// returns the ops to remove them from the provided logical router +func DeleteLogicalRouterStaticRoutesOps(nbClient libovsdbclient.Client, ops []libovsdb.Operation, routerName string, lrsrs ...*nbdb.LogicalRouterStaticRoute) ([]libovsdb.Operation, error) { router := &nbdb.LogicalRouter{ Name: routerName, StaticRoutes: make([]string, 0, len(lrsrs)), @@ -759,24 +771,31 @@ func DeleteLogicalRouterStaticRoutes(nbClient libovsdbclient.Client, routerName for _, lrsr := range lrsrs { lrsr := lrsr router.StaticRoutes = append(router.StaticRoutes, lrsr.UUID) - opModel := operationModel{ - Model: lrsr, - ErrNotFound: false, - BulkOp: false, - } - opModels = append(opModels, opModel) } opModel := operationModel{ Model: router, OnModelMutations: []interface{}{&router.StaticRoutes}, - ErrNotFound: true, + ErrNotFound: false, BulkOp: false, } opModels = append(opModels, opModel) m := newModelClient(nbClient) - return m.Delete(opModels...) + return m.DeleteOps(ops, opModels...) +} + +// DeleteLogicalRouterStaticRoutes deletes the logical router static routes and +// removes them from the provided logical router +func DeleteLogicalRouterStaticRoutes(nbClient libovsdbclient.Client, routerName string, lrsrs ...*nbdb.LogicalRouterStaticRoute) error { + var ops []libovsdb.Operation + var err error + ops, err = DeleteLogicalRouterStaticRoutesOps(nbClient, ops, routerName, lrsrs...) + if err != nil { + return err + } + _, err = TransactAndCheck(nbClient, ops) + return err } // BFD ops @@ -1220,3 +1239,22 @@ func DeleteNATsWithPredicateOps(nbClient libovsdbclient.Client, ops []libovsdb.O m := newModelClient(nbClient) return m.DeleteOps(ops, opModels...) } + +func UpdateNATOps(nbClient libovsdbclient.Client, ops []libovsdb.Operation, nats ...*nbdb.NAT) ([]libovsdb.Operation, error) { + opModels := make([]operationModel, 0, len(nats)) + for i := range nats { + nat := nats[i] + opModel := []operationModel{ + { + Model: nat, + OnModelUpdates: onModelUpdatesAllNonDefault(), + ErrNotFound: true, + BulkOp: false, + }, + } + opModels = append(opModels, opModel...) + } + + m := newModelClient(nbClient) + return m.CreateOrUpdateOps(ops, opModels...) +} diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/switch.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/switch.go index 964e711bb7..250868667b 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/switch.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/switch.go @@ -4,9 +4,9 @@ import ( "context" "errors" "fmt" - libovsdbclient "github.com/ovn-org/libovsdb/client" libovsdb "github.com/ovn-org/libovsdb/ovsdb" + ovntypes "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types" "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config" "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/nbdb" @@ -15,6 +15,17 @@ import ( // LOGICAL_SWITCH OPs type switchPredicate func(*nbdb.LogicalSwitch) bool +type switchPortPredicate func(port *nbdb.LogicalSwitchPort) bool + +// FindLogicalSwitchPortWithPredicate looks up logical switches ports from the cache +// based on a given predicate +func FindLogicalSwitchPortWithPredicate(nbClient libovsdbclient.Client, p switchPortPredicate) ([]*nbdb.LogicalSwitchPort, error) { + found := []*nbdb.LogicalSwitchPort{} + ctx, cancel := context.WithTimeout(context.Background(), ovntypes.OVSDBTimeout) + defer cancel() + err := nbClient.WhereCache(p).List(ctx, &found) + return found, err +} // FindLogicalSwitchesWithPredicate looks up logical switches from the cache // based on a given predicate @@ -286,28 +297,42 @@ func GetLogicalSwitchPort(nbClient libovsdbclient.Client, lsp *nbdb.LogicalSwitc return found[0], nil } -func createOrUpdateLogicalSwitchPortsOps(nbClient libovsdbclient.Client, ops []libovsdb.Operation, sw *nbdb.LogicalSwitch, createSwitch bool, lsps ...*nbdb.LogicalSwitchPort) ([]libovsdb.Operation, error) { +func createOrUpdateLogicalSwitchPortOpModelWithCustomFields(sw *nbdb.LogicalSwitch, lsp *nbdb.LogicalSwitchPort, createLSP bool, customFields []ModelUpdateField) operationModel { + var fieldInterfaces []interface{} + if len(customFields) != 0 { + fieldInterfaces = getFieldsToUpdate(lsp, customFields) + } else { + fieldInterfaces = getAllUpdatableFields(lsp) + } + return operationModel{ + Model: lsp, + OnModelUpdates: fieldInterfaces, + DoAfter: func() { + // lsp.UUID should be set here + sw.Ports = append(sw.Ports, lsp.UUID) + }, + ErrNotFound: !createLSP, + BulkOp: false, + } +} + +func createOrUpdateLogicalSwitchPortsOps(nbClient libovsdbclient.Client, ops []libovsdb.Operation, sw *nbdb.LogicalSwitch, createSwitch, createLSP bool, customFields []ModelUpdateField, lsps ...*nbdb.LogicalSwitchPort) ([]libovsdb.Operation, error) { originalPorts := sw.Ports sw.Ports = make([]string, 0, len(lsps)) opModels := make([]operationModel, 0, len(lsps)+1) - for i := range lsps { - lsp := lsps[i] - opModel := operationModel{ - Model: lsp, - OnModelUpdates: getAllUpdatableFields(lsp), - DoAfter: func() { sw.Ports = append(sw.Ports, lsp.UUID) }, - ErrNotFound: false, - BulkOp: false, - } + + for _, lsp := range lsps { + opModel := createOrUpdateLogicalSwitchPortOpModelWithCustomFields(sw, lsp, createLSP, customFields) opModels = append(opModels, opModel) } - opModel := operationModel{ + + opModelSwitch := operationModel{ Model: sw, OnModelMutations: []interface{}{&sw.Ports}, ErrNotFound: !createSwitch, BulkOp: false, } - opModels = append(opModels, opModel) + opModels = append(opModels, opModelSwitch) m := newModelClient(nbClient) ops, err := m.CreateOrUpdateOps(ops, opModels...) @@ -319,7 +344,7 @@ func createOrUpdateLogicalSwitchPortsOps(nbClient libovsdbclient.Client, ops []l } func createOrUpdateLogicalSwitchPorts(nbClient libovsdbclient.Client, sw *nbdb.LogicalSwitch, createSwitch bool, lsps ...*nbdb.LogicalSwitchPort) error { - ops, err := createOrUpdateLogicalSwitchPortsOps(nbClient, nil, sw, createSwitch, lsps...) + ops, err := createOrUpdateLogicalSwitchPortsOps(nbClient, nil, sw, createSwitch, true, nil, lsps...) if err != nil { return err } @@ -328,11 +353,18 @@ func createOrUpdateLogicalSwitchPorts(nbClient libovsdbclient.Client, sw *nbdb.L return err } -// CreateOrUpdateLogicalSwitchPortsOnSwitchOps creates or updates the provided +// CreateOrUpdateLogicalSwitchPortsOnSwitchWithCustomFieldsOps creates or updates the provided +// logical switch ports, adds them to the provided logical switch and returns +// the corresponding ops +func CreateOrUpdateLogicalSwitchPortsOnSwitchWithCustomFieldsOps(nbClient libovsdbclient.Client, ops []libovsdb.Operation, sw *nbdb.LogicalSwitch, customFields []ModelUpdateField, lsps ...*nbdb.LogicalSwitchPort) ([]libovsdb.Operation, error) { + return createOrUpdateLogicalSwitchPortsOps(nbClient, ops, sw, false, true, customFields, lsps...) +} + +// UpdateLogicalSwitchPortsOnSwitchWithCustomFieldsOps updates the provided // logical switch ports, adds them to the provided logical switch and returns // the corresponding ops -func CreateOrUpdateLogicalSwitchPortsOnSwitchOps(nbClient libovsdbclient.Client, ops []libovsdb.Operation, sw *nbdb.LogicalSwitch, lsps ...*nbdb.LogicalSwitchPort) ([]libovsdb.Operation, error) { - return createOrUpdateLogicalSwitchPortsOps(nbClient, ops, sw, false, lsps...) +func UpdateLogicalSwitchPortsOnSwitchWithCustomFieldsOps(nbClient libovsdbclient.Client, ops []libovsdb.Operation, sw *nbdb.LogicalSwitch, customFields []ModelUpdateField, lsps ...*nbdb.LogicalSwitchPort) ([]libovsdb.Operation, error) { + return createOrUpdateLogicalSwitchPortsOps(nbClient, ops, sw, false, false, customFields, lsps...) } // CreateOrUpdateLogicalSwitchPortsOnSwitch creates or updates the provided diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types/const.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types/const.go index d014dc3a3b..9c6afae5ba 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types/const.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types/const.go @@ -115,7 +115,9 @@ const ( EgressSVCReroutePriority = 101 EgressIPReroutePriority = 100 EgressIPRerouteQoSRulePriority = 103 - EgressLiveMigrationReroutePiority = 10 + // priority of logical router policies on a nodes gateway router + EgressIPSNATMarkPriority = 95 + EgressLiveMigrationReroutePriority = 10 // EndpointSliceMirrorControllerName mirror EndpointSlice controller name (used as a value for the "endpointslice.kubernetes.io/managed-by" label) EndpointSliceMirrorControllerName = "endpointslice-mirror-controller.k8s.ovn.org" @@ -153,9 +155,21 @@ const ( // OVN-K8S annotation & taint constants OvnK8sPrefix = "k8s.ovn.org" + + // DefaultNetworkLabelSelector is the label that needs to be matched on a + // selector to select the default network + DefaultNetworkLabelSelector = OvnK8sPrefix + "/default-network" + // OvnNetworkNameAnnotation is the name of the network annotated on the NAD + // by cluster manager nad controller + OvnNetworkNameAnnotation = OvnK8sPrefix + "/network-name" + // OvnNetworkIDAnnotation is a unique network identifier annotated on the + // NAD by cluster manager nad controller + OvnNetworkIDAnnotation = OvnK8sPrefix + "/network-id" + // Deprecated: we used to set topology version as an annotation on the node. We don't do this anymore. - OvnK8sTopoAnno = OvnK8sPrefix + "/" + "topology-version" - OvnK8sSmallMTUTaintKey = OvnK8sPrefix + "/" + "mtu-too-small" + OvnK8sTopoAnno = OvnK8sPrefix + "/" + "topology-version" + OvnK8sSmallMTUTaintKey = OvnK8sPrefix + "/" + "mtu-too-small" + OvnRouteAdvertisementsKey = OvnK8sPrefix + "/route-advertisements" // name of the configmap used to synchronize status (e.g. watch for topology changes) OvnK8sStatusCMName = "control-plane-status" diff --git a/vendor/go.opentelemetry.io/otel/.gitignore b/vendor/go.opentelemetry.io/otel/.gitignore index 895c7664be..ae8577ef36 100644 --- a/vendor/go.opentelemetry.io/otel/.gitignore +++ b/vendor/go.opentelemetry.io/otel/.gitignore @@ -12,11 +12,3 @@ go.work go.work.sum gen/ - -/example/dice/dice -/example/namedtracer/namedtracer -/example/otel-collector/otel-collector -/example/opencensus/opencensus -/example/passthrough/passthrough -/example/prometheus/prometheus -/example/zipkin/zipkin diff --git a/vendor/go.opentelemetry.io/otel/.golangci.yml b/vendor/go.opentelemetry.io/otel/.golangci.yml index d09555506f..dbfb2a165a 100644 --- a/vendor/go.opentelemetry.io/otel/.golangci.yml +++ b/vendor/go.opentelemetry.io/otel/.golangci.yml @@ -127,8 +127,6 @@ linters-settings: - "**/metric/**/*.go" - "**/bridge/*.go" - "**/bridge/**/*.go" - - "**/example/*.go" - - "**/example/**/*.go" - "**/trace/*.go" - "**/trace/**/*.go" - "**/log/*.go" diff --git a/vendor/go.opentelemetry.io/otel/CHANGELOG.md b/vendor/go.opentelemetry.io/otel/CHANGELOG.md index 4b361d0269..8f68dbd04a 100644 --- a/vendor/go.opentelemetry.io/otel/CHANGELOG.md +++ b/vendor/go.opentelemetry.io/otel/CHANGELOG.md @@ -11,6 +11,52 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm +## [1.32.0/0.54.0/0.8.0/0.0.11] 2024-11-08 + +### Added + +- Add `go.opentelemetry.io/otel/sdk/metric/exemplar.AlwaysOffFilter`, which can be used to disable exemplar recording. (#5850) +- Add `go.opentelemetry.io/otel/sdk/metric.WithExemplarFilter`, which can be used to configure the exemplar filter used by the metrics SDK. (#5850) +- Add `ExemplarReservoirProviderSelector` and `DefaultExemplarReservoirProviderSelector` to `go.opentelemetry.io/otel/sdk/metric`, which defines the exemplar reservoir to use based on the aggregation of the metric. (#5861) +- Add `ExemplarReservoirProviderSelector` to `go.opentelemetry.io/otel/sdk/metric.Stream` to allow using views to configure the exemplar reservoir to use for a metric. (#5861) +- Add `ReservoirProvider`, `HistogramReservoirProvider` and `FixedSizeReservoirProvider` to `go.opentelemetry.io/otel/sdk/metric/exemplar` to make it convenient to use providers of Reservoirs. (#5861) +- The `go.opentelemetry.io/otel/semconv/v1.27.0` package. + The package contains semantic conventions from the `v1.27.0` version of the OpenTelemetry Semantic Conventions. (#5894) +- Add `Attributes attribute.Set` field to `Scope` in `go.opentelemetry.io/otel/sdk/instrumentation`. (#5903) +- Add `Attributes attribute.Set` field to `ScopeRecords` in `go.opentelemetry.io/otel/log/logtest`. (#5927) +- `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` adds instrumentation scope attributes. (#5934) +- `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` adds instrumentation scope attributes. (#5934) +- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` adds instrumentation scope attributes. (#5935) +- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` adds instrumentation scope attributes. (#5935) +- `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc` adds instrumentation scope attributes. (#5933) +- `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp` adds instrumentation scope attributes. (#5933) +- `go.opentelemetry.io/otel/exporters/prometheus` adds instrumentation scope attributes in `otel_scope_info` metric as labels. (#5932) + +### Changed + +- Support scope attributes and make them as identifying for `Tracer` in `go.opentelemetry.io/otel` and `go.opentelemetry.io/otel/sdk/trace`. (#5924) +- Support scope attributes and make them as identifying for `Meter` in `go.opentelemetry.io/otel` and `go.opentelemetry.io/otel/sdk/metric`. (#5926) +- Support scope attributes and make them as identifying for `Logger` in `go.opentelemetry.io/otel` and `go.opentelemetry.io/otel/sdk/log`. (#5925) +- Make schema URL and scope attributes as identifying for `Tracer` in `go.opentelemetry.io/otel/bridge/opentracing`. (#5931) +- Clear unneeded slice elements to allow GC to collect the objects in `go.opentelemetry.io/otel/sdk/metric` and `go.opentelemetry.io/otel/sdk/trace`. (#5804) + +### Fixed + +- Global MeterProvider registration unwraps global instrument Observers, the undocumented Unwrap() methods are now private. (#5881) +- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` now keeps the metadata already present in the context when `WithHeaders` is used. (#5892) +- `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc` now keeps the metadata already present in the context when `WithHeaders` is used. (#5911) +- `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` now keeps the metadata already present in the context when `WithHeaders` is used. (#5915) +- Fix `go.opentelemetry.io/otel/exporters/prometheus` trying to add exemplars to Gauge metrics, which is unsupported. (#5912) +- Fix `WithEndpointURL` to always use a secure connection when an https URL is passed in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`. (#5944) +- Fix `WithEndpointURL` to always use a secure connection when an https URL is passed in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#5944) +- Fix `WithEndpointURL` to always use a secure connection when an https URL is passed in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#5944) +- Fix `WithEndpointURL` to always use a secure connection when an https URL is passed in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#5944) +- Fix incorrect metrics generated from callbacks when multiple readers are used in `go.opentelemetry.io/otel/sdk/metric`. (#5900) + +### Removed + +- Remove all examples under `go.opentelemetry.io/otel/example` as they are moved to [Contrib repository](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/examples). (#5930) + ## [1.31.0/0.53.0/0.7.0/0.0.10] 2024-10-11 ### Added @@ -3110,7 +3156,8 @@ It contains api and sdk for trace and meter. - CircleCI build CI manifest files. - CODEOWNERS file to track owners of this project. -[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.31.0...HEAD +[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.32.0...HEAD +[1.32.0/0.54.0/0.8.0/0.0.11]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.32.0 [1.31.0/0.53.0/0.7.0/0.0.10]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.31.0 [1.30.0/0.52.0/0.6.0/0.0.9]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.30.0 [1.29.0/0.51.0/0.5.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.29.0 diff --git a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md index bb33965574..22a2e9dbd4 100644 --- a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md +++ b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md @@ -629,6 +629,10 @@ should be canceled. ## Approvers and Maintainers +### Triagers + +- [Cheng-Zhen Yang](https://github.com/scorpionknifes), Independent + ### Approvers ### Maintainers @@ -641,13 +645,13 @@ should be canceled. ### Emeritus -- [Aaron Clawson](https://github.com/MadVikingGod), LightStep -- [Anthony Mirabella](https://github.com/Aneurysm9), AWS -- [Chester Cheung](https://github.com/hanyuancheung), Tencent -- [Evan Torrie](https://github.com/evantorrie), Yahoo -- [Gustavo Silva Paiva](https://github.com/paivagustavo), LightStep -- [Josh MacDonald](https://github.com/jmacd), LightStep -- [Liz Fong-Jones](https://github.com/lizthegrey), Honeycomb +- [Aaron Clawson](https://github.com/MadVikingGod) +- [Anthony Mirabella](https://github.com/Aneurysm9) +- [Chester Cheung](https://github.com/hanyuancheung) +- [Evan Torrie](https://github.com/evantorrie) +- [Gustavo Silva Paiva](https://github.com/paivagustavo) +- [Josh MacDonald](https://github.com/jmacd) +- [Liz Fong-Jones](https://github.com/lizthegrey) ### Become an Approver or a Maintainer diff --git a/vendor/go.opentelemetry.io/otel/Makefile b/vendor/go.opentelemetry.io/otel/Makefile index a1228a2124..b8292a4fb9 100644 --- a/vendor/go.opentelemetry.io/otel/Makefile +++ b/vendor/go.opentelemetry.io/otel/Makefile @@ -260,7 +260,7 @@ SEMCONVPKG ?= "semconv/" semconv-generate: $(SEMCONVGEN) $(SEMCONVKIT) [ "$(TAG)" ] || ( echo "TAG unset: missing opentelemetry semantic-conventions tag"; exit 1 ) [ "$(OTEL_SEMCONV_REPO)" ] || ( echo "OTEL_SEMCONV_REPO unset: missing path to opentelemetry semantic-conventions repo"; exit 1 ) - $(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=attribute_group -p conventionType=trace -f attribute_group.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" + $(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=attribute_group -p conventionType=trace -f attribute_group.go -z "$(SEMCONVPKG)/capitalizations.txt" -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" $(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=metric -f metric.go -t "$(SEMCONVPKG)/metric_template.j2" -s "$(TAG)" $(SEMCONVKIT) -output "$(SEMCONVPKG)/$(TAG)" -tag "$(TAG)" diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go index 428cfea233..e0fa0570a8 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go @@ -155,7 +155,12 @@ func (c *client) exportContext(parent context.Context) (context.Context, context } if c.metadata.Len() > 0 { - ctx = metadata.NewOutgoingContext(ctx, c.metadata) + md := c.metadata + if outMD, ok := metadata.FromOutgoingContext(ctx); ok { + md = metadata.Join(md, outMD) + } + + ctx = metadata.NewOutgoingContext(ctx, md) } return ctx, cancel diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/options.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/options.go index b6ed9a2bb6..c016b4dbe9 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/options.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/options.go @@ -139,7 +139,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config { if cfg.ServiceConfig != "" { cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig)) } - // Priroritize GRPCCredentials over Insecure (passing both is an error). + // Prioritize GRPCCredentials over Insecure (passing both is an error). if cfg.Metrics.GRPCCredentials != nil { cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Metrics.GRPCCredentials)) } else if cfg.Metrics.Insecure { @@ -287,9 +287,7 @@ func WithEndpointURL(v string) GenericOption { cfg.Metrics.Endpoint = u.Host cfg.Metrics.URLPath = u.Path - if u.Scheme != "https" { - cfg.Metrics.Insecure = true - } + cfg.Metrics.Insecure = u.Scheme != "https" return cfg }) diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/tls.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/tls.go index 0229ac80be..03e7fbcdfb 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/tls.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/tls.go @@ -14,7 +14,7 @@ import ( ) // ReadTLSConfigFromFile reads a PEM certificate file and creates -// a tls.Config that will use this certifate to verify a server certificate. +// a tls.Config that will use this certificate to verify a server certificate. func ReadTLSConfigFromFile(path string) (*tls.Config, error) { b, err := os.ReadFile(path) if err != nil { diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/transform/metricdata.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/transform/metricdata.go index 975e3b7aa1..abf7f02196 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/transform/metricdata.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/transform/metricdata.go @@ -46,8 +46,9 @@ func ScopeMetrics(sms []metricdata.ScopeMetrics) ([]*mpb.ScopeMetrics, error) { out = append(out, &mpb.ScopeMetrics{ Scope: &cpb.InstrumentationScope{ - Name: sm.Scope.Name, - Version: sm.Scope.Version, + Name: sm.Scope.Name, + Version: sm.Scope.Version, + Attributes: AttrIter(sm.Scope.Attributes.Iter()), }, Metrics: ms, SchemaUrl: sm.Scope.SchemaURL, @@ -83,13 +84,13 @@ func metric(m metricdata.Metrics) (*mpb.Metric, error) { } switch a := m.Data.(type) { case metricdata.Gauge[int64]: - out.Data = Gauge[int64](a) + out.Data = Gauge(a) case metricdata.Gauge[float64]: - out.Data = Gauge[float64](a) + out.Data = Gauge(a) case metricdata.Sum[int64]: - out.Data, err = Sum[int64](a) + out.Data, err = Sum(a) case metricdata.Sum[float64]: - out.Data, err = Sum[float64](a) + out.Data, err = Sum(a) case metricdata.Histogram[int64]: out.Data, err = Histogram(a) case metricdata.Histogram[float64]: @@ -279,10 +280,7 @@ func Temporality(t metricdata.Temporality) (mpb.AggregationTemporality, error) { // timeUnixNano on the zero Time returns 0. // The result does not depend on the location associated with t. func timeUnixNano(t time.Time) uint64 { - if t.IsZero() { - return 0 - } - return uint64(t.UnixNano()) + return uint64(max(0, t.UnixNano())) // nolint:gosec // Overflow checked. } // Exemplars returns a slice of OTLP Exemplars generated from exemplars. diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/version.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/version.go index 1046eb5939..19b789b8b9 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/version.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/version.go @@ -5,5 +5,5 @@ package otlpmetricgrpc // import "go.opentelemetry.io/otel/exporters/otlp/otlpme // Version is the current release version of the OpenTelemetry OTLP over gRPC metrics exporter in use. func Version() string { - return "1.29.0" + return "1.32.0" } diff --git a/vendor/go.opentelemetry.io/otel/internal/global/instruments.go b/vendor/go.opentelemetry.io/otel/internal/global/instruments.go index 3a0cc42f6a..ae92a42516 100644 --- a/vendor/go.opentelemetry.io/otel/internal/global/instruments.go +++ b/vendor/go.opentelemetry.io/otel/internal/global/instruments.go @@ -13,7 +13,7 @@ import ( // unwrapper unwraps to return the underlying instrument implementation. type unwrapper interface { - Unwrap() metric.Observable + unwrap() metric.Observable } type afCounter struct { @@ -40,7 +40,7 @@ func (i *afCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *afCounter) Unwrap() metric.Observable { +func (i *afCounter) unwrap() metric.Observable { if ctr := i.delegate.Load(); ctr != nil { return ctr.(metric.Float64ObservableCounter) } @@ -71,7 +71,7 @@ func (i *afUpDownCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *afUpDownCounter) Unwrap() metric.Observable { +func (i *afUpDownCounter) unwrap() metric.Observable { if ctr := i.delegate.Load(); ctr != nil { return ctr.(metric.Float64ObservableUpDownCounter) } @@ -102,7 +102,7 @@ func (i *afGauge) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *afGauge) Unwrap() metric.Observable { +func (i *afGauge) unwrap() metric.Observable { if ctr := i.delegate.Load(); ctr != nil { return ctr.(metric.Float64ObservableGauge) } @@ -133,7 +133,7 @@ func (i *aiCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *aiCounter) Unwrap() metric.Observable { +func (i *aiCounter) unwrap() metric.Observable { if ctr := i.delegate.Load(); ctr != nil { return ctr.(metric.Int64ObservableCounter) } @@ -164,7 +164,7 @@ func (i *aiUpDownCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *aiUpDownCounter) Unwrap() metric.Observable { +func (i *aiUpDownCounter) unwrap() metric.Observable { if ctr := i.delegate.Load(); ctr != nil { return ctr.(metric.Int64ObservableUpDownCounter) } @@ -195,7 +195,7 @@ func (i *aiGauge) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *aiGauge) Unwrap() metric.Observable { +func (i *aiGauge) unwrap() metric.Observable { if ctr := i.delegate.Load(); ctr != nil { return ctr.(metric.Int64ObservableGauge) } diff --git a/vendor/go.opentelemetry.io/otel/internal/global/meter.go b/vendor/go.opentelemetry.io/otel/internal/global/meter.go index e3db438a09..a6acd8dca6 100644 --- a/vendor/go.opentelemetry.io/otel/internal/global/meter.go +++ b/vendor/go.opentelemetry.io/otel/internal/global/meter.go @@ -5,6 +5,7 @@ package global // import "go.opentelemetry.io/otel/internal/global" import ( "container/list" + "context" "reflect" "sync" @@ -66,6 +67,7 @@ func (p *meterProvider) Meter(name string, opts ...metric.MeterOption) metric.Me name: name, version: c.InstrumentationVersion(), schema: c.SchemaURL(), + attrs: c.InstrumentationAttributes(), } if p.meters == nil { @@ -472,8 +474,7 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable) defer m.mtx.Unlock() if m.delegate != nil { - insts = unwrapInstruments(insts) - return m.delegate.RegisterCallback(f, insts...) + return m.delegate.RegisterCallback(unwrapCallback(f), unwrapInstruments(insts)...) } reg := ®istration{instruments: insts, function: f} @@ -487,15 +488,11 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable) return reg, nil } -type wrapped interface { - unwrap() metric.Observable -} - func unwrapInstruments(instruments []metric.Observable) []metric.Observable { out := make([]metric.Observable, 0, len(instruments)) for _, inst := range instruments { - if in, ok := inst.(wrapped); ok { + if in, ok := inst.(unwrapper); ok { out = append(out, in.unwrap()) } else { out = append(out, inst) @@ -515,9 +512,61 @@ type registration struct { unregMu sync.Mutex } -func (c *registration) setDelegate(m metric.Meter) { - insts := unwrapInstruments(c.instruments) +type unwrapObs struct { + embedded.Observer + obs metric.Observer +} + +// unwrapFloat64Observable returns an expected metric.Float64Observable after +// unwrapping the global object. +func unwrapFloat64Observable(inst metric.Float64Observable) metric.Float64Observable { + if unwrapped, ok := inst.(unwrapper); ok { + if floatObs, ok := unwrapped.unwrap().(metric.Float64Observable); ok { + // Note: if the unwrapped object does not + // unwrap as an observable for either of the + // predicates here, it means an internal bug in + // this package. We avoid logging an error in + // this case, because the SDK has to try its + // own type conversion on the object. The SDK + // will see this and be forced to respond with + // its own error. + // + // This code uses a double-nested if statement + // to avoid creating a branch that is + // impossible to cover. + inst = floatObs + } + } + return inst +} + +// unwrapInt64Observable returns an expected metric.Int64Observable after +// unwrapping the global object. +func unwrapInt64Observable(inst metric.Int64Observable) metric.Int64Observable { + if unwrapped, ok := inst.(unwrapper); ok { + if unint, ok := unwrapped.unwrap().(metric.Int64Observable); ok { + // See the comment in unwrapFloat64Observable(). + inst = unint + } + } + return inst +} + +func (uo *unwrapObs) ObserveFloat64(inst metric.Float64Observable, value float64, opts ...metric.ObserveOption) { + uo.obs.ObserveFloat64(unwrapFloat64Observable(inst), value, opts...) +} + +func (uo *unwrapObs) ObserveInt64(inst metric.Int64Observable, value int64, opts ...metric.ObserveOption) { + uo.obs.ObserveInt64(unwrapInt64Observable(inst), value, opts...) +} +func unwrapCallback(f metric.Callback) metric.Callback { + return func(ctx context.Context, obs metric.Observer) error { + return f(ctx, &unwrapObs{obs: obs}) + } +} + +func (c *registration) setDelegate(m metric.Meter) { c.unregMu.Lock() defer c.unregMu.Unlock() @@ -526,7 +575,7 @@ func (c *registration) setDelegate(m metric.Meter) { return } - reg, err := m.RegisterCallback(c.function, insts...) + reg, err := m.RegisterCallback(unwrapCallback(c.function), unwrapInstruments(c.instruments)...) if err != nil { GetErrorHandler().Handle(err) return diff --git a/vendor/go.opentelemetry.io/otel/internal/global/trace.go b/vendor/go.opentelemetry.io/otel/internal/global/trace.go index e31f442b48..ac65262c65 100644 --- a/vendor/go.opentelemetry.io/otel/internal/global/trace.go +++ b/vendor/go.opentelemetry.io/otel/internal/global/trace.go @@ -87,6 +87,7 @@ func (p *tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T name: name, version: c.InstrumentationVersion(), schema: c.SchemaURL(), + attrs: c.InstrumentationAttributes(), } if p.tracers == nil { @@ -102,7 +103,12 @@ func (p *tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T return t } -type il struct{ name, version, schema string } +type il struct { + name string + version string + schema string + attrs attribute.Set +} // tracer is a placeholder for a trace.Tracer. // diff --git a/vendor/go.opentelemetry.io/otel/sdk/instrumentation/scope.go b/vendor/go.opentelemetry.io/otel/sdk/instrumentation/scope.go index 728115045b..34852a47b2 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/instrumentation/scope.go +++ b/vendor/go.opentelemetry.io/otel/sdk/instrumentation/scope.go @@ -3,6 +3,8 @@ package instrumentation // import "go.opentelemetry.io/otel/sdk/instrumentation" +import "go.opentelemetry.io/otel/attribute" + // Scope represents the instrumentation scope. type Scope struct { // Name is the name of the instrumentation scope. This should be the @@ -12,4 +14,6 @@ type Scope struct { Version string // SchemaURL of the telemetry emitted by the scope. SchemaURL string + // Attributes of the telemetry emitted by the scope. + Attributes attribute.Set } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/config.go b/vendor/go.opentelemetry.io/otel/sdk/metric/config.go index bbe7bf671f..203cd9d650 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/config.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/config.go @@ -5,17 +5,22 @@ package metric // import "go.opentelemetry.io/otel/sdk/metric" import ( "context" - "fmt" + "errors" + "os" + "strings" "sync" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/sdk/metric/exemplar" "go.opentelemetry.io/otel/sdk/resource" ) // config contains configuration options for a MeterProvider. type config struct { - res *resource.Resource - readers []Reader - views []View + res *resource.Resource + readers []Reader + views []View + exemplarFilter exemplar.Filter } // readerSignals returns a force-flush and shutdown function for a @@ -39,25 +44,13 @@ func (c config) readerSignals() (forceFlush, shutdown func(context.Context) erro // value. func unify(funcs []func(context.Context) error) func(context.Context) error { return func(ctx context.Context) error { - var errs []error + var err error for _, f := range funcs { - if err := f(ctx); err != nil { - errs = append(errs, err) + if e := f(ctx); e != nil { + err = errors.Join(err, e) } } - return unifyErrors(errs) - } -} - -// unifyErrors combines multiple errors into a single error. -func unifyErrors(errs []error) error { - switch len(errs) { - case 0: - return nil - case 1: - return errs[0] - default: - return fmt.Errorf("%v", errs) + return err } } @@ -75,7 +68,13 @@ func unifyShutdown(funcs []func(context.Context) error) func(context.Context) er // newConfig returns a config configured with options. func newConfig(options []Option) config { - conf := config{res: resource.Default()} + conf := config{ + res: resource.Default(), + exemplarFilter: exemplar.TraceBasedFilter, + } + for _, o := range meterProviderOptionsFromEnv() { + conf = o.apply(conf) + } for _, o := range options { conf = o.apply(conf) } @@ -103,7 +102,11 @@ func (o optionFunc) apply(conf config) config { // go.opentelemetry.io/otel/sdk/resource package will be used. func WithResource(res *resource.Resource) Option { return optionFunc(func(conf config) config { - conf.res = res + var err error + conf.res, err = resource.Merge(resource.Environment(), res) + if err != nil { + otel.Handle(err) + } return conf }) } @@ -135,3 +138,35 @@ func WithView(views ...View) Option { return cfg }) } + +// WithExemplarFilter configures the exemplar filter. +// +// The exemplar filter determines which measurements are offered to the +// exemplar reservoir, but the exemplar reservoir makes the final decision of +// whether to store an exemplar. +// +// By default, the [exemplar.SampledFilter] +// is used. Exemplars can be entirely disabled by providing the +// [exemplar.AlwaysOffFilter]. +func WithExemplarFilter(filter exemplar.Filter) Option { + return optionFunc(func(cfg config) config { + cfg.exemplarFilter = filter + return cfg + }) +} + +func meterProviderOptionsFromEnv() []Option { + var opts []Option + // https://github.com/open-telemetry/opentelemetry-specification/blob/d4b241f451674e8f611bb589477680341006ad2b/specification/configuration/sdk-environment-variables.md#exemplar + const filterEnvKey = "OTEL_METRICS_EXEMPLAR_FILTER" + + switch strings.ToLower(strings.TrimSpace(os.Getenv(filterEnvKey))) { + case "always_on": + opts = append(opts, WithExemplarFilter(exemplar.AlwaysOnFilter)) + case "always_off": + opts = append(opts, WithExemplarFilter(exemplar.AlwaysOffFilter)) + case "trace_based": + opts = append(opts, WithExemplarFilter(exemplar.TraceBasedFilter)) + } + return opts +} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar.go index 82619da78e..0335b8ae48 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar.go @@ -4,51 +4,49 @@ package metric // import "go.opentelemetry.io/otel/sdk/metric" import ( - "os" "runtime" - "slices" - "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" - "go.opentelemetry.io/otel/sdk/metric/internal/x" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/metric/exemplar" + "go.opentelemetry.io/otel/sdk/metric/internal/aggregate" ) -// reservoirFunc returns the appropriately configured exemplar reservoir -// creation func based on the passed InstrumentKind and user defined -// environment variables. -// -// Note: This will only return non-nil values when the experimental exemplar -// feature is enabled and the OTEL_METRICS_EXEMPLAR_FILTER environment variable -// is not set to always_off. -func reservoirFunc[N int64 | float64](agg Aggregation) func() exemplar.FilteredReservoir[N] { - if !x.Exemplars.Enabled() { - return nil - } - // https://github.com/open-telemetry/opentelemetry-specification/blob/d4b241f451674e8f611bb589477680341006ad2b/specification/configuration/sdk-environment-variables.md#exemplar - const filterEnvKey = "OTEL_METRICS_EXEMPLAR_FILTER" +// ExemplarReservoirProviderSelector selects the +// [exemplar.ReservoirProvider] to use +// based on the [Aggregation] of the metric. +type ExemplarReservoirProviderSelector func(Aggregation) exemplar.ReservoirProvider - var filter exemplar.Filter - - switch os.Getenv(filterEnvKey) { - case "always_on": - filter = exemplar.AlwaysOnFilter - case "always_off": - return exemplar.Drop - case "trace_based": - fallthrough - default: - filter = exemplar.SampledFilter +// reservoirFunc returns the appropriately configured exemplar reservoir +// creation func based on the passed InstrumentKind and filter configuration. +func reservoirFunc[N int64 | float64](provider exemplar.ReservoirProvider, filter exemplar.Filter) func(attribute.Set) aggregate.FilteredExemplarReservoir[N] { + return func(attrs attribute.Set) aggregate.FilteredExemplarReservoir[N] { + return aggregate.NewFilteredExemplarReservoir[N](filter, provider(attrs)) } +} +// DefaultExemplarReservoirProviderSelector returns the default +// [exemplar.ReservoirProvider] for the +// provided [Aggregation]. +// +// For explicit bucket histograms with more than 1 bucket, it uses the +// [exemplar.HistogramReservoirProvider]. +// For exponential histograms, it uses the +// [exemplar.FixedSizeReservoirProvider] +// with a size of min(20, max_buckets). +// For all other aggregations, it uses the +// [exemplar.FixedSizeReservoirProvider] +// with a size equal to the number of CPUs. +// +// Exemplar default reservoirs MAY change in a minor version bump. No +// guarantees are made on the shape or statistical properties of returned +// exemplars. +func DefaultExemplarReservoirProviderSelector(agg Aggregation) exemplar.ReservoirProvider { // https://github.com/open-telemetry/opentelemetry-specification/blob/d4b241f451674e8f611bb589477680341006ad2b/specification/metrics/sdk.md#exemplar-defaults // Explicit bucket histogram aggregation with more than 1 bucket will // use AlignedHistogramBucketExemplarReservoir. a, ok := agg.(AggregationExplicitBucketHistogram) if ok && len(a.Boundaries) > 0 { - cp := slices.Clone(a.Boundaries) - return func() exemplar.FilteredReservoir[N] { - bounds := cp - return exemplar.NewFilteredReservoir[N](filter, exemplar.Histogram(bounds)) - } + return exemplar.HistogramReservoirProvider(a.Boundaries) } var n int @@ -75,7 +73,5 @@ func reservoirFunc[N int64 | float64](agg Aggregation) func() exemplar.FilteredR } } - return func() exemplar.FilteredReservoir[N] { - return exemplar.NewFilteredReservoir[N](filter, exemplar.FixedSize(n)) - } + return exemplar.FixedSizeReservoirProvider(n) } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/README.md b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/README.md new file mode 100644 index 0000000000..d1025f5eb8 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/README.md @@ -0,0 +1,3 @@ +# Metric SDK Exemplars + +[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/sdk/metric/exemplar)](https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric/exemplar) diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/doc.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/doc.go similarity index 93% rename from vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/doc.go rename to vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/doc.go index 5394f48e0d..9f23893768 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/doc.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/doc.go @@ -3,4 +3,4 @@ // Package exemplar provides an implementation of the OpenTelemetry exemplar // reservoir to be used in metric collection pipelines. -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar" diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/exemplar.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/exemplar.go similarity index 98% rename from vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/exemplar.go rename to vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/exemplar.go index fcaa6a4697..1ab6946786 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/exemplar.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/exemplar.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar" import ( "time" diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filter.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/filter.go similarity index 75% rename from vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filter.go rename to vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/filter.go index 152a069a09..b595e2acef 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filter.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/filter.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar" import ( "context" @@ -16,10 +16,10 @@ import ( // Reservoir in making a sampling decision. type Filter func(context.Context) bool -// SampledFilter is a [Filter] that will only offer measurements +// TraceBasedFilter is a [Filter] that will only offer measurements // if the passed context associated with the measurement contains a sampled // [go.opentelemetry.io/otel/trace.SpanContext]. -func SampledFilter(ctx context.Context) bool { +func TraceBasedFilter(ctx context.Context) bool { return trace.SpanContextFromContext(ctx).IsSampled() } @@ -27,3 +27,8 @@ func SampledFilter(ctx context.Context) bool { func AlwaysOnFilter(ctx context.Context) bool { return true } + +// AlwaysOffFilter is a [Filter] that never offers measurements. +func AlwaysOffFilter(ctx context.Context) bool { + return false +} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/rand.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/fixed_size_reservoir.go similarity index 73% rename from vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/rand.go rename to vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/fixed_size_reservoir.go index 199a2608f7..d4aab0aad4 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/rand.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/fixed_size_reservoir.go @@ -1,31 +1,69 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar" import ( "context" "math" "math/rand" - "sync" "time" "go.opentelemetry.io/otel/attribute" ) -var ( +// FixedSizeReservoirProvider returns a provider of [FixedSizeReservoir]. +func FixedSizeReservoirProvider(k int) ReservoirProvider { + return func(_ attribute.Set) Reservoir { + return NewFixedSizeReservoir(k) + } +} + +// NewFixedSizeReservoir returns a [FixedSizeReservoir] that samples at most +// k exemplars. If there are k or less measurements made, the Reservoir will +// sample each one. If there are more than k, the Reservoir will then randomly +// sample all additional measurement with a decreasing probability. +func NewFixedSizeReservoir(k int) *FixedSizeReservoir { + return newFixedSizeReservoir(newStorage(k)) +} + +var _ Reservoir = &FixedSizeReservoir{} + +// FixedSizeReservoir is a [Reservoir] that samples at most k exemplars. If +// there are k or less measurements made, the Reservoir will sample each one. +// If there are more than k, the Reservoir will then randomly sample all +// additional measurement with a decreasing probability. +type FixedSizeReservoir struct { + *storage + + // count is the number of measurement seen. + count int64 + // next is the next count that will store a measurement at a random index + // once the reservoir has been filled. + next int64 + // w is the largest random number in a distribution that is used to compute + // the next next. + w float64 + // rng is used to make sampling decisions. // // Do not use crypto/rand. There is no reason for the decrease in performance // given this is not a security sensitive decision. - rng = rand.New(rand.NewSource(time.Now().UnixNano())) - // Ensure concurrent safe accecess to rng and its underlying source. - rngMu sync.Mutex -) + rng *rand.Rand +} -// random returns, as a float64, a uniform pseudo-random number in the open -// interval (0.0,1.0). -func random() float64 { +func newFixedSizeReservoir(s *storage) *FixedSizeReservoir { + r := &FixedSizeReservoir{ + storage: s, + rng: rand.New(rand.NewSource(time.Now().UnixNano())), + } + r.reset() + return r +} + +// randomFloat64 returns, as a float64, a uniform pseudo-random number in the +// open interval (0.0,1.0). +func (r *FixedSizeReservoir) randomFloat64() float64 { // TODO: This does not return a uniform number. rng.Float64 returns a // uniformly random int in [0,2^53) that is divided by 2^53. Meaning it // returns multiples of 2^-53, and not all floating point numbers between 0 @@ -43,40 +81,25 @@ func random() float64 { // // There are likely many other methods to explore here as well. - rngMu.Lock() - defer rngMu.Unlock() - - f := rng.Float64() + f := r.rng.Float64() for f == 0 { - f = rng.Float64() + f = r.rng.Float64() } return f } -// FixedSize returns a [Reservoir] that samples at most k exemplars. If there -// are k or less measurements made, the Reservoir will sample each one. If -// there are more than k, the Reservoir will then randomly sample all -// additional measurement with a decreasing probability. -func FixedSize(k int) Reservoir { - r := &randRes{storage: newStorage(k)} - r.reset() - return r -} - -type randRes struct { - *storage - - // count is the number of measurement seen. - count int64 - // next is the next count that will store a measurement at a random index - // once the reservoir has been filled. - next int64 - // w is the largest random number in a distribution that is used to compute - // the next next. - w float64 -} - -func (r *randRes) Offer(ctx context.Context, t time.Time, n Value, a []attribute.KeyValue) { +// Offer accepts the parameters associated with a measurement. The +// parameters will be stored as an exemplar if the Reservoir decides to +// sample the measurement. +// +// The passed ctx needs to contain any baggage or span that were active +// when the measurement was made. This information may be used by the +// Reservoir in making a sampling decision. +// +// The time t is the time when the measurement was made. The v and a +// parameters are the value and dropped (filtered) attributes of the +// measurement respectively. +func (r *FixedSizeReservoir) Offer(ctx context.Context, t time.Time, n Value, a []attribute.KeyValue) { // The following algorithm is "Algorithm L" from Li, Kim-Hung (4 December // 1994). "Reservoir-Sampling Algorithms of Time Complexity // O(n(1+log(N/n)))". ACM Transactions on Mathematical Software. 20 (4): @@ -123,7 +146,7 @@ func (r *randRes) Offer(ctx context.Context, t time.Time, n Value, a []attribute } else { if r.count == r.next { // Overwrite a random existing measurement with the one offered. - idx := int(rng.Int63n(int64(cap(r.store)))) + idx := int(r.rng.Int63n(int64(cap(r.store)))) r.store[idx] = newMeasurement(ctx, t, n, a) r.advance() } @@ -132,7 +155,7 @@ func (r *randRes) Offer(ctx context.Context, t time.Time, n Value, a []attribute } // reset resets r to the initial state. -func (r *randRes) reset() { +func (r *FixedSizeReservoir) reset() { // This resets the number of exemplars known. r.count = 0 // Random index inserts should only happen after the storage is full. @@ -147,14 +170,14 @@ func (r *randRes) reset() { // This maps the uniform random number in (0,1) to a geometric distribution // over the same interval. The mean of the distribution is inversely // proportional to the storage capacity. - r.w = math.Exp(math.Log(random()) / float64(cap(r.store))) + r.w = math.Exp(math.Log(r.randomFloat64()) / float64(cap(r.store))) r.advance() } // advance updates the count at which the offered measurement will overwrite an // existing exemplar. -func (r *randRes) advance() { +func (r *FixedSizeReservoir) advance() { // Calculate the next value in the random number series. // // The current value of r.w is based on the max of a distribution of random @@ -167,7 +190,7 @@ func (r *randRes) advance() { // therefore the next r.w will be based on the same distribution (i.e. // `max(u_1,u_2,...,u_k)`). Therefore, we can sample the next r.w by // computing the next random number `u` and take r.w as `w * u^(1/k)`. - r.w *= math.Exp(math.Log(random()) / float64(cap(r.store))) + r.w *= math.Exp(math.Log(r.randomFloat64()) / float64(cap(r.store))) // Use the new random number in the series to calculate the count of the // next measurement that will be stored. // @@ -178,10 +201,13 @@ func (r *randRes) advance() { // // Important to note, the new r.next will always be at least 1 more than // the last r.next. - r.next += int64(math.Log(random())/math.Log(1-r.w)) + 1 + r.next += int64(math.Log(r.randomFloat64())/math.Log(1-r.w)) + 1 } -func (r *randRes) Collect(dest *[]Exemplar) { +// Collect returns all the held exemplars. +// +// The Reservoir state is preserved after this call. +func (r *FixedSizeReservoir) Collect(dest *[]Exemplar) { r.storage.Collect(dest) // Call reset here even though it will reset r.count and restart the random // number series. This will persist any old exemplars as long as no new diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/histogram_reservoir.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/histogram_reservoir.go new file mode 100644 index 0000000000..3b76cf305a --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/histogram_reservoir.go @@ -0,0 +1,70 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar" + +import ( + "context" + "slices" + "sort" + "time" + + "go.opentelemetry.io/otel/attribute" +) + +// HistogramReservoirProvider is a provider of [HistogramReservoir]. +func HistogramReservoirProvider(bounds []float64) ReservoirProvider { + cp := slices.Clone(bounds) + slices.Sort(cp) + return func(_ attribute.Set) Reservoir { + return NewHistogramReservoir(cp) + } +} + +// NewHistogramReservoir returns a [HistogramReservoir] that samples the last +// measurement that falls within a histogram bucket. The histogram bucket +// upper-boundaries are define by bounds. +// +// The passed bounds must be sorted before calling this function. +func NewHistogramReservoir(bounds []float64) *HistogramReservoir { + return &HistogramReservoir{ + bounds: bounds, + storage: newStorage(len(bounds) + 1), + } +} + +var _ Reservoir = &HistogramReservoir{} + +// HistogramReservoir is a [Reservoir] that samples the last measurement that +// falls within a histogram bucket. The histogram bucket upper-boundaries are +// define by bounds. +type HistogramReservoir struct { + *storage + + // bounds are bucket bounds in ascending order. + bounds []float64 +} + +// Offer accepts the parameters associated with a measurement. The +// parameters will be stored as an exemplar if the Reservoir decides to +// sample the measurement. +// +// The passed ctx needs to contain any baggage or span that were active +// when the measurement was made. This information may be used by the +// Reservoir in making a sampling decision. +// +// The time t is the time when the measurement was made. The v and a +// parameters are the value and dropped (filtered) attributes of the +// measurement respectively. +func (r *HistogramReservoir) Offer(ctx context.Context, t time.Time, v Value, a []attribute.KeyValue) { + var x float64 + switch v.Type() { + case Int64ValueType: + x = float64(v.Int64()) + case Float64ValueType: + x = v.Float64() + default: + panic("unknown value type") + } + r.store[sort.SearchFloat64s(r.bounds, x)] = newMeasurement(ctx, t, v, a) +} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/reservoir.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/reservoir.go similarity index 73% rename from vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/reservoir.go rename to vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/reservoir.go index 80fa59554f..ba5cd1a6b3 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/reservoir.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/reservoir.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar" import ( "context" @@ -30,3 +30,11 @@ type Reservoir interface { // The Reservoir state is preserved after this call. Collect(dest *[]Exemplar) } + +// ReservoirProvider creates new [Reservoir]s. +// +// The attributes provided are attributes which are kept by the aggregation, and +// are exclusive with attributes passed to Offer. The combination of these +// attributes and the attributes passed to Offer is the complete set of +// attributes a measurement was made with. +type ReservoirProvider func(attr attribute.Set) Reservoir diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/storage.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/storage.go similarity index 94% rename from vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/storage.go rename to vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/storage.go index 10b2976f79..0e2e26dfb1 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/storage.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/storage.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar" import ( "context" @@ -35,7 +35,7 @@ func (r *storage) Collect(dest *[]Exemplar) { continue } - m.Exemplar(&(*dest)[n]) + m.exemplar(&(*dest)[n]) n++ } *dest = (*dest)[:n] @@ -66,8 +66,8 @@ func newMeasurement(ctx context.Context, ts time.Time, v Value, droppedAttr []at } } -// Exemplar returns m as an [Exemplar]. -func (m measurement) Exemplar(dest *Exemplar) { +// exemplar returns m as an [Exemplar]. +func (m measurement) exemplar(dest *Exemplar) { dest.FilteredAttributes = m.FilteredAttributes dest.Time = m.Time dest.Value = m.Value diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/value.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/value.go similarity index 91% rename from vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/value.go rename to vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/value.go index 1957d6b1e3..590b089a80 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/value.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/value.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar" import "math" @@ -28,7 +28,8 @@ type Value struct { func NewValue[N int64 | float64](value N) Value { switch v := any(value).(type) { case int64: - return Value{t: Int64ValueType, val: uint64(v)} + // This can be later converted back to int64 (overflow not checked). + return Value{t: Int64ValueType, val: uint64(v)} // nolint:gosec case float64: return Value{t: Float64ValueType, val: math.Float64bits(v)} } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go b/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go index b52a330b3b..48b723a7b3 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go @@ -144,6 +144,12 @@ type Stream struct { // Use NewAllowKeysFilter from "go.opentelemetry.io/otel/attribute" to // provide an allow-list of attribute keys here. AttributeFilter attribute.Filter + // ExemplarReservoirProvider selects the + // [go.opentelemetry.io/otel/sdk/metric/exemplar.ReservoirProvider] based + // on the [Aggregation]. + // + // If unspecified, [DefaultExemplarReservoirProviderSelector] is used. + ExemplarReservoirProviderSelector ExemplarReservoirProviderSelector } // instID are the identifying properties of a instrument. @@ -234,8 +240,8 @@ func (i *float64Inst) aggregate(ctx context.Context, val float64, s attribute.Se } } -// observablID is a comparable unique identifier of an observable. -type observablID[N int64 | float64] struct { +// observableID is a comparable unique identifier of an observable. +type observableID[N int64 | float64] struct { name string description string kind InstrumentKind @@ -287,7 +293,7 @@ func newInt64Observable(m *meter, kind InstrumentKind, name, desc, u string) int type observable[N int64 | float64] struct { metric.Observable - observablID[N] + observableID[N] meter *meter measures measures[N] @@ -296,7 +302,7 @@ type observable[N int64 | float64] struct { func newObservable[N int64 | float64](m *meter, kind InstrumentKind, name, desc, u string) *observable[N] { return &observable[N]{ - observablID: observablID[N]{ + observableID: observableID[N]{ name: name, description: desc, kind: kind, diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/aggregate.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/aggregate.go index b18ee719bd..fde2193338 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/aggregate.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/aggregate.go @@ -8,7 +8,6 @@ import ( "time" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" "go.opentelemetry.io/otel/sdk/metric/metricdata" ) @@ -38,8 +37,8 @@ type Builder[N int64 | float64] struct { // create new exemplar reservoirs for a new seen attribute set. // // If this is not provided a default factory function that returns an - // exemplar.Drop reservoir will be used. - ReservoirFunc func() exemplar.FilteredReservoir[N] + // dropReservoir reservoir will be used. + ReservoirFunc func(attribute.Set) FilteredExemplarReservoir[N] // AggregationLimit is the cardinality limit of measurement attributes. Any // measurement for new attributes once the limit has been reached will be // aggregated into a single aggregate for the "otel.metric.overflow" @@ -50,12 +49,12 @@ type Builder[N int64 | float64] struct { AggregationLimit int } -func (b Builder[N]) resFunc() func() exemplar.FilteredReservoir[N] { +func (b Builder[N]) resFunc() func(attribute.Set) FilteredExemplarReservoir[N] { if b.ReservoirFunc != nil { return b.ReservoirFunc } - return exemplar.Drop + return dropReservoir } type fltrMeasure[N int64 | float64] func(ctx context.Context, value N, fltrAttr attribute.Set, droppedAttr []attribute.KeyValue) diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/drop.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/drop.go new file mode 100644 index 0000000000..8396faaa4a --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/drop.go @@ -0,0 +1,27 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package aggregate // import "go.opentelemetry.io/otel/sdk/metric/internal/aggregate" + +import ( + "context" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/metric/exemplar" +) + +// dropReservoir returns a [FilteredReservoir] that drops all measurements it is offered. +func dropReservoir[N int64 | float64](attribute.Set) FilteredExemplarReservoir[N] { + return &dropRes[N]{} +} + +type dropRes[N int64 | float64] struct{} + +// Offer does nothing, all measurements offered will be dropped. +func (r *dropRes[N]) Offer(context.Context, N, []attribute.KeyValue) {} + +// Collect resets dest. No exemplars will ever be returned. +func (r *dropRes[N]) Collect(dest *[]exemplar.Exemplar) { + clear(*dest) // Erase elements to let GC collect objects + *dest = (*dest)[:0] +} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exemplar.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exemplar.go index 170ae8e58e..25d709948e 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exemplar.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exemplar.go @@ -6,7 +6,7 @@ package aggregate // import "go.opentelemetry.io/otel/sdk/metric/internal/aggreg import ( "sync" - "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" + "go.opentelemetry.io/otel/sdk/metric/exemplar" "go.opentelemetry.io/otel/sdk/metric/metricdata" ) @@ -17,6 +17,7 @@ var exemplarPool = sync.Pool{ func collectExemplars[N int64 | float64](out *[]metricdata.Exemplar[N], f func(*[]exemplar.Exemplar)) { dest := exemplarPool.Get().(*[]exemplar.Exemplar) defer func() { + clear(*dest) // Erase elements to let GC collect objects. *dest = (*dest)[:0] exemplarPool.Put(dest) }() diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go index 707342408a..b7aa721651 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go @@ -12,7 +12,6 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" "go.opentelemetry.io/otel/sdk/metric/metricdata" ) @@ -31,7 +30,7 @@ const ( // expoHistogramDataPoint is a single data point in an exponential histogram. type expoHistogramDataPoint[N int64 | float64] struct { attrs attribute.Set - res exemplar.FilteredReservoir[N] + res FilteredExemplarReservoir[N] count uint64 min N @@ -284,7 +283,7 @@ func (b *expoBuckets) downscale(delta int32) { // newExponentialHistogram returns an Aggregator that summarizes a set of // measurements as an exponential histogram. Each histogram is scoped by attributes // and the aggregation cycle the measurements were made in. -func newExponentialHistogram[N int64 | float64](maxSize, maxScale int32, noMinMax, noSum bool, limit int, r func() exemplar.FilteredReservoir[N]) *expoHistogram[N] { +func newExponentialHistogram[N int64 | float64](maxSize, maxScale int32, noMinMax, noSum bool, limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *expoHistogram[N] { return &expoHistogram[N]{ noSum: noSum, noMinMax: noMinMax, @@ -307,7 +306,7 @@ type expoHistogram[N int64 | float64] struct { maxSize int maxScale int32 - newRes func() exemplar.FilteredReservoir[N] + newRes func(attribute.Set) FilteredExemplarReservoir[N] limit limiter[*expoHistogramDataPoint[N]] values map[attribute.Distinct]*expoHistogramDataPoint[N] valuesMu sync.Mutex @@ -328,7 +327,7 @@ func (e *expoHistogram[N]) measure(ctx context.Context, value N, fltrAttr attrib v, ok := e.values[attr.Equivalent()] if !ok { v = newExpoHistogramDataPoint[N](attr, e.maxSize, e.maxScale, e.noMinMax, e.noSum) - v.res = e.newRes() + v.res = e.newRes(attr) e.values[attr.Equivalent()] = v } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/filtered_reservoir.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/filtered_reservoir.go new file mode 100644 index 0000000000..691a910608 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/filtered_reservoir.go @@ -0,0 +1,50 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package aggregate // import "go.opentelemetry.io/otel/sdk/metric/internal/aggregate" + +import ( + "context" + "time" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/metric/exemplar" +) + +// FilteredExemplarReservoir wraps a [exemplar.Reservoir] with a filter. +type FilteredExemplarReservoir[N int64 | float64] interface { + // Offer accepts the parameters associated with a measurement. The + // parameters will be stored as an exemplar if the filter decides to + // sample the measurement. + // + // The passed ctx needs to contain any baggage or span that were active + // when the measurement was made. This information may be used by the + // Reservoir in making a sampling decision. + Offer(ctx context.Context, val N, attr []attribute.KeyValue) + // Collect returns all the held exemplars in the reservoir. + Collect(dest *[]exemplar.Exemplar) +} + +// filteredExemplarReservoir handles the pre-sampled exemplar of measurements made. +type filteredExemplarReservoir[N int64 | float64] struct { + filter exemplar.Filter + reservoir exemplar.Reservoir +} + +// NewFilteredExemplarReservoir creates a [FilteredExemplarReservoir] which only offers values +// that are allowed by the filter. +func NewFilteredExemplarReservoir[N int64 | float64](f exemplar.Filter, r exemplar.Reservoir) FilteredExemplarReservoir[N] { + return &filteredExemplarReservoir[N]{ + filter: f, + reservoir: r, + } +} + +func (f *filteredExemplarReservoir[N]) Offer(ctx context.Context, val N, attr []attribute.KeyValue) { + if f.filter(ctx) { + // only record the current time if we are sampling this measurement. + f.reservoir.Offer(ctx, time.Now(), exemplar.NewValue(val), attr) + } +} + +func (f *filteredExemplarReservoir[N]) Collect(dest *[]exemplar.Exemplar) { f.reservoir.Collect(dest) } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/histogram.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/histogram.go index ade0941f5f..d577ae2c19 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/histogram.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/histogram.go @@ -11,13 +11,12 @@ import ( "time" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" "go.opentelemetry.io/otel/sdk/metric/metricdata" ) type buckets[N int64 | float64] struct { attrs attribute.Set - res exemplar.FilteredReservoir[N] + res FilteredExemplarReservoir[N] counts []uint64 count uint64 @@ -48,13 +47,13 @@ type histValues[N int64 | float64] struct { noSum bool bounds []float64 - newRes func() exemplar.FilteredReservoir[N] + newRes func(attribute.Set) FilteredExemplarReservoir[N] limit limiter[*buckets[N]] values map[attribute.Distinct]*buckets[N] valuesMu sync.Mutex } -func newHistValues[N int64 | float64](bounds []float64, noSum bool, limit int, r func() exemplar.FilteredReservoir[N]) *histValues[N] { +func newHistValues[N int64 | float64](bounds []float64, noSum bool, limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *histValues[N] { // The responsibility of keeping all buckets correctly associated with the // passed boundaries is ultimately this type's responsibility. Make a copy // here so we can always guarantee this. Or, in the case of failure, have @@ -94,7 +93,7 @@ func (s *histValues[N]) measure(ctx context.Context, value N, fltrAttr attribute // // buckets = (-∞, 0], (0, 5.0], (5.0, 10.0], (10.0, +∞) b = newBuckets[N](attr, len(s.bounds)+1) - b.res = s.newRes() + b.res = s.newRes(attr) // Ensure min and max are recorded values (not zero), for new buckets. b.min, b.max = value, value @@ -109,7 +108,7 @@ func (s *histValues[N]) measure(ctx context.Context, value N, fltrAttr attribute // newHistogram returns an Aggregator that summarizes a set of measurements as // an histogram. -func newHistogram[N int64 | float64](boundaries []float64, noMinMax, noSum bool, limit int, r func() exemplar.FilteredReservoir[N]) *histogram[N] { +func newHistogram[N int64 | float64](boundaries []float64, noMinMax, noSum bool, limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *histogram[N] { return &histogram[N]{ histValues: newHistValues[N](boundaries, noSum, limit, r), noMinMax: noMinMax, diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/lastvalue.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/lastvalue.go index c359368403..d3a93f085c 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/lastvalue.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/lastvalue.go @@ -9,7 +9,6 @@ import ( "time" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" "go.opentelemetry.io/otel/sdk/metric/metricdata" ) @@ -17,10 +16,10 @@ import ( type datapoint[N int64 | float64] struct { attrs attribute.Set value N - res exemplar.FilteredReservoir[N] + res FilteredExemplarReservoir[N] } -func newLastValue[N int64 | float64](limit int, r func() exemplar.FilteredReservoir[N]) *lastValue[N] { +func newLastValue[N int64 | float64](limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *lastValue[N] { return &lastValue[N]{ newRes: r, limit: newLimiter[datapoint[N]](limit), @@ -33,7 +32,7 @@ func newLastValue[N int64 | float64](limit int, r func() exemplar.FilteredReserv type lastValue[N int64 | float64] struct { sync.Mutex - newRes func() exemplar.FilteredReservoir[N] + newRes func(attribute.Set) FilteredExemplarReservoir[N] limit limiter[datapoint[N]] values map[attribute.Distinct]datapoint[N] start time.Time @@ -46,7 +45,7 @@ func (s *lastValue[N]) measure(ctx context.Context, value N, fltrAttr attribute. attr := s.limit.Attributes(fltrAttr, s.values) d, ok := s.values[attr.Equivalent()] if !ok { - d.res = s.newRes() + d.res = s.newRes(attr) } d.attrs = attr @@ -115,7 +114,7 @@ func (s *lastValue[N]) copyDpts(dest *[]metricdata.DataPoint[N], t time.Time) in // newPrecomputedLastValue returns an aggregator that summarizes a set of // observations as the last one made. -func newPrecomputedLastValue[N int64 | float64](limit int, r func() exemplar.FilteredReservoir[N]) *precomputedLastValue[N] { +func newPrecomputedLastValue[N int64 | float64](limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *precomputedLastValue[N] { return &precomputedLastValue[N]{lastValue: newLastValue[N](limit, r)} } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go index 8913669226..8e132ad618 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go @@ -9,25 +9,24 @@ import ( "time" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" "go.opentelemetry.io/otel/sdk/metric/metricdata" ) type sumValue[N int64 | float64] struct { n N - res exemplar.FilteredReservoir[N] + res FilteredExemplarReservoir[N] attrs attribute.Set } // valueMap is the storage for sums. type valueMap[N int64 | float64] struct { sync.Mutex - newRes func() exemplar.FilteredReservoir[N] + newRes func(attribute.Set) FilteredExemplarReservoir[N] limit limiter[sumValue[N]] values map[attribute.Distinct]sumValue[N] } -func newValueMap[N int64 | float64](limit int, r func() exemplar.FilteredReservoir[N]) *valueMap[N] { +func newValueMap[N int64 | float64](limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *valueMap[N] { return &valueMap[N]{ newRes: r, limit: newLimiter[sumValue[N]](limit), @@ -42,7 +41,7 @@ func (s *valueMap[N]) measure(ctx context.Context, value N, fltrAttr attribute.S attr := s.limit.Attributes(fltrAttr, s.values) v, ok := s.values[attr.Equivalent()] if !ok { - v.res = s.newRes() + v.res = s.newRes(attr) } v.attrs = attr @@ -55,7 +54,7 @@ func (s *valueMap[N]) measure(ctx context.Context, value N, fltrAttr attribute.S // newSum returns an aggregator that summarizes a set of measurements as their // arithmetic sum. Each sum is scoped by attributes and the aggregation cycle // the measurements were made in. -func newSum[N int64 | float64](monotonic bool, limit int, r func() exemplar.FilteredReservoir[N]) *sum[N] { +func newSum[N int64 | float64](monotonic bool, limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *sum[N] { return &sum[N]{ valueMap: newValueMap[N](limit, r), monotonic: monotonic, @@ -142,9 +141,9 @@ func (s *sum[N]) cumulative(dest *metricdata.Aggregation) int { } // newPrecomputedSum returns an aggregator that summarizes a set of -// observatrions as their arithmetic sum. Each sum is scoped by attributes and +// observations as their arithmetic sum. Each sum is scoped by attributes and // the aggregation cycle the measurements were made in. -func newPrecomputedSum[N int64 | float64](monotonic bool, limit int, r func() exemplar.FilteredReservoir[N]) *precomputedSum[N] { +func newPrecomputedSum[N int64 | float64](monotonic bool, limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *precomputedSum[N] { return &precomputedSum[N]{ valueMap: newValueMap[N](limit, r), monotonic: monotonic, @@ -152,7 +151,7 @@ func newPrecomputedSum[N int64 | float64](monotonic bool, limit int, r func() ex } } -// precomputedSum summarizes a set of observatrions as their arithmetic sum. +// precomputedSum summarizes a set of observations as their arithmetic sum. type precomputedSum[N int64 | float64] struct { *valueMap[N] diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/drop.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/drop.go deleted file mode 100644 index 5a0f39ae14..0000000000 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/drop.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" - -import ( - "context" - - "go.opentelemetry.io/otel/attribute" -) - -// Drop returns a [FilteredReservoir] that drops all measurements it is offered. -func Drop[N int64 | float64]() FilteredReservoir[N] { return &dropRes[N]{} } - -type dropRes[N int64 | float64] struct{} - -// Offer does nothing, all measurements offered will be dropped. -func (r *dropRes[N]) Offer(context.Context, N, []attribute.KeyValue) {} - -// Collect resets dest. No exemplars will ever be returned. -func (r *dropRes[N]) Collect(dest *[]Exemplar) { - *dest = (*dest)[:0] -} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filtered_reservoir.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filtered_reservoir.go deleted file mode 100644 index 9fedfa4be6..0000000000 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filtered_reservoir.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" - -import ( - "context" - "time" - - "go.opentelemetry.io/otel/attribute" -) - -// FilteredReservoir wraps a [Reservoir] with a filter. -type FilteredReservoir[N int64 | float64] interface { - // Offer accepts the parameters associated with a measurement. The - // parameters will be stored as an exemplar if the filter decides to - // sample the measurement. - // - // The passed ctx needs to contain any baggage or span that were active - // when the measurement was made. This information may be used by the - // Reservoir in making a sampling decision. - Offer(ctx context.Context, val N, attr []attribute.KeyValue) - // Collect returns all the held exemplars in the reservoir. - Collect(dest *[]Exemplar) -} - -// filteredReservoir handles the pre-sampled exemplar of measurements made. -type filteredReservoir[N int64 | float64] struct { - filter Filter - reservoir Reservoir -} - -// NewFilteredReservoir creates a [FilteredReservoir] which only offers values -// that are allowed by the filter. -func NewFilteredReservoir[N int64 | float64](f Filter, r Reservoir) FilteredReservoir[N] { - return &filteredReservoir[N]{ - filter: f, - reservoir: r, - } -} - -func (f *filteredReservoir[N]) Offer(ctx context.Context, val N, attr []attribute.KeyValue) { - if f.filter(ctx) { - // only record the current time if we are sampling this measurment. - f.reservoir.Offer(ctx, time.Now(), NewValue(val), attr) - } -} - -func (f *filteredReservoir[N]) Collect(dest *[]Exemplar) { f.reservoir.Collect(dest) } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/hist.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/hist.go deleted file mode 100644 index a6ff86d027..0000000000 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/hist.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" - -import ( - "context" - "slices" - "sort" - "time" - - "go.opentelemetry.io/otel/attribute" -) - -// Histogram returns a [Reservoir] that samples the last measurement that falls -// within a histogram bucket. The histogram bucket upper-boundaries are define -// by bounds. -// -// The passed bounds will be sorted by this function. -func Histogram(bounds []float64) Reservoir { - slices.Sort(bounds) - return &histRes{ - bounds: bounds, - storage: newStorage(len(bounds) + 1), - } -} - -type histRes struct { - *storage - - // bounds are bucket bounds in ascending order. - bounds []float64 -} - -func (r *histRes) Offer(ctx context.Context, t time.Time, v Value, a []attribute.KeyValue) { - var x float64 - switch v.Type() { - case Int64ValueType: - x = float64(v.Int64()) - case Float64ValueType: - x = v.Float64() - default: - panic("unknown value type") - } - r.store[sort.SearchFloat64s(r.bounds, x)] = newMeasurement(ctx, t, v, a) -} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/x.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/x.go index 8cd2f37417..0891993706 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/x.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/x.go @@ -10,39 +10,23 @@ package x // import "go.opentelemetry.io/otel/sdk/metric/internal/x" import ( "os" "strconv" - "strings" ) -var ( - // Exemplars is an experimental feature flag that defines if exemplars - // should be recorded for metric data-points. - // - // To enable this feature set the OTEL_GO_X_EXEMPLAR environment variable - // to the case-insensitive string value of "true" (i.e. "True" and "TRUE" - // will also enable this). - Exemplars = newFeature("EXEMPLAR", func(v string) (string, bool) { - if strings.ToLower(v) == "true" { - return v, true - } - return "", false - }) - - // CardinalityLimit is an experimental feature flag that defines if - // cardinality limits should be applied to the recorded metric data-points. - // - // To enable this feature set the OTEL_GO_X_CARDINALITY_LIMIT environment - // variable to the integer limit value you want to use. - // - // Setting OTEL_GO_X_CARDINALITY_LIMIT to a value less than or equal to 0 - // will disable the cardinality limits. - CardinalityLimit = newFeature("CARDINALITY_LIMIT", func(v string) (int, bool) { - n, err := strconv.Atoi(v) - if err != nil { - return 0, false - } - return n, true - }) -) +// CardinalityLimit is an experimental feature flag that defines if +// cardinality limits should be applied to the recorded metric data-points. +// +// To enable this feature set the OTEL_GO_X_CARDINALITY_LIMIT environment +// variable to the integer limit value you want to use. +// +// Setting OTEL_GO_X_CARDINALITY_LIMIT to a value less than or equal to 0 +// will disable the cardinality limits. +var CardinalityLimit = newFeature("CARDINALITY_LIMIT", func(v string) (int, bool) { + n, err := strconv.Atoi(v) + if err != nil { + return 0, false + } + return n, true +}) // Feature is an experimental feature control flag. It provides a uniform way // to interact with these feature flags and parse their values. diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/manual_reader.go b/vendor/go.opentelemetry.io/otel/sdk/metric/manual_reader.go index e0fd86ca78..c495985bc2 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/manual_reader.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/manual_reader.go @@ -113,18 +113,17 @@ func (mr *ManualReader) Collect(ctx context.Context, rm *metricdata.ResourceMetr if err != nil { return err } - var errs []error for _, producer := range mr.externalProducers.Load().([]Producer) { - externalMetrics, err := producer.Produce(ctx) - if err != nil { - errs = append(errs, err) + externalMetrics, e := producer.Produce(ctx) + if e != nil { + err = errors.Join(err, e) } rm.ScopeMetrics = append(rm.ScopeMetrics, externalMetrics...) } global.Debug("ManualReader collection", "Data", rm) - return unifyErrors(errs) + return err } // MarshalLog returns logging data about the ManualReader. diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go b/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go index 2309e5b2b0..823cdf2c62 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go @@ -150,6 +150,11 @@ func (m *meter) int64ObservableInstrument(id Instrument, callbacks []metric.Int6 continue } inst.appendMeasures(in) + + // Add the measures to the pipeline. It is required to maintain + // measures per pipeline to avoid calling the measure that + // is not part of the pipeline. + insert.pipeline.addInt64Measure(inst.observableID, in) for _, cback := range callbacks { inst := int64Observer{measures: in} fn := cback @@ -309,6 +314,11 @@ func (m *meter) float64ObservableInstrument(id Instrument, callbacks []metric.Fl continue } inst.appendMeasures(in) + + // Add the measures to the pipeline. It is required to maintain + // measures per pipeline to avoid calling the measure that + // is not part of the pipeline. + insert.pipeline.addFloat64Measure(inst.observableID, in) for _, cback := range callbacks { inst := float64Observer{measures: in} fn := cback @@ -441,73 +451,80 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable) return noopRegister{}, nil } - reg := newObserver() - var errs multierror + var err error + validInstruments := make([]metric.Observable, 0, len(insts)) for _, inst := range insts { - // Unwrap any global. - if u, ok := inst.(interface { - Unwrap() metric.Observable - }); ok { - inst = u.Unwrap() - } - switch o := inst.(type) { case int64Observable: - if err := o.registerable(m); err != nil { - if !errors.Is(err, errEmptyAgg) { - errs.append(err) + if e := o.registerable(m); e != nil { + if !errors.Is(e, errEmptyAgg) { + err = errors.Join(err, e) } continue } - reg.registerInt64(o.observablID) + + validInstruments = append(validInstruments, inst) case float64Observable: - if err := o.registerable(m); err != nil { - if !errors.Is(err, errEmptyAgg) { - errs.append(err) + if e := o.registerable(m); e != nil { + if !errors.Is(e, errEmptyAgg) { + err = errors.Join(err, e) } continue } - reg.registerFloat64(o.observablID) + + validInstruments = append(validInstruments, inst) default: // Instrument external to the SDK. return nil, fmt.Errorf("invalid observable: from different implementation") } } - err := errs.errorOrNil() - if reg.len() == 0 { + if len(validInstruments) == 0 { // All insts use drop aggregation or are invalid. return noopRegister{}, err } - // Some or all instruments were valid. - cback := func(ctx context.Context) error { return f(ctx, reg) } - return m.pipes.registerMultiCallback(cback), err + unregs := make([]func(), len(m.pipes)) + for ix, pipe := range m.pipes { + reg := newObserver(pipe) + for _, inst := range validInstruments { + switch o := inst.(type) { + case int64Observable: + reg.registerInt64(o.observableID) + case float64Observable: + reg.registerFloat64(o.observableID) + } + } + + // Some or all instruments were valid. + cBack := func(ctx context.Context) error { return f(ctx, reg) } + unregs[ix] = pipe.addMultiCallback(cBack) + } + + return unregisterFuncs{f: unregs}, err } type observer struct { embedded.Observer - float64 map[observablID[float64]]struct{} - int64 map[observablID[int64]]struct{} + pipe *pipeline + float64 map[observableID[float64]]struct{} + int64 map[observableID[int64]]struct{} } -func newObserver() observer { +func newObserver(p *pipeline) observer { return observer{ - float64: make(map[observablID[float64]]struct{}), - int64: make(map[observablID[int64]]struct{}), + pipe: p, + float64: make(map[observableID[float64]]struct{}), + int64: make(map[observableID[int64]]struct{}), } } -func (r observer) len() int { - return len(r.float64) + len(r.int64) -} - -func (r observer) registerFloat64(id observablID[float64]) { +func (r observer) registerFloat64(id observableID[float64]) { r.float64[id] = struct{}{} } -func (r observer) registerInt64(id observablID[int64]) { +func (r observer) registerInt64(id observableID[int64]) { r.int64[id] = struct{}{} } @@ -521,22 +538,12 @@ func (r observer) ObserveFloat64(o metric.Float64Observable, v float64, opts ... switch conv := o.(type) { case float64Observable: oImpl = conv - case interface { - Unwrap() metric.Observable - }: - // Unwrap any global. - async := conv.Unwrap() - var ok bool - if oImpl, ok = async.(float64Observable); !ok { - global.Error(errUnknownObserver, "failed to record asynchronous") - return - } default: global.Error(errUnknownObserver, "failed to record") return } - if _, registered := r.float64[oImpl.observablID]; !registered { + if _, registered := r.float64[oImpl.observableID]; !registered { if !oImpl.dropAggregation { global.Error(errUnregObserver, "failed to record", "name", oImpl.name, @@ -548,7 +555,12 @@ func (r observer) ObserveFloat64(o metric.Float64Observable, v float64, opts ... return } c := metric.NewObserveConfig(opts) - oImpl.observe(v, c.Attributes()) + // Access to r.pipe.float64Measure is already guarded by a lock in pipeline.produce. + // TODO (#5946): Refactor pipeline and observable measures. + measures := r.pipe.float64Measures[oImpl.observableID] + for _, m := range measures { + m(context.Background(), v, c.Attributes()) + } } func (r observer) ObserveInt64(o metric.Int64Observable, v int64, opts ...metric.ObserveOption) { @@ -556,22 +568,12 @@ func (r observer) ObserveInt64(o metric.Int64Observable, v int64, opts ...metric switch conv := o.(type) { case int64Observable: oImpl = conv - case interface { - Unwrap() metric.Observable - }: - // Unwrap any global. - async := conv.Unwrap() - var ok bool - if oImpl, ok = async.(int64Observable); !ok { - global.Error(errUnknownObserver, "failed to record asynchronous") - return - } default: global.Error(errUnknownObserver, "failed to record") return } - if _, registered := r.int64[oImpl.observablID]; !registered { + if _, registered := r.int64[oImpl.observableID]; !registered { if !oImpl.dropAggregation { global.Error(errUnregObserver, "failed to record", "name", oImpl.name, @@ -583,7 +585,12 @@ func (r observer) ObserveInt64(o metric.Int64Observable, v int64, opts ...metric return } c := metric.NewObserveConfig(opts) - oImpl.observe(v, c.Attributes()) + // Access to r.pipe.int64Measures is already guarded b a lock in pipeline.produce. + // TODO (#5946): Refactor pipeline and observable measures. + measures := r.pipe.int64Measures[oImpl.observableID] + for _, m := range measures { + m(context.Background(), v, c.Attributes()) + } } type noopRegister struct{ embedded.Registration } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/periodic_reader.go b/vendor/go.opentelemetry.io/otel/sdk/metric/periodic_reader.go index 67ee1b11a2..dcd2182d9a 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/periodic_reader.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/periodic_reader.go @@ -251,18 +251,17 @@ func (r *PeriodicReader) collect(ctx context.Context, p interface{}, rm *metricd if err != nil { return err } - var errs []error for _, producer := range r.externalProducers.Load().([]Producer) { - externalMetrics, err := producer.Produce(ctx) - if err != nil { - errs = append(errs, err) + externalMetrics, e := producer.Produce(ctx) + if e != nil { + err = errors.Join(err, e) } rm.ScopeMetrics = append(rm.ScopeMetrics, externalMetrics...) } global.Debug("PeriodicReader collection", "Data", rm) - return unifyErrors(errs) + return err } // export exports metric data m using r's exporter. diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/pipeline.go b/vendor/go.opentelemetry.io/otel/sdk/metric/pipeline.go index 823bf2fe3d..775e245261 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/pipeline.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/pipeline.go @@ -8,14 +8,13 @@ import ( "context" "errors" "fmt" - "strings" "sync" "sync/atomic" "go.opentelemetry.io/otel/internal/global" - "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/sdk/instrumentation" + "go.opentelemetry.io/otel/sdk/metric/exemplar" "go.opentelemetry.io/otel/sdk/metric/internal" "go.opentelemetry.io/otel/sdk/metric/internal/aggregate" "go.opentelemetry.io/otel/sdk/metric/internal/x" @@ -38,14 +37,17 @@ type instrumentSync struct { compAgg aggregate.ComputeAggregation } -func newPipeline(res *resource.Resource, reader Reader, views []View) *pipeline { +func newPipeline(res *resource.Resource, reader Reader, views []View, exemplarFilter exemplar.Filter) *pipeline { if res == nil { res = resource.Empty() } return &pipeline{ - resource: res, - reader: reader, - views: views, + resource: res, + reader: reader, + views: views, + int64Measures: map[observableID[int64]][]aggregate.Measure[int64]{}, + float64Measures: map[observableID[float64]][]aggregate.Measure[float64]{}, + exemplarFilter: exemplarFilter, // aggregations is lazy allocated when needed. } } @@ -63,9 +65,26 @@ type pipeline struct { views []View sync.Mutex - aggregations map[instrumentation.Scope][]instrumentSync - callbacks []func(context.Context) error - multiCallbacks list.List + int64Measures map[observableID[int64]][]aggregate.Measure[int64] + float64Measures map[observableID[float64]][]aggregate.Measure[float64] + aggregations map[instrumentation.Scope][]instrumentSync + callbacks []func(context.Context) error + multiCallbacks list.List + exemplarFilter exemplar.Filter +} + +// addInt64Measure adds a new int64 measure to the pipeline for each observer. +func (p *pipeline) addInt64Measure(id observableID[int64], m []aggregate.Measure[int64]) { + p.Lock() + defer p.Unlock() + p.int64Measures[id] = m +} + +// addFloat64Measure adds a new float64 measure to the pipeline for each observer. +func (p *pipeline) addFloat64Measure(id observableID[float64], m []aggregate.Measure[float64]) { + p.Lock() + defer p.Unlock() + p.float64Measures[id] = m } // addSync adds the instrumentSync to pipeline p with scope. This method is not @@ -105,14 +124,15 @@ func (p *pipeline) produce(ctx context.Context, rm *metricdata.ResourceMetrics) p.Lock() defer p.Unlock() - var errs multierror + var err error for _, c := range p.callbacks { // TODO make the callbacks parallel. ( #3034 ) - if err := c(ctx); err != nil { - errs.append(err) + if e := c(ctx); e != nil { + err = errors.Join(err, e) } if err := ctx.Err(); err != nil { rm.Resource = nil + clear(rm.ScopeMetrics) // Erase elements to let GC collect objects. rm.ScopeMetrics = rm.ScopeMetrics[:0] return err } @@ -120,12 +140,13 @@ func (p *pipeline) produce(ctx context.Context, rm *metricdata.ResourceMetrics) for e := p.multiCallbacks.Front(); e != nil; e = e.Next() { // TODO make the callbacks parallel. ( #3034 ) f := e.Value.(multiCallback) - if err := f(ctx); err != nil { - errs.append(err) + if e := f(ctx); e != nil { + err = errors.Join(err, e) } if err := ctx.Err(); err != nil { // This means the context expired before we finished running callbacks. rm.Resource = nil + clear(rm.ScopeMetrics) // Erase elements to let GC collect objects. rm.ScopeMetrics = rm.ScopeMetrics[:0] return err } @@ -157,7 +178,7 @@ func (p *pipeline) produce(ctx context.Context, rm *metricdata.ResourceMetrics) rm.ScopeMetrics = rm.ScopeMetrics[:i] - return errs.errorOrNil() + return err } // inserter facilitates inserting of new instruments from a single scope into a @@ -219,7 +240,7 @@ func (i *inserter[N]) Instrument(inst Instrument, readerAggregation Aggregation) measures []aggregate.Measure[N] ) - errs := &multierror{wrapped: errCreatingAggregators} + var err error seen := make(map[uint64]struct{}) for _, v := range i.pipeline.views { stream, match := v(inst) @@ -227,9 +248,9 @@ func (i *inserter[N]) Instrument(inst Instrument, readerAggregation Aggregation) continue } matched = true - in, id, err := i.cachedAggregator(inst.Scope, inst.Kind, stream, readerAggregation) - if err != nil { - errs.append(err) + in, id, e := i.cachedAggregator(inst.Scope, inst.Kind, stream, readerAggregation) + if e != nil { + err = errors.Join(err, e) } if in == nil { // Drop aggregation. continue @@ -242,8 +263,12 @@ func (i *inserter[N]) Instrument(inst Instrument, readerAggregation Aggregation) measures = append(measures, in) } + if err != nil { + err = errors.Join(errCreatingAggregators, err) + } + if matched { - return measures, errs.errorOrNil() + return measures, err } // Apply implicit default view if no explicit matched. @@ -252,15 +277,18 @@ func (i *inserter[N]) Instrument(inst Instrument, readerAggregation Aggregation) Description: inst.Description, Unit: inst.Unit, } - in, _, err := i.cachedAggregator(inst.Scope, inst.Kind, stream, readerAggregation) - if err != nil { - errs.append(err) + in, _, e := i.cachedAggregator(inst.Scope, inst.Kind, stream, readerAggregation) + if e != nil { + if err == nil { + err = errCreatingAggregators + } + err = errors.Join(err, e) } if in != nil { // Ensured to have not seen given matched was false. measures = append(measures, in) } - return measures, errs.errorOrNil() + return measures, err } // addCallback registers a single instrument callback to be run when @@ -329,6 +357,9 @@ func (i *inserter[N]) cachedAggregator(scope instrumentation.Scope, kind Instrum // The view explicitly requested the default aggregation. stream.Aggregation = DefaultAggregationSelector(kind) } + if stream.ExemplarReservoirProviderSelector == nil { + stream.ExemplarReservoirProviderSelector = DefaultExemplarReservoirProviderSelector + } if err := isAggregatorCompatible(kind, stream.Aggregation); err != nil { return nil, 0, fmt.Errorf( @@ -349,7 +380,7 @@ func (i *inserter[N]) cachedAggregator(scope instrumentation.Scope, kind Instrum cv := i.aggregators.Lookup(normID, func() aggVal[N] { b := aggregate.Builder[N]{ Temporality: i.pipeline.reader.temporality(kind), - ReservoirFunc: reservoirFunc[N](stream.Aggregation), + ReservoirFunc: reservoirFunc[N](stream.ExemplarReservoirProviderSelector(stream.Aggregation), i.pipeline.exemplarFilter), } b.Filter = stream.AttributeFilter // A value less than or equal to zero will disable the aggregation @@ -552,24 +583,16 @@ func isAggregatorCompatible(kind InstrumentKind, agg Aggregation) error { // measurement. type pipelines []*pipeline -func newPipelines(res *resource.Resource, readers []Reader, views []View) pipelines { +func newPipelines(res *resource.Resource, readers []Reader, views []View, exemplarFilter exemplar.Filter) pipelines { pipes := make([]*pipeline, 0, len(readers)) for _, r := range readers { - p := newPipeline(res, r, views) + p := newPipeline(res, r, views, exemplarFilter) r.register(p) pipes = append(pipes, p) } return pipes } -func (p pipelines) registerMultiCallback(c multiCallback) metric.Registration { - unregs := make([]func(), len(p)) - for i, pipe := range p { - unregs[i] = pipe.addMultiCallback(c) - } - return unregisterFuncs{f: unregs} -} - type unregisterFuncs struct { embedded.Registration f []func() @@ -602,15 +625,15 @@ func newResolver[N int64 | float64](p pipelines, vc *cache[string, instID]) reso func (r resolver[N]) Aggregators(id Instrument) ([]aggregate.Measure[N], error) { var measures []aggregate.Measure[N] - errs := &multierror{} + var err error for _, i := range r.inserters { - in, err := i.Instrument(id, i.readerDefaultAggregation(id.Kind)) - if err != nil { - errs.append(err) + in, e := i.Instrument(id, i.readerDefaultAggregation(id.Kind)) + if e != nil { + err = errors.Join(err, e) } measures = append(measures, in...) } - return measures, errs.errorOrNil() + return measures, err } // HistogramAggregators returns the histogram Aggregators that must be updated by the instrument @@ -619,37 +642,18 @@ func (r resolver[N]) Aggregators(id Instrument) ([]aggregate.Measure[N], error) func (r resolver[N]) HistogramAggregators(id Instrument, boundaries []float64) ([]aggregate.Measure[N], error) { var measures []aggregate.Measure[N] - errs := &multierror{} + var err error for _, i := range r.inserters { agg := i.readerDefaultAggregation(id.Kind) if histAgg, ok := agg.(AggregationExplicitBucketHistogram); ok && len(boundaries) > 0 { histAgg.Boundaries = boundaries agg = histAgg } - in, err := i.Instrument(id, agg) - if err != nil { - errs.append(err) + in, e := i.Instrument(id, agg) + if e != nil { + err = errors.Join(err, e) } measures = append(measures, in...) } - return measures, errs.errorOrNil() -} - -type multierror struct { - wrapped error - errors []string -} - -func (m *multierror) errorOrNil() error { - if len(m.errors) == 0 { - return nil - } - if m.wrapped == nil { - return errors.New(strings.Join(m.errors, "; ")) - } - return fmt.Errorf("%w: %s", m.wrapped, strings.Join(m.errors, "; ")) -} - -func (m *multierror) append(err error) { - m.errors = append(m.errors, err.Error()) + return measures, err } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/provider.go b/vendor/go.opentelemetry.io/otel/sdk/metric/provider.go index a82af538e6..2fca89e5a8 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/provider.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/provider.go @@ -42,7 +42,7 @@ func NewMeterProvider(options ...Option) *MeterProvider { flush, sdown := conf.readerSignals() mp := &MeterProvider{ - pipes: newPipelines(conf.res, conf.readers, conf.views), + pipes: newPipelines(conf.res, conf.readers, conf.views, conf.exemplarFilter), forceFlush: flush, shutdown: sdown, } @@ -76,15 +76,17 @@ func (mp *MeterProvider) Meter(name string, options ...metric.MeterOption) metri c := metric.NewMeterConfig(options...) s := instrumentation.Scope{ - Name: name, - Version: c.InstrumentationVersion(), - SchemaURL: c.SchemaURL(), + Name: name, + Version: c.InstrumentationVersion(), + SchemaURL: c.SchemaURL(), + Attributes: c.InstrumentationAttributes(), } global.Info("Meter created", "Name", s.Name, "Version", s.Version, "SchemaURL", s.SchemaURL, + "Attributes", s.Attributes, ) return mp.meters.Lookup(s, func() *meter { diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/version.go b/vendor/go.opentelemetry.io/otel/sdk/metric/version.go index 44316caa11..6347060bf4 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/version.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/version.go @@ -5,5 +5,5 @@ package metric // import "go.opentelemetry.io/otel/sdk/metric" // version is the current release version of the metric SDK in use. func version() string { - return "1.29.0" + return "1.32.0" } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/view.go b/vendor/go.opentelemetry.io/otel/sdk/metric/view.go index cd08c67324..630890f426 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/view.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/view.go @@ -96,11 +96,12 @@ func NewView(criteria Instrument, mask Stream) View { return func(i Instrument) (Stream, bool) { if matchFunc(i) { return Stream{ - Name: nonZero(mask.Name, i.Name), - Description: nonZero(mask.Description, i.Description), - Unit: nonZero(mask.Unit, i.Unit), - Aggregation: agg, - AttributeFilter: mask.AttributeFilter, + Name: nonZero(mask.Name, i.Name), + Description: nonZero(mask.Description, i.Description), + Unit: nonZero(mask.Unit, i.Unit), + Aggregation: agg, + AttributeFilter: mask.AttributeFilter, + ExemplarReservoirProviderSelector: mask.ExemplarReservoirProviderSelector, }, true } return Stream{}, false diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go b/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go index 95a61d61d4..c02aeefdde 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go @@ -7,7 +7,6 @@ import ( "context" "errors" "fmt" - "strings" ) // ErrPartialResource is returned by a detector when complete source @@ -57,62 +56,37 @@ func Detect(ctx context.Context, detectors ...Detector) (*Resource, error) { // these errors will be returned. Otherwise, nil is returned. func detect(ctx context.Context, res *Resource, detectors []Detector) error { var ( - r *Resource - errs detectErrs - err error + r *Resource + err error + e error ) for _, detector := range detectors { if detector == nil { continue } - r, err = detector.Detect(ctx) - if err != nil { - errs = append(errs, err) - if !errors.Is(err, ErrPartialResource) { + r, e = detector.Detect(ctx) + if e != nil { + err = errors.Join(err, e) + if !errors.Is(e, ErrPartialResource) { continue } } - r, err = Merge(res, r) - if err != nil { - errs = append(errs, err) + r, e = Merge(res, r) + if e != nil { + err = errors.Join(err, e) } *res = *r } - if len(errs) == 0 { - return nil - } - if errors.Is(errs, ErrSchemaURLConflict) { - // If there has been a merge conflict, ensure the resource has no - // schema URL. - res.schemaURL = "" - } - return errs -} - -type detectErrs []error - -func (e detectErrs) Error() string { - errStr := make([]string, len(e)) - for i, err := range e { - errStr[i] = fmt.Sprintf("* %s", err) - } - - format := "%d errors occurred detecting resource:\n\t%s" - return fmt.Sprintf(format, len(e), strings.Join(errStr, "\n\t")) -} + if err != nil { + if errors.Is(err, ErrSchemaURLConflict) { + // If there has been a merge conflict, ensure the resource has no + // schema URL. + res.schemaURL = "" + } -func (e detectErrs) Unwrap() error { - switch len(e) { - case 0: - return nil - case 1: - return e[0] + err = fmt.Errorf("error detecting resource: %w", err) } - return e[1:] -} - -func (e detectErrs) Is(target error) bool { - return len(e) != 0 && errors.Is(e[0], target) + return err } diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go b/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go index 6ac1cdbf7b..cf3c88e15c 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go @@ -20,15 +20,13 @@ type ( // telemetrySDK is a Detector that provides information about // the OpenTelemetry SDK used. This Detector is included as a // builtin. If these resource attributes are not wanted, use - // the WithTelemetrySDK(nil) or WithoutBuiltin() options to - // explicitly disable them. + // resource.New() to explicitly disable them. telemetrySDK struct{} // host is a Detector that provides information about the host // being run on. This Detector is included as a builtin. If // these resource attributes are not wanted, use the - // WithHost(nil) or WithoutBuiltin() options to explicitly - // disable them. + // resource.New() to explicitly disable them. host struct{} stringDetector struct { diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go b/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go index 71386e2da4..3677c83d7d 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go @@ -10,17 +10,16 @@ import ( "golang.org/x/sys/windows/registry" ) -// implements hostIDReader +// implements hostIDReader. type hostIDReaderWindows struct{} -// read reads MachineGuid from the windows registry key: -// SOFTWARE\Microsoft\Cryptography +// read reads MachineGuid from the Windows registry key: +// SOFTWARE\Microsoft\Cryptography. func (*hostIDReaderWindows) read() (string, error) { k, err := registry.OpenKey( registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Cryptography`, registry.QUERY_VALUE|registry.WOW64_64KEY, ) - if err != nil { return "", err } diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go b/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go index 5e3d199d78..a6a5a53c0e 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go @@ -17,7 +17,6 @@ import ( func platformOSDescription() (string, error) { k, err := registry.OpenKey( registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) - if err != nil { return "", err } diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go b/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go index 1d399a75db..ccc97e1b66 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go @@ -280,6 +280,7 @@ func (bsp *batchSpanProcessor) exportSpans(ctx context.Context) error { // // It is up to the exporter to implement any type of retry logic if a batch is failing // to be exported, since it is specific to the protocol and backend being sent to. + clear(bsp.batch) // Erase elements to let GC collect objects bsp.batch = bsp.batch[:0] if err != nil { @@ -316,7 +317,11 @@ func (bsp *batchSpanProcessor) processQueue() { bsp.batchMutex.Unlock() if shouldExport { if !bsp.timer.Stop() { - <-bsp.timer.C + // Handle both GODEBUG=asynctimerchan=[0|1] properly. + select { + case <-bsp.timer.C: + default: + } } if err := bsp.exportSpans(ctx); err != nil { otel.Handle(err) diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go b/vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go index 821c83faa1..8c308dd60a 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go @@ -12,25 +12,26 @@ import ( // evictedQueue is a FIFO queue with a configurable capacity. type evictedQueue[T any] struct { - queue []T - capacity int - droppedCount int - logDropped func() + queue []T + capacity int + droppedCount int + logDroppedMsg string + logDroppedOnce sync.Once } func newEvictedQueueEvent(capacity int) evictedQueue[Event] { // Do not pre-allocate queue, do this lazily. return evictedQueue[Event]{ - capacity: capacity, - logDropped: sync.OnceFunc(func() { global.Warn("limit reached: dropping trace trace.Event") }), + capacity: capacity, + logDroppedMsg: "limit reached: dropping trace trace.Event", } } func newEvictedQueueLink(capacity int) evictedQueue[Link] { // Do not pre-allocate queue, do this lazily. return evictedQueue[Link]{ - capacity: capacity, - logDropped: sync.OnceFunc(func() { global.Warn("limit reached: dropping trace trace.Link") }), + capacity: capacity, + logDroppedMsg: "limit reached: dropping trace trace.Link", } } @@ -53,6 +54,10 @@ func (eq *evictedQueue[T]) add(value T) { eq.queue = append(eq.queue, value) } +func (eq *evictedQueue[T]) logDropped() { + eq.logDroppedOnce.Do(func() { global.Warn(eq.logDroppedMsg) }) +} + // copy returns a copy of the evictedQueue. func (eq *evictedQueue[T]) copy() []T { return slices.Clone(eq.queue) diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go b/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go index 14c2e5bebd..185aa7c08f 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go @@ -139,9 +139,10 @@ func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T name = defaultTracerName } is := instrumentation.Scope{ - Name: name, - Version: c.InstrumentationVersion(), - SchemaURL: c.SchemaURL(), + Name: name, + Version: c.InstrumentationVersion(), + SchemaURL: c.SchemaURL(), + Attributes: c.InstrumentationAttributes(), } t, ok := func() (trace.Tracer, bool) { @@ -168,7 +169,7 @@ func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T // slowing down all tracing consumers. // - Logging code may be instrumented with tracing and deadlock because it could try // acquiring the same non-reentrant mutex. - global.Info("Tracer created", "name", name, "version", is.Version, "schemaURL", is.SchemaURL) + global.Info("Tracer created", "name", name, "version", is.Version, "schemaURL", is.SchemaURL, "attributes", is.Attributes) } return t } diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/span.go b/vendor/go.opentelemetry.io/otel/sdk/trace/span.go index 4945f50830..17f883c2c8 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/span.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/span.go @@ -174,6 +174,17 @@ func (s *recordingSpan) IsRecording() bool { s.mu.Lock() defer s.mu.Unlock() + return s.isRecording() +} + +// isRecording returns if this span is being recorded. If this span has ended +// this will return false. +// +// This method assumes s.mu.Lock is held by the caller. +func (s *recordingSpan) isRecording() bool { + if s == nil { + return false + } return s.endTime.IsZero() } @@ -182,11 +193,15 @@ func (s *recordingSpan) IsRecording() bool { // included in the set status when the code is for an error. If this span is // not being recorded than this method does nothing. func (s *recordingSpan) SetStatus(code codes.Code, description string) { - if !s.IsRecording() { + if s == nil { return } + s.mu.Lock() defer s.mu.Unlock() + if !s.isRecording() { + return + } if s.status.Code > code { return } @@ -210,12 +225,15 @@ func (s *recordingSpan) SetStatus(code codes.Code, description string) { // attributes the span is configured to have, the last added attributes will // be dropped. func (s *recordingSpan) SetAttributes(attributes ...attribute.KeyValue) { - if !s.IsRecording() { + if s == nil || len(attributes) == 0 { return } s.mu.Lock() defer s.mu.Unlock() + if !s.isRecording() { + return + } limit := s.tracer.provider.spanLimits.AttributeCountLimit if limit == 0 { @@ -233,7 +251,7 @@ func (s *recordingSpan) SetAttributes(attributes ...attribute.KeyValue) { // Otherwise, add without deduplication. When attributes are read they // will be deduplicated, optimizing the operation. - s.attributes = slices.Grow(s.attributes, len(s.attributes)+len(attributes)) + s.attributes = slices.Grow(s.attributes, len(attributes)) for _, a := range attributes { if !a.Valid() { // Drop all invalid attributes. @@ -280,13 +298,17 @@ func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) { // Do not set a capacity when creating this map. Benchmark testing has // showed this to only add unused memory allocations in general use. - exists := make(map[attribute.Key]int) - s.dedupeAttrsFromRecord(&exists) + exists := make(map[attribute.Key]int, len(s.attributes)) + s.dedupeAttrsFromRecord(exists) // Now that s.attributes is deduplicated, adding unique attributes up to // the capacity of s will not over allocate s.attributes. - sum := len(attrs) + len(s.attributes) - s.attributes = slices.Grow(s.attributes, min(sum, limit)) + + // max size = limit + maxCap := min(len(attrs)+len(s.attributes), limit) + if cap(s.attributes) < maxCap { + s.attributes = slices.Grow(s.attributes, maxCap-cap(s.attributes)) + } for _, a := range attrs { if !a.Valid() { // Drop all invalid attributes. @@ -296,6 +318,7 @@ func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) { if idx, ok := exists[a.Key]; ok { // Perform all updates before dropping, even when at capacity. + a = truncateAttr(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a) s.attributes[idx] = a continue } @@ -386,9 +409,10 @@ func (s *recordingSpan) End(options ...trace.SpanEndOption) { // the span's duration in case some operation below takes a while. et := monotonicEndTime(s.startTime) - // Do relative expensive check now that we have an end time and see if we - // need to do any more processing. - if !s.IsRecording() { + // Lock the span now that we have an end time and see if we need to do any more processing. + s.mu.Lock() + if !s.isRecording() { + s.mu.Unlock() return } @@ -413,10 +437,11 @@ func (s *recordingSpan) End(options ...trace.SpanEndOption) { } if s.executionTracerTaskEnd != nil { + s.mu.Unlock() s.executionTracerTaskEnd() + s.mu.Lock() } - s.mu.Lock() // Setting endTime to non-zero marks the span as ended and not recording. if config.Timestamp().IsZero() { s.endTime = et @@ -450,7 +475,13 @@ func monotonicEndTime(start time.Time) time.Time { // does not change the Span status. If this span is not being recorded or err is nil // than this method does nothing. func (s *recordingSpan) RecordError(err error, opts ...trace.EventOption) { - if s == nil || err == nil || !s.IsRecording() { + if s == nil || err == nil { + return + } + + s.mu.Lock() + defer s.mu.Unlock() + if !s.isRecording() { return } @@ -486,14 +517,23 @@ func recordStackTrace() string { } // AddEvent adds an event with the provided name and options. If this span is -// not being recorded than this method does nothing. +// not being recorded then this method does nothing. func (s *recordingSpan) AddEvent(name string, o ...trace.EventOption) { - if !s.IsRecording() { + if s == nil { + return + } + + s.mu.Lock() + defer s.mu.Unlock() + if !s.isRecording() { return } s.addEvent(name, o...) } +// addEvent adds an event with the provided name and options. +// +// This method assumes s.mu.Lock is held by the caller. func (s *recordingSpan) addEvent(name string, o ...trace.EventOption) { c := trace.NewEventConfig(o...) e := Event{Name: name, Attributes: c.Attributes(), Time: c.Timestamp()} @@ -510,20 +550,21 @@ func (s *recordingSpan) addEvent(name string, o ...trace.EventOption) { e.Attributes = e.Attributes[:limit] } - s.mu.Lock() s.events.add(e) - s.mu.Unlock() } // SetName sets the name of this span. If this span is not being recorded than // this method does nothing. func (s *recordingSpan) SetName(name string) { - if !s.IsRecording() { + if s == nil { return } s.mu.Lock() defer s.mu.Unlock() + if !s.isRecording() { + return + } s.name = name } @@ -579,29 +620,26 @@ func (s *recordingSpan) Attributes() []attribute.KeyValue { func (s *recordingSpan) dedupeAttrs() { // Do not set a capacity when creating this map. Benchmark testing has // showed this to only add unused memory allocations in general use. - exists := make(map[attribute.Key]int) - s.dedupeAttrsFromRecord(&exists) + exists := make(map[attribute.Key]int, len(s.attributes)) + s.dedupeAttrsFromRecord(exists) } // dedupeAttrsFromRecord deduplicates the attributes of s to fit capacity // using record as the record of unique attribute keys to their index. // // This method assumes s.mu.Lock is held by the caller. -func (s *recordingSpan) dedupeAttrsFromRecord(record *map[attribute.Key]int) { +func (s *recordingSpan) dedupeAttrsFromRecord(record map[attribute.Key]int) { // Use the fact that slices share the same backing array. unique := s.attributes[:0] for _, a := range s.attributes { - if idx, ok := (*record)[a.Key]; ok { + if idx, ok := record[a.Key]; ok { unique[idx] = a } else { unique = append(unique, a) - (*record)[a.Key] = len(unique) - 1 + record[a.Key] = len(unique) - 1 } } - // s.attributes have element types of attribute.KeyValue. These types are - // not pointers and they themselves do not contain pointer fields, - // therefore the duplicate values do not need to be zeroed for them to be - // garbage collected. + clear(s.attributes[len(unique):]) // Erase unneeded elements to let GC collect objects. s.attributes = unique } @@ -657,7 +695,7 @@ func (s *recordingSpan) Resource() *resource.Resource { } func (s *recordingSpan) AddLink(link trace.Link) { - if !s.IsRecording() { + if s == nil { return } if !link.SpanContext.IsValid() && len(link.Attributes) == 0 && @@ -665,6 +703,12 @@ func (s *recordingSpan) AddLink(link trace.Link) { return } + s.mu.Lock() + defer s.mu.Unlock() + if !s.isRecording() { + return + } + l := Link{SpanContext: link.SpanContext, Attributes: link.Attributes} // Discard attributes over limit. @@ -678,9 +722,7 @@ func (s *recordingSpan) AddLink(link trace.Link) { l.Attributes = l.Attributes[:limit] } - s.mu.Lock() s.links.add(l) - s.mu.Unlock() } // DroppedAttributes returns the number of attributes dropped by the span @@ -755,12 +797,16 @@ func (s *recordingSpan) snapshot() ReadOnlySpan { } func (s *recordingSpan) addChild() { - if !s.IsRecording() { + if s == nil { return } + s.mu.Lock() + defer s.mu.Unlock() + if !s.isRecording() { + return + } s.childSpanCount++ - s.mu.Unlock() } func (*recordingSpan) private() {} diff --git a/vendor/go.opentelemetry.io/otel/sdk/version.go b/vendor/go.opentelemetry.io/otel/sdk/version.go index b7cede891c..0b214d3fe9 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/version.go +++ b/vendor/go.opentelemetry.io/otel/sdk/version.go @@ -5,5 +5,5 @@ package sdk // import "go.opentelemetry.io/otel/sdk" // Version is the current release version of the OpenTelemetry SDK in use. func Version() string { - return "1.29.0" + return "1.32.0" } diff --git a/vendor/go.opentelemetry.io/otel/version.go b/vendor/go.opentelemetry.io/otel/version.go index 6d3c7b1f40..59e2481613 100644 --- a/vendor/go.opentelemetry.io/otel/version.go +++ b/vendor/go.opentelemetry.io/otel/version.go @@ -5,5 +5,5 @@ package otel // import "go.opentelemetry.io/otel" // Version is the current release version of OpenTelemetry in use. func Version() string { - return "1.31.0" + return "1.32.0" } diff --git a/vendor/go.opentelemetry.io/otel/versions.yaml b/vendor/go.opentelemetry.io/otel/versions.yaml index cdebdb5eb7..c04b12f6b7 100644 --- a/vendor/go.opentelemetry.io/otel/versions.yaml +++ b/vendor/go.opentelemetry.io/otel/versions.yaml @@ -3,19 +3,13 @@ module-sets: stable-v1: - version: v1.31.0 + version: v1.32.0 modules: - go.opentelemetry.io/otel - go.opentelemetry.io/otel/bridge/opencensus - go.opentelemetry.io/otel/bridge/opencensus/test - go.opentelemetry.io/otel/bridge/opentracing - go.opentelemetry.io/otel/bridge/opentracing/test - - go.opentelemetry.io/otel/example/dice - - go.opentelemetry.io/otel/example/namedtracer - - go.opentelemetry.io/otel/example/opencensus - - go.opentelemetry.io/otel/example/otel-collector - - go.opentelemetry.io/otel/example/passthrough - - go.opentelemetry.io/otel/example/zipkin - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp - go.opentelemetry.io/otel/exporters/otlp/otlptrace @@ -29,12 +23,11 @@ module-sets: - go.opentelemetry.io/otel/sdk/metric - go.opentelemetry.io/otel/trace experimental-metrics: - version: v0.53.0 + version: v0.54.0 modules: - - go.opentelemetry.io/otel/example/prometheus - go.opentelemetry.io/otel/exporters/prometheus experimental-logs: - version: v0.7.0 + version: v0.8.0 modules: - go.opentelemetry.io/otel/log - go.opentelemetry.io/otel/sdk/log @@ -42,7 +35,7 @@ module-sets: - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp - go.opentelemetry.io/otel/exporters/stdout/stdoutlog experimental-schema: - version: v0.0.10 + version: v0.0.11 modules: - go.opentelemetry.io/otel/schema excluded-modules: diff --git a/vendor/modules.txt b/vendor/modules.txt index 2bc8054178..552383d467 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -244,7 +244,7 @@ github.com/google/uuid ## explicit; go 1.20 github.com/gopacket/gopacket github.com/gopacket/gopacket/layers -# github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 +# github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 ## explicit; go 1.21 github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule github.com/grpc-ecosystem/grpc-gateway/v2/runtime @@ -267,8 +267,8 @@ github.com/jpillora/backoff # github.com/json-iterator/go v1.1.12 ## explicit; go 1.12 github.com/json-iterator/go -# github.com/klauspost/compress v1.17.9 -## explicit; go 1.20 +# github.com/klauspost/compress v1.17.11 +## explicit; go 1.21 github.com/klauspost/compress github.com/klauspost/compress/flate github.com/klauspost/compress/fse @@ -298,8 +298,8 @@ github.com/mdlayher/ethernet # github.com/minio/md5-simd v1.1.2 ## explicit; go 1.14 github.com/minio/md5-simd -# github.com/minio/minio-go/v7 v7.0.77 -## explicit; go 1.21 +# github.com/minio/minio-go/v7 v7.0.82 +## explicit; go 1.22 github.com/minio/minio-go/v7 github.com/minio/minio-go/v7/pkg/cors github.com/minio/minio-go/v7/pkg/credentials @@ -327,7 +327,7 @@ github.com/munnerz/goautoneg # github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f ## explicit github.com/mwitkow/go-conntrack -# github.com/netobserv/flowlogs-pipeline v1.7.0-community.0.20241126155124-18e017f67001 +# github.com/netobserv/flowlogs-pipeline v1.7.0-community.0.20241217113023-fa0540a1658e ## explicit; go 1.22.3 github.com/netobserv/flowlogs-pipeline/pkg/api github.com/netobserv/flowlogs-pipeline/pkg/config @@ -369,7 +369,7 @@ github.com/netobserv/loki-client-go/pkg/labelutil github.com/netobserv/loki-client-go/pkg/logproto github.com/netobserv/loki-client-go/pkg/metric github.com/netobserv/loki-client-go/pkg/urlutil -# github.com/netobserv/netobserv-ebpf-agent v1.6.1-crc2.0.20241008130234-a20397fb8f88 => github.com/msherif1234/netobserv-ebpf-agent v0.0.0-20241213142900-5c07db3a6c0b +# github.com/netobserv/netobserv-ebpf-agent v1.7.0-community.0.20250122180127-fa88f3515234 ## explicit; go 1.22.3 github.com/netobserv/netobserv-ebpf-agent/pkg/agent github.com/netobserv/netobserv-ebpf-agent/pkg/decode @@ -460,7 +460,7 @@ github.com/ovn-org/libovsdb/model github.com/ovn-org/libovsdb/ovsdb github.com/ovn-org/libovsdb/ovsdb/serverdb github.com/ovn-org/libovsdb/updates -# github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20241126140656-c95491e46334 +# github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20250116185920-20e7a0e40c93 ## explicit; go 1.22.0 github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/model github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/ovsdb @@ -674,7 +674,7 @@ github.com/xrash/smetrics go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil -# go.opentelemetry.io/otel v1.31.0 +# go.opentelemetry.io/otel v1.32.0 ## explicit; go 1.22 go.opentelemetry.io/otel go.opentelemetry.io/otel/attribute @@ -690,8 +690,8 @@ go.opentelemetry.io/otel/semconv/v1.20.0 go.opentelemetry.io/otel/semconv/v1.21.0 go.opentelemetry.io/otel/semconv/v1.24.0 go.opentelemetry.io/otel/semconv/v1.26.0 -# go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 -## explicit; go 1.21 +# go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 +## explicit; go 1.22 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/envconfig @@ -724,28 +724,28 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry -# go.opentelemetry.io/otel/metric v1.31.0 +# go.opentelemetry.io/otel/metric v1.32.0 ## explicit; go 1.22 go.opentelemetry.io/otel/metric go.opentelemetry.io/otel/metric/embedded go.opentelemetry.io/otel/metric/noop -# go.opentelemetry.io/otel/sdk v1.29.0 -## explicit; go 1.21 +# go.opentelemetry.io/otel/sdk v1.32.0 +## explicit; go 1.22 go.opentelemetry.io/otel/sdk go.opentelemetry.io/otel/sdk/instrumentation go.opentelemetry.io/otel/sdk/internal/env go.opentelemetry.io/otel/sdk/internal/x go.opentelemetry.io/otel/sdk/resource go.opentelemetry.io/otel/sdk/trace -# go.opentelemetry.io/otel/sdk/metric v1.29.0 -## explicit; go 1.21 +# go.opentelemetry.io/otel/sdk/metric v1.32.0 +## explicit; go 1.22 go.opentelemetry.io/otel/sdk/metric +go.opentelemetry.io/otel/sdk/metric/exemplar go.opentelemetry.io/otel/sdk/metric/internal go.opentelemetry.io/otel/sdk/metric/internal/aggregate -go.opentelemetry.io/otel/sdk/metric/internal/exemplar go.opentelemetry.io/otel/sdk/metric/internal/x go.opentelemetry.io/otel/sdk/metric/metricdata -# go.opentelemetry.io/otel/trace v1.31.0 +# go.opentelemetry.io/otel/trace v1.32.0 ## explicit; go 1.22 go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace/embedded @@ -862,11 +862,11 @@ golang.org/x/tools/go/ast/inspector # gomodules.xyz/jsonpatch/v2 v2.4.0 ## explicit; go 1.20 gomodules.xyz/jsonpatch/v2 -# google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 +# google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 ## explicit; go 1.21 google.golang.org/genproto/googleapis/api/expr/v1alpha1 google.golang.org/genproto/googleapis/api/httpbody -# google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 +# google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 ## explicit; go 1.21 google.golang.org/genproto/googleapis/rpc/errdetails google.golang.org/genproto/googleapis/rpc/status @@ -1661,4 +1661,3 @@ sigs.k8s.io/structured-merge-diff/v4/value ## explicit; go 1.12 sigs.k8s.io/yaml sigs.k8s.io/yaml/goyaml.v2 -# github.com/netobserv/netobserv-ebpf-agent => github.com/msherif1234/netobserv-ebpf-agent v0.0.0-20241213142900-5c07db3a6c0b
  • %CUJ|nP23^w##z1} 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 diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_x86_bpfel.go b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_x86_bpfel.go index a5839acdd8..3fe7112084 100644 --- a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_x86_bpfel.go +++ b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_x86_bpfel.go @@ -13,14 +13,19 @@ import ( ) type BpfAdditionalMetrics struct { + StartMonoTimeTs uint64 + EndMonoTimeTs uint64 DnsRecord BpfDnsRecordT PktDrops BpfPktDropsT FlowRtt uint64 - NetworkEventsIdx uint8 NetworkEvents [4][8]uint8 - _ [1]byte TranslatedFlow BpfTranslatedFlowT - _ [6]byte + _ [2]byte + ObservedIntf [4]BpfObservedIntfT + EthProtocol uint16 + NetworkEventsIdx uint8 + NbObservedIntf uint8 + _ [4]byte } type BpfDirectionT uint32 @@ -42,12 +47,11 @@ type BpfDnsFlowId struct { } type BpfDnsRecordT struct { + Latency uint64 Id uint16 Flags uint16 - _ [4]byte - Latency uint64 Errno uint8 - _ [7]byte + _ [3]byte } type BpfFilterActionT uint32 @@ -64,61 +68,63 @@ type BpfFilterKeyT struct { } type BpfFilterValueT struct { - Protocol uint8 - DstPortStart uint16 - DstPortEnd uint16 - DstPort1 uint16 - DstPort2 uint16 - SrcPortStart uint16 - SrcPortEnd uint16 - SrcPort1 uint16 - SrcPort2 uint16 - PortStart uint16 - PortEnd uint16 - Port1 uint16 - Port2 uint16 - IcmpType uint8 - IcmpCode uint8 - Direction BpfDirectionT - Action BpfFilterActionT - TcpFlags BpfTcpFlagsT - FilterDrops uint8 - Sample uint32 - Ip [16]uint8 + Protocol uint8 + _ [1]byte + DstPortStart uint16 + DstPortEnd uint16 + DstPort1 uint16 + DstPort2 uint16 + SrcPortStart uint16 + SrcPortEnd uint16 + SrcPort1 uint16 + SrcPort2 uint16 + PortStart uint16 + PortEnd uint16 + Port1 uint16 + Port2 uint16 + IcmpType uint8 + IcmpCode uint8 + Direction BpfDirectionT + Action BpfFilterActionT + TcpFlags BpfTcpFlagsT + FilterDrops uint8 + _ [3]byte + Sample uint32 + DoPeerCIDR_lookup uint8 + _ [3]byte } type BpfFlowId BpfFlowIdT type BpfFlowIdT struct { - Direction uint8 SrcIp [16]uint8 DstIp [16]uint8 - _ [1]byte SrcPort uint16 DstPort uint16 TransportProtocol uint8 IcmpType uint8 IcmpCode uint8 - _ [3]byte - IfIndex uint32 + _ [1]byte } type BpfFlowMetrics BpfFlowMetricsT type BpfFlowMetricsT struct { - Lock struct{ Val uint32 } - EthProtocol uint16 - SrcMac [6]uint8 - DstMac [6]uint8 - _ [2]byte - Packets uint32 - Bytes uint64 - StartMonoTimeTs uint64 - EndMonoTimeTs uint64 - Flags uint16 - Errno uint8 - Dscp uint8 - Sampling uint32 + StartMonoTimeTs uint64 + EndMonoTimeTs uint64 + Bytes uint64 + Packets uint32 + EthProtocol uint16 + Flags uint16 + SrcMac [6]uint8 + DstMac [6]uint8 + IfIndexFirstSeen uint32 + Lock struct{ Val uint32 } + Sampling uint32 + DirectionFirstSeen uint8 + Errno uint8 + Dscp uint8 + _ [5]byte } type BpfFlowRecordT struct { @@ -138,17 +144,23 @@ const ( BpfGlobalCountersKeyTNETWORK_EVENTS_ERR_GROUPID_MISMATCH BpfGlobalCountersKeyT = 6 BpfGlobalCountersKeyTNETWORK_EVENTS_ERR_UPDATE_MAP_FLOWS BpfGlobalCountersKeyT = 7 BpfGlobalCountersKeyTNETWORK_EVENTS_GOOD BpfGlobalCountersKeyT = 8 - BpfGlobalCountersKeyTMAX_COUNTERS BpfGlobalCountersKeyT = 9 + BpfGlobalCountersKeyTOBSERVED_INTF_MISSED BpfGlobalCountersKeyT = 9 + BpfGlobalCountersKeyTMAX_COUNTERS BpfGlobalCountersKeyT = 10 ) +type BpfObservedIntfT struct { + Direction uint8 + _ [3]byte + IfIndex uint32 +} + type BpfPktDropsT struct { - Packets uint32 - _ [4]byte Bytes uint64 + Packets uint32 + LatestDropCause uint32 LatestFlags uint16 LatestState uint8 - _ [1]byte - LatestDropCause uint32 + _ [5]byte } type BpfTcpFlagsT uint32 @@ -173,8 +185,6 @@ type BpfTranslatedFlowT struct { Sport uint16 Dport uint16 ZoneId uint16 - IcmpId uint8 - _ [1]byte } // LoadBpf returns the embedded CollectionSpec for Bpf. @@ -244,6 +254,7 @@ type BpfMapSpecs struct { FilterMap *ebpf.MapSpec `ebpf:"filter_map"` GlobalCounters *ebpf.MapSpec `ebpf:"global_counters"` PacketRecord *ebpf.MapSpec `ebpf:"packet_record"` + PeerFilterMap *ebpf.MapSpec `ebpf:"peer_filter_map"` } // BpfObjects contains all objects after they have been loaded into the kernel. @@ -272,6 +283,7 @@ type BpfMaps struct { FilterMap *ebpf.Map `ebpf:"filter_map"` GlobalCounters *ebpf.Map `ebpf:"global_counters"` PacketRecord *ebpf.Map `ebpf:"packet_record"` + PeerFilterMap *ebpf.Map `ebpf:"peer_filter_map"` } func (m *BpfMaps) Close() error { @@ -283,6 +295,7 @@ func (m *BpfMaps) Close() error { m.FilterMap, m.GlobalCounters, m.PacketRecord, + m.PeerFilterMap, ) } diff --git a/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_x86_bpfel.o b/vendor/github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf/bpf_x86_bpfel.o index 9399eaff32c6d2196412ef7f52ff351045ff211c..aa3039e88f3411a8624533837cf3982361183342 100644 GIT binary patch literal 293984 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 mlsiX8>e@cFZ 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