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

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

Issue 1320006: Updates and fixes for MIPS support. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 months 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
Index: test/cctest/test-assembler-mips.cc
===================================================================
--- test/cctest/test-assembler-mips.cc (revision 4259)
+++ test/cctest/test-assembler-mips.cc (working copy)
@@ -104,12 +104,12 @@
__ nop();
__ bind(&L);
- __ add(v0, v0, a1);
+ __ addu(v0, v0, a1);
__ addiu(a1, a1, -1);
__ bind(&C);
__ xori(v1, a1, 0);
- __ Branch(ne, &L, v1, Operand(0));
+ __ Branch(&L, ne, v1, Operand(0));
__ nop();
__ jr(ra);
@@ -170,62 +170,81 @@
__ srav(v0, v0, t0); // 0xff234560
__ sllv(v0, v0, t0); // 0xf2345600
__ srlv(v0, v0, t0); // 0x0f234560
- __ Branch(ne, &error, v0, Operand(0x0f234560));
+ __ Branch(&error, ne, v0, Operand(0x0f234560));
__ nop();
- __ add(v0, t0, t1); // 0x00001238
- __ sub(v0, v0, t0); // 0x00001234
- __ Branch(ne, &error, v0, Operand(0x00001234));
+ __ addu(v0, t0, t1); // 0x00001238
+ __ subu(v0, v0, t0); // 0x00001234
+ __ Branch(&error, ne, v0, Operand(0x00001234));
__ nop();
__ addu(v1, t3, t0);
- __ Branch(ne, &error, v1, Operand(0x80000003));
+ __ Branch(&error, ne, v1, Operand(0x80000003));
__ nop();
__ subu(v1, t7, t0); // 0x7ffffffc
- __ Branch(ne, &error, v1, Operand(0x7ffffffc));
+ __ Branch(&error, ne, v1, Operand(0x7ffffffc));
__ nop();
__ and_(v0, t1, t2); // 0x00001230
__ or_(v0, v0, t1); // 0x00001234
__ xor_(v0, v0, t2); // 0x1234444c
__ nor(v0, v0, t2); // 0xedcba987
- __ Branch(ne, &error, v0, Operand(0xedcba983));
+ __ Branch(&error, ne, v0, Operand(0xedcba983));
__ nop();
__ slt(v0, t7, t3);
- __ Branch(ne, &error, v0, Operand(0x1));
+ __ Branch(&error, ne, v0, Operand(0x1));
__ nop();
__ sltu(v0, t7, t3);
- __ Branch(ne, &error, v0, Operand(0x0));
+ __ Branch(&error, ne, v0, Operand(0x0));
__ nop();
// End of SPECIAL class.
- __ addi(v0, zero_reg, 0x7421); // 0x00007421
- __ addi(v0, v0, -0x1); // 0x00007420
+ __ addiu(v0, zero_reg, 0x7421); // 0x00007421
+ __ addiu(v0, v0, -0x1); // 0x00007420
__ addiu(v0, v0, -0x20); // 0x00007400
- __ Branch(ne, &error, v0, Operand(0x00007400));
+ __ Branch(&error, ne, v0, Operand(0x00007400));
__ nop();
__ addiu(v1, t3, 0x1); // 0x80000000
- __ Branch(ne, &error, v1, Operand(0x80000000));
+ __ Branch(&error, ne, v1, Operand(0x80000000));
__ nop();
__ slti(v0, t1, 0x00002000); // 0x1
__ slti(v0, v0, 0xffff8000); // 0x0
- __ Branch(ne, &error, v0, Operand(0x0));
+ __ Branch(&error, ne, v0, Operand(0x0));
__ nop();
__ sltiu(v0, t1, 0x00002000); // 0x1
__ sltiu(v0, v0, 0x00008000); // 0x1
- __ Branch(ne, &error, v0, Operand(0x1));
+ __ Branch(&error, ne, v0, Operand(0x1));
__ nop();
__ andi(v0, t1, 0xf0f0); // 0x00001030
__ ori(v0, v0, 0x8a00); // 0x00009a30
__ xori(v0, v0, 0x83cc); // 0x000019fc
- __ Branch(ne, &error, v0, Operand(0x000019fc));
+ __ Branch(&error, ne, v0, Operand(0x000019fc));
__ nop();
__ lui(v1, 0x8123); // 0x81230000
- __ Branch(ne, &error, v1, Operand(0x81230000));
+ __ Branch(&error, ne, v1, Operand(0x81230000));
__ nop();
+ // Bit twiddling instructions & conditional moves.
+ // Uses t0-t7 as set above.
+ __ clz(v0, t0); // 29
+ __ clz(v1, t1); // 19
+ __ addu(v0, v0, v1); // 48
+ __ clz(v1, t2); // 3
+ __ addu(v0, v0, v1); // 51
+ __ clz(v1, t7); // 0
+ __ addu(v0, v0, v1); // 51
+ __ Branch(&error, ne, v0, Operand(51));
+ __ movn(a0, t3, t0); // move a0<-t3 (t0 is NOT 0)
+ __ ins(a0, t1, 12, 8); // 0x7ff34fff
+ __ Branch(&error, ne, a0, Operand(0x7ff34fff));
+ __ movz(a0, t6, t7); // a0 not updated (t7 is NOT 0)
+ __ ext(a1, a0, 8, 12); // 0x34f
+ __ Branch(&error, ne, a1, Operand(0x34f));
+ __ movz(a0, t6, v1); // a0<-t6, v0 is 0, from 8 instr back
+ __ Branch(&error, ne, a0, Operand(t6));
+
// Everything was correctly executed. Load the expected result.
__ li(v0, 0x31415926);
__ b(&exit);
@@ -233,6 +252,7 @@
__ bind(&error);
// Got an error. Return a wrong result.
+ __ li(v0, 666);
__ bind(&exit);
__ jr(ra);
@@ -254,4 +274,358 @@
CHECK_EQ(0x31415926, res);
}
+
+TEST(MIPS3) {
+ // Test floating point instructions.
+ InitializeVM();
+ v8::HandleScope scope;
+
+ typedef struct {
+ double a;
+ double b;
+ double c;
+ double d;
+ double e;
+ double f;
+ } T;
+ T t;
+
+ // Create a function that accepts &t, and loads, manipulates, and stores
+ // the doubles t.a ... t.f.
+ MacroAssembler assm(NULL, 0);
+ Label L, C;
+
+ __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
+ __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
+ __ add_d(f8, f4, f6);
+ __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b
+
+ __ mov_d(f10, f8); // c
+ __ neg_d(f12, f6); // -b
+ __ sub_d(f10, f10, f12);
+ __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b)
+
+ __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a
+
+ __ li(t0, 120);
+ __ mtc1(t0, f14);
+ __ cvt_d_w(f14, f14); // f14 = 120.0
+ __ mul_d(f10, f10, f14);
+ __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16
+
+ __ div_d(f12, f10, f4);
+ __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44
+
+ __ jr(ra);
+ __ nop();
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Object* code = Heap::CreateCode(desc,
+ NULL,
+ Code::ComputeFlags(Code::STUB),
+ Handle<Object>(Heap::undefined_value()));
+ CHECK(code->IsCode());
+#ifdef DEBUG
+ Code::cast(code)->Print();
+#endif
+ F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ t.a = 1.5e14;
+ t.b = 2.75e11;
+ t.c = 0.0;
+ t.d = 0.0;
+ t.e = 0.0;
+ t.f = 0.0;
+ Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+ USE(dummy);
+ CHECK_EQ(1.5e14, t.a);
+ CHECK_EQ(1.5e14, t.b);
+ CHECK_EQ(1.50275e14, t.c);
+ CHECK_EQ(1.50550e14, t.d);
+ CHECK_EQ(1.8066e16, t.e);
+ CHECK_EQ(120.44, t.f);
+}
+
+
+TEST(MIPS4) {
+ // Test moves between floating point and integer registers.
+ InitializeVM();
+ v8::HandleScope scope;
+
+ typedef struct {
+ double a;
+ double b;
+ double c;
+ } T;
+ T t;
+
+ Assembler assm(NULL, 0);
+ Label L, C;
+
+ __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
+ __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
+
+ // swap f4 and f6, by using four integer registers, t0-t3
+ __ mfc1(t0, f4);
+ __ mfc1(t1, f5);
+ __ mfc1(t2, f6);
+ __ mfc1(t3, f7);
+
+ __ mtc1(t0, f6);
+ __ mtc1(t1, f7);
+ __ mtc1(t2, f4);
+ __ mtc1(t3, f5);
+
+ // store the swapped f4 and f5 back to memory
+ __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
+ __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) );
+
+ __ jr(ra);
+ __ nop();
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Object* code = Heap::CreateCode(desc,
+ NULL,
+ Code::ComputeFlags(Code::STUB),
+ Handle<Object>(Heap::undefined_value()));
+ CHECK(code->IsCode());
+#ifdef DEBUG
+ Code::cast(code)->Print();
+#endif
+ F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ t.a = 1.5e22;
+ t.b = 2.75e11;
+ t.c = 17.17;
+ Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+ USE(dummy);
+
+ CHECK_EQ(2.75e11, t.a);
+ CHECK_EQ(2.75e11, t.b);
+ CHECK_EQ(1.5e22, t.c);
+}
+
+
+TEST(MIPS5) {
+ // Test conversions between doubles and integers
+ InitializeVM();
+ v8::HandleScope scope;
+
+ typedef struct {
+ double a;
+ double b;
+ int i;
+ int j;
+ } T;
+ T t;
+
+ Assembler assm(NULL, 0);
+ Label L, C;
+
+ // load all structure elements to registers
+ __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
+ __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
+ __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) );
+ __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) );
+
+ // convert double in f4 to int in element i
+ __ cvt_w_d(f8, f4);
+ __ mfc1(t2, f8);
+ __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) );
+
+ // convert double in f6 to int in element j
+ __ cvt_w_d(f10, f6);
+ __ mfc1(t3, f10);
+ __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) );
+
+ // convert int in original i (t0) to double in a
+ __ mtc1(t0, f12);
+ __ cvt_d_w(f0, f12);
+ __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) );
+
+ // convert int in original j (t1) to double in b
+ __ mtc1(t1, f14);
+ __ cvt_d_w(f2, f14);
+ __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) );
+
+ __ jr(ra);
+ __ nop();
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Object* code = Heap::CreateCode(desc,
+ NULL,
+ Code::ComputeFlags(Code::STUB),
+ Handle<Object>(Heap::undefined_value()));
+ CHECK(code->IsCode());
+#ifdef DEBUG
+ Code::cast(code)->Print();
+#endif
+ F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ t.a = 1.5e4;
+ t.b = 2.75e8;
+ t.i = 12345678;
+ t.j = -100000;
+ Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+ USE(dummy);
+
+ CHECK_EQ(12345678.0, t.a);
+ CHECK_EQ(-100000.0, t.b);
+ CHECK_EQ(15000, t.i);
+ CHECK_EQ(275000000, t.j);
+}
+
+
+TEST(MIPS6) {
+ // Test simple memory loads and stores
+ InitializeVM();
+ v8::HandleScope scope;
+
+ typedef struct {
+ uint32_t ui;
+ int32_t si;
+ int32_t r1;
+ int32_t r2;
+ int32_t r3;
+ int32_t r4;
+ int32_t r5;
+ int32_t r6;
+ } T;
+ T t;
+
+ Assembler assm(NULL, 0);
+ Label L, C;
+
+ // basic word load/store
+ __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) );
+ __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) );
+
+ // lh with positive data
+ __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) );
+ __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) );
+
+ // lh with negative data
+ __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) );
+ __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) );
+
+ // lhu with negative data
+ __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) );
+ __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) );
+
+ // lb with negative data
+ __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) );
+ __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) );
+
+ // sh writes only 1/2 of word
+ __ lui(t5, 0x3333);
+ __ ori(t5, t5, 0x3333);
+ __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
+ __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) );
+ __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
+
+
+ __ jr(ra);
+ __ nop();
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Object* code = Heap::CreateCode(desc,
+ NULL,
+ Code::ComputeFlags(Code::STUB),
+ Handle<Object>(Heap::undefined_value()));
+ CHECK(code->IsCode());
+#ifdef DEBUG
+ Code::cast(code)->Print();
+#endif
+ F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ t.ui = 0x11223344;
+ t.si = 0x99aabbcc;
+ Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+ USE(dummy);
+
+ CHECK_EQ(0x11223344, t.r1);
+ CHECK_EQ(0x3344, t.r2);
+ CHECK_EQ(0xffffbbcc, t.r3);
+ CHECK_EQ(0x0000bbcc, t.r4);
+ CHECK_EQ(0xffffffcc, t.r5);
+ CHECK_EQ(0x3333bbcc, t.r6);
+}
+
+
+TEST(MIPS7) {
+ // Test floating point compare and branch instructions.
+ InitializeVM();
+ v8::HandleScope scope;
+
+ typedef struct {
+ double a;
+ double b;
+ double c;
+ double d;
+ double e;
+ double f;
+ int32_t result;
+ } T;
+ T t;
+
+ // Create a function that accepts &t, and loads, manipulates, and stores
+ // the doubles t.a ... t.f.
+ MacroAssembler assm(NULL, 0);
+ Label neither_is_nan, less_than, outa_here;
+
+ __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
+ __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
+ __ c(UN, D, f4, f6);
+ __ bc1f(&neither_is_nan);
+ __ nop();
+ __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
+ __ Branch(&outa_here, al);
+
+ __ bind(&neither_is_nan);
+
+ __ c(OLT, D, f6, f4, 2);
+ __ bc1t(&less_than, 2);
+ __ nop();
+ __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
+ __ Branch(&outa_here, al);
+
+ __ bind(&less_than);
+ __ Addu(t0, zero_reg, Operand(1));
+ __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true.
+
+
+ // This test-case needs additional tests, this is not quite sufficient.
+
+ __ bind(&outa_here);
+
+ __ jr(ra);
+ __ nop();
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Object* code = Heap::CreateCode(desc,
+ NULL,
+ Code::ComputeFlags(Code::STUB),
+ Handle<Object>(Heap::undefined_value()));
+ CHECK(code->IsCode());
+#ifdef DEBUG
+ Code::cast(code)->Print();
+#endif
+ F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+ t.a = 1.5e14;
+ t.b = 2.75e11;
+ t.c = 2.0;
+ t.d = -4.0;
+ t.e = 0.0;
+ t.f = 0.0;
+ t.result = 0;
+ Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+ USE(dummy);
+ CHECK_EQ(1.5e14, t.a);
+ CHECK_EQ(2.75e11, t.b);
+ CHECK_EQ(1, t.result);
+}
+
+
+
#undef __

Powered by Google App Engine
This is Rietveld 408576698