Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Unified Diff: test/cctest/test-assembler-sh4.cc

Issue 11275184: First draft of the sh4 port Base URL: http://github.com/v8/v8.git@master
Patch Set: Use GYP and fixe some typos Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/cctest/cctest.gyp ('k') | test/cctest/test-code-stub-sh4.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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));
+}
« no previous file with comments | « test/cctest/cctest.gyp ('k') | test/cctest/test-code-stub-sh4.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698