ager@chromium.org | 5c83825 | 2010-02-19 08:53:10 +0000 | [diff] [blame] | 1 | // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 | // Redistribution and use in source and binary forms, with or without |
| 3 | // modification, are permitted provided that the following conditions are |
| 4 | // met: |
| 5 | // |
| 6 | // * Redistributions of source code must retain the above copyright |
| 7 | // notice, this list of conditions and the following disclaimer. |
| 8 | // * Redistributions in binary form must reproduce the above |
| 9 | // copyright notice, this list of conditions and the following |
| 10 | // disclaimer in the documentation and/or other materials provided |
| 11 | // with the distribution. |
| 12 | // * Neither the name of Google Inc. nor the names of its |
| 13 | // contributors may be used to endorse or promote products derived |
| 14 | // from this software without specific prior written permission. |
| 15 | // |
| 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | |
| 28 | #include "v8.h" |
| 29 | |
| 30 | #include "disassembler.h" |
| 31 | #include "factory.h" |
| 32 | #include "macro-assembler.h" |
| 33 | #include "mips/macro-assembler-mips.h" |
| 34 | #include "mips/simulator-mips.h" |
| 35 | |
| 36 | #include "cctest.h" |
| 37 | |
| 38 | using namespace v8::internal; |
| 39 | |
| 40 | |
| 41 | // Define these function prototypes to match JSEntryFunction in execution.cc. |
| 42 | typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); |
| 43 | typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); |
| 44 | typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); |
| 45 | |
| 46 | |
| 47 | static v8::Persistent<v8::Context> env; |
| 48 | |
| 49 | |
| 50 | // The test framework does not accept flags on the command line, so we set them. |
| 51 | static void InitializeVM() { |
kmillikin@chromium.org | 5d8f0e6 | 2010-03-24 08:21:20 +0000 | [diff] [blame] | 52 | // Disable compilation of natives. |
| 53 | FLAG_disable_native_files = true; |
ager@chromium.org | 5c83825 | 2010-02-19 08:53:10 +0000 | [diff] [blame] | 54 | |
| 55 | // Enable generation of comments. |
| 56 | FLAG_debug_code = true; |
| 57 | |
| 58 | if (env.IsEmpty()) { |
| 59 | env = v8::Context::New(); |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | |
| 64 | #define __ assm. |
| 65 | |
| 66 | TEST(MIPS0) { |
| 67 | InitializeVM(); |
| 68 | v8::HandleScope scope; |
| 69 | |
| 70 | MacroAssembler assm(NULL, 0); |
| 71 | |
| 72 | // Addition. |
| 73 | __ addu(v0, a0, a1); |
| 74 | __ jr(ra); |
| 75 | __ nop(); |
| 76 | |
| 77 | CodeDesc desc; |
| 78 | assm.GetCode(&desc); |
| 79 | Object* code = Heap::CreateCode(desc, |
| 80 | NULL, |
| 81 | Code::ComputeFlags(Code::STUB), |
| 82 | Handle<Object>(Heap::undefined_value())); |
| 83 | CHECK(code->IsCode()); |
| 84 | #ifdef DEBUG |
| 85 | Code::cast(code)->Print(); |
| 86 | #endif |
| 87 | F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry()); |
| 88 | int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); |
| 89 | ::printf("f() = %d\n", res); |
| 90 | CHECK_EQ(0xabc, res); |
| 91 | } |
| 92 | |
| 93 | |
| 94 | TEST(MIPS1) { |
| 95 | InitializeVM(); |
| 96 | v8::HandleScope scope; |
| 97 | |
| 98 | MacroAssembler assm(NULL, 0); |
| 99 | Label L, C; |
| 100 | |
| 101 | __ mov(a1, a0); |
| 102 | __ li(v0, 0); |
| 103 | __ b(&C); |
| 104 | __ nop(); |
| 105 | |
| 106 | __ bind(&L); |
| 107 | __ add(v0, v0, a1); |
| 108 | __ addiu(a1, a1, -1); |
| 109 | |
| 110 | __ bind(&C); |
| 111 | __ xori(v1, a1, 0); |
ager@chromium.org | 5b2fbee | 2010-09-08 06:38:15 +0000 | [diff] [blame^] | 112 | __ Branch(ne, &L, v1, Operand(0, RelocInfo::NONE)); |
ager@chromium.org | 5c83825 | 2010-02-19 08:53:10 +0000 | [diff] [blame] | 113 | __ nop(); |
| 114 | |
| 115 | __ jr(ra); |
| 116 | __ nop(); |
| 117 | |
| 118 | CodeDesc desc; |
| 119 | assm.GetCode(&desc); |
| 120 | Object* code = Heap::CreateCode(desc, |
| 121 | NULL, |
| 122 | Code::ComputeFlags(Code::STUB), |
| 123 | Handle<Object>(Heap::undefined_value())); |
| 124 | CHECK(code->IsCode()); |
| 125 | #ifdef DEBUG |
| 126 | Code::cast(code)->Print(); |
| 127 | #endif |
| 128 | F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); |
| 129 | int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0)); |
| 130 | ::printf("f() = %d\n", res); |
| 131 | CHECK_EQ(1275, res); |
| 132 | } |
| 133 | |
| 134 | |
| 135 | TEST(MIPS2) { |
| 136 | InitializeVM(); |
| 137 | v8::HandleScope scope; |
| 138 | |
| 139 | MacroAssembler assm(NULL, 0); |
| 140 | |
| 141 | Label exit, error; |
| 142 | |
| 143 | // ----- Test all instructions. |
| 144 | |
| 145 | // Test lui, ori, and addiu, used in the li pseudo-instruction. |
| 146 | // This way we can then safely load registers with chosen values. |
| 147 | |
| 148 | __ ori(t0, zero_reg, 0); |
| 149 | __ lui(t0, 0x1234); |
| 150 | __ ori(t0, t0, 0); |
| 151 | __ ori(t0, t0, 0x0f0f); |
| 152 | __ ori(t0, t0, 0xf0f0); |
| 153 | __ addiu(t1, t0, 1); |
| 154 | __ addiu(t2, t1, -0x10); |
| 155 | |
| 156 | // Load values in temporary registers. |
| 157 | __ li(t0, 0x00000004); |
| 158 | __ li(t1, 0x00001234); |
| 159 | __ li(t2, 0x12345678); |
| 160 | __ li(t3, 0x7fffffff); |
| 161 | __ li(t4, 0xfffffffc); |
| 162 | __ li(t5, 0xffffedcc); |
| 163 | __ li(t6, 0xedcba988); |
| 164 | __ li(t7, 0x80000000); |
| 165 | |
| 166 | // SPECIAL class. |
| 167 | __ srl(v0, t2, 8); // 0x00123456 |
| 168 | __ sll(v0, v0, 11); // 0x91a2b000 |
| 169 | __ sra(v0, v0, 3); // 0xf2345600 |
| 170 | __ srav(v0, v0, t0); // 0xff234560 |
| 171 | __ sllv(v0, v0, t0); // 0xf2345600 |
| 172 | __ srlv(v0, v0, t0); // 0x0f234560 |
| 173 | __ Branch(ne, &error, v0, Operand(0x0f234560)); |
| 174 | __ nop(); |
| 175 | |
| 176 | __ add(v0, t0, t1); // 0x00001238 |
| 177 | __ sub(v0, v0, t0); // 0x00001234 |
| 178 | __ Branch(ne, &error, v0, Operand(0x00001234)); |
| 179 | __ nop(); |
| 180 | __ addu(v1, t3, t0); |
| 181 | __ Branch(ne, &error, v1, Operand(0x80000003)); |
| 182 | __ nop(); |
| 183 | __ subu(v1, t7, t0); // 0x7ffffffc |
| 184 | __ Branch(ne, &error, v1, Operand(0x7ffffffc)); |
| 185 | __ nop(); |
| 186 | |
| 187 | __ and_(v0, t1, t2); // 0x00001230 |
| 188 | __ or_(v0, v0, t1); // 0x00001234 |
| 189 | __ xor_(v0, v0, t2); // 0x1234444c |
| 190 | __ nor(v0, v0, t2); // 0xedcba987 |
| 191 | __ Branch(ne, &error, v0, Operand(0xedcba983)); |
| 192 | __ nop(); |
| 193 | |
| 194 | __ slt(v0, t7, t3); |
| 195 | __ Branch(ne, &error, v0, Operand(0x1)); |
| 196 | __ nop(); |
| 197 | __ sltu(v0, t7, t3); |
| 198 | __ Branch(ne, &error, v0, Operand(0x0)); |
| 199 | __ nop(); |
| 200 | // End of SPECIAL class. |
| 201 | |
| 202 | __ addi(v0, zero_reg, 0x7421); // 0x00007421 |
| 203 | __ addi(v0, v0, -0x1); // 0x00007420 |
| 204 | __ addiu(v0, v0, -0x20); // 0x00007400 |
| 205 | __ Branch(ne, &error, v0, Operand(0x00007400)); |
| 206 | __ nop(); |
| 207 | __ addiu(v1, t3, 0x1); // 0x80000000 |
| 208 | __ Branch(ne, &error, v1, Operand(0x80000000)); |
| 209 | __ nop(); |
| 210 | |
| 211 | __ slti(v0, t1, 0x00002000); // 0x1 |
| 212 | __ slti(v0, v0, 0xffff8000); // 0x0 |
| 213 | __ Branch(ne, &error, v0, Operand(0x0)); |
| 214 | __ nop(); |
| 215 | __ sltiu(v0, t1, 0x00002000); // 0x1 |
| 216 | __ sltiu(v0, v0, 0x00008000); // 0x1 |
| 217 | __ Branch(ne, &error, v0, Operand(0x1)); |
| 218 | __ nop(); |
| 219 | |
| 220 | __ andi(v0, t1, 0xf0f0); // 0x00001030 |
| 221 | __ ori(v0, v0, 0x8a00); // 0x00009a30 |
| 222 | __ xori(v0, v0, 0x83cc); // 0x000019fc |
| 223 | __ Branch(ne, &error, v0, Operand(0x000019fc)); |
| 224 | __ nop(); |
| 225 | __ lui(v1, 0x8123); // 0x81230000 |
| 226 | __ Branch(ne, &error, v1, Operand(0x81230000)); |
| 227 | __ nop(); |
| 228 | |
| 229 | // Everything was correctly executed. Load the expected result. |
| 230 | __ li(v0, 0x31415926); |
| 231 | __ b(&exit); |
| 232 | __ nop(); |
| 233 | |
| 234 | __ bind(&error); |
| 235 | // Got an error. Return a wrong result. |
| 236 | |
| 237 | __ bind(&exit); |
| 238 | __ jr(ra); |
| 239 | __ nop(); |
| 240 | |
| 241 | CodeDesc desc; |
| 242 | assm.GetCode(&desc); |
| 243 | Object* code = Heap::CreateCode(desc, |
| 244 | NULL, |
| 245 | Code::ComputeFlags(Code::STUB), |
| 246 | Handle<Object>(Heap::undefined_value())); |
| 247 | CHECK(code->IsCode()); |
| 248 | #ifdef DEBUG |
| 249 | Code::cast(code)->Print(); |
| 250 | #endif |
| 251 | F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry()); |
| 252 | int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); |
| 253 | ::printf("f() = %d\n", res); |
| 254 | CHECK_EQ(0x31415926, res); |
| 255 | } |
| 256 | |
| 257 | #undef __ |