You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
4.4 KiB
118 lines
4.4 KiB
// Copyright 2020, VIXL authors
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
// and/or other materials provided with the distribution.
|
|
// * Neither the name of ARM Limited nor the names of its contributors may be
|
|
// used to endorse or promote products derived from this software without
|
|
// specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
|
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
#include "examples.h"
|
|
|
|
using namespace vixl;
|
|
using namespace vixl::aarch64;
|
|
|
|
#define __ masm->
|
|
|
|
// size_t sve_strlen(const char* str);
|
|
void GenerateSVEStrlen(MacroAssembler* masm) {
|
|
// We will accumulate the length as we load each chunk.
|
|
Register len = x1;
|
|
__ Mov(len, 0);
|
|
|
|
// We want to load as much as we can on each iteration, so set up an all-true
|
|
// predicate for that purpose.
|
|
PRegister all_true = p0;
|
|
__ Ptrue(all_true.VnB());
|
|
|
|
Label loop;
|
|
__ Bind(&loop);
|
|
// FFR is cumulative, so reset it to all-true for each iteration.
|
|
__ Setffr();
|
|
|
|
// Load as many characters as we can from &str[len]. We have to use a NF or FF
|
|
// load, because we don't know how long the string is. An FF load is a good
|
|
// choice, because we know that we will see at least a NULL termination, even
|
|
// for an empty string.
|
|
__ Ldff1b(z0.VnB(), all_true.Zeroing(), SVEMemOperand(x0, len));
|
|
// For example, if str = "Test string.", and we load every byte:
|
|
// z0.b: \0 . g n i r t s t s e T
|
|
|
|
// FFR now represents the number of bytes that we actually loaded, so use it
|
|
// to predicate the data processing instructions.
|
|
__ Rdffr(p1.VnB());
|
|
|
|
// Find the NULL termination (if there is one), and set the flags.
|
|
__ Cmpeq(p2.VnB(), p1.Zeroing(), z0.VnB(), 0);
|
|
// p2.b: 1 0 0 0 0 0 0 0 0 0 0 0 0
|
|
|
|
// Activate every lane up to (but not including) the NULL termination. If we
|
|
// found no NULL termination, this activates every lane, and indicates that we
|
|
// have to load another vector of characters. Lanes activated in this way
|
|
// represent string characters that we need to count.
|
|
__ Brkb(p1.VnB(), p1.Zeroing(), p2.VnB());
|
|
// p1.b: 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1
|
|
|
|
// Count the active lanes, and add them to the length count.
|
|
__ Incp(len, p1.VnB());
|
|
|
|
// Loop until `cmpeq` finds a NULL termination.
|
|
__ B(sve_none, &loop);
|
|
|
|
// Put the length in the AAPCS64 return register.
|
|
__ Mov(x0, len);
|
|
__ Ret();
|
|
}
|
|
|
|
#ifndef TEST_EXAMPLES
|
|
#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
|
|
int main(void) {
|
|
MacroAssembler masm;
|
|
Decoder decoder;
|
|
Simulator simulator(&decoder);
|
|
|
|
// We're running on the simulator, so we can assume that SVE is present.
|
|
masm.GetCPUFeatures()->Combine(CPUFeatures::kSVE);
|
|
|
|
// Generate the code for the example function.
|
|
Label sve_strlen;
|
|
masm.Bind(&sve_strlen);
|
|
GenerateSVEStrlen(&masm);
|
|
masm.FinalizeCode();
|
|
|
|
const char* example_input = "This is a string of exactly 42 characters.";
|
|
VIXL_ASSERT(strlen(example_input) == 42);
|
|
|
|
simulator.ResetState();
|
|
simulator.WriteXRegister(0, reinterpret_cast<uintptr_t>(example_input));
|
|
simulator.RunFrom(masm.GetLabelAddress<Instruction*>(&sve_strlen));
|
|
|
|
printf("strlen(\"%s\") == %" PRIu64 "\n",
|
|
example_input,
|
|
simulator.ReadXRegister(0));
|
|
|
|
return 0;
|
|
}
|
|
#else
|
|
// Without the simulator there is nothing to test.
|
|
int main(void) { return 0; }
|
|
#endif // VIXL_INCLUDE_SIMULATOR_AARCH64
|
|
#endif // TEST_EXAMPLES
|