OLD | NEW |
(Empty) | |
| 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() { |
| 52 // Disable compilation of natives by specifying an empty natives file. |
| 53 FLAG_natives_file = ""; |
| 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); |
| 112 __ Branch(ne, &L, v1, Operand(0)); |
| 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 __ |
OLD | NEW |