| Index: test/cctest/test-assembler-sh4.cc
|
| diff --git a/test/cctest/test-assembler-sh4.cc b/test/cctest/test-assembler-sh4.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8bed1d3c1cfb809d83fc64bb5b6f98fc676764cf
|
| --- /dev/null
|
| +++ b/test/cctest/test-assembler-sh4.cc
|
| @@ -0,0 +1,2157 @@
|
| +// Copyright 2011 the V8 project 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 Google Inc. 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 AND 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 "v8.h"
|
| +
|
| +#include "disassembler.h"
|
| +#include "factory.h"
|
| +#include "sh4/constants-sh4.h"
|
| +#include "sh4/simulator-sh4.h"
|
| +#include "sh4/assembler-sh4-inl.h"
|
| +#include "cctest.h"
|
| +
|
| +using namespace v8::internal;
|
| +
|
| +
|
| +// Define these function prototypes to match JSEntryFunction in execution.cc.
|
| +typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
|
| +typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
|
| +typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
|
| +typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
|
| +typedef Object* (*F5)(double x, double y, int p2, int p3, int p4);
|
| +
|
| +
|
| +static v8::Persistent<v8::Context> env;
|
| +
|
| +
|
| +static void InitializeVM() {
|
| + if (env.IsEmpty()) {
|
| + env = v8::Context::New();
|
| + }
|
| +}
|
| +
|
| +#define BEGIN() \
|
| + /* Disable compilation of natives. */ \
|
| + i::FLAG_disable_native_files = true; \
|
| + \
|
| + InitializeVM(); \
|
| + v8::HandleScope scope; \
|
| + Assembler assm(Isolate::Current(), NULL, 0);
|
| +
|
| +#define JIT() \
|
| + CodeDesc desc; \
|
| + assm.GetCode(&desc); \
|
| + Object* code = HEAP->CreateCode( \
|
| + desc, \
|
| + Code::ComputeFlags(Code::STUB), \
|
| + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); \
|
| + CHECK(code->IsCode());
|
| +
|
| +#define __ assm.
|
| +
|
| +TEST(0) {
|
| + BEGIN();
|
| +
|
| + __ add(r0, r4, r5);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(3+4, res);
|
| +}
|
| +
|
| +TEST(1) {
|
| + BEGIN();
|
| +
|
| + __ add(r0, r4, r5);
|
| + __ add(r0, r0, Operand(123456789), r4);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 1, -10, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(1-10+123456789, res);
|
| +}
|
| +
|
| +TEST(2) {
|
| + BEGIN();
|
| +
|
| + __ add(r0, r4, r5);
|
| + __ sub(r0, r0, Operand(987654), r4);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 1, -10, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(1-10-987654, res);
|
| +}
|
| +
|
| +TEST(3) {
|
| + BEGIN();
|
| +
|
| + __ rsb(r0, r4, r5);
|
| + __ rsb(r0, r0, Operand(5678), r4);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 5, 123, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(5678-(123-5), res);
|
| +}
|
| +
|
| +TEST(4) {
|
| + BEGIN();
|
| +
|
| + __ asl(r0, r4, Operand(17), r1);
|
| + __ asl(r0, r0, Operand(1));
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 42, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(42<<(17+1), res);
|
| +}
|
| +
|
| +TEST(5) {
|
| + BEGIN();
|
| +
|
| + __ asr(r1, r4, r5, false, r3);
|
| + __ asr(r1, r1, Operand(1), r3);
|
| + __ asr(r4, r4, r5, false, r3);
|
| + __ asr(r4, r4, Operand(2), r3);
|
| + __ add(r0, r4, r1);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0x7fecba98, 4,
|
| + 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ((0x7fecba98>>(4+1))+(0x7fecba98>>(4+2)), res);
|
| +}
|
| +
|
| +TEST(5b) {
|
| + BEGIN();
|
| +
|
| + __ asr(r0, r4, r5, false, r3);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 16, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(4, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 16, 32,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, -16, 32,
|
| + 0, 0, 0));
|
| + CHECK_EQ(-1, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0x80000000, 33,
|
| + 0, 0, 0));
|
| + CHECK_EQ(-1, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0x7fffffff, 33,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +TEST(5c) {
|
| + BEGIN();
|
| +
|
| + __ asr(r0, r4, r5, true, r3);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 16, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(4, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 1, 0,
|
| + 0, 0, 0));
|
| + CHECK_EQ(1, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0x80000000, 31,
|
| + 0, 0, 0));
|
| + CHECK_EQ(-1, res);
|
| +}
|
| +
|
| +TEST(6) {
|
| + BEGIN();
|
| +
|
| + __ lsl(r0, r4, Operand(14), r1);
|
| + __ lsl(r0, r0, Operand(1));
|
| + __ lsl(r4, r0, Operand(2));
|
| + __ mov(r0, Operand(0));
|
| + __ add(r4, r4, r0);
|
| + __ mov(r1, Operand(1));
|
| + __ lsl(r4, r4, r1);
|
| + __ lsl(r1, r4, r1);
|
| + __ mov(r0, r1);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 42, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(42<<(14+1+2+1+1), res);
|
| +}
|
| +
|
| +
|
| +TEST(6b) {
|
| + BEGIN();
|
| +
|
| + __ lsl(r0, r4, r5, false, r3);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 16, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(64, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 16, 32,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, -16, 32,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0x80000000, 33,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0x7fffffff, 33,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +
|
| +TEST(6c) {
|
| + BEGIN();
|
| +
|
| + __ lsl(r0, r4, r5, true, r3);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 16, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(64, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 1, 0,
|
| + 0, 0, 0));
|
| + CHECK_EQ(1, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 1, 31,
|
| + 0, 0, 0));
|
| + CHECK_EQ((1<<31), res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 1, 32,
|
| + 0, 0, 0));
|
| + CHECK_EQ(1, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 1, 33,
|
| + 0, 0, 0));
|
| + CHECK_EQ(2, res);
|
| +}
|
| +
|
| +
|
| +TEST(7) {
|
| + BEGIN();
|
| +
|
| + __ lsr(r0, r4, r5);
|
| + __ mov(r1, Operand(1));
|
| + __ lsr(r0, r0, r1, false, r3);
|
| + __ lsr(r4, r0, Operand(1));
|
| + __ lsr(r4, r4, Operand(2));
|
| + __ lsr(r0, r4, Operand(3));
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0x7fecba98, 4,
|
| + 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ((uint32_t)0x7fecba98>>(4+1+1+2+3), res);
|
| +}
|
| +
|
| +TEST(7b) {
|
| + BEGIN();
|
| +
|
| + __ lsr(r0, r4, r5, false, r3);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 16, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(4, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 16, 32,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, -16, 32,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0x80000000, 33,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0x7fffffff, 33,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +TEST(7c) {
|
| + BEGIN();
|
| +
|
| + __ lsr(r0, r4, r5, true, r3);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 16, 2,
|
| + 0, 0, 0));
|
| + CHECK_EQ(4, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 1, 0,
|
| + 0, 0, 0));
|
| + CHECK_EQ(1, res);
|
| + res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0x80000000, 31,
|
| + 0, 0, 0));
|
| + CHECK_EQ(1, res);
|
| +}
|
| +
|
| +TEST(8) {
|
| + BEGIN();
|
| +
|
| + __ mov(r0, r4);
|
| + for (int i = 0; i < 10000; i++)
|
| + __ add(r0, r0, Operand(1));
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| +// Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 12, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(10000+12, res);
|
| +}
|
| +
|
| +TEST(9) {
|
| + BEGIN();
|
| +
|
| + Label top, middle, bottom;
|
| +
|
| + __ cmpeq(r5, Operand(12), r1);
|
| + __ bt(&bottom);
|
| + __ mov(r0, Operand(0));
|
| + __ rts();
|
| +
|
| + __ bind(&top);
|
| + __ mov(r0, r4);
|
| + __ rts();
|
| +
|
| + __ bind(&middle);
|
| + __ add(r4, r4, Operand(1));
|
| + __ jmp(&top);
|
| +
|
| + __ bind(&bottom);
|
| + __ add(r4, r4, Operand(3));
|
| + __ jmp(&middle);
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 42, 12, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(42+3+1, res);
|
| +}
|
| +
|
| +TEST(10) {
|
| + BEGIN();
|
| +
|
| + Label end;
|
| + __ mov(r0, r4);
|
| +
|
| + for (int i = 0; i < 2000; i++)
|
| + __ add(r0, r0, Operand(1));
|
| + __ cmpeq(r0, Operand(0), r1);
|
| + __ bt(&end);
|
| +
|
| + for (int i = 0; i < 2000; i++)
|
| + __ add(r0, r0, Operand(1));
|
| + __ cmpeq(r0, Operand(0), r1);
|
| + __ bt(&end);
|
| +
|
| + for (int i = 0; i < 2000; i++)
|
| + __ add(r0, r0, Operand(1));
|
| + __ cmpeq(r0, Operand(0), r1);
|
| + __ bf(&end);
|
| +
|
| + for (int i = 0; i < 2000; i++)
|
| + __ add(r0, r0, Operand(1));
|
| +
|
| + __ bind(&end);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| +// Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 12, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(3*2000+12, res);
|
| +}
|
| +
|
| +
|
| +TEST(11) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ cmpeq(r4, Operand(-27), r1); // true
|
| + __ bf(&error);
|
| +
|
| + __ cmpgt(r5, Operand(546), r1); // false
|
| + __ bt(&error);
|
| +
|
| + __ cmpgt(r5, Operand(545), r1); // true
|
| + __ bf(&error);
|
| +
|
| + __ cmphi(r4, Operand(-27), r1); // false
|
| + __ bt(&error);
|
| +
|
| + __ cmphi(r4, Operand(-28), r1); // true
|
| + __ bf(&error);
|
| +
|
| + __ cmpge(r5, Operand(546), r1); // true
|
| + __ bf(&error);
|
| +
|
| + __ cmpge(r5, Operand(545), r1); // false
|
| + __ bt(&error);
|
| +
|
| + __ cmphs(r4, Operand(-27), r1); // true
|
| + __ bf(&error);
|
| +
|
| + __ cmphs(r4, Operand(-26), r1); // false
|
| + __ bt(&error);
|
| +
|
| + __ mov(r0, Operand(1));
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, Operand(1));
|
| + __ rts();
|
| +
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, -27, 546, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(1, res);
|
| +}
|
| +
|
| +TEST(12) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + __ pushm(r4.bit() | r5.bit() | r6.bit() | r7.bit());
|
| + __ popm(r0.bit() | r1.bit() | r2.bit() | r3.bit());
|
| +
|
| + __ cmpeq(r0, r4);
|
| + __ bf(&error);
|
| + __ cmpeq(r1, r5);
|
| + __ bf(&error);
|
| + __ cmpeq(r2, r6);
|
| + __ bf(&error);
|
| + __ cmpeq(r3, r7);
|
| + __ bf(&error);
|
| +
|
| + __ pushm(r4.bit() | r5.bit() | r6.bit() | r7.bit());
|
| + __ pop(r0);
|
| + __ pop(r1);
|
| + __ add(r0, r0, r1);
|
| +
|
| + __ pop(r1);
|
| + __ add(r0, r0, r1);
|
| +
|
| + __ pop(r1);
|
| + __ add(r0, r0, r1);
|
| +
|
| + __ rts();
|
| +
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, Operand(0));
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 12, 816, 53, 6543, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(12+816+53+6543, res);
|
| +}
|
| +
|
| +TEST(13) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + __ mov(r0, Operand(2));
|
| + __ push(r0);
|
| + __ mov(r0, Operand(3));
|
| + __ push(r0);
|
| + __ mov(r0, Operand(5));
|
| + __ push(r0);
|
| + __ mov(r0, Operand(7));
|
| + __ push(r0);
|
| +
|
| + __ mov(r0, MemOperand(sp, 3 * sizeof(void*)));
|
| + __ cmpeq(r0, Operand(2), r1);
|
| + __ bf(&error);
|
| +
|
| + __ mov(r0, MemOperand(sp, 2 * sizeof(void*)));
|
| + __ cmpeq(r0, Operand(3), r1);
|
| + __ bf(&error);
|
| +
|
| + __ mov(r0, MemOperand(sp, 1 * sizeof(void*)));
|
| + __ cmpeq(r0, Operand(5), r1);
|
| + __ bf(&error);
|
| +
|
| + __ mov(r0, MemOperand(sp, 0 * sizeof(void*)));
|
| + __ cmpeq(r0, Operand(7), r1);
|
| + __ bf(&error);
|
| +
|
| + __ mov(r0, Operand(1));
|
| + __ pop(r1);
|
| + __ pop(r1);
|
| + __ pop(r1);
|
| + __ pop(r1);
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ pop(r1);
|
| + __ pop(r1);
|
| + __ pop(r1);
|
| + __ pop(r1);
|
| + __ mov(r0, Operand(0));
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(1, res);
|
| +}
|
| +
|
| +TEST(14) {
|
| + BEGIN();
|
| +
|
| + Label begin, end;
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ bind(&begin);
|
| + __ cmpeq(r0, Operand(0), r1);
|
| + __ bf(&end);
|
| +
|
| + for (int i = 0; i < 10000; i++)
|
| + __ add(r0, r0, Operand(1), r1);
|
| +
|
| + __ jmp(&begin);
|
| +
|
| + __ bind(&end);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| +// Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(10000, res);
|
| +}
|
| +
|
| +TEST(15) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + __ mov(r1, Operand(1));
|
| + __ mov(r4, Operand(2147483647));
|
| + __ addv(r1, r1, r4); // set the T bit
|
| + __ bf(&error, r2);
|
| +
|
| + __ mov(r1, Operand(1));
|
| + __ mov(r4, Operand(2147483647-1));
|
| + __ addv(r1, r4, r1); // does not set the T bit
|
| + __ bt(&error, r2);
|
| +
|
| + __ mov(r1, Operand(1));
|
| + __ mov(r4, Operand(0));
|
| + __ addv(r0, r1, r4); // does not set the T bit
|
| + __ bt(&error, r2);
|
| +
|
| +
|
| + __ mov(r1, Operand(1));
|
| + __ mov(r4, Operand(-2147483647-1));
|
| + __ subv(r1, r4, r1); // set the T bit
|
| + __ bf(&error, r2);
|
| +
|
| + __ mov(r1, Operand(1));
|
| + __ mov(r4, Operand(-2147483647));
|
| + __ subv(r1, r4, r1); // does not set the T bit
|
| + __ bt(&error, r2);
|
| +
|
| + __ mov(r1, Operand(1));
|
| + __ mov(r4, Operand(0));
|
| + __ subv(r0, r1, r4); // does not set the T bit
|
| + __ bt(&error, r2);
|
| +
|
| +
|
| + __ mov(r0, Operand(1));
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, Operand(0));
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| +
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(1, res);
|
| +}
|
| +
|
| +// This macro stores in r10 the line number before branching to the error label.
|
| +// At the error label r10 can be moved to r0 such that return code of the
|
| +// function if not 0 indicates an error at the line of the branch.
|
| +#define B_LINE(cond, target) do { \
|
| + __ mov(r10, Operand(__LINE__)); \
|
| + __ b(cond, target); \
|
| + } while (0);
|
| +
|
| +// Saves sh4_rtmp (r11) and sh4_ip (r10) which are calle saved
|
| +#define PROLOGUE() \
|
| + __ push(r10); __ push(r11)
|
| +#define EPILOGUE() \
|
| + __ pop(r11); __ pop(r10)
|
| +
|
| +// Test logical and, or, xor
|
| +TEST(16) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| +
|
| + __ mov(r1, Operand(0x00ff00ff));
|
| + __ land(r1, r1, Operand(0xff00ff00), r2);
|
| + __ cmpeq(r1, Operand(0)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(0x00ffff00));
|
| + __ land(r1, r1, Operand(0xff00ff00));
|
| + __ cmpeq(r1, Operand(0x0000ff00)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0xff));
|
| + __ land(r0, r0, Operand(0x0f));
|
| + __ cmpeq(r0, Operand(0x0f)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(0x0f0));
|
| + __ mov(r2, Operand(0xfff));
|
| + __ land(r3, r1, r2);
|
| + __ cmpeq(r3, Operand(0x0f0)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ land(r1, r1, r2); // left auto-modifying
|
| + __ cmpeq(r1, Operand(0x0f0)); // true
|
| + B_LINE(f, &error);
|
| +
|
| +
|
| + __ mov(r1, Operand(0x0f0));
|
| + __ land(r1, r2, r1); // right auto-modifying
|
| + __ cmpeq(r1, Operand(0x0f0)); // true
|
| + B_LINE(f, &error);
|
| +
|
| +
|
| + __ mov(r1, Operand(0x00ff00ff));
|
| + __ lor(r1, r1, Operand(0xff00ff00));
|
| + __ cmpeq(r1, Operand(0xffffffff)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(0x00ffff00));
|
| + __ lor(r1, r1, Operand(0xff00ff00));
|
| + __ cmpeq(r1, Operand(0xffffff00)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0xf0));
|
| + __ lor(r0, r0, Operand(0x0e));
|
| + __ cmpeq(r0, Operand(0xfe)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(0x0f0));
|
| + __ mov(r2, Operand(0xf12));
|
| + __ lor(r3, r1, r2);
|
| + __ cmpeq(r3, Operand(0xff2)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ lor(r1, r1, r2); // left auto-modifying
|
| + __ cmpeq(r1, Operand(0xff2)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(0x0f0));
|
| + __ lor(r1, r2, r1); // right auto-modifying
|
| + __ cmpeq(r1, Operand(0xff2)); // true
|
| + B_LINE(f, &error);
|
| +
|
| +
|
| + __ mov(r1, Operand(0xffffffff));
|
| + __ lxor(r1, r1, Operand(0xff00ff00));
|
| + __ cmpeq(r1, Operand(0x00ff00ff)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0xff));
|
| + __ lxor(r0, r0, Operand(0x0e));
|
| + __ cmpeq(r0, Operand(0xf1)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(0xff));
|
| + __ mov(r2, Operand(0x0f));
|
| + __ lxor(r3, r1, r2);
|
| + __ cmpeq(r3, Operand(0xf0)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ lxor(r1, r1, r2); // left auto-modifying
|
| + __ cmpeq(r1, Operand(0xf0)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(0x0ff));
|
| + __ lxor(r1, r2, r1); // right auto-modifying
|
| + __ cmpeq(r1, Operand(0xf0)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(0x0ff));
|
| + __ mov(r2, Operand(0x040));
|
| + __ bic(r1, r1, r2);
|
| + __ cmpeq(r1, Operand(0xbf)); // true
|
| + B_LINE(f, &error);
|
| + __ bic(r0, r1, Operand(0x80));
|
| + __ cmpeq(r0, Operand(0x3f)); // true
|
| + B_LINE(f, &error);
|
| +
|
| + // All ok.
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| +
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +
|
| +// Test conditional moves
|
| +TEST(17) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(0));
|
| + __ mov(r2, Operand(0));
|
| + __ tst(r0, r0);
|
| + __ mov(r1, Operand(1), eq);
|
| + __ mov(r2, Operand(1), ne);
|
| + __ cmpeq(r1, Operand(1));
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r2, Operand(0));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(1));
|
| + __ mov(r1, Operand(0));
|
| + __ mov(r2, Operand(0));
|
| + __ tst(r0, r0);
|
| + __ mov(r1, Operand(1), eq);
|
| + __ mov(r2, Operand(1), ne);
|
| + __ cmpeq(r1, Operand(0));
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r2, Operand(1));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(0));
|
| + __ mov(r2, Operand(0));
|
| + __ tst(r0, r0);
|
| + __ mov(r1, Operand(0xffff), eq);
|
| + __ mov(r2, Operand(0xffff), ne);
|
| + __ cmpeq(r1, Operand(0xffff));
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r2, Operand(0));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(1));
|
| + __ mov(r1, Operand(0));
|
| + __ mov(r2, Operand(0));
|
| + __ tst(r0, r0);
|
| + __ mov(r1, Operand(0xffff), eq);
|
| + __ mov(r2, Operand(0xffff), ne);
|
| + __ cmpeq(r1, Operand(0));
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r2, Operand(0xffff));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(0));
|
| + __ mov(r2, Operand(0));
|
| + __ mov(r3, Operand(1));
|
| + __ tst(r0, r0);
|
| + __ mov(r1, r3, eq);
|
| + __ mov(r2, r3, ne);
|
| + __ cmpeq(r1, Operand(1));
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r2, Operand(0));
|
| + B_LINE(f, &error);
|
| +
|
| + // All ok.
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| +
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +
|
| +// Test addc/subc
|
| +TEST(18) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| + __ mov(r0, Operand(0xFFFFFFFE));
|
| + __ mov(r1, Operand(1));
|
| + __ addc(r2, r0, r1);
|
| + B_LINE(t, &error); // check that carry is clear
|
| + __ cmpeq(r2, Operand(0xFFFFFFFF));
|
| + B_LINE(f, &error);
|
| +
|
| + __ addc(r1, r1, r0); // left auto-modified
|
| + B_LINE(t, &error);
|
| + __ cmpeq(r1, Operand(0xFFFFFFFF));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(1));
|
| + __ addc(r1, r0, r1); // right auto-modified
|
| + B_LINE(t, &error);
|
| + __ cmpeq(r1, Operand(0xFFFFFFFF));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0xFFFFFFFF));
|
| + __ mov(r1, Operand(1));
|
| + __ addc(r2, r0, r1);
|
| + B_LINE(f, &error); // check that carry is set
|
| + __ cmpeq(r2, Operand(0));
|
| + B_LINE(f, &error);
|
| +
|
| + __ addc(r1, r1, r0); // left auto-modified
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r1, Operand(0));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(1));
|
| + __ addc(r1, r0, r1); // right auto-modified
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r1, Operand(0));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(1));
|
| + __ mov(r1, Operand(1));
|
| + __ subc(r2, r0, r1);
|
| + B_LINE(t, &error); // check that carry is clear
|
| + __ cmpeq(r2, Operand(0));
|
| + B_LINE(f, &error);
|
| +
|
| + __ subc(r0, r0, r1); // left auto-modified
|
| + B_LINE(t, &error);
|
| + __ cmpeq(r0, Operand(0));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(1));
|
| + __ subc(r1, r0, r1); // right auto-modified
|
| + B_LINE(t, &error);
|
| + __ cmpeq(r1, Operand(0));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(1));
|
| + __ subc(r2, r0, r1);
|
| + B_LINE(f, &error); // check that carry is set
|
| + __ cmpeq(r2, Operand(-1));
|
| + B_LINE(f, &error);
|
| +
|
| + __ subc(r0, r0, r1); // left auto-modified
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r0, Operand(-1));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ subc(r1, r0, r1); // right auto-modified
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r1, Operand(-1));
|
| + B_LINE(f, &error);
|
| +
|
| + // All ok.
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| +
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +// Test addv/subv
|
| +TEST(19) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| + __ mov(r0, Operand(0x7FFFFFFE));
|
| + __ mov(r1, Operand(1));
|
| + __ addv(r2, r0, r1);
|
| + B_LINE(t, &error); // check that overflow is clear
|
| + __ cmpeq(r2, Operand(0x7FFFFFFF));
|
| + B_LINE(f, &error);
|
| +
|
| + __ addv(r1, r1, r0); // left auto-modified
|
| + B_LINE(t, &error);
|
| + __ cmpeq(r1, Operand(0x7FFFFFFF));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(1));
|
| + __ addv(r1, r0, r1); // right auto-modified
|
| + B_LINE(t, &error);
|
| + __ cmpeq(r1, Operand(0x7FFFFFFF));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0x7FFFFFFF));
|
| + __ mov(r1, Operand(1));
|
| + __ addv(r2, r0, r1);
|
| + B_LINE(f, &error); // check that overflow is set
|
| + __ cmpeq(r2, Operand(0x80000000));
|
| + B_LINE(f, &error);
|
| +
|
| + __ addv(r1, r1, r0); // left auto-modified
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r1, Operand(0x80000000));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r1, Operand(1));
|
| + __ addv(r1, r0, r1); // right auto-modified
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r1, Operand(0x80000000));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0x80000001));
|
| + __ mov(r1, Operand(1));
|
| + __ subv(r2, r0, r1);
|
| + B_LINE(t, &error); // check that overflow is clear
|
| + __ cmpeq(r2, Operand(0x80000000));
|
| + B_LINE(f, &error);
|
| +
|
| + __ subv(r0, r0, r1); // left auto-modified
|
| + B_LINE(t, &error);
|
| + __ cmpeq(r0, Operand(0x80000000));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0x80000001));
|
| + __ subv(r1, r0, r1); // right auto-modified
|
| + B_LINE(t, &error);
|
| + __ cmpeq(r1, Operand(0x80000000));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0x80000000));
|
| + __ mov(r1, Operand(1));
|
| + __ subv(r2, r0, r1);
|
| + B_LINE(f, &error); // check that carry is set
|
| + __ cmpeq(r2, Operand(0x7FFFFFFF));
|
| + B_LINE(f, &error);
|
| +
|
| + __ subv(r0, r0, r1); // left auto-modified
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r0, Operand(0x7FFFFFFF));
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r0, Operand(0x80000000));
|
| + __ subv(r1, r0, r1); // right auto-modified
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r1, Operand(0x7FFFFFFF));
|
| + B_LINE(f, &error);
|
| +
|
| + // All ok.
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| +
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +TEST(20) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| + Condition cond;
|
| +
|
| + PROLOGUE();
|
| + cond = eq;
|
| + __ cmp(&cond, r4, Operand(0), r0);
|
| + CHECK_EQ(eq, cond);
|
| + B_LINE(cond, &error);
|
| +
|
| + cond = ge;
|
| + __ cmp(&cond, r4, Operand(0), r0);
|
| + CHECK_EQ(eq, cond);
|
| + B_LINE(f, &error);
|
| +
|
| + cond = lt;
|
| + __ cmp(&cond, r4, Operand(654), r0);
|
| + CHECK_EQ(ne, cond);
|
| + B_LINE(t, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| +
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 456, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +// test storing uint8 value in the cmp immediate
|
| +TEST(21) {
|
| + BEGIN();
|
| +
|
| + Label top;
|
| + __ bind(&top);
|
| + __ cmpeq(r0, r1);
|
| + __ cmpgt(r0, r1);
|
| + // > 127, ie. would normally exceed signed range
|
| + __ cmpeq_r0_unsigned_imm(173);
|
| + __ bt(&top);
|
| + __ bf(&top);
|
| + __ mov(r0, Operand(12));
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + CHECK_EQ(true, __ IsCmpRegister((reinterpret_cast<Instr*>(desc.buffer)[0])));
|
| + CHECK_EQ(false, __ IsCmpRegister((reinterpret_cast<Instr*>(desc.buffer)[1])));
|
| +
|
| + CHECK_EQ(false, __ IsCmpImmediate(reinterpret_cast<Instr*>(desc.buffer)[1]));
|
| + CHECK_EQ(true, __ IsCmpImmediate(reinterpret_cast<Instr*>(desc.buffer)[2]));
|
| + CHECK_EQ(true, (__ GetCmpImmediateRegister(
|
| + reinterpret_cast<Instr*>(desc.buffer)[2])).is(r0));
|
| + CHECK_EQ(173, __ GetCmpImmediateAsUnsigned(
|
| + reinterpret_cast<Instr*>(desc.buffer)[2]));
|
| +
|
| + CHECK_EQ(true, (__ GetRn((reinterpret_cast<Instr*>(desc.buffer)[0])).is(r0)));
|
| + CHECK_EQ(true, (__ GetRm((reinterpret_cast<Instr*>(desc.buffer)[0])).is(r1)));
|
| +
|
| + // __ bt() generate bt/nop
|
| + CHECK_EQ(eq, __ GetCondition((reinterpret_cast<Instr*>(desc.buffer)[3])));
|
| + CHECK_EQ(ne, __ GetCondition((reinterpret_cast<Instr*>(desc.buffer)[5])));
|
| +
|
| + CHECK_EQ(true, __ IsMovImmediate(reinterpret_cast<Instr*>(desc.buffer)[7]));
|
| +}
|
| +
|
| +TEST(22) {
|
| + BEGIN();
|
| +
|
| + Label function, end_function;
|
| +
|
| + __ mov(r5, Operand(1));
|
| + __ mov(r0, r4);
|
| + __ add(r0, Operand(1), r1);
|
| + __ push(pr);
|
| + __ jsr(&function);
|
| + __ pop(pr);
|
| + __ rts();
|
| +
|
| + __ bind(&function);
|
| + __ add(r0, Operand(1), r1);
|
| + __ add(r0, Operand(2), r1);
|
| + __ add(r0, Operand(3), r1);
|
| + __ add(r0, Operand(4), r1);
|
| + __ cmpeq(r5, Operand(0), r1);
|
| + __ bt(&end_function);
|
| + __ mov(r5, Operand(0));
|
| + __ push(pr);
|
| + __ jsr(&function);
|
| + __ pop(pr);
|
| +
|
| + __ bind(&end_function);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| +
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 53, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(53+1+(1+2+3+4)*2, res);
|
| +}
|
| +
|
| +TEST(22_bis) {
|
| + BEGIN();
|
| +
|
| + Label function, label;
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ bind(&function);
|
| + __ tst(r0, r0);
|
| + __ bt(&label);
|
| + __ rts();
|
| + __ bind(&label);
|
| + for (int i = 0; i < 10000; i++)
|
| + __ add(r0, r0, Operand(1), r1);
|
| +
|
| + __ push(pr);
|
| + __ jsr(&function);
|
| + __ pop(pr);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +
|
| +#ifdef DEBUG
|
| +// Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| +
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(10000, res);
|
| +}
|
| +
|
| +TEST(23) {
|
| + BEGIN();
|
| + Label error;
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ cmpeq(r0, Operand(0), r4);
|
| + __ mov(r1, Operand(0x00ff00ff));
|
| + __ mov(r2, Operand(0xff00ff00));
|
| + __ lor(r1, r1, r2, eq);
|
| + __ cmpeq(r1, Operand(0xffffffff));
|
| + __ bf(&error);
|
| +
|
| + __ cmpeq(r0, Operand(0), r4);
|
| + __ mov(r1, Operand(0x0000ff00));
|
| + __ mov(r2, Operand(0x000000ff));
|
| + __ lor(r1, r1, r2, ne);
|
| + __ cmpeq(r1, Operand(0x0000ff00), r4);
|
| + __ bf(&error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ cmpeq(r0, Operand(0), r4);
|
| + __ mov(r1, Operand(0xffff00ff));
|
| + __ lor(r1, r1, Operand(0xffffeeff), eq, r2);
|
| + __ cmpeq(r1, Operand(0xffffeeff), r2);
|
| + __ bf(&error);
|
| +
|
| + __ cmpeq(r0, Operand(0), r4);
|
| + __ mov(r1, Operand(0x0000ff00));
|
| + __ lor(r1, r1, Operand(0x000000ff), ne, r2);
|
| + __ cmpeq(r1, Operand(0x0000ff00), r2);
|
| + __ bf(&error);
|
| +
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, Operand(1));
|
| + __ rts();
|
| +
|
| + JIT();
|
| +
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| +
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +TEST(24) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + __ dmuls(r1, r0, r4, r5);
|
| + __ cmpeq(r0, r6);
|
| + __ bf(&error);
|
| + __ cmpeq(r1, r7);
|
| + __ bf(&error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, Operand(1));
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + CHECK_EQ(0, reinterpret_cast<int>(CALL_GENERATED_CODE(f, 2, 0, 0, 0, 0)));
|
| + CHECK_EQ(0, reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 12, 0)));
|
| + CHECK_EQ(0, reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 45, 0, 10*45,
|
| + 0)));
|
| + CHECK_EQ(0, reinterpret_cast<int>(
|
| + CALL_GENERATED_CODE(f, 1000000000, 10000, 2328,
|
| + 1316134912, 0)));
|
| + CHECK_EQ(0, reinterpret_cast<int>(
|
| + CALL_GENERATED_CODE(f, 123465879, 123465780, 3549226,
|
| + 1458007724, 0)));
|
| + CHECK_EQ(0, reinterpret_cast<int>(
|
| + CALL_GENERATED_CODE(f, 13246579, 0, 0, 0, 0)));
|
| +}
|
| +
|
| +TEST(25) {
|
| + BEGIN();
|
| +
|
| + Label function;
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ push(pr);
|
| +
|
| + __ call(&function);
|
| + __ add(r0, r0, Operand(1), r2);
|
| + __ add(r0, r0, Operand(1), r2);
|
| + __ add(r0, r0, Operand(1), r2);
|
| + __ add(r0, r0, Operand(1), r2);
|
| +
|
| + __ pop(pr);
|
| + __ rts();
|
| +
|
| + __ bind(&function);
|
| + // return to the second add (skiping the one just after the call)
|
| + __ strpr(r1);
|
| + __ add(r1, r1, Operand(10), r2);
|
| + __ ldrpr(r1);
|
| + __ add(r0, r0, Operand(1), r2);
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + CHECK_EQ(4, reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)));
|
| +}
|
| +
|
| +TEST(26) {
|
| + CHECK_EQ(0, strcmp(Registers::Name(1), "r1"));
|
| + CHECK_EQ(0, strcmp(Registers::Name(10), "r10"));
|
| + CHECK_EQ(0, strcmp(Registers::Name(15), "r15"));
|
| + CHECK_EQ(0, strcmp(Registers::Name(16), "noreg"));
|
| +
|
| + CHECK_EQ(0, Registers::Number("r0"));
|
| + CHECK_EQ(5, Registers::Number("r5"));
|
| + CHECK_EQ(14, Registers::Number("r14"));
|
| + CHECK_EQ(15, Registers::Number("r15"));
|
| + CHECK_EQ(14, Registers::Number("fp"));
|
| + CHECK_EQ(15, Registers::Number("sp"));
|
| + CHECK_EQ(kNoRegister, Registers::Number("r16"));
|
| +}
|
| +
|
| +
|
| +// Test load/store operations
|
| +TEST(27) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| + __ mov(r3, sp);
|
| + __ sub(sp, sp, Operand(16));
|
| +
|
| + // Test str/ldr
|
| + __ mov(r1, Operand(3));
|
| + __ str(r1, MemOperand(sp, 0));
|
| + __ mov(r1, Operand(7));
|
| + __ mov(r2, Operand(4));
|
| + __ str(r1, MemOperand(sp, r2));
|
| + __ mov(r1, Operand(9));
|
| + __ str(r1, MemOperand(sp, 8));
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldr(r0, MemOperand(sp, 0));
|
| + __ cmpeq(r0, Operand(3));
|
| + B_LINE(f, &error);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldr(r0, MemOperand(sp, r2));
|
| + __ cmpeq(r0, Operand(7));
|
| + B_LINE(f, &error);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldr(r0, MemOperand(sp, 8));
|
| + __ cmpeq(r0, Operand(9));
|
| + B_LINE(f, &error);
|
| +
|
| + // Test strh/ldrh/ldrsh
|
| + __ mov(r1, Operand(3));
|
| + __ strh(r1, MemOperand(sp, 0));
|
| + __ mov(r1, Operand(0xff07));
|
| + __ strh(r1, MemOperand(sp, 2));
|
| + __ mov(r2, Operand(4));
|
| + __ mov(r1, Operand(0x09));
|
| + __ strh(r1, MemOperand(sp, r2));
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldr(r0, MemOperand(sp, 0));
|
| + __ cmpeq(r0, Operand(0xff070003));
|
| + B_LINE(f, &error);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldrh(r0, MemOperand(sp, 0));
|
| + __ cmpeq(r0, Operand(0x03));
|
| + B_LINE(f, &error);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldrh(r0, MemOperand(sp, 2));
|
| + __ cmpeq(r0, Operand(0xff07));
|
| + B_LINE(f, &error);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldrh(r0, MemOperand(sp, r2));
|
| + __ cmpeq(r0, Operand(0x09));
|
| + B_LINE(f, &error);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldrsh(r0, MemOperand(sp, 2));
|
| + __ cmpeq(r0, Operand(0xffffff07));
|
| + B_LINE(f, &error);
|
| +
|
| + // Test strb/ldrb
|
| + __ mov(r1, Operand(3));
|
| + __ strb(r1, MemOperand(sp, 0));
|
| + __ mov(r1, Operand(0xf7));
|
| + __ mov(r2, Operand(1));
|
| + __ strb(r1, MemOperand(sp, r2));
|
| + __ mov(r1, Operand(5));
|
| + __ strb(r1, MemOperand(sp, 2));
|
| + __ mov(r1, Operand(1));
|
| + __ strb(r1, MemOperand(sp, 3));
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldr(r0, MemOperand(sp, 0));
|
| + __ cmpeq(r0, Operand(0x0105f703));
|
| + B_LINE(f, &error);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldrb(r0, MemOperand(sp, 0));
|
| + __ cmpeq(r0, Operand(0x03));
|
| + B_LINE(f, &error);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldrb(r0, MemOperand(sp, r2));
|
| + __ cmpeq(r0, Operand(0xf7));
|
| + B_LINE(f, &error);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldrb(r0, MemOperand(sp, 2));
|
| + __ cmpeq(r0, Operand(0x05));
|
| + B_LINE(f, &error);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ ldrsb(r0, MemOperand(sp, 1));
|
| + __ cmpeq(r0, Operand(0xfffffff7));
|
| + B_LINE(f, &error);
|
| +
|
| +
|
| + // Test ldr/str with Pre/post Index
|
| + __ mov(r1, Operand(3));
|
| + __ str(r1, MemOperand(sp, 0));
|
| + __ mov(r1, Operand(7));
|
| + __ str(r1, MemOperand(sp, 4));
|
| + __ mov(r1, Operand(9));
|
| + __ str(r1, MemOperand(sp, 8));
|
| +
|
| + __ mov(r2, sp);
|
| + __ ldr(r0, MemOperand(r2, 0, PostIndex));
|
| + __ cmpeq(r0, Operand(3));
|
| + B_LINE(f, &error);
|
| + __ cmpeq(r2, sp);
|
| + B_LINE(f, &error);
|
| +
|
| + __ ldr(r0, MemOperand(r2, 4, PostIndex));
|
| + __ cmpeq(r0, Operand(3));
|
| + B_LINE(f, &error);
|
| + __ add(r1, sp, Operand(4));
|
| + __ cmpeq(r1, r2);
|
| + B_LINE(f, &error);
|
| +
|
| + __ ldr(r0, MemOperand(r2, 4, PostIndex));
|
| + __ cmpeq(r0, Operand(7));
|
| + B_LINE(f, &error);
|
| + __ add(r1, sp, Operand(8));
|
| + __ cmpeq(r1, r2);
|
| + B_LINE(f, &error);
|
| +
|
| + __ ldr(r0, MemOperand(r2, 4, PostIndex));
|
| + __ cmpeq(r0, Operand(9));
|
| + B_LINE(f, &error);
|
| + __ add(r1, sp, Operand(12));
|
| + __ cmpeq(r1, r2);
|
| + B_LINE(f, &error);
|
| +
|
| + __ sub(r2, sp, Operand(4));
|
| + __ ldr(r0, MemOperand(r2, 4, PreIndex));
|
| + __ cmpeq(r0, Operand(3));
|
| + B_LINE(f, &error);
|
| + __ cmpeq(sp, r2);
|
| + B_LINE(f, &error);
|
| +
|
| + __ ldr(r0, MemOperand(r2, 4, PreIndex));
|
| + __ cmpeq(r0, Operand(7));
|
| + B_LINE(f, &error);
|
| + __ add(r1, sp, Operand(4));
|
| + __ cmpeq(r1, r2);
|
| + B_LINE(f, &error);
|
| +
|
| + __ ldr(r0, MemOperand(r2, 4, PreIndex));
|
| + __ cmpeq(r0, Operand(9));
|
| + B_LINE(f, &error);
|
| + __ add(r1, sp, Operand(8));
|
| + __ cmpeq(r1, r2);
|
| + B_LINE(f, &error);
|
| +
|
| +
|
| + __ mov(r2, sp);
|
| + __ mov(r1, Operand(4212));
|
| + __ str(r1, MemOperand(r2, 4, PostIndex));
|
| + __ mov(r1, Operand(1234));
|
| + __ str(r1, MemOperand(r2, 4, PostIndex));
|
| + __ add(r1, sp, Operand(8));
|
| + __ cmpeq(r1, r2);
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r2, sp);
|
| + __ ldr(r1, MemOperand(r2, 4, PostIndex));
|
| + __ cmpeq(r1, Operand(4212));
|
| + B_LINE(f, &error);
|
| + __ ldr(r1, MemOperand(r2, 4, PostIndex));
|
| + __ cmpeq(r1, Operand(1234));
|
| + B_LINE(f, &error);
|
| + __ add(r1, sp, Operand(8));
|
| + __ cmpeq(r1, r2);
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r2, sp);
|
| + __ mov(r1, Operand(98765));
|
| + __ str(r1, MemOperand(r2, 4, PreIndex));
|
| + __ mov(r1, Operand(0));
|
| + __ str(r1, MemOperand(r2, 4, PreIndex));
|
| + __ add(r1, sp, Operand(8));
|
| + __ cmpeq(r1, r2);
|
| + B_LINE(f, &error);
|
| +
|
| + __ mov(r2, sp);
|
| + __ ldr(r1, MemOperand(r2));
|
| + __ cmpeq(r1, Operand(4212));
|
| + B_LINE(f, &error);
|
| + __ ldr(r1, MemOperand(r2, 4, PreIndex));
|
| + __ cmpeq(r1, Operand(98765));
|
| + B_LINE(f, &error);
|
| + __ ldr(r1, MemOperand(r2, 4, PreIndex));
|
| + __ cmpeq(r1, Operand(0));
|
| + B_LINE(f, &error);
|
| + __ add(r1, sp, Operand(8));
|
| + __ cmpeq(r1, r2);
|
| + B_LINE(f, &error);
|
| +
|
| +
|
| + // All ok.
|
| + __ mov(sp, r3);
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(sp, r3);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| +
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +// Test near labels
|
| +TEST(28) {
|
| + BEGIN();
|
| +
|
| + Label l1, l2, l3, l4;
|
| +
|
| + PROLOGUE();
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ cmpeq(r4, r5);
|
| + __ bf_near(&l1);
|
| + __ bf_near(&l1);
|
| + __ bf_near(&l1);
|
| +
|
| + __ add(r0, Operand(1));
|
| + __ bind(&l1);
|
| + __ cmpeq(r4, r5);
|
| + __ bt_near(&l2);
|
| + __ bt_near(&l2);
|
| + __ bt_near(&l2);
|
| + __ bt_near(&l2);
|
| +
|
| + __ sub(r0, r0, Operand(1));
|
| + __ sub(r0, r0, Operand(1));
|
| + __ sub(r0, r0, Operand(1));
|
| + __ sub(r0, r0, Operand(1));
|
| + __ bind(&l2);
|
| + __ add(r0, Operand(1));
|
| + __ add(r0, Operand(1));
|
| + __ add(r0, Operand(1));
|
| + __ add(r0, Operand(1));
|
| +
|
| + __ bind(&l3);
|
| + __ add(r4, Operand(1));
|
| + __ cmpeq(r4, Operand(2));
|
| + __ bf_near(&l3);
|
| +
|
| + __ jmp_near(&l4);
|
| + __ jmp_near(&l4);
|
| + __ add(r0, Operand(1));
|
| + __ bind(&l4);
|
| +
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| +
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0, 1, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +TEST(29) {
|
| + BEGIN();
|
| +
|
| + Label l1;
|
| +
|
| + PROLOGUE();
|
| +
|
| + __ mov(r0, Operand(0));
|
| +
|
| + __ cmpeq(r4, r5);
|
| + __ bf_near(&l1);
|
| + for (int i = 0; i < 50; i++)
|
| + __ nop();
|
| + __ add(r0, Operand(1));
|
| + __ bind(&l1);
|
| + __ add(r0, Operand(2));
|
| +
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| +// Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 12, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(2, res);
|
| +}
|
| +
|
| +
|
| +TEST(30) {
|
| + typedef struct {
|
| + double a;
|
| + double b;
|
| + } T;
|
| + T t;
|
| + t.a = 12345.012456021864;
|
| + t.b = 0.1348714347684218;
|
| +
|
| + BEGIN();
|
| + PROLOGUE();
|
| + __ dldr(dr0, MemOperand(r4, OFFSET_OF(T, a)), r6);
|
| + __ dldr(dr2, MemOperand(r4, OFFSET_OF(T, b)), r6);
|
| +
|
| + __ dstr(dr0, MemOperand(r4, OFFSET_OF(T, b)), r6);
|
| + __ dstr(dr2, MemOperand(r4, OFFSET_OF(T, a)), r6);
|
| +
|
| + __ mov(r0, r5);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 123156, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(123156, res);
|
| + CHECK_EQ(t.a, 0.1348714347684218);
|
| + CHECK_EQ(t.b, 12345.012456021864);
|
| +}
|
| +
|
| +
|
| +TEST(31) {
|
| + Label end;
|
| +
|
| + BEGIN();
|
| + PROLOGUE();
|
| + __ dfloat(dr0, Operand(123));
|
| + __ mov(r0, Operand(0));
|
| +
|
| + __ dcmpeq(dr0, dr4);
|
| + __ bt(&end);
|
| +
|
| + __ mov(r0, Operand(1));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&end);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F5 f = FUNCTION_CAST<F5>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 123, 0, 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +
|
| +TEST(32) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| + PROLOGUE();
|
| +
|
| + __ dfloat(dr0, Operand(34));
|
| + __ fadd(dr0, dr4);
|
| + __ dfloat(dr2, Operand(456 + 34));
|
| + __ dcmpeq(dr2, dr0);
|
| + B_LINE(f, &error);
|
| +
|
| + __ dfloat(dr2, Operand(56));
|
| + __ fsub(dr0, dr2);
|
| + __ dfloat(dr2, Operand(456 + 34 - 56));
|
| + __ dcmpeq(dr2, dr0);
|
| + B_LINE(f, &error);
|
| +
|
| + __ dfloat(dr2, Operand(7));
|
| + __ fmul(dr0, dr2);
|
| + __ dfloat(dr2, Operand((456 + 34 - 56) * 7));
|
| + __ dcmpeq(dr2, dr0);
|
| + B_LINE(f, &error);
|
| +
|
| + __ dfloat(dr2, Operand(2));
|
| + __ fdiv(dr0, dr2);
|
| + __ dfloat(dr2, Operand(((456 + 34 - 56) * 7) / 2));
|
| + __ dcmpeq(dr2, dr0);
|
| + B_LINE(f, &error);
|
| +
|
| + // All ok
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F5 f = FUNCTION_CAST<F5>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 456, 0, 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +
|
| +TEST(33) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| + PROLOGUE();
|
| +
|
| + __ idouble(r1, dr4);
|
| + __ cmpeq(r1, Operand(4212));
|
| + B_LINE(f, &error);
|
| +
|
| + __ dfloat(dr2, Operand(343575789));
|
| + __ idouble(r3, dr2);
|
| + __ cmpeq(r3, Operand(343575789));
|
| + B_LINE(f, &error);
|
| +
|
| + // All ok
|
| + EPILOGUE();
|
| + __ mov(r0, Operand(0));
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + F5 f = FUNCTION_CAST<F5>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 4212, 0, 0, 0, 0));
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +
|
| +// These test case are taken from the arm ones
|
| +TEST(from_arm_2) {
|
| + BEGIN();
|
| + Label L, C;
|
| +
|
| + PROLOGUE();
|
| + __ mov(r1, r4);
|
| + __ mov(r0, Operand(1));
|
| + __ b(&C);
|
| +
|
| + __ bind(&L);
|
| + __ mul(r0, r1, r0);
|
| + __ sub(r1, r1, Operand(1));
|
| +
|
| + __ bind(&C);
|
| + __ teq(r1, Operand(0, RelocInfo::NONE));
|
| + __ b(ne, &L);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + // some relocated stuff here, not executed
|
| + __ RecordComment("dead code, just testing relocations");
|
| + __ mov(r0, Operand(FACTORY->true_value()));
|
| + __ RecordComment("dead code, just testing immediate operands");
|
| + __ mov(r0, Operand(-1));
|
| + __ mov(r0, Operand(0xFF000000));
|
| + __ mov(r0, Operand(0xF0F0F0F0));
|
| + __ mov(r0, Operand(0xFFF0FFFF));
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| + F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(3628800, res);
|
| +}
|
| +
|
| +
|
| +TEST(from_arm_3) {
|
| + BEGIN();
|
| +
|
| + typedef struct {
|
| + int i;
|
| + char c;
|
| + int16_t s;
|
| + } T;
|
| + T t;
|
| +
|
| + Label L, C;
|
| + PROLOGUE();
|
| + __ mov(r0, r4);
|
| + __ push(pr);
|
| + __ push(fp);
|
| + __ sub(fp, sp, Operand(4));
|
| +
|
| + __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)), r5);
|
| + __ asr(r2, r0, Operand(1), r5);
|
| + __ str(r2, MemOperand(r4, OFFSET_OF(T, i)), r5);
|
| +
|
| + __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
|
| + __ add(r0, r2, r0);
|
| + __ lsl(r2, r2, Operand(2));
|
| + __ strb(r2, MemOperand(r4, OFFSET_OF(T, c)), r5);
|
| +
|
| + __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)), r5);
|
| + __ add(r0, r2, r0);
|
| + __ asr(r2, r2, Operand(3));
|
| + __ strh(r2, MemOperand(r4, OFFSET_OF(T, s)), r5);
|
| +
|
| + __ pop(fp);
|
| + __ pop(pr);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
|
| + t.i = 100000;
|
| + t.c = 10;
|
| + t.s = 1000;
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(101010, res);
|
| + CHECK_EQ(100000/2, t.i);
|
| + CHECK_EQ(10*4, t.c);
|
| + CHECK_EQ(1000/8, t.s);
|
| +}
|
| +
|
| +
|
| +TEST(from_arm_4) {
|
| + // Test the FPU floating point instructions.
|
| + BEGIN();
|
| +
|
| + typedef struct {
|
| + double a;
|
| + double b;
|
| + double c;
|
| + double d;
|
| + double e;
|
| + double f;
|
| + double g;
|
| + double h;
|
| + int i;
|
| + float x;
|
| + float y;
|
| + } T;
|
| + T t;
|
| +
|
| + Label L, C;
|
| + PROLOGUE();
|
| + __ mov(r0, sp);
|
| + __ push(pr);
|
| + __ push(fp);
|
| + __ push(r4);
|
| + __ sub(fp, r0, Operand(4));
|
| +
|
| + __ dldr(dr0, MemOperand(r4, OFFSET_OF(T, a)));
|
| + __ dldr(dr2, MemOperand(r4, OFFSET_OF(T, b)));
|
| + __ fadd(dr0, dr2);
|
| + __ dstr(dr0, MemOperand(r4, OFFSET_OF(T, c)));
|
| +
|
| + __ movd(r2, r3, dr0);
|
| + __ movd(dr0, r2, r3);
|
| + __ dstr(dr0, MemOperand(r4, OFFSET_OF(T, b)));
|
| +
|
| + // Load t.x and t.y, switch values, and store back to the struct.
|
| + __ fldr(fr0, MemOperand(r4, OFFSET_OF(T, x)));
|
| + __ fldr(fr1, MemOperand(r4, OFFSET_OF(T, y)));
|
| + __ fstr(fr1, MemOperand(r4, OFFSET_OF(T, x)));
|
| + __ fstr(fr0, MemOperand(r4, OFFSET_OF(T, y)));
|
| +
|
| + // Load a double and store it as an integer
|
| + __ dldr(dr0, MemOperand(r4, OFFSET_OF(T, d)));
|
| + __ idouble(r0, dr0);
|
| + __ str(r0, MemOperand(r4, OFFSET_OF(T, i)));
|
| +
|
| + // Divisions and multiplications
|
| + __ dldr(dr0, MemOperand(r4, OFFSET_OF(T, e)));
|
| + __ dldr(dr2, MemOperand(r4, OFFSET_OF(T, f)));
|
| + __ fmul(dr2, dr0);
|
| + __ dstr(dr2, MemOperand(r4, OFFSET_OF(T, e)));
|
| +
|
| + __ dldr(dr2, MemOperand(r4, OFFSET_OF(T, f)));
|
| + __ fdiv(dr2, dr0);
|
| + __ dstr(dr2, MemOperand(r4, OFFSET_OF(T, f)));
|
| +
|
| + __ dldr(dr4, MemOperand(r4, OFFSET_OF(T, g)));
|
| + __ dldr(dr6, MemOperand(r4, OFFSET_OF(T, h)));
|
| + __ fsub(dr4, dr6);
|
| + __ dstr(dr4, MemOperand(r4, OFFSET_OF(T, g)));
|
| +
|
| + __ pop(r4);
|
| + __ pop(fp);
|
| + __ pop(pr);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| + F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
|
| + t.a = 1.5;
|
| + t.b = 2.75;
|
| + t.c = 17.17;
|
| + t.d = 17.17;
|
| + t.e = 1234.56;
|
| + t.f = 12.1;
|
| + t.g = 2718.2818;
|
| + t.h = 31415926.5;
|
| + t.i = 0;
|
| + t.x = 4.5;
|
| + t.y = 9.0;
|
| + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
|
| + USE(dummy);
|
| + CHECK_EQ(1.5, t.a);
|
| + CHECK_EQ(1.5+2.75, t.b);
|
| + CHECK_EQ(1.5+2.75, t.c);
|
| + CHECK_EQ(4.5, t.y);
|
| + CHECK_EQ(9.0, t.x);
|
| + CHECK_EQ(17, t.i);
|
| + CHECK_EQ(1234.56*12.1, t.e);
|
| + CHECK_EQ(12.1/1234.56, t.f);
|
| + CHECK_EQ(2718.2818-31415926.5, t.g);
|
| + CHECK_EQ(31415926.5, t.h);
|
| +}
|
| +
|
| +TEST(from_arm_12) {
|
| + // Test chaining of label usages within instructions (issue 1644).
|
| + BEGIN();
|
| +
|
| + Label target;
|
| + __ b(eq, &target);
|
| + __ b(ne, &target);
|
| + __ bind(&target);
|
| + __ nop();
|
| +}
|
| +
|
| +TEST(memcpy) {
|
| + BEGIN();
|
| + PROLOGUE();
|
| + __ memcpy(r4, r5, r6, r1, r2, r3, r7);
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + const char *psz_buffer = "this string will be copied to the second buffer";
|
| + char psz_dest[47 + 1] = { 0 };
|
| +
|
| + F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
| + int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, (int)psz_dest,
|
| + (int)psz_buffer, 47 + 1, 0, 0));
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| + CHECK_EQ(0, strcmp(psz_buffer, psz_dest));
|
| +}
|
|
|