diff options
author | armvixl <vixl@arm.com> | 2015-10-23 13:38:33 +0100 |
---|---|---|
committer | armvixl <vixl@arm.com> | 2015-10-23 13:38:33 +0100 |
commit | 684cd2a7f5845539b58d0da7e012e39df49ceff0 (patch) | |
tree | 9cc167c2cf3a42d44477bdf0f6d8f67bc479c2f2 | |
parent | db6443499376478f5281607a3923e6ffc4c8d8ec (diff) |
VIXL Release 1.11
Refer to the README.md and LICENCE files for details.
38 files changed, 812 insertions, 440 deletions
@@ -1,4 +1,4 @@ -VIXL: AArch64 Runtime Code Generation Library Version 1.10 +VIXL: AArch64 Runtime Code Generation Library Version 1.11 ========================================================== Contents: @@ -52,7 +52,7 @@ class TopLevelTargets: self.targets.append(target) self.help_messages.append(help_message) def Help(self): - res = "" + res = "" for i in range(len(self.targets)): res += '\t{0:<{1}}{2:<{3}}\n'.format( 'scons ' + self.targets[i], @@ -78,6 +78,7 @@ options = { '-Wextra', '-Wredundant-decls', '-pedantic', + '-Wmissing-noreturn', '-Wwrite-strings'], 'CPPPATH' : [config.dir_src_vixl] }, @@ -91,7 +92,7 @@ options = { 'CCFLAGS' : ['-O3'] }, 'simulator:on' : { - 'CCFLAGS' : ['-DUSE_SIMULATOR'], + 'CCFLAGS' : ['-DVIXL_INCLUDE_SIMULATOR'], }, 'symbols:on' : { 'CCFLAGS' : ['-g'], diff --git a/doc/changelog.md b/doc/changelog.md index 83a9c269..e3c4e2a6 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -1,6 +1,13 @@ VIXL Change Log =============== +* 1.11 + + Fix bug in simulation of add with carry. + + Fix use-after-free bug in Literal handling. + + Build system updates for Android. + + Add option to run test.py under Valgrind. + + Other small bug fixes and improvements. + * 1.10 + Improved support for externally managed literals. + Reworked build and test infrastructure. diff --git a/examples/abs.cc b/examples/abs.cc index 8d6d052c..634c375c 100644 --- a/examples/abs.cc +++ b/examples/abs.cc @@ -43,7 +43,7 @@ void GenerateAbs(MacroAssembler* masm) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { // Create and initialize the assembler and the simulator. byte assm_buf[BUF_SIZE]; @@ -68,5 +68,5 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/add2-vectors.cc b/examples/add2-vectors.cc index 47618552..4992708e 100644 --- a/examples/add2-vectors.cc +++ b/examples/add2-vectors.cc @@ -126,7 +126,7 @@ int main(void) { vecC[i] = vecA[i] + vecB[i]; } -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR uintptr_t vecA_addr = reinterpret_cast<uintptr_t>(vecA); uintptr_t vecB_addr = reinterpret_cast<uintptr_t>(vecB); @@ -148,7 +148,7 @@ int main(void) { // Placeholder to run test natively. printf("Running tests natively is not supported yet.\n"); return 0; -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR // Check that the computed value in NEON matches the C version. for (unsigned i = 0; i < ARRAY_SIZE(vecA); i++) { assert(vecC[i] == vecA[i]); diff --git a/examples/add3-double.cc b/examples/add3-double.cc index 460917ce..f14947f0 100644 --- a/examples/add3-double.cc +++ b/examples/add3-double.cc @@ -44,7 +44,7 @@ void GenerateAdd3Double(MacroAssembler* masm) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { // Create and initialize the assembler and the simulator. byte assm_buf[BUF_SIZE]; @@ -73,5 +73,5 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/add4-double.cc b/examples/add4-double.cc index 51addbba..ac259641 100644 --- a/examples/add4-double.cc +++ b/examples/add4-double.cc @@ -52,7 +52,7 @@ void GenerateAdd4Double(MacroAssembler* masm) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { // Create and initialize the assembler and the simulator. byte assm_buf[BUF_SIZE]; @@ -83,5 +83,5 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/check-bounds.cc b/examples/check-bounds.cc index 18622b24..635918e5 100644 --- a/examples/check-bounds.cc +++ b/examples/check-bounds.cc @@ -58,7 +58,7 @@ void GenerateCheckBounds(MacroAssembler* masm) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR void run_function(Simulator *simulator, Instruction * function, uint64_t value, uint64_t low, uint64_t high) { simulator->set_xreg(0, value); @@ -97,5 +97,5 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/crc-checksums.cc b/examples/crc-checksums.cc index e6fbb355..4fc9556b 100644 --- a/examples/crc-checksums.cc +++ b/examples/crc-checksums.cc @@ -77,7 +77,7 @@ void runExample(const char *msg) { GenerateCrc32(&masm); masm.FinalizeCode(); -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR // Run example function in the simulator. uintptr_t msg_addr = reinterpret_cast<uintptr_t>(msg); size_t msg_size = strlen(msg); @@ -91,7 +91,7 @@ void runExample(const char *msg) { // Run example function natively. printf("Not yet implemented.\n"); USE(msg); -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR } diff --git a/examples/debugger.cc b/examples/debugger.cc index 3a6db63e..db56f2d2 100644 --- a/examples/debugger.cc +++ b/examples/debugger.cc @@ -49,7 +49,7 @@ void GenerateBreak(MacroAssembler* masm) { } -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { // Create and initialize the assembler and the debugger. byte assm_buf[BUF_SIZE]; @@ -72,5 +72,5 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/factorial-rec.cc b/examples/factorial-rec.cc index ee07ef74..5d1e5df3 100644 --- a/examples/factorial-rec.cc +++ b/examples/factorial-rec.cc @@ -55,7 +55,7 @@ void GenerateFactorialRec(MacroAssembler* masm) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { // Create and initialize the assembler and the simulator. byte assm_buf[BUF_SIZE]; @@ -80,5 +80,5 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/factorial.cc b/examples/factorial.cc index 78d4c5f4..9df65f1e 100644 --- a/examples/factorial.cc +++ b/examples/factorial.cc @@ -53,7 +53,7 @@ void GenerateFactorial(MacroAssembler* masm) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { // Create and initialize the assembler and the simulator. byte assm_buf[BUF_SIZE]; @@ -78,5 +78,5 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/getting-started.cc b/examples/getting-started.cc index 0987429c..6cd8bba2 100644 --- a/examples/getting-started.cc +++ b/examples/getting-started.cc @@ -41,7 +41,7 @@ void GenerateDemoFunction(MacroAssembler *masm) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main() { byte assm_buf[BUF_SIZE]; MacroAssembler masm(assm_buf, BUF_SIZE); @@ -62,5 +62,5 @@ int main() { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/literal.cc b/examples/literal.cc index e7d475d5..02de7efc 100644 --- a/examples/literal.cc +++ b/examples/literal.cc @@ -29,7 +29,7 @@ #define BASE_BUF_SIZE (4096) #define __ masm. -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int64_t LiteralExample(int64_t a, int64_t b) { // Create and initialize the macro-assembler and the simulator. MacroAssembler masm(BASE_BUF_SIZE); @@ -85,13 +85,13 @@ int64_t LiteralExample(int64_t a, int64_t b) { #endif #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { - LiteralExample(1, 2); + VIXL_CHECK(LiteralExample(1, 2) == 3); return 0; } #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/neon-matrix-multiply.cc b/examples/neon-matrix-multiply.cc index 6a271508..26193396 100644 --- a/examples/neon-matrix-multiply.cc +++ b/examples/neon-matrix-multiply.cc @@ -95,7 +95,7 @@ void GenerateNEONMatrixMultiply(MacroAssembler* masm) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { // Create and initialize the assembler and the simulator. byte assm_buf[BUF_SIZE]; @@ -164,5 +164,5 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/non-const-visitor.cc b/examples/non-const-visitor.cc index bd022392..a616f12c 100644 --- a/examples/non-const-visitor.cc +++ b/examples/non-const-visitor.cc @@ -43,7 +43,7 @@ void GenerateNonConstVisitorTestCode(MacroAssembler* masm) { int64_t RunNonConstVisitorTestGeneratedCode(const Instruction* start_instr) { -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR Decoder simulator_decoder; Simulator simulator(&simulator_decoder); @@ -65,7 +65,7 @@ int64_t RunNonConstVisitorTestGeneratedCode(const Instruction* start_instr) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { // Create and initialize the assembler. byte assm_buf[BUF_SIZE]; @@ -110,7 +110,7 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/sum-array.cc b/examples/sum-array.cc index 03f41d45..88039623 100644 --- a/examples/sum-array.cc +++ b/examples/sum-array.cc @@ -59,7 +59,7 @@ void GenerateSumArray(MacroAssembler* masm) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { // Create and initialize the assembler and the simulator. byte assm_buf[BUF_SIZE]; @@ -91,5 +91,5 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/swap-int32.cc b/examples/swap-int32.cc index 29074cad..0ea24352 100644 --- a/examples/swap-int32.cc +++ b/examples/swap-int32.cc @@ -61,7 +61,7 @@ void GenerateSwapInt32(MacroAssembler* masm) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { // Create and initialize the assembler and the simulator. byte assm_buf[BUF_SIZE]; @@ -96,5 +96,5 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/examples/swap4.cc b/examples/swap4.cc index 132df940..808b148c 100644 --- a/examples/swap4.cc +++ b/examples/swap4.cc @@ -47,7 +47,7 @@ void GenerateSwap4(MacroAssembler* masm) { #ifndef TEST_EXAMPLES -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR int main(void) { // Create and initialize the assembler and the simulator. byte assm_buf[BUF_SIZE]; @@ -90,5 +90,5 @@ int main(void) { #else // Without the simulator there is nothing to test. int main(void) { return 0; } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR #endif // TEST_EXAMPLES diff --git a/src/vixl/a64/debugger-a64.cc b/src/vixl/a64/debugger-a64.cc index 5f5b36ca..359e51b2 100644 --- a/src/vixl/a64/debugger-a64.cc +++ b/src/vixl/a64/debugger-a64.cc @@ -24,7 +24,7 @@ // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR #include "vixl/a64/debugger-a64.h" @@ -55,7 +55,7 @@ class Token { virtual bool IsUnknown() const { return false; } // Token properties. virtual bool CanAddressMemory() const { return false; } - virtual uint8_t* ToAddress(Debugger* debugger) const; + virtual uint8_t* ToAddress(Debugger* debugger) const = 0; virtual void Print(FILE* out = stdout) const = 0; static Token* Tokenize(const char* arg); @@ -69,6 +69,11 @@ template<typename T> class ValueToken : public Token { T value() const { return value_; } + VIXL_NO_RETURN virtual uint8_t* ToAddress(Debugger* debugger) const { + USE(debugger); + VIXL_ABORT(); + } + protected: T value_; }; @@ -194,6 +199,11 @@ class FormatToken : public Token { virtual void PrintData(void* data, FILE* out = stdout) const = 0; virtual void Print(FILE* out = stdout) const = 0; + VIXL_NO_RETURN virtual uint8_t* ToAddress(Debugger* debugger) const { + USE(debugger); + VIXL_ABORT(); + } + static Token* Tokenize(const char* arg); static FormatToken* Cast(Token* tok) { VIXL_ASSERT(tok->IsFormat()); @@ -229,6 +239,10 @@ class UnknownToken : public Token { strncpy(unknown_, arg, size); } virtual ~UnknownToken() { delete[] unknown_; } + VIXL_NO_RETURN virtual uint8_t* ToAddress(Debugger* debugger) const { + USE(debugger); + VIXL_ABORT(); + } virtual bool IsUnknown() const { return true; } virtual void Print(FILE* out = stdout) const; @@ -788,13 +802,6 @@ static bool StringToInt64(int64_t* value, const char* line, int base = 10) { } -uint8_t* Token::ToAddress(Debugger* debugger) const { - USE(debugger); - VIXL_UNREACHABLE(); - return NULL; -} - - Token* Token::Tokenize(const char* arg) { if ((arg == NULL) || (*arg == '\0')) { return NULL; @@ -1516,4 +1523,4 @@ bool InvalidCommand::Run(Debugger* debugger) { } // namespace vixl -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR diff --git a/src/vixl/a64/debugger-a64.h b/src/vixl/a64/debugger-a64.h index 0be170f2..16394f13 100644 --- a/src/vixl/a64/debugger-a64.h +++ b/src/vixl/a64/debugger-a64.h @@ -24,6 +24,8 @@ // 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. +#ifdef VIXL_INCLUDE_SIMULATOR + #ifndef VIXL_A64_DEBUGGER_A64_H_ #define VIXL_A64_DEBUGGER_A64_H_ @@ -112,3 +114,5 @@ class Debugger : public Simulator { } // namespace vixl #endif // VIXL_A64_DEBUGGER_A64_H_ + +#endif // VIXL_INCLUDE_SIMULATOR diff --git a/src/vixl/a64/decoder-a64.h b/src/vixl/a64/decoder-a64.h index 4f4f19c6..b3f04f68 100644 --- a/src/vixl/a64/decoder-a64.h +++ b/src/vixl/a64/decoder-a64.h @@ -35,7 +35,7 @@ // List macro containing all visitors needed by the decoder class. -#define VISITOR_LIST(V) \ +#define VISITOR_LIST_THAT_RETURN(V) \ V(PCRelAddressing) \ V(AddSubImmediate) \ V(LogicalImmediate) \ @@ -104,8 +104,14 @@ V(NEONShiftImmediate) \ V(NEONTable) \ V(NEONPerm) \ - V(Unallocated) \ - V(Unimplemented) + +#define VISITOR_LIST_THAT_DONT_RETURN(V) \ + V(Unallocated) \ + V(Unimplemented) \ + +#define VISITOR_LIST(V) \ + VISITOR_LIST_THAT_RETURN(V) \ + VISITOR_LIST_THAT_DONT_RETURN(V) \ namespace vixl { diff --git a/src/vixl/a64/instrument-a64.cc b/src/vixl/a64/instrument-a64.cc index 21ec6041..7de12559 100644 --- a/src/vixl/a64/instrument-a64.cc +++ b/src/vixl/a64/instrument-a64.cc @@ -169,7 +169,8 @@ void Instrument::Update() { VIXL_ASSERT(counter->type() == Cumulative); counter->Increment(); - if (counter->IsEnabled() && (counter->count() % sample_period_) == 0) { + if ((sample_period_ != 0) && counter->IsEnabled() + && (counter->count() % sample_period_) == 0) { DumpCounters(); } } diff --git a/src/vixl/a64/instrument-a64.h b/src/vixl/a64/instrument-a64.h index 8468ceb6..e1da5b3b 100644 --- a/src/vixl/a64/instrument-a64.h +++ b/src/vixl/a64/instrument-a64.h @@ -99,6 +99,10 @@ class Instrument: public DecoderVisitor { std::list<Counter*> counters_; FILE *output_stream_; + + // Counter information is dumped every sample_period_ instructions decoded. + // For a sample_period_ = 0 a final counter value is only produced when the + // Instrumentation class is destroyed. uint64_t sample_period_; }; diff --git a/src/vixl/a64/logic-a64.cc b/src/vixl/a64/logic-a64.cc index 5ee62ade..3bccb6ea 100644 --- a/src/vixl/a64/logic-a64.cc +++ b/src/vixl/a64/logic-a64.cc @@ -24,6 +24,8 @@ // 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. +#ifdef VIXL_INCLUDE_SIMULATOR + #include <cmath> #include "vixl/a64/simulator-a64.h" @@ -4871,3 +4873,5 @@ LogicVRegister Simulator::ucvtf(VectorFormat vform, } // namespace vixl + +#endif // VIXL_INCLUDE_SIMULATOR diff --git a/src/vixl/a64/macro-assembler-a64.cc b/src/vixl/a64/macro-assembler-a64.cc index 25d222f1..44f0f0d0 100644 --- a/src/vixl/a64/macro-assembler-a64.cc +++ b/src/vixl/a64/macro-assembler-a64.cc @@ -24,6 +24,8 @@ // 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 <ctype.h> + #include "vixl/a64/macro-assembler-a64.h" namespace vixl { @@ -287,6 +289,7 @@ MacroAssembler::MacroAssembler(size_t capacity, #ifdef VIXL_DEBUG allow_macro_instructions_(true), #endif + allow_simulator_instructions_(VIXL_GENERATE_SIMULATOR_INSTRUCTIONS_VALUE), sp_(sp), tmp_list_(ip0, ip1), fptmp_list_(d31), @@ -304,6 +307,7 @@ MacroAssembler::MacroAssembler(byte * buffer, #ifdef VIXL_DEBUG allow_macro_instructions_(true), #endif + allow_simulator_instructions_(VIXL_GENERATE_SIMULATOR_INSTRUCTIONS_VALUE), sp_(sp), tmp_list_(ip0, ip1), fptmp_list_(d31), @@ -2183,8 +2187,7 @@ void MacroAssembler::PrintfNoPreserve(const char * format, // Actually call printf. This part needs special handling for the simulator, // since the system printf function will use a different instruction set and // the procedure-call standard will not be compatible. -#ifdef USE_SIMULATOR - { + if (allow_simulator_instructions_) { InstructionAccurateScope scope(this, kPrintfLength / kInstructionSize); hlt(kPrintfOpcode); dc32(arg_count); // kPrintfArgCountOffset @@ -2203,12 +2206,11 @@ void MacroAssembler::PrintfNoPreserve(const char * format, arg_pattern_list |= (arg_pattern << (kPrintfArgPatternBits * i)); } dc32(arg_pattern_list); // kPrintfArgPatternListOffset + } else { + Register tmp = temps.AcquireX(); + Mov(tmp, reinterpret_cast<uintptr_t>(printf)); + Blr(tmp); } -#else - Register tmp = temps.AcquireX(); - Mov(tmp, reinterpret_cast<uintptr_t>(printf)); - Blr(tmp); -#endif } @@ -2283,51 +2285,51 @@ void MacroAssembler::Printf(const char * format, void MacroAssembler::Trace(TraceParameters parameters, TraceCommand command) { VIXL_ASSERT(allow_macro_instructions_); -#ifdef USE_SIMULATOR - // The arguments to the trace pseudo instruction need to be contiguous in - // memory, so make sure we don't try to emit a literal pool. - InstructionAccurateScope scope(this, kTraceLength / kInstructionSize); + if (allow_simulator_instructions_) { + // The arguments to the trace pseudo instruction need to be contiguous in + // memory, so make sure we don't try to emit a literal pool. + InstructionAccurateScope scope(this, kTraceLength / kInstructionSize); - Label start; - bind(&start); + Label start; + bind(&start); - // Refer to simulator-a64.h for a description of the marker and its - // arguments. - hlt(kTraceOpcode); + // Refer to simulator-a64.h for a description of the marker and its + // arguments. + hlt(kTraceOpcode); - VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceParamsOffset); - dc32(parameters); + VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceParamsOffset); + dc32(parameters); - VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceCommandOffset); - dc32(command); -#else - // Emit nothing on real hardware. - USE(parameters, command); -#endif + VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kTraceCommandOffset); + dc32(command); + } else { + // Emit nothing on real hardware. + USE(parameters, command); + } } void MacroAssembler::Log(TraceParameters parameters) { VIXL_ASSERT(allow_macro_instructions_); -#ifdef USE_SIMULATOR - // The arguments to the log pseudo instruction need to be contiguous in - // memory, so make sure we don't try to emit a literal pool. - InstructionAccurateScope scope(this, kLogLength / kInstructionSize); + if (allow_simulator_instructions_) { + // The arguments to the log pseudo instruction need to be contiguous in + // memory, so make sure we don't try to emit a literal pool. + InstructionAccurateScope scope(this, kLogLength / kInstructionSize); - Label start; - bind(&start); + Label start; + bind(&start); - // Refer to simulator-a64.h for a description of the marker and its - // arguments. - hlt(kLogOpcode); + // Refer to simulator-a64.h for a description of the marker and its + // arguments. + hlt(kLogOpcode); - VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kLogParamsOffset); - dc32(parameters); -#else - // Emit nothing on real hardware. - USE(parameters); -#endif + VIXL_ASSERT(SizeOfCodeGeneratedSince(&start) == kLogParamsOffset); + dc32(parameters); + } else { + // Emit nothing on real hardware. + USE(parameters); + } } diff --git a/src/vixl/a64/macro-assembler-a64.h b/src/vixl/a64/macro-assembler-a64.h index 6d3838dd..c635af2c 100644 --- a/src/vixl/a64/macro-assembler-a64.h +++ b/src/vixl/a64/macro-assembler-a64.h @@ -33,6 +33,8 @@ #include "vixl/globals.h" #include "vixl/a64/assembler-a64.h" #include "vixl/a64/debugger-a64.h" +#include "vixl/a64/instrument-a64.h" +#include "vixl/a64/simulator-constants-a64.h" #define LS_MACRO_LIST(V) \ @@ -2074,13 +2076,13 @@ class MacroAssembler : public Assembler { void Unreachable() { VIXL_ASSERT(allow_macro_instructions_); SingleEmissionCheckScope guard(this); -#ifdef USE_SIMULATOR - hlt(kUnreachableOpcode); -#else - // Branch to 0 to generate a segfault. - // lr - kInstructionSize is the address of the offending instruction. - blr(xzr); -#endif + if (allow_simulator_instructions_) { + hlt(kUnreachableOpcode); + } else { + // Branch to 0 to generate a segfault. + // lr - kInstructionSize is the address of the offending instruction. + blr(xzr); + } } void Uxtb(const Register& rd, const Register& rn) { VIXL_ASSERT(allow_macro_instructions_); @@ -2902,7 +2904,7 @@ class MacroAssembler : public Assembler { // one instruction. Refer to the implementation for details. void BumpSystemStackPointer(const Operand& space); -#if VIXL_DEBUG +#ifdef VIXL_DEBUG void SetAllowMacroInstructions(bool value) { allow_macro_instructions_ = value; } @@ -2912,6 +2914,14 @@ class MacroAssembler : public Assembler { } #endif + void SetAllowSimulatorInstructions(bool value) { + allow_simulator_instructions_ = value; + } + + bool AllowSimulatorInstructions() const { + return allow_simulator_instructions_; + } + void BlockLiteralPool() { literal_pool_.Block(); } void ReleaseLiteralPool() { literal_pool_.Release(); } bool IsLiteralPoolBlocked() const { return literal_pool_.IsBlocked(); } @@ -3099,13 +3109,16 @@ class MacroAssembler : public Assembler { label->location() - CursorOffset()); } -#if VIXL_DEBUG +#ifdef VIXL_DEBUG // Tell whether any of the macro instruction can be used. When false the // MacroAssembler will assert if a method which can emit a variable number // of instructions is called. bool allow_macro_instructions_; #endif + // Tell whether we should generate code that will run on the simulator or not. + bool allow_simulator_instructions_; + // The register to use as a stack pointer for stack operations. Register sp_; @@ -3326,10 +3339,10 @@ class UseScratchRegisterScope { #endif // Disallow copy constructor and operator=. - UseScratchRegisterScope(const UseScratchRegisterScope&) { + VIXL_DEBUG_NO_RETURN UseScratchRegisterScope(const UseScratchRegisterScope&) { VIXL_UNREACHABLE(); } - void operator=(const UseScratchRegisterScope&) { + VIXL_DEBUG_NO_RETURN void operator=(const UseScratchRegisterScope&) { VIXL_UNREACHABLE(); } }; diff --git a/src/vixl/a64/simulator-a64.cc b/src/vixl/a64/simulator-a64.cc index 3cb029a3..69a664ba 100644 --- a/src/vixl/a64/simulator-a64.cc +++ b/src/vixl/a64/simulator-a64.cc @@ -24,7 +24,7 @@ // 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. -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR #include <string.h> #include <cmath> @@ -273,56 +273,39 @@ void Simulator::set_instruction_stats(bool value) { } // Helpers --------------------------------------------------------------------- -int64_t Simulator::AddWithCarry(unsigned reg_size, - bool set_flags, - int64_t src1, - int64_t src2, - int64_t carry_in) { +uint64_t Simulator::AddWithCarry(unsigned reg_size, + bool set_flags, + uint64_t left, + uint64_t right, + int carry_in) { VIXL_ASSERT((carry_in == 0) || (carry_in == 1)); VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize)); - uint64_t u1, u2; - int64_t result; - int64_t signed_sum = src1 + src2 + carry_in; + uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt; + uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask; + uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask; - uint32_t N, Z, C, V; + left &= reg_mask; + right &= reg_mask; + uint64_t result = (left + right + carry_in) & reg_mask; - if (reg_size == kWRegSize) { - u1 = static_cast<uint64_t>(src1) & kWRegMask; - u2 = static_cast<uint64_t>(src2) & kWRegMask; - - result = signed_sum & kWRegMask; - // Compute the C flag by comparing the sum to the max unsigned integer. - C = ((kWMaxUInt - u1) < (u2 + carry_in)) || - ((kWMaxUInt - u1 - carry_in) < u2); - // Overflow iff the sign bit is the same for the two inputs and different - // for the result. - int64_t s_src1 = src1 << (kXRegSize - kWRegSize); - int64_t s_src2 = src2 << (kXRegSize - kWRegSize); - int64_t s_result = result << (kXRegSize - kWRegSize); - V = ((s_src1 ^ s_src2) >= 0) && ((s_src1 ^ s_result) < 0); + if (set_flags) { + nzcv().SetN(CalcNFlag(result, reg_size)); + nzcv().SetZ(CalcZFlag(result)); - } else { - u1 = static_cast<uint64_t>(src1); - u2 = static_cast<uint64_t>(src2); + // Compute the C flag by comparing the result to the max unsigned integer. + uint64_t max_uint_2op = max_uint - carry_in; + bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right); + nzcv().SetC(C ? 1 : 0); - result = signed_sum; - // Compute the C flag by comparing the sum to the max unsigned integer. - C = ((kXMaxUInt - u1) < (u2 + carry_in)) || - ((kXMaxUInt - u1 - carry_in) < u2); // Overflow iff the sign bit is the same for the two inputs and different // for the result. - V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0); - } + uint64_t left_sign = left & sign_mask; + uint64_t right_sign = right & sign_mask; + uint64_t result_sign = result & sign_mask; + bool V = (left_sign == right_sign) && (left_sign != result_sign); + nzcv().SetV(V ? 1 : 0); - N = CalcNFlag(result, reg_size); - Z = CalcZFlag(result); - - if (set_flags) { - nzcv().SetN(N); - nzcv().SetZ(Z); - nzcv().SetC(C); - nzcv().SetV(V); LogSystemRegister(NZCV); } return result; @@ -4052,4 +4035,4 @@ void Simulator::DoPrintf(const Instruction* instr) { } // namespace vixl -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR diff --git a/src/vixl/a64/simulator-a64.h b/src/vixl/a64/simulator-a64.h index dd8f6a83..8eb1ea9f 100644 --- a/src/vixl/a64/simulator-a64.h +++ b/src/vixl/a64/simulator-a64.h @@ -33,123 +33,10 @@ #include "vixl/a64/assembler-a64.h" #include "vixl/a64/disasm-a64.h" #include "vixl/a64/instrument-a64.h" +#include "vixl/a64/simulator-constants-a64.h" namespace vixl { -// Debug instructions. -// -// VIXL's macro-assembler and simulator support a few pseudo instructions to -// make debugging easier. These pseudo instructions do not exist on real -// hardware. -// -// TODO: Provide controls to prevent the macro assembler from emitting -// pseudo-instructions. This is important for ahead-of-time compilers, where the -// macro assembler is built with USE_SIMULATOR but the code will eventually be -// run on real hardware. -// -// TODO: Also consider allowing these pseudo-instructions to be disabled in the -// simulator, so that users can check that the input is a valid native code. -// (This isn't possible in all cases. Printf won't work, for example.) -// -// Each debug pseudo instruction is represented by a HLT instruction. The HLT -// immediate field is used to identify the type of debug pseudo instruction. - -enum DebugHltOpcodes { - kUnreachableOpcode = 0xdeb0, - kPrintfOpcode, - kTraceOpcode, - kLogOpcode, - // Aliases. - kDebugHltFirstOpcode = kUnreachableOpcode, - kDebugHltLastOpcode = kLogOpcode -}; - -// Each pseudo instruction uses a custom encoding for additional arguments, as -// described below. - -// Unreachable - kUnreachableOpcode -// -// Instruction which should never be executed. This is used as a guard in parts -// of the code that should not be reachable, such as in data encoded inline in -// the instructions. - -// Printf - kPrintfOpcode -// - arg_count: The number of arguments. -// - arg_pattern: A set of PrintfArgPattern values, packed into two-bit fields. -// -// Simulate a call to printf. -// -// Floating-point and integer arguments are passed in separate sets of registers -// in AAPCS64 (even for varargs functions), so it is not possible to determine -// the type of each argument without some information about the values that were -// passed in. This information could be retrieved from the printf format string, -// but the format string is not trivial to parse so we encode the relevant -// information with the HLT instruction. -// -// Also, the following registers are populated (as if for a native A64 call): -// x0: The format string -// x1-x7: Optional arguments, if type == CPURegister::kRegister -// d0-d7: Optional arguments, if type == CPURegister::kFPRegister -const unsigned kPrintfArgCountOffset = 1 * kInstructionSize; -const unsigned kPrintfArgPatternListOffset = 2 * kInstructionSize; -const unsigned kPrintfLength = 3 * kInstructionSize; - -const unsigned kPrintfMaxArgCount = 4; - -// The argument pattern is a set of two-bit-fields, each with one of the -// following values: -enum PrintfArgPattern { - kPrintfArgW = 1, - kPrintfArgX = 2, - // There is no kPrintfArgS because floats are always converted to doubles in C - // varargs calls. - kPrintfArgD = 3 -}; -static const unsigned kPrintfArgPatternBits = 2; - -// Trace - kTraceOpcode -// - parameter: TraceParameter stored as a uint32_t -// - command: TraceCommand stored as a uint32_t -// -// Allow for trace management in the generated code. This enables or disables -// automatic tracing of the specified information for every simulated -// instruction. -const unsigned kTraceParamsOffset = 1 * kInstructionSize; -const unsigned kTraceCommandOffset = 2 * kInstructionSize; -const unsigned kTraceLength = 3 * kInstructionSize; - -// Trace parameters. -enum TraceParameters { - LOG_DISASM = 1 << 0, // Log disassembly. - LOG_REGS = 1 << 1, // Log general purpose registers. - LOG_VREGS = 1 << 2, // Log NEON and floating-point registers. - LOG_SYSREGS = 1 << 3, // Log the flags and system registers. - LOG_WRITE = 1 << 4, // Log writes to memory. - - LOG_NONE = 0, - LOG_STATE = LOG_REGS | LOG_VREGS | LOG_SYSREGS, - LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE -}; - -// Trace commands. -enum TraceCommand { - TRACE_ENABLE = 1, - TRACE_DISABLE = 2 -}; - -// Log - kLogOpcode -// - parameter: TraceParameter stored as a uint32_t -// -// Print the specified information once. This mechanism is separate from Trace. -// In particular, _all_ of the specified registers are printed, rather than just -// the registers that the instruction writes. -// -// Any combination of the TraceParameters values can be used, except that -// LOG_DISASM is not supported for Log. -const unsigned kLogParamsOffset = 1 * kInstructionSize; -const unsigned kLogLength = 2 * kInstructionSize; - - // Assemble the specified IEEE-754 components into the target type and apply // appropriate rounding. // sign: 0 = positive, 1 = negative @@ -831,9 +718,15 @@ class Simulator : public DecoderVisitor { // Declare all Visitor functions. #define DECLARE(A) virtual void Visit##A(const Instruction* instr); - VISITOR_LIST(DECLARE) + VISITOR_LIST_THAT_RETURN(DECLARE) #undef DECLARE + #define DECLARE(A) \ + VIXL_DEBUG_NO_RETURN virtual void Visit##A(const Instruction* instr); + VISITOR_LIST_THAT_DONT_RETURN(DECLARE) + #undef DECLARE + + // Integer register accessors. // Basic accessor: Read the register as the specified type. @@ -1295,7 +1188,7 @@ class Simulator : public DecoderVisitor { void PrintVRegisterFPHelper(unsigned code, unsigned lane_size_in_bytes, int lane_count = 1, int rightmost_lane = 0); - void DoUnreachable(const Instruction* instr); + VIXL_NO_RETURN void DoUnreachable(const Instruction* instr); void DoTrace(const Instruction* instr); void DoLog(const Instruction* instr); @@ -1388,11 +1281,11 @@ class Simulator : public DecoderVisitor { } void AddSubHelper(const Instruction* instr, int64_t op2); - int64_t AddWithCarry(unsigned reg_size, - bool set_flags, - int64_t src1, - int64_t src2, - int64_t carry_in = 0); + uint64_t AddWithCarry(unsigned reg_size, + bool set_flags, + uint64_t left, + uint64_t right, + int carry_in = 0); void LogicalHelper(const Instruction* instr, int64_t op2); void ConditionalCompareHelper(const Instruction* instr, int64_t op2); void LoadStoreHelper(const Instruction* instr, @@ -2631,7 +2524,7 @@ class Simulator : public DecoderVisitor { } static int CalcZFlag(uint64_t result) { - return result == 0; + return (result == 0) ? 1 : 0; } static const uint32_t kConditionFlagsMask = 0xf0000000; diff --git a/src/vixl/a64/simulator-constants-a64.h b/src/vixl/a64/simulator-constants-a64.h new file mode 100644 index 00000000..16a3c32a --- /dev/null +++ b/src/vixl/a64/simulator-constants-a64.h @@ -0,0 +1,141 @@ +// Copyright 2015, ARM Limited +// 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. + +#ifndef VIXL_A64_SIMULATOR_CONSTANTS_A64_H_ +#define VIXL_A64_SIMULATOR_CONSTANTS_A64_H_ + +namespace vixl { + +// Debug instructions. +// +// VIXL's macro-assembler and simulator support a few pseudo instructions to +// make debugging easier. These pseudo instructions do not exist on real +// hardware. +// +// TODO: Also consider allowing these pseudo-instructions to be disabled in the +// simulator, so that users can check that the input is a valid native code. +// (This isn't possible in all cases. Printf won't work, for example.) +// +// Each debug pseudo instruction is represented by a HLT instruction. The HLT +// immediate field is used to identify the type of debug pseudo instruction. + +enum DebugHltOpcodes { + kUnreachableOpcode = 0xdeb0, + kPrintfOpcode, + kTraceOpcode, + kLogOpcode, + // Aliases. + kDebugHltFirstOpcode = kUnreachableOpcode, + kDebugHltLastOpcode = kLogOpcode +}; + +// Each pseudo instruction uses a custom encoding for additional arguments, as +// described below. + +// Unreachable - kUnreachableOpcode +// +// Instruction which should never be executed. This is used as a guard in parts +// of the code that should not be reachable, such as in data encoded inline in +// the instructions. + +// Printf - kPrintfOpcode +// - arg_count: The number of arguments. +// - arg_pattern: A set of PrintfArgPattern values, packed into two-bit fields. +// +// Simulate a call to printf. +// +// Floating-point and integer arguments are passed in separate sets of registers +// in AAPCS64 (even for varargs functions), so it is not possible to determine +// the type of each argument without some information about the values that were +// passed in. This information could be retrieved from the printf format string, +// but the format string is not trivial to parse so we encode the relevant +// information with the HLT instruction. +// +// Also, the following registers are populated (as if for a native A64 call): +// x0: The format string +// x1-x7: Optional arguments, if type == CPURegister::kRegister +// d0-d7: Optional arguments, if type == CPURegister::kFPRegister +const unsigned kPrintfArgCountOffset = 1 * kInstructionSize; +const unsigned kPrintfArgPatternListOffset = 2 * kInstructionSize; +const unsigned kPrintfLength = 3 * kInstructionSize; + +const unsigned kPrintfMaxArgCount = 4; + +// The argument pattern is a set of two-bit-fields, each with one of the +// following values: +enum PrintfArgPattern { + kPrintfArgW = 1, + kPrintfArgX = 2, + // There is no kPrintfArgS because floats are always converted to doubles in C + // varargs calls. + kPrintfArgD = 3 +}; +static const unsigned kPrintfArgPatternBits = 2; + +// Trace - kTraceOpcode +// - parameter: TraceParameter stored as a uint32_t +// - command: TraceCommand stored as a uint32_t +// +// Allow for trace management in the generated code. This enables or disables +// automatic tracing of the specified information for every simulated +// instruction. +const unsigned kTraceParamsOffset = 1 * kInstructionSize; +const unsigned kTraceCommandOffset = 2 * kInstructionSize; +const unsigned kTraceLength = 3 * kInstructionSize; + +// Trace parameters. +enum TraceParameters { + LOG_DISASM = 1 << 0, // Log disassembly. + LOG_REGS = 1 << 1, // Log general purpose registers. + LOG_VREGS = 1 << 2, // Log NEON and floating-point registers. + LOG_SYSREGS = 1 << 3, // Log the flags and system registers. + LOG_WRITE = 1 << 4, // Log writes to memory. + + LOG_NONE = 0, + LOG_STATE = LOG_REGS | LOG_VREGS | LOG_SYSREGS, + LOG_ALL = LOG_DISASM | LOG_STATE | LOG_WRITE +}; + +// Trace commands. +enum TraceCommand { + TRACE_ENABLE = 1, + TRACE_DISABLE = 2 +}; + +// Log - kLogOpcode +// - parameter: TraceParameter stored as a uint32_t +// +// Print the specified information once. This mechanism is separate from Trace. +// In particular, _all_ of the specified registers are printed, rather than just +// the registers that the instruction writes. +// +// Any combination of the TraceParameters values can be used, except that +// LOG_DISASM is not supported for Log. +const unsigned kLogParamsOffset = 1 * kInstructionSize; +const unsigned kLogLength = 2 * kInstructionSize; +} // namespace vixl + +#endif // VIXL_A64_SIMULATOR_CONSTANTS_A64_H_ diff --git a/src/vixl/globals.h b/src/vixl/globals.h index 42938dbb..61dc9f7f 100644 --- a/src/vixl/globals.h +++ b/src/vixl/globals.h @@ -116,4 +116,36 @@ inline void USE(T1, T2, T3, T4) {} #define VIXL_FALLTHROUGH() do {} while (0) #endif +#if __cplusplus >= 201103L + #define VIXL_NO_RETURN [[noreturn]] //NOLINT +#else + #define VIXL_NO_RETURN __attribute__((noreturn)) +#endif + +// Some functions might only be marked as "noreturn" for the DEBUG build. This +// macro should be used for such cases (for more details see what +// VIXL_UNREACHABLE expands to). +#ifdef VIXL_DEBUG + #define VIXL_DEBUG_NO_RETURN VIXL_NO_RETURN +#else + #define VIXL_DEBUG_NO_RETURN +#endif + +#ifdef VIXL_INCLUDE_SIMULATOR +#ifndef VIXL_GENERATE_SIMULATOR_INSTRUCTIONS_VALUE + #define VIXL_GENERATE_SIMULATOR_INSTRUCTIONS_VALUE 1 +#endif +#else +#ifndef VIXL_GENERATE_SIMULATOR_INSTRUCTIONS_VALUE + #define VIXL_GENERATE_SIMULATOR_INSTRUCTIONS_VALUE 0 +#endif +#if VIXL_GENERATE_SIMULATOR_INSTRUCTIONS_VALUE + #warning "Generating Simulator instructions without Simulator support." +#endif +#endif + +#ifdef USE_SIMULATOR + #error "Please see the release notes for USE_SIMULATOR." +#endif + #endif // VIXL_GLOBALS_H diff --git a/test/examples/test-examples.cc b/test/examples/test-examples.cc index 5ff9625f..83fe5467 100644 --- a/test/examples/test-examples.cc +++ b/test/examples/test-examples.cc @@ -45,7 +45,7 @@ TEST(custom_disassembler) { // The tests below only work with the simulator. -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR #define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0])) #define BUF_SIZE (4096) @@ -573,4 +573,4 @@ TEST(literal_example) { LiteralExample(INT64_C(0x100000000), 0x1) == INT64_C(0x100000001)); } -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR diff --git a/test/test-assembler-a64.cc b/test/test-assembler-a64.cc index 642b3d4d..67cdf736 100644 --- a/test/test-assembler-a64.cc +++ b/test/test-assembler-a64.cc @@ -94,7 +94,7 @@ namespace vixl { #define BUF_SIZE (4096) -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR // Run tests with the simulator. #define SETUP() \ @@ -107,6 +107,7 @@ namespace vixl { SETUP_COMMON() #define SETUP_COMMON() \ + masm.SetAllowSimulatorInstructions(true); \ Decoder decoder; \ Simulator* simulator = Test::run_debugger() ? new Debugger(&decoder) \ : new Simulator(&decoder); \ @@ -158,7 +159,7 @@ namespace vixl { #define TEARDOWN_COMMON() \ delete simulator; -#else // ifdef USE_SIMULATOR. +#else // ifdef VIXL_INCLUDE_SIMULATOR. // Run the test on real hardware or models. #define SETUP() \ MacroAssembler masm(BUF_SIZE); \ @@ -170,6 +171,7 @@ namespace vixl { SETUP_COMMON() #define SETUP_COMMON() \ + masm.SetAllowSimulatorInstructions(false); \ RegisterDump core; \ CPU::SetUp() @@ -205,7 +207,7 @@ namespace vixl { #define TEARDOWN_CUSTOM() \ delete[] buf; \ -#endif // ifdef USE_SIMULATOR. +#endif // ifdef VIXL_INCLUDE_SIMULATOR. #define ASSERT_EQUAL_NZCV(expected) \ assert(EqualNzcv(expected, core.flags_nzcv())) @@ -7664,6 +7666,378 @@ TEST(neg) { } +template<typename T, typename Op> +static void AdcsSbcsHelper(Op op, T left, T right, int carry, + T expected, StatusFlags expected_flags) { + int reg_size = sizeof(T) * 8; + Register left_reg(0, reg_size); + Register right_reg(1, reg_size); + Register result_reg(2, reg_size); + + SETUP(); + START(); + + __ Mov(left_reg, left); + __ Mov(right_reg, right); + __ Mov(x10, (carry ? CFlag : NoFlag)); + + __ Msr(NZCV, x10); + (masm.*op)(result_reg, left_reg, right_reg); + + END(); + RUN(); + + ASSERT_EQUAL_64(left, left_reg.X()); + ASSERT_EQUAL_64(right, right_reg.X()); + ASSERT_EQUAL_64(expected, result_reg.X()); + ASSERT_EQUAL_NZCV(expected_flags); + + TEARDOWN(); +} + + +TEST(adcs_sbcs_x) { + uint64_t inputs[] = { + 0x0000000000000000, 0x0000000000000001, + 0x7ffffffffffffffe, 0x7fffffffffffffff, + 0x8000000000000000, 0x8000000000000001, + 0xfffffffffffffffe, 0xffffffffffffffff, + }; + static const size_t input_count = sizeof(inputs) / sizeof(inputs[0]); + + struct Expected { + uint64_t carry0_result; + StatusFlags carry0_flags; + uint64_t carry1_result; + StatusFlags carry1_flags; + }; + + static const Expected expected_adcs_x[input_count][input_count] = { + {{0x0000000000000000, ZFlag, 0x0000000000000001, NoFlag}, + {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag}, + {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag}, + {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, + {0x8000000000000000, NFlag, 0x8000000000000001, NFlag}, + {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, + {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}}, + {{0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag}, + {0x0000000000000002, NoFlag, 0x0000000000000003, NoFlag}, + {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, + {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag}, + {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, + {0x8000000000000002, NFlag, 0x8000000000000003, NFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}}, + {{0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag}, + {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, + {0xfffffffffffffffc, NVFlag, 0xfffffffffffffffd, NVFlag}, + {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag}, + {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag}, + {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}}, + {{0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, + {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag}, + {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag}, + {0xfffffffffffffffe, NVFlag, 0xffffffffffffffff, NVFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, + {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, + {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag}}, + {{0x8000000000000000, NFlag, 0x8000000000000001, NFlag}, + {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, + {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0x0000000000000000, ZCVFlag, 0x0000000000000001, CVFlag}, + {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag}, + {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag}, + {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}}, + {{0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, + {0x8000000000000002, NFlag, 0x8000000000000003, NFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, + {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag}, + {0x0000000000000002, CVFlag, 0x0000000000000003, CVFlag}, + {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, + {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag}}, + {{0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag}, + {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, + {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag}, + {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, + {0xfffffffffffffffc, NCFlag, 0xfffffffffffffffd, NCFlag}, + {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag}}, + {{0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, + {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, + {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag}, + {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, + {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag}, + {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag}, + {0xfffffffffffffffe, NCFlag, 0xffffffffffffffff, NCFlag}} + }; + + static const Expected expected_sbcs_x[input_count][input_count] = { + {{0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, + {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, + {0x8000000000000000, NFlag, 0x8000000000000001, NFlag}, + {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, + {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag}, + {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag}, + {0x0000000000000000, ZFlag, 0x0000000000000001, NoFlag}}, + {{0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0x8000000000000002, NFlag, 0x8000000000000003, NFlag}, + {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, + {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag}, + {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, + {0x0000000000000002, NoFlag, 0x0000000000000003, NoFlag}, + {0x0000000000000001, NoFlag, 0x0000000000000002, NoFlag}}, + {{0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, + {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, + {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag}, + {0xfffffffffffffffc, NVFlag, 0xfffffffffffffffd, NVFlag}, + {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}, + {0x7ffffffffffffffe, NoFlag, 0x7fffffffffffffff, NoFlag}}, + {{0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag}, + {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, + {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0xfffffffffffffffe, NVFlag, 0xffffffffffffffff, NVFlag}, + {0xfffffffffffffffd, NVFlag, 0xfffffffffffffffe, NVFlag}, + {0x8000000000000000, NVFlag, 0x8000000000000001, NVFlag}, + {0x7fffffffffffffff, NoFlag, 0x8000000000000000, NVFlag}}, + {{0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, + {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag}, + {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag}, + {0x0000000000000000, ZCVFlag, 0x0000000000000001, CVFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}, + {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}, + {0x8000000000000000, NFlag, 0x8000000000000001, NFlag}}, + {{0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag}, + {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, + {0x0000000000000002, CVFlag, 0x0000000000000003, CVFlag}, + {0x0000000000000001, CVFlag, 0x0000000000000002, CVFlag}, + {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0x8000000000000002, NFlag, 0x8000000000000003, NFlag}, + {0x8000000000000001, NFlag, 0x8000000000000002, NFlag}}, + {{0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag}, + {0xfffffffffffffffc, NCFlag, 0xfffffffffffffffd, NCFlag}, + {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, + {0x7ffffffffffffffe, CVFlag, 0x7fffffffffffffff, CVFlag}, + {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, + {0x7ffffffffffffffc, CFlag, 0x7ffffffffffffffd, CFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}, + {0xfffffffffffffffe, NFlag, 0xffffffffffffffff, NFlag}}, + {{0xfffffffffffffffe, NCFlag, 0xffffffffffffffff, NCFlag}, + {0xfffffffffffffffd, NCFlag, 0xfffffffffffffffe, NCFlag}, + {0x8000000000000000, NCFlag, 0x8000000000000001, NCFlag}, + {0x7fffffffffffffff, CVFlag, 0x8000000000000000, NCFlag}, + {0x7ffffffffffffffe, CFlag, 0x7fffffffffffffff, CFlag}, + {0x7ffffffffffffffd, CFlag, 0x7ffffffffffffffe, CFlag}, + {0x0000000000000000, ZCFlag, 0x0000000000000001, CFlag}, + {0xffffffffffffffff, NFlag, 0x0000000000000000, ZCFlag}} + }; + + for (size_t left = 0; left < input_count; left++) { + for (size_t right = 0; right < input_count; right++) { + const Expected & expected = expected_adcs_x[left][right]; + AdcsSbcsHelper(&MacroAssembler::Adcs, inputs[left], inputs[right], 0, + expected.carry0_result, expected.carry0_flags); + AdcsSbcsHelper(&MacroAssembler::Adcs, inputs[left], inputs[right], 1, + expected.carry1_result, expected.carry1_flags); + } + } + + for (size_t left = 0; left < input_count; left++) { + for (size_t right = 0; right < input_count; right++) { + const Expected & expected = expected_sbcs_x[left][right]; + AdcsSbcsHelper(&MacroAssembler::Sbcs, inputs[left], inputs[right], 0, + expected.carry0_result, expected.carry0_flags); + AdcsSbcsHelper(&MacroAssembler::Sbcs, inputs[left], inputs[right], 1, + expected.carry1_result, expected.carry1_flags); + } + } +} + + +TEST(adcs_sbcs_w) { + uint32_t inputs[] = { + 0x00000000, 0x00000001, 0x7ffffffe, 0x7fffffff, + 0x80000000, 0x80000001, 0xfffffffe, 0xffffffff, + }; + static const size_t input_count = sizeof(inputs) / sizeof(inputs[0]); + + struct Expected { + uint32_t carry0_result; + StatusFlags carry0_flags; + uint32_t carry1_result; + StatusFlags carry1_flags; + }; + + static const Expected expected_adcs_w[input_count][input_count] = { + {{0x00000000, ZFlag, 0x00000001, NoFlag}, + {0x00000001, NoFlag, 0x00000002, NoFlag}, + {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag}, + {0x7fffffff, NoFlag, 0x80000000, NVFlag}, + {0x80000000, NFlag, 0x80000001, NFlag}, + {0x80000001, NFlag, 0x80000002, NFlag}, + {0xfffffffe, NFlag, 0xffffffff, NFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}}, + {{0x00000001, NoFlag, 0x00000002, NoFlag}, + {0x00000002, NoFlag, 0x00000003, NoFlag}, + {0x7fffffff, NoFlag, 0x80000000, NVFlag}, + {0x80000000, NVFlag, 0x80000001, NVFlag}, + {0x80000001, NFlag, 0x80000002, NFlag}, + {0x80000002, NFlag, 0x80000003, NFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0x00000000, ZCFlag, 0x00000001, CFlag}}, + {{0x7ffffffe, NoFlag, 0x7fffffff, NoFlag}, + {0x7fffffff, NoFlag, 0x80000000, NVFlag}, + {0xfffffffc, NVFlag, 0xfffffffd, NVFlag}, + {0xfffffffd, NVFlag, 0xfffffffe, NVFlag}, + {0xfffffffe, NFlag, 0xffffffff, NFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0x7ffffffc, CFlag, 0x7ffffffd, CFlag}, + {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}}, + {{0x7fffffff, NoFlag, 0x80000000, NVFlag}, + {0x80000000, NVFlag, 0x80000001, NVFlag}, + {0xfffffffd, NVFlag, 0xfffffffe, NVFlag}, + {0xfffffffe, NVFlag, 0xffffffff, NVFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0x00000000, ZCFlag, 0x00000001, CFlag}, + {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, + {0x7ffffffe, CFlag, 0x7fffffff, CFlag}}, + {{0x80000000, NFlag, 0x80000001, NFlag}, + {0x80000001, NFlag, 0x80000002, NFlag}, + {0xfffffffe, NFlag, 0xffffffff, NFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0x00000000, ZCVFlag, 0x00000001, CVFlag}, + {0x00000001, CVFlag, 0x00000002, CVFlag}, + {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag}, + {0x7fffffff, CVFlag, 0x80000000, NCFlag}}, + {{0x80000001, NFlag, 0x80000002, NFlag}, + {0x80000002, NFlag, 0x80000003, NFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0x00000000, ZCFlag, 0x00000001, CFlag}, + {0x00000001, CVFlag, 0x00000002, CVFlag}, + {0x00000002, CVFlag, 0x00000003, CVFlag}, + {0x7fffffff, CVFlag, 0x80000000, NCFlag}, + {0x80000000, NCFlag, 0x80000001, NCFlag}}, + {{0xfffffffe, NFlag, 0xffffffff, NFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0x7ffffffc, CFlag, 0x7ffffffd, CFlag}, + {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, + {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag}, + {0x7fffffff, CVFlag, 0x80000000, NCFlag}, + {0xfffffffc, NCFlag, 0xfffffffd, NCFlag}, + {0xfffffffd, NCFlag, 0xfffffffe, NCFlag}}, + {{0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0x00000000, ZCFlag, 0x00000001, CFlag}, + {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, + {0x7ffffffe, CFlag, 0x7fffffff, CFlag}, + {0x7fffffff, CVFlag, 0x80000000, NCFlag}, + {0x80000000, NCFlag, 0x80000001, NCFlag}, + {0xfffffffd, NCFlag, 0xfffffffe, NCFlag}, + {0xfffffffe, NCFlag, 0xffffffff, NCFlag}} + }; + + static const Expected expected_sbcs_w[input_count][input_count] = { + {{0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0xfffffffe, NFlag, 0xffffffff, NFlag}, + {0x80000001, NFlag, 0x80000002, NFlag}, + {0x80000000, NFlag, 0x80000001, NFlag}, + {0x7fffffff, NoFlag, 0x80000000, NVFlag}, + {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag}, + {0x00000001, NoFlag, 0x00000002, NoFlag}, + {0x00000000, ZFlag, 0x00000001, NoFlag}}, + {{0x00000000, ZCFlag, 0x00000001, CFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0x80000002, NFlag, 0x80000003, NFlag}, + {0x80000001, NFlag, 0x80000002, NFlag}, + {0x80000000, NVFlag, 0x80000001, NVFlag}, + {0x7fffffff, NoFlag, 0x80000000, NVFlag}, + {0x00000002, NoFlag, 0x00000003, NoFlag}, + {0x00000001, NoFlag, 0x00000002, NoFlag}}, + {{0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, + {0x7ffffffc, CFlag, 0x7ffffffd, CFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0xfffffffe, NFlag, 0xffffffff, NFlag}, + {0xfffffffd, NVFlag, 0xfffffffe, NVFlag}, + {0xfffffffc, NVFlag, 0xfffffffd, NVFlag}, + {0x7fffffff, NoFlag, 0x80000000, NVFlag}, + {0x7ffffffe, NoFlag, 0x7fffffff, NoFlag}}, + {{0x7ffffffe, CFlag, 0x7fffffff, CFlag}, + {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, + {0x00000000, ZCFlag, 0x00000001, CFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0xfffffffe, NVFlag, 0xffffffff, NVFlag}, + {0xfffffffd, NVFlag, 0xfffffffe, NVFlag}, + {0x80000000, NVFlag, 0x80000001, NVFlag}, + {0x7fffffff, NoFlag, 0x80000000, NVFlag}}, + {{0x7fffffff, CVFlag, 0x80000000, NCFlag}, + {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag}, + {0x00000001, CVFlag, 0x00000002, CVFlag}, + {0x00000000, ZCVFlag, 0x00000001, CVFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0xfffffffe, NFlag, 0xffffffff, NFlag}, + {0x80000001, NFlag, 0x80000002, NFlag}, + {0x80000000, NFlag, 0x80000001, NFlag}}, + {{0x80000000, NCFlag, 0x80000001, NCFlag}, + {0x7fffffff, CVFlag, 0x80000000, NCFlag}, + {0x00000002, CVFlag, 0x00000003, CVFlag}, + {0x00000001, CVFlag, 0x00000002, CVFlag}, + {0x00000000, ZCFlag, 0x00000001, CFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0x80000002, NFlag, 0x80000003, NFlag}, + {0x80000001, NFlag, 0x80000002, NFlag}}, + {{0xfffffffd, NCFlag, 0xfffffffe, NCFlag}, + {0xfffffffc, NCFlag, 0xfffffffd, NCFlag}, + {0x7fffffff, CVFlag, 0x80000000, NCFlag}, + {0x7ffffffe, CVFlag, 0x7fffffff, CVFlag}, + {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, + {0x7ffffffc, CFlag, 0x7ffffffd, CFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}, + {0xfffffffe, NFlag, 0xffffffff, NFlag}}, + {{0xfffffffe, NCFlag, 0xffffffff, NCFlag}, + {0xfffffffd, NCFlag, 0xfffffffe, NCFlag}, + {0x80000000, NCFlag, 0x80000001, NCFlag}, + {0x7fffffff, CVFlag, 0x80000000, NCFlag}, + {0x7ffffffe, CFlag, 0x7fffffff, CFlag}, + {0x7ffffffd, CFlag, 0x7ffffffe, CFlag}, + {0x00000000, ZCFlag, 0x00000001, CFlag}, + {0xffffffff, NFlag, 0x00000000, ZCFlag}} + }; + + for (size_t left = 0; left < input_count; left++) { + for (size_t right = 0; right < input_count; right++) { + const Expected & expected = expected_adcs_w[left][right]; + AdcsSbcsHelper(&MacroAssembler::Adcs, inputs[left], inputs[right], 0, + expected.carry0_result, expected.carry0_flags); + AdcsSbcsHelper(&MacroAssembler::Adcs, inputs[left], inputs[right], 1, + expected.carry1_result, expected.carry1_flags); + } + } + + for (size_t left = 0; left < input_count; left++) { + for (size_t right = 0; right < input_count; right++) { + const Expected & expected = expected_sbcs_w[left][right]; + AdcsSbcsHelper(&MacroAssembler::Sbcs, inputs[left], inputs[right], 0, + expected.carry0_result, expected.carry0_flags); + AdcsSbcsHelper(&MacroAssembler::Sbcs, inputs[left], inputs[right], 1, + expected.carry1_result, expected.carry1_flags); + } + } +} + + TEST(adc_sbc_shift) { SETUP(); @@ -7731,132 +8105,6 @@ TEST(adc_sbc_shift) { ASSERT_EQUAL_32(0x91111110 + 1, w26); ASSERT_EQUAL_32(0x9a222221 + 1, w27); - // Check that adc correctly sets the condition flags. - START(); - __ Mov(x0, 1); - __ Mov(x1, 0xffffffffffffffff); - // Clear the C flag. - __ Adds(x0, x0, Operand(0)); - __ Adcs(x10, x0, Operand(x1)); - END(); - - RUN(); - - ASSERT_EQUAL_NZCV(ZCFlag); - ASSERT_EQUAL_64(0, x10); - - START(); - __ Mov(x0, 1); - __ Mov(x1, 0x8000000000000000); - // Clear the C flag. - __ Adds(x0, x0, Operand(0)); - __ Adcs(x10, x0, Operand(x1, ASR, 63)); - END(); - - RUN(); - - ASSERT_EQUAL_NZCV(ZCFlag); - ASSERT_EQUAL_64(0, x10); - - START(); - __ Mov(x0, 0x10); - __ Mov(x1, 0x07ffffffffffffff); - // Clear the C flag. - __ Adds(x0, x0, Operand(0)); - __ Adcs(x10, x0, Operand(x1, LSL, 4)); - END(); - - RUN(); - - ASSERT_EQUAL_NZCV(NVFlag); - ASSERT_EQUAL_64(0x8000000000000000, x10); - - // Check that sbc correctly sets the condition flags. - START(); - __ Mov(x0, 0); - __ Mov(x1, 0xffffffffffffffff); - // Clear the C flag. - __ Adds(x0, x0, Operand(0)); - __ Sbcs(x10, x0, Operand(x1)); - END(); - - RUN(); - - ASSERT_EQUAL_NZCV(ZFlag); - ASSERT_EQUAL_64(0, x10); - - START(); - __ Mov(x0, 1); - __ Mov(x1, 0xffffffffffffffff); - // Clear the C flag. - __ Adds(x0, x0, Operand(0)); - __ Sbcs(x10, x0, Operand(x1, LSR, 1)); - END(); - - RUN(); - - ASSERT_EQUAL_NZCV(NFlag); - ASSERT_EQUAL_64(0x8000000000000001, x10); - - START(); - __ Mov(x0, 0); - // Clear the C flag. - __ Adds(x0, x0, Operand(0)); - __ Sbcs(x10, x0, Operand(0xffffffffffffffff)); - END(); - - RUN(); - - ASSERT_EQUAL_NZCV(ZFlag); - ASSERT_EQUAL_64(0, x10); - - START(); - __ Mov(w0, 0x7fffffff); - // Clear the C flag. - __ Adds(x0, x0, Operand(0)); - __ Ngcs(w10, w0); - END(); - - RUN(); - - ASSERT_EQUAL_NZCV(NFlag); - ASSERT_EQUAL_64(0x80000000, x10); - - START(); - // Clear the C flag. - __ Adds(x0, x0, Operand(0)); - __ Ngcs(x10, 0x7fffffffffffffff); - END(); - - RUN(); - - ASSERT_EQUAL_NZCV(NFlag); - ASSERT_EQUAL_64(0x8000000000000000, x10); - - START(); - __ Mov(x0, 0); - // Set the C flag. - __ Cmp(x0, Operand(x0)); - __ Sbcs(x10, x0, Operand(1)); - END(); - - RUN(); - - ASSERT_EQUAL_NZCV(NFlag); - ASSERT_EQUAL_64(0xffffffffffffffff, x10); - - START(); - __ Mov(x0, 0); - // Set the C flag. - __ Cmp(x0, Operand(x0)); - __ Ngcs(x10, 0x7fffffffffffffff); - END(); - - RUN(); - - ASSERT_EQUAL_NZCV(NFlag); - ASSERT_EQUAL_64(0x8000000000000001, x10); - TEARDOWN(); } @@ -14080,7 +14328,7 @@ TEST(printf_no_preserve) { } -#ifndef USE_SIMULATOR +#ifndef VIXL_INCLUDE_SIMULATOR TEST(trace) { // The Trace helper should not generate any code unless the simulator (or // debugger) is being used. @@ -14099,7 +14347,7 @@ TEST(trace) { #endif -#ifndef USE_SIMULATOR +#ifndef VIXL_INCLUDE_SIMULATOR TEST(log) { // The Log helper should not generate any code unless the simulator (or // debugger) is being used. @@ -15140,7 +15388,7 @@ TEST(clrex) { } -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR // Check that the simulator occasionally makes store-exclusive fail. TEST(ldxr_stxr_fail) { uint64_t data[] = {0, 0, 0}; @@ -15224,7 +15472,7 @@ TEST(ldxr_stxr_fail) { #endif -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR // Check that the simulator occasionally makes store-exclusive fail. TEST(ldaxr_stlxr_fail) { uint64_t data[] = {0, 0, 0}; @@ -21744,7 +21992,6 @@ TEST(literal_deletion_policies) { masm.EmitLiteralPool(LiteralPool::kBranchRequired); VIXL_ASSERT(lit_manual.IsPlaced()); - VIXL_ASSERT(lit_deleted_on_placement->IsPlaced()); VIXL_ASSERT(lit_deleted_on_pool_destruction->IsPlaced()); lit_deleted_on_pool_destruction->UpdateValue(128, &masm); diff --git a/test/test-disasm-a64.cc b/test/test-disasm-a64.cc index 0f54288c..d4fa02f3 100644 --- a/test/test-disasm-a64.cc +++ b/test/test-disasm-a64.cc @@ -45,7 +45,18 @@ #define SETUP() SETUP_CLASS(Assembler) -#define SETUP_MACRO() SETUP_CLASS(MacroAssembler) +#ifdef VIXL_INCLUDE_SIMULATOR +// Run tests with the simulator. +#define SETUP_MACRO() \ + SETUP_CLASS(MacroAssembler); \ + masm->SetAllowSimulatorInstructions(true) + +#else // ifdef VIXL_INCLUDE_SIMULATOR. +#define SETUP_MACRO() \ + SETUP_CLASS(MacroAssembler); \ + masm->SetAllowSimulatorInstructions(false) + +#endif // ifdef VIXL_INCLUDE_SIMULATOR. #define COMPARE(ASM, EXP) \ masm->Reset(); \ @@ -137,7 +148,7 @@ TEST(bootstrap) { TEST(mov_mvn) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Mov(w0, Operand(0x1234)), "mov w0, #0x1234"); COMPARE(Mov(x1, Operand(0x1234)), "mov x1, #0x1234"); @@ -203,7 +214,7 @@ TEST(move_immediate) { TEST(move_immediate_2) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); // Move instructions expected for certain immediates. This is really a macro // assembler test, to ensure it generates immediates efficiently. @@ -1848,7 +1859,7 @@ TEST(load_store_pair_nontemp) { TEST(load_literal_macro) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); // In each case, the literal will be placed at PC+8: // ldr x10, pc+8 // Test instruction. @@ -2187,7 +2198,7 @@ TEST(cond_select) { TEST(cond_select_macro) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Csel(w0, w1, -1, eq), "csinv w0, w1, wzr, eq"); COMPARE(Csel(w2, w3, 0, ne), "csel w2, w3, wzr, ne"); @@ -2219,7 +2230,7 @@ TEST(cond_cmp) { TEST(cond_cmp_macro) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Ccmp(w0, -1, VFlag, hi), "ccmn w0, #1, #nzcV, hi"); COMPARE(Ccmp(x1, -31, CFlag, ge), "ccmn x1, #31, #nzCv, ge"); @@ -2584,9 +2595,9 @@ TEST(system_nop) { TEST(unreachable) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR VIXL_ASSERT(kUnreachableOpcode == 0xdeb0); COMPARE(Unreachable(), "hlt #0xdeb0"); #else @@ -2597,9 +2608,9 @@ TEST(unreachable) { } -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR TEST(trace) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); VIXL_ASSERT(kTraceOpcode == 0xdeb2); @@ -2612,9 +2623,9 @@ TEST(trace) { #endif -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR TEST(log) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); VIXL_ASSERT(kLogOpcode == 0xdeb3); @@ -2661,7 +2672,7 @@ TEST(svc) { TEST(add_sub_negative) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Add(x10, x0, -42), "sub x10, x0, #0x2a (42)"); COMPARE(Add(x11, x1, -687), "sub x11, x1, #0x2af (687)"); @@ -2698,7 +2709,7 @@ TEST(add_sub_negative) { TEST(logical_immediate_move) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(And(w0, w1, 0), "mov w0, #0x0"); COMPARE(And(x0, x1, 0), "mov x0, #0x0"); @@ -2737,7 +2748,7 @@ TEST(logical_immediate_move) { TEST(barriers) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); // DMB COMPARE(Dmb(FullSystem, BarrierAll), "dmb sy"); @@ -2837,7 +2848,7 @@ TEST(barriers) { V(V4S(), "4s") TEST(neon_load_store_vector) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); #define DISASM_INST(M, S) \ COMPARE(Ld1(v0.M, MemOperand(x15)), \ @@ -3023,7 +3034,7 @@ TEST(neon_load_store_vector) { TEST(neon_load_store_lane) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Ld1(v0.V8B(), 0, MemOperand(x15)), "ld1 {v0.b}[0], [x15]"); COMPARE(Ld1(v1.V16B(), 1, MemOperand(x16)), "ld1 {v1.b}[1], [x16]"); @@ -3419,7 +3430,7 @@ TEST(neon_load_store_lane) { TEST(neon_load_all_lanes) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Ld1r(v14.V8B(), MemOperand(x0)), "ld1r {v14.8b}, [x0]"); COMPARE(Ld1r(v15.V16B(), MemOperand(x1)), "ld1r {v15.16b}, [x1]"); @@ -3567,7 +3578,7 @@ TEST(neon_load_all_lanes) { TEST(neon_3same) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); #define DISASM_INST(M, S) \ COMPARE(Cmeq(v0.M, v1.M, v2.M), "cmeq v0." S ", v1." S ", v2." S); @@ -3832,7 +3843,7 @@ TEST(neon_3same) { V(V2D(), "2d") TEST(neon_fp_3same) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); #define DISASM_INST(M, S) \ COMPARE(Fadd(v0.M, v1.M, v2.M), "fadd v0." S ", v1." S ", v2." S); @@ -3965,7 +3976,7 @@ TEST(neon_fp_3same) { V(D(), "d") TEST(neon_scalar_3same) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); // Instructions that only support D-sized scalar operations. COMPARE(Add(v0.D(), v1.D(), v2.D()), "add d0, d1, d2"); @@ -4050,7 +4061,7 @@ TEST(neon_scalar_3same) { TEST(neon_byelement) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Mul(v0.V4H(), v1.V4H(), v2.H(), 0), "mul v0.4h, v1.4h, v2.h[0]"); COMPARE(Mul(v2.V8H(), v3.V8H(), v15.H(), 7), "mul v2.8h, v3.8h, v15.h[7]"); @@ -4169,7 +4180,7 @@ TEST(neon_byelement) { TEST(neon_fp_byelement) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Fmul(v0.V2S(), v1.V2S(), v2.S(), 0), "fmul v0.2s, v1.2s, v2.s[0]"); COMPARE(Fmul(v2.V4S(), v3.V4S(), v15.S(), 3), "fmul v2.4s, v3.4s, v15.s[3]"); @@ -4200,7 +4211,7 @@ TEST(neon_fp_byelement) { TEST(neon_3different) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); #define DISASM_INST(TA, TAS, TB, TBS) \ COMPARE(Uaddl(v0.TA, v1.TB, v2.TB), "uaddl v0." TAS ", v1." TBS ", v2." TBS); @@ -4465,7 +4476,7 @@ TEST(neon_3different) { TEST(neon_perm) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); #define DISASM_INST(M, S) \ COMPARE(Trn1(v0.M, v1.M, v2.M), "trn1 v0." S ", v1." S ", v2." S); @@ -4502,7 +4513,7 @@ TEST(neon_perm) { TEST(neon_copy) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Ins(v1.V16B(), 4, v5.V16B(), 0), "mov v1.b[4], v5.b[0]"); COMPARE(Ins(v2.V8B(), 5, v6.V8B(), 1), "mov v2.b[5], v6.b[1]"); @@ -4618,7 +4629,7 @@ TEST(neon_copy) { TEST(neon_extract) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Ext(v4.V8B(), v5.V8B(), v6.V8B(), 0), "ext v4.8b, v5.8b, v6.8b, #0"); COMPARE(Ext(v1.V8B(), v2.V8B(), v3.V8B(), 7), "ext v1.8b, v2.8b, v3.8b, #7"); @@ -4632,7 +4643,7 @@ TEST(neon_extract) { TEST(neon_modimm) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Orr(v4.V4H(), 0xaa, 0), "orr v4.4h, #0xaa, lsl #0"); COMPARE(Orr(v1.V8H(), 0xcc, 8), "orr v1.8h, #0xcc, lsl #8"); @@ -4691,7 +4702,7 @@ TEST(neon_modimm) { TEST(neon_2regmisc) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Shll(v1.V8H(), v8.V8B(), 8), "shll v1.8h, v8.8b, #8"); COMPARE(Shll(v3.V4S(), v1.V4H(), 16), "shll v3.4s, v1.4h, #16"); @@ -5072,7 +5083,7 @@ TEST(neon_2regmisc) { } TEST(neon_acrosslanes) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Smaxv(b4, v5.V8B()), "smaxv b4, v5.8b"); COMPARE(Smaxv(b4, v5.V16B()), "smaxv b4, v5.16b"); @@ -5125,7 +5136,7 @@ TEST(neon_acrosslanes) { } TEST(neon_scalar_pairwise) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Addp(d0, v1.V2D()), "addp d0, v1.2d"); COMPARE(Faddp(s0, v1.V2S()), "faddp s0, v1.2s"); @@ -5142,7 +5153,7 @@ TEST(neon_scalar_pairwise) { } TEST(neon_shift_immediate) { - SETUP_CLASS(MacroAssembler); + SETUP_MACRO(); COMPARE(Sshr(v0.V8B(), v1.V8B(), 1), "sshr v0.8b, v1.8b, #1"); COMPARE(Sshr(v2.V8B(), v3.V8B(), 8), "sshr v2.8b, v3.8b, #8"); diff --git a/test/test-simulator-a64.cc b/test/test-simulator-a64.cc index 863fd4cc..e67177bf 100644 --- a/test/test-simulator-a64.cc +++ b/test/test-simulator-a64.cc @@ -52,7 +52,7 @@ namespace vixl { #define BUF_SIZE (256) -#ifdef USE_SIMULATOR +#ifdef VIXL_INCLUDE_SIMULATOR #define SETUP() \ MacroAssembler masm(BUF_SIZE); \ @@ -94,7 +94,7 @@ namespace vixl { #define TEARDOWN() \ delete simulator; -#else // USE_SIMULATOR +#else // VIXL_INCLUDE_SIMULATOR #define SETUP() \ MacroAssembler masm(BUF_SIZE); \ @@ -123,7 +123,7 @@ namespace vixl { #define TEARDOWN() -#endif // USE_SIMULATOR +#endif // VIXL_INCLUDE_SIMULATOR // The maximum number of errors to report in detail for each test. diff --git a/third_party/android/Android.mk.template b/third_party/android/Android.mk.template index 12472513..9a1cee6b 100644 --- a/third_party/android/Android.mk.template +++ b/third_party/android/Android.mk.template @@ -68,13 +68,15 @@ vixl_test_files := \ {vixl_test_files} vixl_cpp_flags := \ - -DUSE_SIMULATOR \ + -DVIXL_INCLUDE_SIMULATOR \ + -DVIXL_GENERATE_SIMULATOR_INSTRUCTIONS_VALUE=0 \ -Wall \ -Wextra \ -Werror \ -fdiagnostics-show-option \ -Wredundant-decls \ -Wunreachable-code \ + -Wmissing-noreturn \ -pedantic \ -std=c++11 \ @@ -105,7 +107,6 @@ LOCAL_CLANG := true LOCAL_CPP_EXTENSION := .cc LOCAL_CPPFLAGS := $(vixl_cpp_flags_release) LOCAL_CLANG_CFLAGS := -Wimplicit-fallthrough -LOCAL_CPPFLAGS_arm64 := -UUSE_SIMULATOR LOCAL_C_INCLUDES := $(vixl_include_files) LOCAL_SRC_FILES := $(vixl_src_files) LOCAL_SHARED_LIBRARIES := liblog @@ -120,7 +121,6 @@ LOCAL_CLANG := true LOCAL_CPP_EXTENSION := .cc LOCAL_CPPFLAGS := $(vixl_cpp_flags_debug) LOCAL_CLANG_CFLAGS := -Wimplicit-fallthrough -LOCAL_CPPFLAGS_arm64 := -UUSE_SIMULATOR LOCAL_C_INCLUDES := $(vixl_include_files) LOCAL_SRC_FILES := $(vixl_src_files) LOCAL_SHARED_LIBRARIES := liblog @@ -222,4 +222,5 @@ include $(BUILD_HOST_EXECUTABLE) run-vixl-tests: vixl-test-runner $(vixl_root)/third_party/android/check_top_level_android_mk.sh $(HOST_OUT)/bin/vixl-test-runner --run_all + $(HOST_OUT)/bin/vixl-test-runner --run_all --debugger @echo vixl tests PASSED diff --git a/tools/test.py b/tools/test.py index efc41ed0..b4e9da9d 100755 --- a/tools/test.py +++ b/tools/test.py @@ -227,6 +227,11 @@ def BuildOptions(): '--simulator', action='store', choices=['on', 'off'], default=sim_default, help='Explicitly enable or disable the simulator.') + general_arguments.add_argument( + '--under_valgrind', action='store_true', + help='''Run the test-runner commands under Valgrind. + Note that a few tests are known to fail because of + issues in Valgrind''') return args.parse_args() @@ -349,6 +354,9 @@ if __name__ == '__main__': args = BuildOptions() + if args.under_valgrind: + util.require_program('valgrind') + if args.fast: def SetFast(option, specified, default): option.val_test_choices = \ @@ -400,6 +408,7 @@ if __name__ == '__main__': rc |= threaded_tests.RunTests(test_executable, args.filters, list(runtime_options), + args.under_valgrind, jobs = args.jobs, prefix = prefix) if not args.nobench: diff --git a/tools/threaded_tests.py b/tools/threaded_tests.py index dcb17cbc..37001422 100644 --- a/tools/threaded_tests.py +++ b/tools/threaded_tests.py @@ -65,6 +65,7 @@ n_tests_failed = multiprocessing.Value('i', 0) # Read-only for workers. test_runner = None test_runner_runtime_options = None +test_runner_under_valgrind = False n_tests = None start_time = None progress_prefix = None @@ -72,6 +73,8 @@ progress_prefix = None def RunTest(test): command = [test_runner, test] + test_runner_runtime_options + if test_runner_under_valgrind: + command = ['valgrind'] + command p = subprocess.Popen(command, stdout=subprocess.PIPE, @@ -109,9 +112,11 @@ def RunTest(test): # multiprocessing module. __run_tests_lock__ = multiprocessing.Lock() def RunTests(test_runner_command, filters, runtime_options, + under_valgrind = False, jobs = 1, prefix = ''): global test_runner global test_runner_runtime_options + global test_runner_under_valgrind global n_tests global start_time global progress_prefix @@ -128,6 +133,7 @@ def RunTests(test_runner_command, filters, runtime_options, start_time = time.time() test_runner = test_runner_command test_runner_runtime_options = runtime_options + test_runner_under_valgrind = under_valgrind n_tests = len(tests) n_tests_passed.value = 0 n_tests_failed.value = 0 |