| Index: test/cctest/test-macro-assembler-sh4.cc
|
| diff --git a/test/cctest/test-macro-assembler-sh4.cc b/test/cctest/test-macro-assembler-sh4.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2b5c58b59ba282d30ffe287918202e33fd1f06a7
|
| --- /dev/null
|
| +++ b/test/cctest/test-macro-assembler-sh4.cc
|
| @@ -0,0 +1,1153 @@
|
| +// 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 "macro-assembler.h"
|
| +#include "factory.h"
|
| +#include "platform.h"
|
| +#include "serialize.h"
|
| +#include "cctest.h"
|
| +
|
| +using namespace v8::internal;
|
| +
|
| +
|
| +typedef int (*F0)();
|
| +
|
| +
|
| +static v8::Persistent<v8::Context> env;
|
| +
|
| +
|
| +static void InitializeVM() {
|
| + if (env.IsEmpty()) {
|
| + env = v8::Context::New();
|
| + }
|
| +}
|
| +
|
| +// We allow use of callee saved r8-r11 for the regression tests
|
| +#define PROLOGUE() \
|
| + do { \
|
| + __ push(r8); \
|
| + __ push(r9); \
|
| + __ push(r10); \
|
| + __ push(r11); \
|
| + __ push(roots); \
|
| + ExternalReference roots_array_start = \
|
| + ExternalReference::roots_array_start(assm.isolate()); \
|
| + __ mov(roots, Operand(roots_array_start)); \
|
| + } while (0)
|
| +
|
| +#define EPILOGUE() \
|
| + do { \
|
| + __ pop(roots); \
|
| + __ pop(r11); \
|
| + __ pop(r10); \
|
| + __ pop(r9); \
|
| + __ pop(r8); \
|
| + } while (0)
|
| +
|
| +#define THE_HOLE_VALUE() (assm.isolate()->factory()->the_hole_value())
|
| +
|
| +#define NAN_VALUE() (assm.isolate()->factory()->nan_value())
|
| +
|
| +#define FALSE_VALUE() (assm.isolate()->factory()->false_value())
|
| +
|
| +#define EMPTY_STRING() (assm.isolate()->factory()->empty_string())
|
| +
|
| +#define GLOBAL_CONTEXT() (assm.isolate()->global_context())
|
| +
|
| +#define GLOBAL_CONTEXT_MAP() (assm.isolate()->factory()->global_context_map())
|
| +
|
| +#define HEAP_NUMBER_MAP() (assm.isolate()->factory()->heap_number_map())
|
| +
|
| +#define STRING_MAP() (assm.isolate()->factory()->string_map())
|
| +
|
| +#define BEGIN() \
|
| + /* Disable compilation of natives. */ \
|
| + i::FLAG_disable_native_files = true; \
|
| + i::FLAG_code_comments = true; \
|
| + \
|
| + InitializeVM(); \
|
| + v8::HandleScope scope; \
|
| + MacroAssembler 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 CMT(msg) do { Comment cmnt(&assm, msg); } while (0)
|
| +
|
| +#define __ assm.
|
| +
|
| +// 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__)); \
|
| + if (cond == al) { \
|
| + __ b(target); \
|
| + } else { \
|
| + __ b(cond, target); \
|
| + } \
|
| + } while (0);
|
| +
|
| +
|
| +// Test Move(...)
|
| +TEST(sh4_ma_0) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| +
|
| + // Verify Move with Immediate
|
| + __ Move(r0, Handle<Object>(reinterpret_cast<Object *>(0x12345678)));
|
| + __ mov(r1, Operand(0x12345678));
|
| + __ cmp(r0, r1);
|
| + B_LINE(ne, &error);
|
| +
|
| +
|
| + // Verify register move
|
| + __ mov(r0, Operand(~0x00110011)); // encodes 0xffeeffee
|
| + __ Move(r1, r0);
|
| + __ cmp(r0, r1);
|
| + B_LINE(ne, &error);
|
| +
|
| +
|
| + // Verify register move to same register does not emit anything
|
| + __ mov(r0, Operand(~0x11001100)); // encodes 0xeeffeeff
|
| + int offset = assm.pc_offset();
|
| + __ Move(r0, r0);
|
| + offset = assm.pc_offset() - offset;
|
| + __ mov(r1, Operand(offset));
|
| + __ cmp(r1, Operand(0));
|
| + B_LINE(ne, &error);
|
| +
|
| +
|
| + // All ok.
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())();
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +
|
| +// Test Bfc/Ubfx/Sbfx/Bfi/Usat
|
| +TEST(sh4_ma_1) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| +
|
| + CMT("Verify Bfc(0xfdeccdefu, 0, 32) == 0");
|
| + __ mov(r0, Operand(0xfdeccdefu));
|
| + __ mov(r1, r0);
|
| + __ Bfc(r1, 0, 32); // a full clear
|
| + __ cmp(r1, Operand(0));
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Bfc(0xfdeccdefu, 0, 31) == 0x80000000");
|
| + __ mov(r1, r0);
|
| + __ Bfc(r1, 0, 31);
|
| + __ cmp(r1, Operand(0x80000000u));
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Bfc(0xfdeccdefu, 1, 31) == 0x80000000");
|
| + __ mov(r1, r0);
|
| + __ Bfc(r1, 1, 30);
|
| + __ cmp(r1, Operand(0x80000001u));
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Bfc(0xfdeccdefu, 9, 16) == 0xfc0001ef");
|
| + __ mov(r1, r0);
|
| + __ Bfc(r1, 9, 16);
|
| + __ cmp(r1, Operand(0xfc0001efu));
|
| + B_LINE(ne, &error);
|
| +
|
| + CMT("Verify Ubfx(0xfdeccdefu, 0, 32) == 0xfdeccdef");
|
| + __ mov(r0, Operand(0xfdeccdefu));
|
| + __ Ubfx(r1, r0, 0, 32); // a mov actually
|
| + __ cmp(r1, Operand(0xfdeccdefu));
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Ubfx(0xfdeccdef, 0, 31) == 0x7deccdef");
|
| + __ Ubfx(r1, r0, 0, 31);
|
| + __ cmp(r1, Operand(0x7deccdef));
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Ubfx(0xfdeccdef, 1, 30) == 0x3ef666f7");
|
| + __ Ubfx(r1, r0, 1, 30);
|
| + __ cmp(r1, Operand(0x3ef666f7));
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Ubfx(0xfdeccdef, 9, 16) == 0xf666");
|
| + __ Ubfx(r1, r0, 9, 16);
|
| + __ cmp(r1, Operand(0xf666));
|
| + B_LINE(ne, &error);
|
| +
|
| + CMT("Verify Sbfx(0xfdeccdef, 0, 32) == 0xfdeccdef");
|
| + __ mov(r0, Operand(0xfdeccdefu));
|
| + __ Sbfx(r1, r0, 0, 32); // a mov actually
|
| + __ cmp(r1, Operand(0xfdeccdefu));
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Sbfx(0xfdeccdef, 0, 31) == 0xfdeccdef");
|
| + __ Sbfx(r1, r0, 0, 31);
|
| + __ cmp(r1, Operand(0xfdeccdefu));
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Sbfx(0xfdeccdef, 1, 31) == 0xfef666f7");
|
| + __ Sbfx(r1, r0, 1, 30);
|
| + __ cmp(r1, Operand(0xfef666f7u));
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Sbfx(0xfdeccdef, 9, 16) == 0xfffff666");
|
| + __ Sbfx(r1, r0, 9, 16);
|
| + __ cmp(r1, Operand(0xfffff666));
|
| + B_LINE(ne, &error);
|
| +
|
| + CMT("Verify Bfi(0xfdeccdef, 0xaaaaaaaa, 0, 0) == 0xfdeccdef");
|
| + __ mov(r2, Operand(0xaaaaaa));
|
| + __ mov(r0, Operand(0xfdeccdefu));
|
| + __ mov(r1, r0);
|
| + __ Bfi(r1, r2, r4, 0, 0); // a nop
|
| + __ cmp(r1, r0);
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Bfi(0xfdeccdef, 0xaaaaaaaa, 0, 32) == 0xaaaaaaaa");
|
| + __ mov(r1, r0);
|
| + __ Bfi(r1, r2, r4, 0, 32); // a mov actually
|
| + __ cmp(r1, r2);
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Bfi(0xfdeccdef, 0xaaaaaaaa, 0, 16) == 0xfdecaaaa");
|
| + __ mov(r1, r0);
|
| + __ Bfi(r1, r2, r4, 0, 16);
|
| + __ cmp(r1, Operand(0xfdecaaaau));
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Bfi(0xfdeccdef, 0xaaaaaaaa, 4, 28) == 0xfd5555ef");
|
| + __ mov(r1, r0);
|
| + __ Bfi(r1, r2, r4, 9, 16);
|
| + __ cmp(r1, Operand(0xfd5555efu));
|
| + B_LINE(ne, &error);
|
| +
|
| + CMT("Verify Usat(-10, 8) == 0");
|
| + __ mov(r0, Operand(-10));
|
| + __ Usat(r1, 8, r0);
|
| + __ cmp(r1, Operand(0));
|
| + B_LINE(ne, &error);
|
| + CMT("Verify Usat(256, 8) == 255");
|
| + __ mov(r0, Operand(256));
|
| + __ Usat(r0, 8, r0);
|
| + __ cmp(r0, Operand(255));
|
| + B_LINE(ne, &error);
|
| +
|
| + // All ok.
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())();
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +// Test Stack Pointer changes
|
| +TEST(sh4_ma_2) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| +
|
| + __ mov(r8, sp);
|
| +
|
| + __ add(sp, sp, Operand(-16));
|
| +
|
| + __ mov(sp, r8);
|
| +
|
| + __ mov(r0, Operand(0));
|
| +
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())();
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +
|
| +// Test Pop/Push
|
| +TEST(sh4_ma_3) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| +
|
| + __ mov(r8, sp);
|
| +
|
| + // Verify Pop and Push
|
| + __ mov(r0, Operand(3));
|
| + __ mov(r1, Operand(5));
|
| + __ mov(r2, Operand(7));
|
| + __ mov(r3, Operand(11));
|
| + __ Push(r0, r1);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ mov(r1, Operand(0xdeadbeef));
|
| + __ Pop(r0, r1);
|
| + __ cmp(r0, Operand(3));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r1, Operand(5));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ Push(r0, r1, r2);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ mov(r1, Operand(0xdeadbeef));
|
| + __ mov(r2, Operand(0xdeadbeef));
|
| + __ pop(r2);
|
| + __ Pop(r0, r1);
|
| + __ cmp(r0, Operand(3));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r1, Operand(5));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r2, Operand(7));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ Push(r0, r1, r2, r3);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ mov(r1, Operand(0xdeadbeef));
|
| + __ mov(r2, Operand(0xdeadbeef));
|
| + __ mov(r3, Operand(0xdeadbeef));
|
| + __ Pop(r2, r3);
|
| + __ Pop(r0, r1);
|
| + __ cmp(r0, Operand(3));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r1, Operand(5));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r2, Operand(7));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r3, Operand(11));
|
| + B_LINE(ne, &error);
|
| +
|
| +
|
| + // All ok.
|
| + __ mov(sp, r8);
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(sp, r8);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())();
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +// Test Ldrd/Strd
|
| +TEST(sh4_ma_4) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| +
|
| + __ mov(r8, sp);
|
| +
|
| + // Verify Pop and Push
|
| + __ mov(r0, Operand(3));
|
| + __ mov(r1, Operand(5));
|
| + __ mov(r2, Operand(7));
|
| + __ mov(r3, Operand(11));
|
| + __ Push(r0, r1, r2, r3);
|
| + __ mov(r0, Operand(0xdeadbeef));
|
| + __ mov(r1, Operand(0xdeadbeef));
|
| + __ mov(r2, Operand(0xdeadbeef));
|
| + __ mov(r3, Operand(0xdeadbeef));
|
| +
|
| + __ Ldrd(r0, r1, MemOperand(sp, 8));
|
| + __ cmp(r1, Operand(3));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r0, Operand(5));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ Ldrd(r2, r3, MemOperand(sp, 0));
|
| + __ cmp(r2, Operand(11));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r3, Operand(7));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r2, Operand(0xdeadbeef));
|
| + __ mov(r3, Operand(0xdeadbeef));
|
| + __ mov(r2, sp); // Test case where base is also destination
|
| + __ Ldrd(r2, r3, MemOperand(r2, 0));
|
| + __ cmp(r2, Operand(11));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r3, Operand(7));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ Strd(r0, r1, MemOperand(sp, 0));
|
| + __ Strd(r2, r3, MemOperand(sp, 8));
|
| + __ Pop(r1, r0);
|
| + __ Pop(r3, r2);
|
| + __ cmp(r0, Operand(5));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r1, Operand(3));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r2, Operand(11));
|
| + B_LINE(ne, &error);
|
| + __ cmp(r3, Operand(7));
|
| + B_LINE(ne, &error);
|
| +
|
| + // All ok.
|
| + __ mov(sp, r8);
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(sp, r8);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())();
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +
|
| +// Test JumpIfSmi(), JumpIfNotSmi(), LoadRoot(), StoreRoot(), CompareRoot(),
|
| +// CheckMap(), IsObjectStringType()
|
| +TEST(sh4_ma_5) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| +
|
| + __ LoadRoot(r1, Heap::kRealStackLimitRootIndex);
|
| + __ tst(r1, Operand(1)); // Check that it is a Smi
|
| + B_LINE(ne, &error);
|
| + __ cmphs(sp, r1); // Check that stack limit is lower than sp
|
| + B_LINE(ne, &error);
|
| +
|
| + __ LoadRoot(r0, Heap::kRealStackLimitRootIndex);
|
| + __ mov(r1, Operand(0xdead));
|
| + __ StoreRoot(r1, Heap::kRealStackLimitRootIndex);
|
| + __ LoadRoot(r1, Heap::kRealStackLimitRootIndex);
|
| + __ cmp(r1, Operand(0xdead));
|
| + B_LINE(ne, &error);
|
| + __ StoreRoot(r0, Heap::kRealStackLimitRootIndex);
|
| +
|
| + __ mov(r0, Operand(THE_HOLE_VALUE()));
|
| + __ LoadRoot(r1, Heap::kTheHoleValueRootIndex);
|
| + __ cmp(r0, r1);
|
| + B_LINE(ne, &error);
|
| + __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
|
| + B_LINE(ne, &error);
|
| +
|
| + Label is_smi1, fail_is_smi1, fail_is_smi2, skip_is_smi1, skip_is_smi2;
|
| + __ mov(r0, Operand(2)); // Smi integer 1
|
| + __ JumpIfSmi(r0, &is_smi1);
|
| + B_LINE(al, &error); // should not be there
|
| + __ bind(&is_smi1);
|
| +
|
| + __ mov(r0, Operand(1)); // Heap object 0
|
| + __ JumpIfSmi(r0, &fail_is_smi1);
|
| + __ jmp(&skip_is_smi1);
|
| + __ bind(&fail_is_smi1);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_is_smi1);
|
| +
|
| + __ mov(r0, Operand(3)); // Failure object 0
|
| + __ JumpIfSmi(r0, &fail_is_smi2);
|
| + __ jmp(&skip_is_smi2);
|
| + __ bind(&fail_is_smi2);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_is_smi2);
|
| +
|
| +
|
| + Label is_not_smi1, is_not_smi2, fail_is_not_smi1, skip_is_not_smi1;
|
| + __ mov(r0, Operand(1)); // Heap object 0
|
| + __ JumpIfNotSmi(r0, &is_not_smi1);
|
| + B_LINE(al, &error); // should not be there
|
| + __ bind(&is_not_smi1);
|
| +
|
| + __ mov(r0, Operand(3)); // Failure object 0
|
| + __ JumpIfNotSmi(r0, &is_not_smi2);
|
| + B_LINE(al, &error); // should not be there
|
| + __ bind(&is_not_smi2);
|
| +
|
| + __ mov(r0, Operand(2)); // Smi integer 1
|
| + __ JumpIfNotSmi(r0, &fail_is_not_smi1);
|
| + __ jmp(&skip_is_not_smi1);
|
| + __ bind(&fail_is_not_smi1);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_is_not_smi1);
|
| +
|
| + Label no_map1, no_map2, no_map3, no_map4, no_map5, skip_no_map1;
|
| + __ mov(r0, Operand(2)); // Smi integer 1
|
| + __ CheckMap(r0, r1/*scratch*/, GLOBAL_CONTEXT_MAP(),
|
| + &no_map1, DO_SMI_CHECK); // Check that Smi fails
|
| + B_LINE(al, &error); // should not be there
|
| + __ bind(&no_map1);
|
| +
|
| + __ mov(r0, Operand(EMPTY_STRING())); // String object
|
| + __ CheckMap(r0, r1/*scratch*/, HEAP_NUMBER_MAP(),
|
| + &no_map2, DO_SMI_CHECK); // Not the right map
|
| + B_LINE(al, &error); // should not be there
|
| + __ bind(&no_map2);
|
| +
|
| + __ mov(r0, Operand(EMPTY_STRING())); // String object
|
| + // Heap object but not the right map
|
| + __ CheckMap(r0, r1/*scratch*/, HEAP_NUMBER_MAP(),
|
| + &no_map3, DONT_DO_SMI_CHECK);
|
| + B_LINE(al, &error); // should not be there
|
| + __ bind(&no_map3);
|
| +
|
| + __ mov(r0, Operand(EMPTY_STRING())); // String object
|
| + // Heap object but not the right map
|
| + __ CheckMap(r0, r1/*scratch*/, Heap::kHeapNumberMapRootIndex,
|
| + &no_map4, DONT_DO_SMI_CHECK);
|
| + B_LINE(al, &error); // should not be there
|
| + __ bind(&no_map4);
|
| +
|
| + __ mov(r0, Operand(NAN_VALUE())); // HeapNumber object
|
| + __ CheckMap(r0, r1/*scratch*/, HEAP_NUMBER_MAP(),
|
| + &no_map5, DO_SMI_CHECK); // This is the right map
|
| + __ CheckMap(r0, r1/*scratch*/, HEAP_NUMBER_MAP(),
|
| + &no_map5, DONT_DO_SMI_CHECK);
|
| + __ CheckMap(r0, r1/*scratch*/, Heap::kHeapNumberMapRootIndex,
|
| + &no_map5, DO_SMI_CHECK);
|
| + __ CheckMap(r0, r1/*scratch*/, Heap::kHeapNumberMapRootIndex,
|
| + &no_map5, DONT_DO_SMI_CHECK);
|
| + __ jmp(&skip_no_map1);
|
| + __ bind(&no_map5);
|
| + B_LINE(al, &error); // should not be there
|
| + __ bind(&skip_no_map1);
|
| +
|
| + Label skip_is_string;
|
| + __ mov(r0, Operand(EMPTY_STRING())); // String object
|
| + Condition cond = assm.IsObjectStringType(r0, r1);
|
| + __ b(cond, &skip_is_string);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_is_string);
|
| + __ mov(r0, Operand(NAN_VALUE())); // HeapNumber object
|
| + cond = assm.IsObjectStringType(r0, r1);
|
| + B_LINE(cond, &error);
|
| +
|
| + // All ok.
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())();
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +
|
| +// Test SmiTag(), SmiUntag(), TrySmiTag(),
|
| +// GetLeastBitsFromSmi(), GetLeastBitsFromInt32()
|
| +// JumpIfNotPowerOfTwoOrZero(), JumpIfNotPowerOfTwoOrZeroAndNeg()
|
| +// JumpIfNotBothSmi()/JumpIfEitherSmi()
|
| +TEST(sh4_ma_6) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| +
|
| + __ mov(r0, Operand(1));
|
| + __ SmiTag(r0);
|
| + __ cmp(r0, Operand(2));
|
| + B_LINE(ne, &error);
|
| + __ SmiUntag(r0);
|
| + __ cmp(r0, Operand(1));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0x3fffffff));
|
| + __ SmiTag(r1, r0);
|
| + __ cmp(r1, Operand(0x7ffffffe));
|
| + B_LINE(ne, &error);
|
| + __ SmiUntag(r0, r1);
|
| + __ cmp(r0, Operand(0x3fffffff));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0xc0000000));
|
| + __ SmiTag(r0);
|
| + __ cmp(r0, Operand(0x80000000));
|
| + B_LINE(ne, &error);
|
| + __ SmiUntag(r1, r0);
|
| + __ cmp(r1, Operand(0xc0000000));
|
| + B_LINE(ne, &error);
|
| +
|
| + CMT("Check GetLeastBitsFromSmi(Smi(33), 5) == 1");
|
| + __ mov(r0, Operand(33<<1));
|
| + __ mov(r2, Operand(1));
|
| + __ GetLeastBitsFromSmi(r1, r0, 5);
|
| + __ cmp(r1, r2);
|
| + B_LINE(ne, &error);
|
| +
|
| + CMT("Check GetLeastBitsFromInt32(34, 5) == 2");
|
| + __ mov(r0, Operand(34));
|
| + __ mov(r2, Operand(2));
|
| + __ GetLeastBitsFromInt32(r1, r0, 5);
|
| + __ cmp(r1, r2);
|
| + B_LINE(ne, &error);
|
| +
|
| + Label not_smi1, not_smi2, not_smi3, skip_smi1;
|
| + __ mov(r0, Operand(0xc0000000));
|
| + __ TrySmiTag(r0, ¬_smi1, r1/*scratch*/);
|
| + __ cmp(r0, Operand(0x80000000));
|
| + B_LINE(ne, &error);
|
| + __ jmp(&skip_smi1);
|
| + __ bind(¬_smi1);
|
| + B_LINE(ne, &error);
|
| + __ bind(&skip_smi1);
|
| +
|
| + __ mov(r0, Operand(0x80000000)); // not a smi
|
| + __ TrySmiTag(r0, ¬_smi2, r1/*scratch*/);
|
| + B_LINE(ne, &error);
|
| + __ bind(¬_smi2);
|
| +
|
| + __ mov(r0, Operand(0x40000000)); // not a smi
|
| + __ TrySmiTag(r0, ¬_smi3, r1/*scratch*/);
|
| + B_LINE(ne, &error);
|
| + __ bind(¬_smi3);
|
| +
|
| +
|
| + Label not_power1, not_power2, not_power3, not_power4,
|
| + skip_power1, skip_power2, skip_power3;
|
| + __ mov(r0, Operand(0));
|
| + __ JumpIfNotPowerOfTwoOrZero(r0, r1, ¬_power1);
|
| + B_LINE(al, &error);
|
| + __ bind(¬_power1);
|
| +
|
| + __ mov(r0, Operand(0x80000000));
|
| + // r1 will contain (r0 - 1) (the power of two mask)
|
| + __ JumpIfNotPowerOfTwoOrZero(r0, r1, ¬_power2);
|
| + __ jmp(&skip_power2);
|
| + __ bind(¬_power2);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_power2);
|
| + __ cmp(r1, Operand(0x7fffffff));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(1));
|
| + __ JumpIfNotPowerOfTwoOrZero(r0, r1, ¬_power2);
|
| + __ jmp(&skip_power3);
|
| + __ bind(¬_power3);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_power3);
|
| + __ cmp(r1, Operand(0));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0x30));
|
| + __ JumpIfNotPowerOfTwoOrZero(r0, r1, ¬_power4);
|
| + B_LINE(al, &error);
|
| + __ bind(¬_power4);
|
| +
|
| + Label not_pow1, zero_neg1, not_pow2, zero_neg2, not_pow3, zero_neg3,
|
| + not_pow4, zero_neg4, not_pow5, zero_neg5, not_pow6, zero_neg6,
|
| + skip_pow5, skip_pow6, skip_pow2;
|
| + __ mov(r0, Operand(0));
|
| + __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg1, ¬_pow1);
|
| + B_LINE(al, &error);
|
| + __ bind(¬_pow1);
|
| + B_LINE(al, &error);
|
| + __ bind(&zero_neg1);
|
| +
|
| + __ mov(r0, Operand(0x80000000));
|
| + __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg2, ¬_pow2);
|
| + __ jmp(&skip_pow2);
|
| + __ bind(¬_pow2);
|
| + B_LINE(al, &error);
|
| + __ bind(&zero_neg2);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_pow2);
|
| + __ cmp(r1, Operand(0x7fffffff));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(-1));
|
| + __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg3, ¬_pow3);
|
| + B_LINE(al, &error);
|
| + __ bind(¬_pow3);
|
| + B_LINE(al, &error);
|
| + __ bind(&zero_neg3);
|
| +
|
| + __ mov(r0, Operand(0x30));
|
| + __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg4, ¬_pow4);
|
| + B_LINE(al, &error);
|
| + __ bind(&zero_neg4);
|
| + B_LINE(al, &error);
|
| + __ bind(¬_pow4);
|
| +
|
| + __ mov(r0, Operand(1));
|
| + __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg5, ¬_pow5);
|
| + __ jmp(&skip_pow5);
|
| + __ bind(¬_pow5);
|
| + B_LINE(al, &error);
|
| + __ bind(&zero_neg5);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_pow5);
|
| + __ cmp(r1, Operand(0));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0x40000000));
|
| + __ JumpIfNotPowerOfTwoOrZeroAndNeg(r0, r1, &zero_neg6, ¬_pow6);
|
| + __ jmp(&skip_pow6);
|
| + __ bind(¬_pow6);
|
| + B_LINE(al, &error);
|
| + __ bind(&zero_neg6);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_pow6);
|
| + __ cmp(r1, Operand(0x3fffffff));
|
| + B_LINE(ne, &error);
|
| +
|
| + Label not_both_smi1, skip_not_both_smi1, not_both_smi2, not_both_smi3,
|
| + not_both_smi4;
|
| + CMT("Check JumpIfNotBothSmi(): both Smi");
|
| + __ mov(r0, Operand(Smi::FromInt(1)));
|
| + __ mov(r1, Operand(Smi::FromInt(2)));
|
| + __ JumpIfNotBothSmi(r0, r1, ¬_both_smi1);
|
| + __ jmp(&skip_not_both_smi1);
|
| + __ bind(¬_both_smi1);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_not_both_smi1);
|
| +
|
| + CMT("Check JumpIfNotBothSmi(): left Smi");
|
| + __ mov(r0, Operand(Smi::FromInt(1)));
|
| + __ mov(r1, Operand(0x41)); // not a smi
|
| + __ JumpIfNotBothSmi(r0, r1, ¬_both_smi2);
|
| + B_LINE(al, &error);
|
| + __ bind(¬_both_smi2);
|
| +
|
| + CMT("Check JumpIfNotBothSmi(): right Smi");
|
| + __ JumpIfNotBothSmi(r1, r0, ¬_both_smi3);
|
| + B_LINE(al, &error);
|
| + __ bind(¬_both_smi3);
|
| +
|
| + CMT("Check JumpIfNotBothSmi(): none Smi");
|
| + __ mov(r0, Operand(0x33)); // not a smi
|
| + __ JumpIfNotBothSmi(r1, r0, ¬_both_smi4);
|
| + B_LINE(al, &error);
|
| + __ bind(¬_both_smi4);
|
| +
|
| +
|
| + Label either_smi1, either_smi2, either_smi3, either_smi4,
|
| + skip_either_smi4;
|
| + CMT("Check JumpIfEitherSmi(): both Smi");
|
| + __ mov(r0, Operand(Smi::FromInt(1)));
|
| + __ mov(r1, Operand(Smi::FromInt(2)));
|
| + __ JumpIfEitherSmi(r0, r1, &either_smi1);
|
| + B_LINE(al, &error);
|
| + __ bind(&either_smi1);
|
| +
|
| + CMT("Check JumpIfEitherSmi(): left Smi");
|
| + __ mov(r0, Operand(Smi::FromInt(1)));
|
| + __ mov(r1, Operand(0x41)); // not a smi
|
| + __ JumpIfEitherSmi(r0, r1, &either_smi2);
|
| + B_LINE(al, &error);
|
| + __ bind(&either_smi2);
|
| +
|
| + CMT("Check JumpIfEitherSmi(): right Smi");
|
| + __ JumpIfEitherSmi(r1, r0, &either_smi3);
|
| + B_LINE(al, &error);
|
| + __ bind(&either_smi3);
|
| +
|
| + CMT("Check JumpIfEitherSmi(): none Smi");
|
| + __ mov(r0, Operand(0x33)); // not a smi also
|
| + __ JumpIfEitherSmi(r1, r0, &either_smi4);
|
| + __ jmp(&skip_either_smi4);
|
| + __ bind(&either_smi4);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_either_smi4);
|
| +
|
| +
|
| + // All ok.
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())();
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +
|
| +// Test ConvertToInt32()
|
| +TEST(sh4_ma_7) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| + PROLOGUE();
|
| +
|
| + Label not_int32_1, skip_int32_1, not_int32_2, not_int32_3;
|
| + Handle<Object> num;
|
| + CMT("Check ConvertToInt32(4.1) == 4");
|
| + num = assm.isolate()->factory()->NewNumber(4.1, TENURED);
|
| + __ mov(r0, Operand(4));
|
| + __ mov(r1, Operand(num));
|
| + __ ConvertToInt32(r1, r2, r3, r4, dr0, ¬_int32_1);
|
| + __ cmp(r2, r0);
|
| + B_LINE(ne, &error);
|
| + __ jmp(&skip_int32_1);
|
| + __ bind(¬_int32_1);
|
| + B_LINE(al, &error);
|
| + __ bind(&skip_int32_1);
|
| +
|
| + CMT("Check ConvertToInt32(nan) == not int32");
|
| + __ mov(r1, Operand(NAN_VALUE()));
|
| + __ ConvertToInt32(r1, r2, r3, r4, dr0, ¬_int32_2);
|
| + B_LINE(al, &error);
|
| + __ bind(¬_int32_2);
|
| +
|
| + CMT("Check ConvertToInt32(0X80000000) == not int32");
|
| + num = assm.isolate()->factory()->NewNumber(static_cast<double>(0x80000000U),
|
| + TENURED);
|
| + __ mov(r1, Operand(num));
|
| + __ ConvertToInt32(r1, r2, r3, r4, dr0, ¬_int32_3);
|
| + B_LINE(al, &error);
|
| + __ bind(¬_int32_3);
|
| +
|
| + // All ok.
|
| + __ mov(r0, Operand(0));
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())();
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +// Test CountLeadingZeros
|
| +TEST(sh4_ma_8) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(0));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(32));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(1));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(31));
|
| + B_LINE(ne, &error);
|
| +
|
| + // Test same register for input and output
|
| + __ mov(r0, Operand(3));
|
| + __ CountLeadingZeros(r0, r0, r3);
|
| + __ cmpeq(r0, Operand(30));
|
| + B_LINE(ne, &error);
|
| +
|
| + // Test same register for input and scratch
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(5));
|
| + __ CountLeadingZeros(r0, r1, r1);
|
| + __ cmpeq(r0, Operand(29));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(13));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(28));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(24));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(27));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(41));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(26));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(83));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(25));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(211));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(24));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(467));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(23));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(726));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(22));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(1782));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(21));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(3824));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(20));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(4336));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(19));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(8388607));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(9));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(1082130431));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(1));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ mov(r0, Operand(0));
|
| + __ mov(r1, Operand(3229614079u));
|
| + __ CountLeadingZeros(r0, r1, r3);
|
| + __ cmpeq(r0, Operand(0));
|
| + B_LINE(ne, &error);
|
| +
|
| +
|
| +
|
| + EPILOGUE();
|
| + __ mov(r0, Operand(0));
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())();
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
| +
|
| +// Test CopyBytes
|
| +TEST(sh4_ma_9) {
|
| + BEGIN();
|
| +
|
| + Label error;
|
| +
|
| + PROLOGUE();
|
| +
|
| + // Push garbage values on the stack
|
| + __ push(Operand(0xdeadbeef));
|
| + __ push(Operand(0xdeadbeef));
|
| + __ push(Operand(0xdeadbeef));
|
| + __ push(Operand(0xdeadbeef));
|
| + __ push(Operand(0xdeadbeef));
|
| + __ push(Operand(0xdeadbeef));
|
| + __ push(Operand(0xdeadbeef));
|
| + __ push(Operand(0xdeadbeef));
|
| + __ push(Operand(0xdeadbeef));
|
| + __ push(Operand(0xdeadbeef));
|
| + __ mov(r0, sp);
|
| +
|
| + // Push nice values that will be copied
|
| + __ push(Operand(0xf0000000));
|
| + __ push(Operand(0x0f000000));
|
| + __ push(Operand(0x00f00000));
|
| + __ push(Operand(0x000f0000));
|
| + __ push(Operand(0x00000f00));
|
| + __ push(Operand(0x000000f0));
|
| + __ push(Operand(0x0000000f));
|
| + __ push(Operand(0x13453abb));
|
| + __ push(Operand(0xabcdef01));
|
| + __ push(Operand(0x789abcde));
|
| + __ mov(r1, sp);
|
| +
|
| + __ mov(r2, Operand(40));
|
| + __ CopyBytes(r1, r0, r2, r3);
|
| +
|
| + // Check that the src is untouched
|
| +#define POP_AND_CHECK(addr, val) \
|
| + __ pop(r0); \
|
| + __ cmpeq(r0, Operand(addr)); \
|
| + __ mov(r1, Operand(val)); \
|
| + B_LINE(ne, &error);
|
| +
|
| + POP_AND_CHECK(0x789abcde, 19 * 4);
|
| + POP_AND_CHECK(0xabcdef01, 18 * 4);
|
| + POP_AND_CHECK(0x13453abb, 17 * 4);
|
| + POP_AND_CHECK(0x0000000f, 16 * 4);
|
| + POP_AND_CHECK(0x000000f0, 15 * 4);
|
| + POP_AND_CHECK(0x00000f00, 14 * 4);
|
| + POP_AND_CHECK(0x000f0000, 13 * 4);
|
| + POP_AND_CHECK(0x00f00000, 12 * 4);
|
| + POP_AND_CHECK(0x0f000000, 11 * 4);
|
| + POP_AND_CHECK(0xf0000000, 10 * 4);
|
| +
|
| + // check that the dst is modified
|
| + POP_AND_CHECK(0x789abcde, 9 * 4);
|
| + POP_AND_CHECK(0xabcdef01, 8 * 4);
|
| + POP_AND_CHECK(0x13453abb, 7 * 4);
|
| + POP_AND_CHECK(0x0000000f, 6 * 4);
|
| + POP_AND_CHECK(0x000000f0, 5 * 4);
|
| + POP_AND_CHECK(0x00000f00, 4 * 4);
|
| + POP_AND_CHECK(0x000f0000, 3 * 4);
|
| + POP_AND_CHECK(0x00f00000, 2 * 4);
|
| + POP_AND_CHECK(0x0f000000, 1 * 4);
|
| + POP_AND_CHECK(0xf0000000, 0 * 4);
|
| +
|
| +#undef POP_AND_CHECK
|
| +
|
| + // Test that copying 0 bytes dos not do anything
|
| + __ push(Operand(0xdeadbeef));
|
| + __ mov(r0, sp);
|
| + __ push(Operand(0x00000ff0));
|
| + __ mov(r1, sp);
|
| +
|
| + __ mov(r2, Operand(0));
|
| + __ CopyBytes(r1, r0, r2, r3);
|
| + __ pop(r0);
|
| + __ cmpeq(r0, Operand(0x00000ff0));
|
| + __ mov(r1, Operand(1 * 4));
|
| + B_LINE(ne, &error);
|
| +
|
| + __ pop(r0);
|
| + __ cmpeq(r0, Operand(0xdeadbeef));
|
| + __ mov(r1, Operand(0 * 4));
|
| + B_LINE(ne, &error);
|
| +
|
| + EPILOGUE();
|
| + __ mov(r0, Operand(0));
|
| + __ rts();
|
| +
|
| + __ bind(&error);
|
| + __ add(sp, sp, r1);
|
| + __ mov(r0, r10);
|
| + EPILOGUE();
|
| + __ rts();
|
| +
|
| + JIT();
|
| +#ifdef DEBUG
|
| + Code::cast(code)->Print();
|
| +#endif
|
| +
|
| + int res = FUNCTION_CAST<F0>(Code::cast(code)->entry())();
|
| + ::printf("f() = %d\n", res);
|
| + CHECK_EQ(0, res);
|
| +}
|
|
|