| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "src/v8.h" | 28 #include "src/v8.h" |
| 29 | 29 |
| 30 #include "src/disassembler.h" | 30 #include "src/disassembler.h" |
| 31 #include "src/factory.h" | 31 #include "src/factory.h" |
| 32 #include "src/macro-assembler.h" | 32 #include "src/macro-assembler.h" |
| 33 #include "src/mips/macro-assembler-mips.h" | 33 #include "src/mips64/macro-assembler-mips64.h" |
| 34 #include "src/mips/simulator-mips.h" | 34 #include "src/mips64/simulator-mips64.h" |
| 35 | 35 |
| 36 #include "test/cctest/cctest.h" | 36 #include "test/cctest/cctest.h" |
| 37 | 37 |
| 38 using namespace v8::internal; | 38 using namespace v8::internal; |
| 39 | 39 |
| 40 | 40 |
| 41 // Define these function prototypes to match JSEntryFunction in execution.cc. | 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); | 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); | 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); | 44 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 57 // Addition. | 57 // Addition. |
| 58 __ addu(v0, a0, a1); | 58 __ addu(v0, a0, a1); |
| 59 __ jr(ra); | 59 __ jr(ra); |
| 60 __ nop(); | 60 __ nop(); |
| 61 | 61 |
| 62 CodeDesc desc; | 62 CodeDesc desc; |
| 63 assm.GetCode(&desc); | 63 assm.GetCode(&desc); |
| 64 Handle<Code> code = isolate->factory()->NewCode( | 64 Handle<Code> code = isolate->factory()->NewCode( |
| 65 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 65 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 66 F2 f = FUNCTION_CAST<F2>(code->entry()); | 66 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 67 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); | 67 int64_t res = |
| 68 ::printf("f() = %d\n", res); | 68 reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); |
| 69 CHECK_EQ(0xabc, res); | 69 ::printf("f() = %ld\n", res); |
| 70 CHECK_EQ(0xabcL, res); |
| 70 } | 71 } |
| 71 | 72 |
| 72 | 73 |
| 73 TEST(MIPS1) { | 74 TEST(MIPS1) { |
| 74 CcTest::InitializeVM(); | 75 CcTest::InitializeVM(); |
| 75 Isolate* isolate = CcTest::i_isolate(); | 76 Isolate* isolate = CcTest::i_isolate(); |
| 76 HandleScope scope(isolate); | 77 HandleScope scope(isolate); |
| 77 | 78 |
| 78 MacroAssembler assm(isolate, NULL, 0); | 79 MacroAssembler assm(isolate, NULL, 0); |
| 79 Label L, C; | 80 Label L, C; |
| 80 | 81 |
| 81 __ mov(a1, a0); | 82 __ mov(a1, a0); |
| 82 __ li(v0, 0); | 83 __ li(v0, 0); |
| 83 __ b(&C); | 84 __ b(&C); |
| 84 __ nop(); | 85 __ nop(); |
| 85 | 86 |
| 86 __ bind(&L); | 87 __ bind(&L); |
| 87 __ addu(v0, v0, a1); | 88 __ addu(v0, v0, a1); |
| 88 __ addiu(a1, a1, -1); | 89 __ addiu(a1, a1, -1); |
| 89 | 90 |
| 90 __ bind(&C); | 91 __ bind(&C); |
| 91 __ xori(v1, a1, 0); | 92 __ xori(v1, a1, 0); |
| 92 __ Branch(&L, ne, v1, Operand(0)); | 93 __ Branch(&L, ne, v1, Operand((int64_t)0)); |
| 93 __ nop(); | 94 __ nop(); |
| 94 | 95 |
| 95 __ jr(ra); | 96 __ jr(ra); |
| 96 __ nop(); | 97 __ nop(); |
| 97 | 98 |
| 98 CodeDesc desc; | 99 CodeDesc desc; |
| 99 assm.GetCode(&desc); | 100 assm.GetCode(&desc); |
| 100 Handle<Code> code = isolate->factory()->NewCode( | 101 Handle<Code> code = isolate->factory()->NewCode( |
| 101 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 102 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 102 F1 f = FUNCTION_CAST<F1>(code->entry()); | 103 F1 f = FUNCTION_CAST<F1>(code->entry()); |
| 103 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0)); | 104 int64_t res = |
| 104 ::printf("f() = %d\n", res); | 105 reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0)); |
| 105 CHECK_EQ(1275, res); | 106 ::printf("f() = %ld\n", res); |
| 107 CHECK_EQ(1275L, res); |
| 106 } | 108 } |
| 107 | 109 |
| 108 | 110 |
| 109 TEST(MIPS2) { | 111 TEST(MIPS2) { |
| 110 CcTest::InitializeVM(); | 112 CcTest::InitializeVM(); |
| 111 Isolate* isolate = CcTest::i_isolate(); | 113 Isolate* isolate = CcTest::i_isolate(); |
| 112 HandleScope scope(isolate); | 114 HandleScope scope(isolate); |
| 113 | 115 |
| 114 MacroAssembler assm(isolate, NULL, 0); | 116 MacroAssembler assm(isolate, NULL, 0); |
| 115 | 117 |
| 116 Label exit, error; | 118 Label exit, error; |
| 117 | 119 |
| 118 // ----- Test all instructions. | 120 // ----- Test all instructions. |
| 119 | 121 |
| 120 // Test lui, ori, and addiu, used in the li pseudo-instruction. | 122 // Test lui, ori, and addiu, used in the li pseudo-instruction. |
| 121 // This way we can then safely load registers with chosen values. | 123 // This way we can then safely load registers with chosen values. |
| 122 | 124 |
| 123 __ ori(t0, zero_reg, 0); | 125 __ ori(a4, zero_reg, 0); |
| 124 __ lui(t0, 0x1234); | 126 __ lui(a4, 0x1234); |
| 125 __ ori(t0, t0, 0); | 127 __ ori(a4, a4, 0); |
| 126 __ ori(t0, t0, 0x0f0f); | 128 __ ori(a4, a4, 0x0f0f); |
| 127 __ ori(t0, t0, 0xf0f0); | 129 __ ori(a4, a4, 0xf0f0); |
| 128 __ addiu(t1, t0, 1); | 130 __ addiu(a5, a4, 1); |
| 129 __ addiu(t2, t1, -0x10); | 131 __ addiu(a6, a5, -0x10); |
| 130 | 132 |
| 131 // Load values in temporary registers. | 133 // Load values in temporary registers. |
| 132 __ li(t0, 0x00000004); | 134 __ li(a4, 0x00000004); |
| 133 __ li(t1, 0x00001234); | 135 __ li(a5, 0x00001234); |
| 134 __ li(t2, 0x12345678); | 136 __ li(a6, 0x12345678); |
| 135 __ li(t3, 0x7fffffff); | 137 __ li(a7, 0x7fffffff); |
| 136 __ li(t4, 0xfffffffc); | 138 __ li(t0, 0xfffffffc); |
| 137 __ li(t5, 0xffffedcc); | 139 __ li(t1, 0xffffedcc); |
| 138 __ li(t6, 0xedcba988); | 140 __ li(t2, 0xedcba988); |
| 139 __ li(t7, 0x80000000); | 141 __ li(t3, 0x80000000); |
| 140 | 142 |
| 141 // SPECIAL class. | 143 // SPECIAL class. |
| 142 __ srl(v0, t2, 8); // 0x00123456 | 144 __ srl(v0, a6, 8); // 0x00123456 |
| 143 __ sll(v0, v0, 11); // 0x91a2b000 | 145 __ sll(v0, v0, 11); // 0x91a2b000 |
| 144 __ sra(v0, v0, 3); // 0xf2345600 | 146 __ sra(v0, v0, 3); // 0xf2345600 |
| 145 __ srav(v0, v0, t0); // 0xff234560 | 147 __ srav(v0, v0, a4); // 0xff234560 |
| 146 __ sllv(v0, v0, t0); // 0xf2345600 | 148 __ sllv(v0, v0, a4); // 0xf2345600 |
| 147 __ srlv(v0, v0, t0); // 0x0f234560 | 149 __ srlv(v0, v0, a4); // 0x0f234560 |
| 148 __ Branch(&error, ne, v0, Operand(0x0f234560)); | 150 __ Branch(&error, ne, v0, Operand(0x0f234560)); |
| 149 __ nop(); | 151 __ nop(); |
| 150 | 152 |
| 151 __ addu(v0, t0, t1); // 0x00001238 | 153 __ addu(v0, a4, a5); // 0x00001238 |
| 152 __ subu(v0, v0, t0); // 0x00001234 | 154 __ subu(v0, v0, a4); // 0x00001234 |
| 153 __ Branch(&error, ne, v0, Operand(0x00001234)); | 155 __ Branch(&error, ne, v0, Operand(0x00001234)); |
| 154 __ nop(); | 156 __ nop(); |
| 155 __ addu(v1, t3, t0); | 157 __ addu(v1, a7, a4); // 32bit addu result is sign-extended into 64bit reg. |
| 156 __ Branch(&error, ne, v1, Operand(0x80000003)); | 158 __ Branch(&error, ne, v1, Operand(0xffffffff80000003)); |
| 157 __ nop(); | 159 __ nop(); |
| 158 __ subu(v1, t7, t0); // 0x7ffffffc | 160 __ subu(v1, t3, a4); // 0x7ffffffc |
| 159 __ Branch(&error, ne, v1, Operand(0x7ffffffc)); | 161 __ Branch(&error, ne, v1, Operand(0x7ffffffc)); |
| 160 __ nop(); | 162 __ nop(); |
| 161 | 163 |
| 162 __ and_(v0, t1, t2); // 0x00001230 | 164 __ and_(v0, a5, a6); // 0x0000000000001230 |
| 163 __ or_(v0, v0, t1); // 0x00001234 | 165 __ or_(v0, v0, a5); // 0x0000000000001234 |
| 164 __ xor_(v0, v0, t2); // 0x1234444c | 166 __ xor_(v0, v0, a6); // 0x000000001234444c |
| 165 __ nor(v0, v0, t2); // 0xedcba987 | 167 __ nor(v0, v0, a6); // 0xffffffffedcba987 |
| 166 __ Branch(&error, ne, v0, Operand(0xedcba983)); | 168 __ Branch(&error, ne, v0, Operand(0xffffffffedcba983)); |
| 167 __ nop(); | 169 __ nop(); |
| 168 | 170 |
| 169 __ slt(v0, t7, t3); | 171 // Shift both 32bit number to left, to preserve meaning of next comparison. |
| 172 __ dsll32(a7, a7, 0); |
| 173 __ dsll32(t3, t3, 0); |
| 174 |
| 175 __ slt(v0, t3, a7); |
| 170 __ Branch(&error, ne, v0, Operand(0x1)); | 176 __ Branch(&error, ne, v0, Operand(0x1)); |
| 171 __ nop(); | 177 __ nop(); |
| 172 __ sltu(v0, t7, t3); | 178 __ sltu(v0, t3, a7); |
| 173 __ Branch(&error, ne, v0, Operand(0x0)); | 179 __ Branch(&error, ne, v0, Operand(zero_reg)); |
| 174 __ nop(); | 180 __ nop(); |
| 181 |
| 182 // Restore original values in registers. |
| 183 __ dsrl32(a7, a7, 0); |
| 184 __ dsrl32(t3, t3, 0); |
| 175 // End of SPECIAL class. | 185 // End of SPECIAL class. |
| 176 | 186 |
| 177 __ addiu(v0, zero_reg, 0x7421); // 0x00007421 | 187 __ addiu(v0, zero_reg, 0x7421); // 0x00007421 |
| 178 __ addiu(v0, v0, -0x1); // 0x00007420 | 188 __ addiu(v0, v0, -0x1); // 0x00007420 |
| 179 __ addiu(v0, v0, -0x20); // 0x00007400 | 189 __ addiu(v0, v0, -0x20); // 0x00007400 |
| 180 __ Branch(&error, ne, v0, Operand(0x00007400)); | 190 __ Branch(&error, ne, v0, Operand(0x00007400)); |
| 181 __ nop(); | 191 __ nop(); |
| 182 __ addiu(v1, t3, 0x1); // 0x80000000 | 192 __ addiu(v1, a7, 0x1); // 0x80000000 - result is sign-extended. |
| 183 __ Branch(&error, ne, v1, Operand(0x80000000)); | 193 __ Branch(&error, ne, v1, Operand(0xffffffff80000000)); |
| 184 __ nop(); | 194 __ nop(); |
| 185 | 195 |
| 186 __ slti(v0, t1, 0x00002000); // 0x1 | 196 __ slti(v0, a5, 0x00002000); // 0x1 |
| 187 __ slti(v0, v0, 0xffff8000); // 0x0 | 197 __ slti(v0, v0, 0xffff8000); // 0x0 |
| 188 __ Branch(&error, ne, v0, Operand(0x0)); | 198 __ Branch(&error, ne, v0, Operand(zero_reg)); |
| 189 __ nop(); | 199 __ nop(); |
| 190 __ sltiu(v0, t1, 0x00002000); // 0x1 | 200 __ sltiu(v0, a5, 0x00002000); // 0x1 |
| 191 __ sltiu(v0, v0, 0x00008000); // 0x1 | 201 __ sltiu(v0, v0, 0x00008000); // 0x1 |
| 192 __ Branch(&error, ne, v0, Operand(0x1)); | 202 __ Branch(&error, ne, v0, Operand(0x1)); |
| 193 __ nop(); | 203 __ nop(); |
| 194 | 204 |
| 195 __ andi(v0, t1, 0xf0f0); // 0x00001030 | 205 __ andi(v0, a5, 0xf0f0); // 0x00001030 |
| 196 __ ori(v0, v0, 0x8a00); // 0x00009a30 | 206 __ ori(v0, v0, 0x8a00); // 0x00009a30 |
| 197 __ xori(v0, v0, 0x83cc); // 0x000019fc | 207 __ xori(v0, v0, 0x83cc); // 0x000019fc |
| 198 __ Branch(&error, ne, v0, Operand(0x000019fc)); | 208 __ Branch(&error, ne, v0, Operand(0x000019fc)); |
| 199 __ nop(); | 209 __ nop(); |
| 200 __ lui(v1, 0x8123); // 0x81230000 | 210 __ lui(v1, 0x8123); // Result is sign-extended into 64bit register. |
| 201 __ Branch(&error, ne, v1, Operand(0x81230000)); | 211 __ Branch(&error, ne, v1, Operand(0xffffffff81230000)); |
| 202 __ nop(); | 212 __ nop(); |
| 203 | 213 |
| 204 // Bit twiddling instructions & conditional moves. | 214 // Bit twiddling instructions & conditional moves. |
| 205 // Uses t0-t7 as set above. | 215 // Uses a4-t3 as set above. |
| 206 __ Clz(v0, t0); // 29 | 216 __ Clz(v0, a4); // 29 |
| 207 __ Clz(v1, t1); // 19 | 217 __ Clz(v1, a5); // 19 |
| 208 __ addu(v0, v0, v1); // 48 | 218 __ addu(v0, v0, v1); // 48 |
| 209 __ Clz(v1, t2); // 3 | 219 __ Clz(v1, a6); // 3 |
| 210 __ addu(v0, v0, v1); // 51 | 220 __ addu(v0, v0, v1); // 51 |
| 211 __ Clz(v1, t7); // 0 | 221 __ Clz(v1, t3); // 0 |
| 212 __ addu(v0, v0, v1); // 51 | 222 __ addu(v0, v0, v1); // 51 |
| 213 __ Branch(&error, ne, v0, Operand(51)); | 223 __ Branch(&error, ne, v0, Operand(51)); |
| 214 __ Movn(a0, t3, t0); // Move a0<-t3 (t0 is NOT 0). | 224 __ Movn(a0, a7, a4); // Move a0<-a7 (a4 is NOT 0). |
| 215 __ Ins(a0, t1, 12, 8); // 0x7ff34fff | 225 __ Ins(a0, a5, 12, 8); // 0x7ff34fff |
| 216 __ Branch(&error, ne, a0, Operand(0x7ff34fff)); | 226 __ Branch(&error, ne, a0, Operand(0x7ff34fff)); |
| 217 __ Movz(a0, t6, t7); // a0 not updated (t7 is NOT 0). | 227 __ Movz(a0, t2, t3); // a0 not updated (t3 is NOT 0). |
| 218 __ Ext(a1, a0, 8, 12); // 0x34f | 228 __ Ext(a1, a0, 8, 12); // 0x34f |
| 219 __ Branch(&error, ne, a1, Operand(0x34f)); | 229 __ Branch(&error, ne, a1, Operand(0x34f)); |
| 220 __ Movz(a0, t6, v1); // a0<-t6, v0 is 0, from 8 instr back. | 230 __ Movz(a0, t2, v1); // a0<-t2, v0 is 0, from 8 instr back. |
| 221 __ Branch(&error, ne, a0, Operand(t6)); | 231 __ Branch(&error, ne, a0, Operand(t2)); |
| 222 | 232 |
| 223 // Everything was correctly executed. Load the expected result. | 233 // Everything was correctly executed. Load the expected result. |
| 224 __ li(v0, 0x31415926); | 234 __ li(v0, 0x31415926); |
| 225 __ b(&exit); | 235 __ b(&exit); |
| 226 __ nop(); | 236 __ nop(); |
| 227 | 237 |
| 228 __ bind(&error); | 238 __ bind(&error); |
| 229 // Got an error. Return a wrong result. | 239 // Got an error. Return a wrong result. |
| 230 __ li(v0, 666); | 240 __ li(v0, 666); |
| 231 | 241 |
| 232 __ bind(&exit); | 242 __ bind(&exit); |
| 233 __ jr(ra); | 243 __ jr(ra); |
| 234 __ nop(); | 244 __ nop(); |
| 235 | 245 |
| 236 CodeDesc desc; | 246 CodeDesc desc; |
| 237 assm.GetCode(&desc); | 247 assm.GetCode(&desc); |
| 238 Handle<Code> code = isolate->factory()->NewCode( | 248 Handle<Code> code = isolate->factory()->NewCode( |
| 239 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 249 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 240 F2 f = FUNCTION_CAST<F2>(code->entry()); | 250 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 241 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); | 251 int64_t res = |
| 242 ::printf("f() = %d\n", res); | 252 reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); |
| 243 CHECK_EQ(0x31415926, res); | 253 ::printf("f() = %ld\n", res); |
| 254 |
| 255 CHECK_EQ(0x31415926L, res); |
| 244 } | 256 } |
| 245 | 257 |
| 246 | 258 |
| 247 TEST(MIPS3) { | 259 TEST(MIPS3) { |
| 248 // Test floating point instructions. | 260 // Test floating point instructions. |
| 249 CcTest::InitializeVM(); | 261 CcTest::InitializeVM(); |
| 250 Isolate* isolate = CcTest::i_isolate(); | 262 Isolate* isolate = CcTest::i_isolate(); |
| 251 HandleScope scope(isolate); | 263 HandleScope scope(isolate); |
| 252 | 264 |
| 253 typedef struct { | 265 typedef struct { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 273 __ add_d(f8, f4, f6); | 285 __ add_d(f8, f4, f6); |
| 274 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b. | 286 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b. |
| 275 | 287 |
| 276 __ mov_d(f10, f8); // c | 288 __ mov_d(f10, f8); // c |
| 277 __ neg_d(f12, f6); // -b | 289 __ neg_d(f12, f6); // -b |
| 278 __ sub_d(f10, f10, f12); | 290 __ sub_d(f10, f10, f12); |
| 279 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b). | 291 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b). |
| 280 | 292 |
| 281 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a. | 293 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a. |
| 282 | 294 |
| 283 __ li(t0, 120); | 295 __ li(a4, 120); |
| 284 __ mtc1(t0, f14); | 296 __ mtc1(a4, f14); |
| 285 __ cvt_d_w(f14, f14); // f14 = 120.0. | 297 __ cvt_d_w(f14, f14); // f14 = 120.0. |
| 286 __ mul_d(f10, f10, f14); | 298 __ mul_d(f10, f10, f14); |
| 287 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16. | 299 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16. |
| 288 | 300 |
| 289 __ div_d(f12, f10, f4); | 301 __ div_d(f12, f10, f4); |
| 290 __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44. | 302 __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44. |
| 291 | 303 |
| 292 __ sqrt_d(f14, f12); | 304 __ sqrt_d(f14, f12); |
| 293 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) ); | 305 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) ); |
| 294 // g = sqrt(f) = 10.97451593465515908537 | 306 // g = sqrt(f) = 10.97451593465515908537 |
| 295 | 307 |
| 296 if (kArchVariant == kMips32r2) { | 308 if (kArchVariant == kMips64r2) { |
| 297 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, h)) ); | 309 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, h)) ); |
| 298 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, i)) ); | 310 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, i)) ); |
| 299 __ madd_d(f14, f6, f4, f6); | 311 __ madd_d(f14, f6, f4, f6); |
| 300 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, h)) ); | 312 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, h)) ); |
| 301 } | 313 } |
| 302 | 314 |
| 303 __ jr(ra); | 315 __ jr(ra); |
| 304 __ nop(); | 316 __ nop(); |
| 305 | 317 |
| 306 CodeDesc desc; | 318 CodeDesc desc; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 318 t.i = 2.75; | 330 t.i = 2.75; |
| 319 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | 331 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 320 USE(dummy); | 332 USE(dummy); |
| 321 CHECK_EQ(1.5e14, t.a); | 333 CHECK_EQ(1.5e14, t.a); |
| 322 CHECK_EQ(1.5e14, t.b); | 334 CHECK_EQ(1.5e14, t.b); |
| 323 CHECK_EQ(1.50275e14, t.c); | 335 CHECK_EQ(1.50275e14, t.c); |
| 324 CHECK_EQ(1.50550e14, t.d); | 336 CHECK_EQ(1.50550e14, t.d); |
| 325 CHECK_EQ(1.8066e16, t.e); | 337 CHECK_EQ(1.8066e16, t.e); |
| 326 CHECK_EQ(120.44, t.f); | 338 CHECK_EQ(120.44, t.f); |
| 327 CHECK_EQ(10.97451593465515908537, t.g); | 339 CHECK_EQ(10.97451593465515908537, t.g); |
| 328 if (kArchVariant == kMips32r2) { | 340 if (kArchVariant == kMips64r2) { |
| 329 CHECK_EQ(6.875, t.h); | 341 CHECK_EQ(6.875, t.h); |
| 330 } | 342 } |
| 331 } | 343 } |
| 332 | 344 |
| 333 | 345 |
| 334 TEST(MIPS4) { | 346 TEST(MIPS4) { |
| 335 // Test moves between floating point and integer registers. | 347 // Test moves between floating point and integer registers. |
| 336 CcTest::InitializeVM(); | 348 CcTest::InitializeVM(); |
| 337 Isolate* isolate = CcTest::i_isolate(); | 349 Isolate* isolate = CcTest::i_isolate(); |
| 338 HandleScope scope(isolate); | 350 HandleScope scope(isolate); |
| 339 | 351 |
| 340 typedef struct { | 352 typedef struct { |
| 341 double a; | 353 double a; |
| 342 double b; | 354 double b; |
| 343 double c; | 355 double c; |
| 344 } T; | 356 } T; |
| 345 T t; | 357 T t; |
| 346 | 358 |
| 347 Assembler assm(isolate, NULL, 0); | 359 Assembler assm(isolate, NULL, 0); |
| 348 Label L, C; | 360 Label L, C; |
| 349 | 361 |
| 350 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); | 362 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
| 351 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); | 363 __ ldc1(f5, MemOperand(a0, OFFSET_OF(T, b)) ); |
| 352 | 364 |
| 353 // Swap f4 and f6, by using four integer registers, t0-t3. | 365 // Swap f4 and f5, by using 3 integer registers, a4-a6, |
| 354 __ mfc1(t0, f4); | 366 // both two 32-bit chunks, and one 64-bit chunk. |
| 355 __ mfc1(t1, f5); | 367 // mXhc1 is mips32/64-r2 only, not r1, |
| 356 __ mfc1(t2, f6); | 368 // but we will not support r1 in practice. |
| 357 __ mfc1(t3, f7); | 369 __ mfc1(a4, f4); |
| 370 __ mfhc1(a5, f4); |
| 371 __ dmfc1(a6, f5); |
| 358 | 372 |
| 359 __ mtc1(t0, f6); | 373 __ mtc1(a4, f5); |
| 360 __ mtc1(t1, f7); | 374 __ mthc1(a5, f5); |
| 361 __ mtc1(t2, f4); | 375 __ dmtc1(a6, f4); |
| 362 __ mtc1(t3, f5); | |
| 363 | 376 |
| 364 // Store the swapped f4 and f5 back to memory. | 377 // Store the swapped f4 and f5 back to memory. |
| 365 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); | 378 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
| 366 __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) ); | 379 __ sdc1(f5, MemOperand(a0, OFFSET_OF(T, c)) ); |
| 367 | 380 |
| 368 __ jr(ra); | 381 __ jr(ra); |
| 369 __ nop(); | 382 __ nop(); |
| 370 | 383 |
| 371 CodeDesc desc; | 384 CodeDesc desc; |
| 372 assm.GetCode(&desc); | 385 assm.GetCode(&desc); |
| 373 Handle<Code> code = isolate->factory()->NewCode( | 386 Handle<Code> code = isolate->factory()->NewCode( |
| 374 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 387 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 375 F3 f = FUNCTION_CAST<F3>(code->entry()); | 388 F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 376 t.a = 1.5e22; | 389 t.a = 1.5e22; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 398 int j; | 411 int j; |
| 399 } T; | 412 } T; |
| 400 T t; | 413 T t; |
| 401 | 414 |
| 402 Assembler assm(isolate, NULL, 0); | 415 Assembler assm(isolate, NULL, 0); |
| 403 Label L, C; | 416 Label L, C; |
| 404 | 417 |
| 405 // Load all structure elements to registers. | 418 // Load all structure elements to registers. |
| 406 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); | 419 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
| 407 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); | 420 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); |
| 408 __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) ); | 421 __ lw(a4, MemOperand(a0, OFFSET_OF(T, i)) ); |
| 409 __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) ); | 422 __ lw(a5, MemOperand(a0, OFFSET_OF(T, j)) ); |
| 410 | 423 |
| 411 // Convert double in f4 to int in element i. | 424 // Convert double in f4 to int in element i. |
| 412 __ cvt_w_d(f8, f4); | 425 __ cvt_w_d(f8, f4); |
| 413 __ mfc1(t2, f8); | 426 __ mfc1(a6, f8); |
| 414 __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) ); | 427 __ sw(a6, MemOperand(a0, OFFSET_OF(T, i)) ); |
| 415 | 428 |
| 416 // Convert double in f6 to int in element j. | 429 // Convert double in f6 to int in element j. |
| 417 __ cvt_w_d(f10, f6); | 430 __ cvt_w_d(f10, f6); |
| 418 __ mfc1(t3, f10); | 431 __ mfc1(a7, f10); |
| 419 __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) ); | 432 __ sw(a7, MemOperand(a0, OFFSET_OF(T, j)) ); |
| 420 | 433 |
| 421 // Convert int in original i (t0) to double in a. | 434 // Convert int in original i (a4) to double in a. |
| 422 __ mtc1(t0, f12); | 435 __ mtc1(a4, f12); |
| 423 __ cvt_d_w(f0, f12); | 436 __ cvt_d_w(f0, f12); |
| 424 __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) ); | 437 __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) ); |
| 425 | 438 |
| 426 // Convert int in original j (t1) to double in b. | 439 // Convert int in original j (a5) to double in b. |
| 427 __ mtc1(t1, f14); | 440 __ mtc1(a5, f14); |
| 428 __ cvt_d_w(f2, f14); | 441 __ cvt_d_w(f2, f14); |
| 429 __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) ); | 442 __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) ); |
| 430 | 443 |
| 431 __ jr(ra); | 444 __ jr(ra); |
| 432 __ nop(); | 445 __ nop(); |
| 433 | 446 |
| 434 CodeDesc desc; | 447 CodeDesc desc; |
| 435 assm.GetCode(&desc); | 448 assm.GetCode(&desc); |
| 436 Handle<Code> code = isolate->factory()->NewCode( | 449 Handle<Code> code = isolate->factory()->NewCode( |
| 437 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 450 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 465 int32_t r4; | 478 int32_t r4; |
| 466 int32_t r5; | 479 int32_t r5; |
| 467 int32_t r6; | 480 int32_t r6; |
| 468 } T; | 481 } T; |
| 469 T t; | 482 T t; |
| 470 | 483 |
| 471 Assembler assm(isolate, NULL, 0); | 484 Assembler assm(isolate, NULL, 0); |
| 472 Label L, C; | 485 Label L, C; |
| 473 | 486 |
| 474 // Basic word load/store. | 487 // Basic word load/store. |
| 475 __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) ); | 488 __ lw(a4, MemOperand(a0, OFFSET_OF(T, ui)) ); |
| 476 __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) ); | 489 __ sw(a4, MemOperand(a0, OFFSET_OF(T, r1)) ); |
| 477 | 490 |
| 478 // lh with positive data. | 491 // lh with positive data. |
| 479 __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) ); | 492 __ lh(a5, MemOperand(a0, OFFSET_OF(T, ui)) ); |
| 480 __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) ); | 493 __ sw(a5, MemOperand(a0, OFFSET_OF(T, r2)) ); |
| 481 | 494 |
| 482 // lh with negative data. | 495 // lh with negative data. |
| 483 __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) ); | 496 __ lh(a6, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 484 __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) ); | 497 __ sw(a6, MemOperand(a0, OFFSET_OF(T, r3)) ); |
| 485 | 498 |
| 486 // lhu with negative data. | 499 // lhu with negative data. |
| 487 __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) ); | 500 __ lhu(a7, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 488 __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) ); | 501 __ sw(a7, MemOperand(a0, OFFSET_OF(T, r4)) ); |
| 489 | 502 |
| 490 // lb with negative data. | 503 // lb with negative data. |
| 491 __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) ); | 504 __ lb(t0, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 492 __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) ); | 505 __ sw(t0, MemOperand(a0, OFFSET_OF(T, r5)) ); |
| 493 | 506 |
| 494 // sh writes only 1/2 of word. | 507 // sh writes only 1/2 of word. |
| 495 __ lui(t5, 0x3333); | 508 __ lui(t1, 0x3333); |
| 496 __ ori(t5, t5, 0x3333); | 509 __ ori(t1, t1, 0x3333); |
| 497 __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) ); | 510 __ sw(t1, MemOperand(a0, OFFSET_OF(T, r6)) ); |
| 498 __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) ); | 511 __ lhu(t1, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 499 __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) ); | 512 __ sh(t1, MemOperand(a0, OFFSET_OF(T, r6)) ); |
| 500 | 513 |
| 501 __ jr(ra); | 514 __ jr(ra); |
| 502 __ nop(); | 515 __ nop(); |
| 503 | 516 |
| 504 CodeDesc desc; | 517 CodeDesc desc; |
| 505 assm.GetCode(&desc); | 518 assm.GetCode(&desc); |
| 506 Handle<Code> code = isolate->factory()->NewCode( | 519 Handle<Code> code = isolate->factory()->NewCode( |
| 507 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 520 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 508 F3 f = FUNCTION_CAST<F3>(code->entry()); | 521 F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 509 t.ui = 0x11223344; | 522 t.ui = 0x11223344; |
| 510 t.si = 0x99aabbcc; | 523 t.si = 0x99aabbcc; |
| 511 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | 524 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 512 USE(dummy); | 525 USE(dummy); |
| 513 | 526 |
| 514 CHECK_EQ(0x11223344, t.r1); | 527 CHECK_EQ(0x11223344, t.r1); |
| 515 #if __BYTE_ORDER == __LITTLE_ENDIAN | |
| 516 CHECK_EQ(0x3344, t.r2); | 528 CHECK_EQ(0x3344, t.r2); |
| 517 CHECK_EQ(0xffffbbcc, t.r3); | 529 CHECK_EQ(0xffffbbcc, t.r3); |
| 518 CHECK_EQ(0x0000bbcc, t.r4); | 530 CHECK_EQ(0x0000bbcc, t.r4); |
| 519 CHECK_EQ(0xffffffcc, t.r5); | 531 CHECK_EQ(0xffffffcc, t.r5); |
| 520 CHECK_EQ(0x3333bbcc, t.r6); | 532 CHECK_EQ(0x3333bbcc, t.r6); |
| 521 #elif __BYTE_ORDER == __BIG_ENDIAN | |
| 522 CHECK_EQ(0x1122, t.r2); | |
| 523 CHECK_EQ(0xffff99aa, t.r3); | |
| 524 CHECK_EQ(0x000099aa, t.r4); | |
| 525 CHECK_EQ(0xffffff99, t.r5); | |
| 526 CHECK_EQ(0x99aa3333, t.r6); | |
| 527 #else | |
| 528 #error Unknown endianness | |
| 529 #endif | |
| 530 } | 533 } |
| 531 | 534 |
| 532 | 535 |
| 533 TEST(MIPS7) { | 536 TEST(MIPS7) { |
| 534 // Test floating point compare and branch instructions. | 537 // Test floating point compare and branch instructions. |
| 535 CcTest::InitializeVM(); | 538 CcTest::InitializeVM(); |
| 536 Isolate* isolate = CcTest::i_isolate(); | 539 Isolate* isolate = CcTest::i_isolate(); |
| 537 HandleScope scope(isolate); | 540 HandleScope scope(isolate); |
| 538 | 541 |
| 539 typedef struct { | 542 typedef struct { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 567 __ bc1t(&less_than); | 570 __ bc1t(&less_than); |
| 568 } else { | 571 } else { |
| 569 __ c(OLT, D, f6, f4, 2); | 572 __ c(OLT, D, f6, f4, 2); |
| 570 __ bc1t(&less_than, 2); | 573 __ bc1t(&less_than, 2); |
| 571 } | 574 } |
| 572 __ nop(); | 575 __ nop(); |
| 573 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); | 576 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); |
| 574 __ Branch(&outa_here); | 577 __ Branch(&outa_here); |
| 575 | 578 |
| 576 __ bind(&less_than); | 579 __ bind(&less_than); |
| 577 __ Addu(t0, zero_reg, Operand(1)); | 580 __ Addu(a4, zero_reg, Operand(1)); |
| 578 __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true. | 581 __ sw(a4, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true. |
| 579 | 582 |
| 580 | 583 |
| 581 // This test-case should have additional tests. | 584 // This test-case should have additional tests. |
| 582 | 585 |
| 583 __ bind(&outa_here); | 586 __ bind(&outa_here); |
| 584 | 587 |
| 585 __ jr(ra); | 588 __ jr(ra); |
| 586 __ nop(); | 589 __ nop(); |
| 587 | 590 |
| 588 CodeDesc desc; | 591 CodeDesc desc; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 626 int32_t result_rotrv_16; | 629 int32_t result_rotrv_16; |
| 627 int32_t result_rotrv_20; | 630 int32_t result_rotrv_20; |
| 628 int32_t result_rotrv_24; | 631 int32_t result_rotrv_24; |
| 629 int32_t result_rotrv_28; | 632 int32_t result_rotrv_28; |
| 630 } T; | 633 } T; |
| 631 T t; | 634 T t; |
| 632 | 635 |
| 633 MacroAssembler assm(isolate, NULL, 0); | 636 MacroAssembler assm(isolate, NULL, 0); |
| 634 | 637 |
| 635 // Basic word load. | 638 // Basic word load. |
| 636 __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) ); | 639 __ lw(a4, MemOperand(a0, OFFSET_OF(T, input)) ); |
| 637 | 640 |
| 638 // ROTR instruction (called through the Ror macro). | 641 // ROTR instruction (called through the Ror macro). |
| 639 __ Ror(t1, t0, 0x0004); | 642 __ Ror(a5, a4, 0x0004); |
| 640 __ Ror(t2, t0, 0x0008); | 643 __ Ror(a6, a4, 0x0008); |
| 641 __ Ror(t3, t0, 0x000c); | 644 __ Ror(a7, a4, 0x000c); |
| 642 __ Ror(t4, t0, 0x0010); | 645 __ Ror(t0, a4, 0x0010); |
| 643 __ Ror(t5, t0, 0x0014); | 646 __ Ror(t1, a4, 0x0014); |
| 644 __ Ror(t6, t0, 0x0018); | 647 __ Ror(t2, a4, 0x0018); |
| 645 __ Ror(t7, t0, 0x001c); | 648 __ Ror(t3, a4, 0x001c); |
| 646 | 649 |
| 647 // Basic word store. | 650 // Basic word store. |
| 648 __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) ); | 651 __ sw(a5, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) ); |
| 649 __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) ); | 652 __ sw(a6, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) ); |
| 650 __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) ); | 653 __ sw(a7, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) ); |
| 651 __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) ); | 654 __ sw(t0, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) ); |
| 652 __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) ); | 655 __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) ); |
| 653 __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) ); | 656 __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) ); |
| 654 __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) ); | 657 __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) ); |
| 655 | 658 |
| 656 // ROTRV instruction (called through the Ror macro). | 659 // ROTRV instruction (called through the Ror macro). |
| 657 __ li(t7, 0x0004); | 660 __ li(t3, 0x0004); |
| 658 __ Ror(t1, t0, t7); | 661 __ Ror(a5, a4, t3); |
| 659 __ li(t7, 0x0008); | 662 __ li(t3, 0x0008); |
| 660 __ Ror(t2, t0, t7); | 663 __ Ror(a6, a4, t3); |
| 661 __ li(t7, 0x000C); | 664 __ li(t3, 0x000C); |
| 662 __ Ror(t3, t0, t7); | 665 __ Ror(a7, a4, t3); |
| 663 __ li(t7, 0x0010); | 666 __ li(t3, 0x0010); |
| 664 __ Ror(t4, t0, t7); | 667 __ Ror(t0, a4, t3); |
| 665 __ li(t7, 0x0014); | 668 __ li(t3, 0x0014); |
| 666 __ Ror(t5, t0, t7); | 669 __ Ror(t1, a4, t3); |
| 667 __ li(t7, 0x0018); | 670 __ li(t3, 0x0018); |
| 668 __ Ror(t6, t0, t7); | 671 __ Ror(t2, a4, t3); |
| 669 __ li(t7, 0x001C); | 672 __ li(t3, 0x001C); |
| 670 __ Ror(t7, t0, t7); | 673 __ Ror(t3, a4, t3); |
| 671 | 674 |
| 672 // Basic word store. | 675 // Basic word store. |
| 673 __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) ); | 676 __ sw(a5, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) ); |
| 674 __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) ); | 677 __ sw(a6, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) ); |
| 675 __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) ); | 678 __ sw(a7, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) ); |
| 676 __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) ); | 679 __ sw(t0, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) ); |
| 677 __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) ); | 680 __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) ); |
| 678 __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) ); | 681 __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) ); |
| 679 __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) ); | 682 __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) ); |
| 680 | 683 |
| 681 __ jr(ra); | 684 __ jr(ra); |
| 682 __ nop(); | 685 __ nop(); |
| 683 | 686 |
| 684 CodeDesc desc; | 687 CodeDesc desc; |
| 685 assm.GetCode(&desc); | 688 assm.GetCode(&desc); |
| 686 Handle<Code> code = isolate->factory()->NewCode( | 689 Handle<Code> code = isolate->factory()->NewCode( |
| 687 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 690 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 688 F3 f = FUNCTION_CAST<F3>(code->entry()); | 691 F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 689 t.input = 0x12345678; | 692 t.input = 0x12345678; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 709 | 712 |
| 710 TEST(MIPS9) { | 713 TEST(MIPS9) { |
| 711 // Test BRANCH improvements. | 714 // Test BRANCH improvements. |
| 712 CcTest::InitializeVM(); | 715 CcTest::InitializeVM(); |
| 713 Isolate* isolate = CcTest::i_isolate(); | 716 Isolate* isolate = CcTest::i_isolate(); |
| 714 HandleScope scope(isolate); | 717 HandleScope scope(isolate); |
| 715 | 718 |
| 716 MacroAssembler assm(isolate, NULL, 0); | 719 MacroAssembler assm(isolate, NULL, 0); |
| 717 Label exit, exit2, exit3; | 720 Label exit, exit2, exit3; |
| 718 | 721 |
| 719 __ Branch(&exit, ge, a0, Operand(0x00000000)); | 722 __ Branch(&exit, ge, a0, Operand(zero_reg)); |
| 720 __ Branch(&exit2, ge, a0, Operand(0x00001FFF)); | 723 __ Branch(&exit2, ge, a0, Operand(0x00001FFF)); |
| 721 __ Branch(&exit3, ge, a0, Operand(0x0001FFFF)); | 724 __ Branch(&exit3, ge, a0, Operand(0x0001FFFF)); |
| 722 | 725 |
| 723 __ bind(&exit); | 726 __ bind(&exit); |
| 724 __ bind(&exit2); | 727 __ bind(&exit2); |
| 725 __ bind(&exit3); | 728 __ bind(&exit3); |
| 726 __ jr(ra); | 729 __ jr(ra); |
| 727 __ nop(); | 730 __ nop(); |
| 728 | 731 |
| 729 CodeDesc desc; | 732 CodeDesc desc; |
| 730 assm.GetCode(&desc); | 733 assm.GetCode(&desc); |
| 731 isolate->factory()->NewCode( | 734 isolate->factory()->NewCode( |
| 732 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 735 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 733 } | 736 } |
| 734 | 737 |
| 735 | 738 |
| 736 TEST(MIPS10) { | 739 TEST(MIPS10) { |
| 737 // Test conversions between doubles and long integers. | 740 // Test conversions between doubles and long integers. |
| 738 // Test hos the long ints map to FP regs pairs. | 741 // Test hos the long ints map to FP regs pairs. |
| 739 CcTest::InitializeVM(); | 742 CcTest::InitializeVM(); |
| 740 Isolate* isolate = CcTest::i_isolate(); | 743 Isolate* isolate = CcTest::i_isolate(); |
| 741 HandleScope scope(isolate); | 744 HandleScope scope(isolate); |
| 742 | 745 |
| 743 typedef struct { | 746 typedef struct { |
| 744 double a; | 747 double a; |
| 748 double a_converted; |
| 745 double b; | 749 double b; |
| 746 int32_t dbl_mant; | 750 int32_t dbl_mant; |
| 747 int32_t dbl_exp; | 751 int32_t dbl_exp; |
| 748 int32_t word; | 752 int32_t long_hi; |
| 749 int32_t b_word; | 753 int32_t long_lo; |
| 754 int64_t long_as_int64; |
| 755 int32_t b_long_hi; |
| 756 int32_t b_long_lo; |
| 757 int64_t b_long_as_int64; |
| 750 } T; | 758 } T; |
| 751 T t; | 759 T t; |
| 752 | 760 |
| 753 Assembler assm(isolate, NULL, 0); | 761 Assembler assm(isolate, NULL, 0); |
| 754 Label L, C; | 762 Label L, C; |
| 755 | 763 |
| 756 if (kArchVariant == kMips32r2) { | 764 if (kArchVariant == kMips64r2) { |
| 765 // Rewritten for FR=1 FPU mode: |
| 766 // - 32 FP regs of 64-bits each, no odd/even pairs. |
| 767 // - Note that cvt_l_d/cvt_d_l ARE legal in FR=1 mode. |
| 757 // Load all structure elements to registers. | 768 // Load all structure elements to registers. |
| 758 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a))); | 769 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a))); |
| 759 | 770 |
| 760 // Save the raw bits of the double. | 771 // Save the raw bits of the double. |
| 761 __ mfc1(t0, f0); | 772 __ mfc1(a4, f0); |
| 762 __ mfc1(t1, f1); | 773 __ mfhc1(a5, f0); |
| 763 __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant))); | 774 __ sw(a4, MemOperand(a0, OFFSET_OF(T, dbl_mant))); |
| 764 __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp))); | 775 __ sw(a5, MemOperand(a0, OFFSET_OF(T, dbl_exp))); |
| 765 | 776 |
| 766 // Convert double in f0 to long, save hi/lo parts. | 777 // Convert double in f0 to long, save hi/lo parts. |
| 767 __ cvt_w_d(f0, f0); | 778 __ cvt_l_d(f0, f0); |
| 768 __ mfc1(t0, f0); // f0 has a 32-bits word. | 779 __ mfc1(a4, f0); // f0 LS 32 bits of long. |
| 769 __ sw(t0, MemOperand(a0, OFFSET_OF(T, word))); | 780 __ mfhc1(a5, f0); // f0 MS 32 bits of long. |
| 781 __ sw(a4, MemOperand(a0, OFFSET_OF(T, long_lo))); |
| 782 __ sw(a5, MemOperand(a0, OFFSET_OF(T, long_hi))); |
| 783 |
| 784 // Combine the high/low ints, convert back to double. |
| 785 __ dsll32(a6, a5, 0); // Move a5 to high bits of a6. |
| 786 __ or_(a6, a6, a4); |
| 787 __ dmtc1(a6, f1); |
| 788 __ cvt_d_l(f1, f1); |
| 789 __ sdc1(f1, MemOperand(a0, OFFSET_OF(T, a_converted))); |
| 790 |
| 770 | 791 |
| 771 // Convert the b long integers to double b. | 792 // Convert the b long integers to double b. |
| 772 __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_word))); | 793 __ lw(a4, MemOperand(a0, OFFSET_OF(T, b_long_lo))); |
| 773 __ mtc1(t0, f8); // f8 has a 32-bits word. | 794 __ lw(a5, MemOperand(a0, OFFSET_OF(T, b_long_hi))); |
| 774 __ cvt_d_w(f10, f8); | 795 __ mtc1(a4, f8); // f8 LS 32-bits. |
| 796 __ mthc1(a5, f8); // f8 MS 32-bits. |
| 797 __ cvt_d_l(f10, f8); |
| 775 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b))); | 798 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b))); |
| 776 | 799 |
| 800 // Convert double b back to long-int. |
| 801 __ ldc1(f31, MemOperand(a0, OFFSET_OF(T, b))); |
| 802 __ cvt_l_d(f31, f31); |
| 803 __ dmfc1(a7, f31); |
| 804 __ sd(a7, MemOperand(a0, OFFSET_OF(T, b_long_as_int64))); |
| 805 |
| 806 |
| 777 __ jr(ra); | 807 __ jr(ra); |
| 778 __ nop(); | 808 __ nop(); |
| 779 | 809 |
| 780 CodeDesc desc; | 810 CodeDesc desc; |
| 781 assm.GetCode(&desc); | 811 assm.GetCode(&desc); |
| 782 Handle<Code> code = isolate->factory()->NewCode( | 812 Handle<Code> code = isolate->factory()->NewCode( |
| 783 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 813 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 784 F3 f = FUNCTION_CAST<F3>(code->entry()); | 814 F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 785 t.a = 2.147483646e+09; // 0x7FFFFFFE -> 0xFF80000041DFFFFF as double. | 815 t.a = 2.147483647e9; // 0x7fffffff -> 0x41DFFFFFFFC00000 as double. |
| 786 t.b_word = 0x0ff00ff0; // 0x0FF00FF0 -> 0x as double. | 816 t.b_long_hi = 0x000000ff; // 0xFF00FF00FF -> 0x426FE01FE01FE000 as double. |
| 817 t.b_long_lo = 0x00ff00ff; |
| 787 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | 818 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 788 USE(dummy); | 819 USE(dummy); |
| 789 | 820 |
| 790 CHECK_EQ(0x41DFFFFF, t.dbl_exp); | 821 CHECK_EQ(0x41DFFFFF, t.dbl_exp); |
| 791 CHECK_EQ(0xFF800000, t.dbl_mant); | 822 CHECK_EQ(0xFFC00000, t.dbl_mant); |
| 792 CHECK_EQ(0X7FFFFFFE, t.word); | 823 CHECK_EQ(0, t.long_hi); |
| 793 // 0x0FF00FF0 -> 2.6739096+e08 | 824 CHECK_EQ(0x7fffffff, t.long_lo); |
| 794 CHECK_EQ(2.6739096e08, t.b); | 825 CHECK_EQ(2.147483647e9, t.a_converted); |
| 826 |
| 827 // 0xFF00FF00FF -> 1.095233372415e12. |
| 828 CHECK_EQ(1.095233372415e12, t.b); |
| 829 CHECK_EQ(0xFF00FF00FF, t.b_long_as_int64); |
| 795 } | 830 } |
| 796 } | 831 } |
| 797 | 832 |
| 798 | 833 |
| 799 TEST(MIPS11) { | 834 TEST(MIPS11) { |
| 800 // Test LWL, LWR, SWL and SWR instructions. | 835 // Test LWL, LWR, SWL and SWR instructions. |
| 801 CcTest::InitializeVM(); | 836 CcTest::InitializeVM(); |
| 802 Isolate* isolate = CcTest::i_isolate(); | 837 Isolate* isolate = CcTest::i_isolate(); |
| 803 HandleScope scope(isolate); | 838 HandleScope scope(isolate); |
| 804 | 839 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 820 int32_t swr_0; | 855 int32_t swr_0; |
| 821 int32_t swr_1; | 856 int32_t swr_1; |
| 822 int32_t swr_2; | 857 int32_t swr_2; |
| 823 int32_t swr_3; | 858 int32_t swr_3; |
| 824 } T; | 859 } T; |
| 825 T t; | 860 T t; |
| 826 | 861 |
| 827 Assembler assm(isolate, NULL, 0); | 862 Assembler assm(isolate, NULL, 0); |
| 828 | 863 |
| 829 // Test all combinations of LWL and vAddr. | 864 // Test all combinations of LWL and vAddr. |
| 830 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 865 __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 831 __ lwl(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); | 866 __ lwl(a4, MemOperand(a0, OFFSET_OF(T, mem_init)) ); |
| 832 __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwl_0)) ); | 867 __ sw(a4, MemOperand(a0, OFFSET_OF(T, lwl_0)) ); |
| 833 | 868 |
| 834 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 869 __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 835 __ lwl(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) ); | 870 __ lwl(a5, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) ); |
| 836 __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwl_1)) ); | 871 __ sw(a5, MemOperand(a0, OFFSET_OF(T, lwl_1)) ); |
| 837 | 872 |
| 838 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 873 __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 839 __ lwl(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) ); | 874 __ lwl(a6, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) ); |
| 840 __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwl_2)) ); | 875 __ sw(a6, MemOperand(a0, OFFSET_OF(T, lwl_2)) ); |
| 841 | 876 |
| 842 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 877 __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 843 __ lwl(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) ); | 878 __ lwl(a7, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) ); |
| 844 __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwl_3)) ); | 879 __ sw(a7, MemOperand(a0, OFFSET_OF(T, lwl_3)) ); |
| 845 | 880 |
| 846 // Test all combinations of LWR and vAddr. | 881 // Test all combinations of LWR and vAddr. |
| 847 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 882 __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 848 __ lwr(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); | 883 __ lwr(a4, MemOperand(a0, OFFSET_OF(T, mem_init)) ); |
| 849 __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwr_0)) ); | 884 __ sw(a4, MemOperand(a0, OFFSET_OF(T, lwr_0)) ); |
| 850 | 885 |
| 851 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 886 __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 852 __ lwr(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) ); | 887 __ lwr(a5, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) ); |
| 853 __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwr_1)) ); | 888 __ sw(a5, MemOperand(a0, OFFSET_OF(T, lwr_1)) ); |
| 854 | 889 |
| 855 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 890 __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 856 __ lwr(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) ); | 891 __ lwr(a6, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) ); |
| 857 __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwr_2)) ); | 892 __ sw(a6, MemOperand(a0, OFFSET_OF(T, lwr_2)) ); |
| 858 | 893 |
| 859 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 894 __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 860 __ lwr(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) ); | 895 __ lwr(a7, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) ); |
| 861 __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwr_3)) ); | 896 __ sw(a7, MemOperand(a0, OFFSET_OF(T, lwr_3)) ); |
| 862 | 897 |
| 863 // Test all combinations of SWL and vAddr. | 898 // Test all combinations of SWL and vAddr. |
| 864 __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); | 899 __ lw(a4, MemOperand(a0, OFFSET_OF(T, mem_init)) ); |
| 865 __ sw(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) ); | 900 __ sw(a4, MemOperand(a0, OFFSET_OF(T, swl_0)) ); |
| 866 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 901 __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 867 __ swl(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) ); | 902 __ swl(a4, MemOperand(a0, OFFSET_OF(T, swl_0)) ); |
| 868 | 903 |
| 869 __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) ); | 904 __ lw(a5, MemOperand(a0, OFFSET_OF(T, mem_init)) ); |
| 870 __ sw(t1, MemOperand(a0, OFFSET_OF(T, swl_1)) ); | 905 __ sw(a5, MemOperand(a0, OFFSET_OF(T, swl_1)) ); |
| 871 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 906 __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 872 __ swl(t1, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) ); | 907 __ swl(a5, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) ); |
| 873 | 908 |
| 874 __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) ); | 909 __ lw(a6, MemOperand(a0, OFFSET_OF(T, mem_init)) ); |
| 875 __ sw(t2, MemOperand(a0, OFFSET_OF(T, swl_2)) ); | 910 __ sw(a6, MemOperand(a0, OFFSET_OF(T, swl_2)) ); |
| 876 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 911 __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 877 __ swl(t2, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) ); | 912 __ swl(a6, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) ); |
| 878 | 913 |
| 879 __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) ); | 914 __ lw(a7, MemOperand(a0, OFFSET_OF(T, mem_init)) ); |
| 880 __ sw(t3, MemOperand(a0, OFFSET_OF(T, swl_3)) ); | 915 __ sw(a7, MemOperand(a0, OFFSET_OF(T, swl_3)) ); |
| 881 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 916 __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 882 __ swl(t3, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) ); | 917 __ swl(a7, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) ); |
| 883 | 918 |
| 884 // Test all combinations of SWR and vAddr. | 919 // Test all combinations of SWR and vAddr. |
| 885 __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); | 920 __ lw(a4, MemOperand(a0, OFFSET_OF(T, mem_init)) ); |
| 886 __ sw(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) ); | 921 __ sw(a4, MemOperand(a0, OFFSET_OF(T, swr_0)) ); |
| 887 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 922 __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 888 __ swr(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) ); | 923 __ swr(a4, MemOperand(a0, OFFSET_OF(T, swr_0)) ); |
| 889 | 924 |
| 890 __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) ); | 925 __ lw(a5, MemOperand(a0, OFFSET_OF(T, mem_init)) ); |
| 891 __ sw(t1, MemOperand(a0, OFFSET_OF(T, swr_1)) ); | 926 __ sw(a5, MemOperand(a0, OFFSET_OF(T, swr_1)) ); |
| 892 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 927 __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 893 __ swr(t1, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) ); | 928 __ swr(a5, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) ); |
| 894 | 929 |
| 895 __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) ); | 930 __ lw(a6, MemOperand(a0, OFFSET_OF(T, mem_init)) ); |
| 896 __ sw(t2, MemOperand(a0, OFFSET_OF(T, swr_2)) ); | 931 __ sw(a6, MemOperand(a0, OFFSET_OF(T, swr_2)) ); |
| 897 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 932 __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 898 __ swr(t2, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) ); | 933 __ swr(a6, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) ); |
| 899 | 934 |
| 900 __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) ); | 935 __ lw(a7, MemOperand(a0, OFFSET_OF(T, mem_init)) ); |
| 901 __ sw(t3, MemOperand(a0, OFFSET_OF(T, swr_3)) ); | 936 __ sw(a7, MemOperand(a0, OFFSET_OF(T, swr_3)) ); |
| 902 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); | 937 __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init)) ); |
| 903 __ swr(t3, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) ); | 938 __ swr(a7, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) ); |
| 904 | 939 |
| 905 __ jr(ra); | 940 __ jr(ra); |
| 906 __ nop(); | 941 __ nop(); |
| 907 | 942 |
| 908 CodeDesc desc; | 943 CodeDesc desc; |
| 909 assm.GetCode(&desc); | 944 assm.GetCode(&desc); |
| 910 Handle<Code> code = isolate->factory()->NewCode( | 945 Handle<Code> code = isolate->factory()->NewCode( |
| 911 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 946 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 912 F3 f = FUNCTION_CAST<F3>(code->entry()); | 947 F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 913 t.reg_init = 0xaabbccdd; | 948 t.reg_init = 0xaabbccdd; |
| 914 t.mem_init = 0x11223344; | 949 t.mem_init = 0x11223344; |
| 915 | 950 |
| 916 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | 951 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 917 USE(dummy); | 952 USE(dummy); |
| 918 | 953 |
| 919 #if __BYTE_ORDER == __LITTLE_ENDIAN | |
| 920 CHECK_EQ(0x44bbccdd, t.lwl_0); | 954 CHECK_EQ(0x44bbccdd, t.lwl_0); |
| 921 CHECK_EQ(0x3344ccdd, t.lwl_1); | 955 CHECK_EQ(0x3344ccdd, t.lwl_1); |
| 922 CHECK_EQ(0x223344dd, t.lwl_2); | 956 CHECK_EQ(0x223344dd, t.lwl_2); |
| 923 CHECK_EQ(0x11223344, t.lwl_3); | 957 CHECK_EQ(0x11223344, t.lwl_3); |
| 924 | 958 |
| 925 CHECK_EQ(0x11223344, t.lwr_0); | 959 CHECK_EQ(0x11223344, t.lwr_0); |
| 926 CHECK_EQ(0xaa112233, t.lwr_1); | 960 CHECK_EQ(0xaa112233, t.lwr_1); |
| 927 CHECK_EQ(0xaabb1122, t.lwr_2); | 961 CHECK_EQ(0xaabb1122, t.lwr_2); |
| 928 CHECK_EQ(0xaabbcc11, t.lwr_3); | 962 CHECK_EQ(0xaabbcc11, t.lwr_3); |
| 929 | 963 |
| 930 CHECK_EQ(0x112233aa, t.swl_0); | 964 CHECK_EQ(0x112233aa, t.swl_0); |
| 931 CHECK_EQ(0x1122aabb, t.swl_1); | 965 CHECK_EQ(0x1122aabb, t.swl_1); |
| 932 CHECK_EQ(0x11aabbcc, t.swl_2); | 966 CHECK_EQ(0x11aabbcc, t.swl_2); |
| 933 CHECK_EQ(0xaabbccdd, t.swl_3); | 967 CHECK_EQ(0xaabbccdd, t.swl_3); |
| 934 | 968 |
| 935 CHECK_EQ(0xaabbccdd, t.swr_0); | 969 CHECK_EQ(0xaabbccdd, t.swr_0); |
| 936 CHECK_EQ(0xbbccdd44, t.swr_1); | 970 CHECK_EQ(0xbbccdd44, t.swr_1); |
| 937 CHECK_EQ(0xccdd3344, t.swr_2); | 971 CHECK_EQ(0xccdd3344, t.swr_2); |
| 938 CHECK_EQ(0xdd223344, t.swr_3); | 972 CHECK_EQ(0xdd223344, t.swr_3); |
| 939 #elif __BYTE_ORDER == __BIG_ENDIAN | |
| 940 CHECK_EQ(0x11223344, t.lwl_0); | |
| 941 CHECK_EQ(0x223344dd, t.lwl_1); | |
| 942 CHECK_EQ(0x3344ccdd, t.lwl_2); | |
| 943 CHECK_EQ(0x44bbccdd, t.lwl_3); | |
| 944 | |
| 945 CHECK_EQ(0xaabbcc11, t.lwr_0); | |
| 946 CHECK_EQ(0xaabb1122, t.lwr_1); | |
| 947 CHECK_EQ(0xaa112233, t.lwr_2); | |
| 948 CHECK_EQ(0x11223344, t.lwr_3); | |
| 949 | |
| 950 CHECK_EQ(0xaabbccdd, t.swl_0); | |
| 951 CHECK_EQ(0x11aabbcc, t.swl_1); | |
| 952 CHECK_EQ(0x1122aabb, t.swl_2); | |
| 953 CHECK_EQ(0x112233aa, t.swl_3); | |
| 954 | |
| 955 CHECK_EQ(0xdd223344, t.swr_0); | |
| 956 CHECK_EQ(0xccdd3344, t.swr_1); | |
| 957 CHECK_EQ(0xbbccdd44, t.swr_2); | |
| 958 CHECK_EQ(0xaabbccdd, t.swr_3); | |
| 959 #else | |
| 960 #error Unknown endianness | |
| 961 #endif | |
| 962 } | 973 } |
| 963 | 974 |
| 964 | 975 |
| 965 TEST(MIPS12) { | 976 TEST(MIPS12) { |
| 966 CcTest::InitializeVM(); | 977 CcTest::InitializeVM(); |
| 967 Isolate* isolate = CcTest::i_isolate(); | 978 Isolate* isolate = CcTest::i_isolate(); |
| 968 HandleScope scope(isolate); | 979 HandleScope scope(isolate); |
| 969 | 980 |
| 970 typedef struct { | 981 typedef struct { |
| 971 int32_t x; | 982 int32_t x; |
| 972 int32_t y; | 983 int32_t y; |
| 973 int32_t y1; | 984 int32_t y1; |
| 974 int32_t y2; | 985 int32_t y2; |
| 975 int32_t y3; | 986 int32_t y3; |
| 976 int32_t y4; | 987 int32_t y4; |
| 977 } T; | 988 } T; |
| 978 T t; | 989 T t; |
| 979 | 990 |
| 980 MacroAssembler assm(isolate, NULL, 0); | 991 MacroAssembler assm(isolate, NULL, 0); |
| 981 | 992 |
| 982 __ mov(t6, fp); // Save frame pointer. | 993 __ mov(t2, fp); // Save frame pointer. |
| 983 __ mov(fp, a0); // Access struct T by fp. | 994 __ mov(fp, a0); // Access struct T by fp. |
| 984 __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) ); | 995 __ lw(a4, MemOperand(a0, OFFSET_OF(T, y)) ); |
| 985 __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) ); | 996 __ lw(a7, MemOperand(a0, OFFSET_OF(T, y4)) ); |
| 986 | 997 |
| 987 __ addu(t1, t0, t3); | 998 __ addu(a5, a4, a7); |
| 988 __ subu(t4, t0, t3); | 999 __ subu(t0, a4, a7); |
| 989 __ nop(); | 1000 __ nop(); |
| 990 __ push(t0); // These instructions disappear after opt. | 1001 __ push(a4); // These instructions disappear after opt. |
| 991 __ Pop(); | 1002 __ Pop(); |
| 992 __ addu(t0, t0, t0); | 1003 __ addu(a4, a4, a4); |
| 993 __ nop(); | 1004 __ nop(); |
| 994 __ Pop(); // These instructions disappear after opt. | 1005 __ Pop(); // These instructions disappear after opt. |
| 995 __ push(t3); | 1006 __ push(a7); |
| 996 __ nop(); | 1007 __ nop(); |
| 997 __ push(t3); // These instructions disappear after opt. | 1008 __ push(a7); // These instructions disappear after opt. |
| 998 __ pop(t3); | 1009 __ pop(a7); |
| 999 __ nop(); | 1010 __ nop(); |
| 1000 __ push(t3); | 1011 __ push(a7); |
| 1001 __ pop(t4); | 1012 __ pop(t0); |
| 1002 __ nop(); | 1013 __ nop(); |
| 1003 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); | 1014 __ sw(a4, MemOperand(fp, OFFSET_OF(T, y)) ); |
| 1004 __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); | 1015 __ lw(a4, MemOperand(fp, OFFSET_OF(T, y)) ); |
| 1005 __ nop(); | 1016 __ nop(); |
| 1006 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); | 1017 __ sw(a4, MemOperand(fp, OFFSET_OF(T, y)) ); |
| 1007 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) ); | 1018 __ lw(a5, MemOperand(fp, OFFSET_OF(T, y)) ); |
| 1008 __ nop(); | 1019 __ nop(); |
| 1009 __ push(t1); | 1020 __ push(a5); |
| 1010 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) ); | 1021 __ lw(a5, MemOperand(fp, OFFSET_OF(T, y)) ); |
| 1011 __ pop(t1); | 1022 __ pop(a5); |
| 1012 __ nop(); | 1023 __ nop(); |
| 1013 __ push(t1); | 1024 __ push(a5); |
| 1014 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); | 1025 __ lw(a6, MemOperand(fp, OFFSET_OF(T, y)) ); |
| 1015 __ pop(t1); | 1026 __ pop(a5); |
| 1016 __ nop(); | 1027 __ nop(); |
| 1017 __ push(t1); | 1028 __ push(a5); |
| 1018 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); | 1029 __ lw(a6, MemOperand(fp, OFFSET_OF(T, y)) ); |
| 1019 __ pop(t2); | 1030 __ pop(a6); |
| 1020 __ nop(); | 1031 __ nop(); |
| 1021 __ push(t2); | 1032 __ push(a6); |
| 1022 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); | 1033 __ lw(a6, MemOperand(fp, OFFSET_OF(T, y)) ); |
| 1023 __ pop(t1); | 1034 __ pop(a5); |
| 1024 __ nop(); | 1035 __ nop(); |
| 1025 __ push(t1); | 1036 __ push(a5); |
| 1026 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); | 1037 __ lw(a6, MemOperand(fp, OFFSET_OF(T, y)) ); |
| 1027 __ pop(t3); | 1038 __ pop(a7); |
| 1028 __ nop(); | 1039 __ nop(); |
| 1029 | 1040 |
| 1030 __ mov(fp, t6); | 1041 __ mov(fp, t2); |
| 1031 __ jr(ra); | 1042 __ jr(ra); |
| 1032 __ nop(); | 1043 __ nop(); |
| 1033 | 1044 |
| 1034 CodeDesc desc; | 1045 CodeDesc desc; |
| 1035 assm.GetCode(&desc); | 1046 assm.GetCode(&desc); |
| 1036 Handle<Code> code = isolate->factory()->NewCode( | 1047 Handle<Code> code = isolate->factory()->NewCode( |
| 1037 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 1048 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1038 F3 f = FUNCTION_CAST<F3>(code->entry()); | 1049 F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1039 t.x = 1; | 1050 t.x = 1; |
| 1040 t.y = 2; | 1051 t.y = 2; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1061 double cvt_small_out; | 1072 double cvt_small_out; |
| 1062 uint32_t trunc_big_out; | 1073 uint32_t trunc_big_out; |
| 1063 uint32_t trunc_small_out; | 1074 uint32_t trunc_small_out; |
| 1064 uint32_t cvt_big_in; | 1075 uint32_t cvt_big_in; |
| 1065 uint32_t cvt_small_in; | 1076 uint32_t cvt_small_in; |
| 1066 } T; | 1077 } T; |
| 1067 T t; | 1078 T t; |
| 1068 | 1079 |
| 1069 MacroAssembler assm(isolate, NULL, 0); | 1080 MacroAssembler assm(isolate, NULL, 0); |
| 1070 | 1081 |
| 1071 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in))); | 1082 __ sw(a4, MemOperand(a0, OFFSET_OF(T, cvt_small_in))); |
| 1072 __ Cvt_d_uw(f10, t0, f22); | 1083 __ Cvt_d_uw(f10, a4, f22); |
| 1073 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out))); | 1084 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out))); |
| 1074 | 1085 |
| 1075 __ Trunc_uw_d(f10, f10, f22); | 1086 __ Trunc_uw_d(f10, f10, f22); |
| 1076 __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out))); | 1087 __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out))); |
| 1077 | 1088 |
| 1078 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in))); | 1089 __ sw(a4, MemOperand(a0, OFFSET_OF(T, cvt_big_in))); |
| 1079 __ Cvt_d_uw(f8, t0, f22); | 1090 __ Cvt_d_uw(f8, a4, f22); |
| 1080 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out))); | 1091 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out))); |
| 1081 | 1092 |
| 1082 __ Trunc_uw_d(f8, f8, f22); | 1093 __ Trunc_uw_d(f8, f8, f22); |
| 1083 __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out))); | 1094 __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out))); |
| 1084 | 1095 |
| 1085 __ jr(ra); | 1096 __ jr(ra); |
| 1086 __ nop(); | 1097 __ nop(); |
| 1087 | 1098 |
| 1088 CodeDesc desc; | 1099 CodeDesc desc; |
| 1089 assm.GetCode(&desc); | 1100 assm.GetCode(&desc); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1220 | 1231 |
| 1221 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | 1232 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 1222 USE(dummy); | 1233 USE(dummy); |
| 1223 | 1234 |
| 1224 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask)) | 1235 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask)) |
| 1225 #define CHECK_ROUND_RESULT(type) \ | 1236 #define CHECK_ROUND_RESULT(type) \ |
| 1226 CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \ | 1237 CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \ |
| 1227 CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \ | 1238 CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \ |
| 1228 CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \ | 1239 CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \ |
| 1229 CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \ | 1240 CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \ |
| 1230 CHECK_EQ(kFPUInvalidResult, t.type##_invalid_result); | 1241 CHECK_EQ(static_cast<int32_t>(kFPUInvalidResult), t.type##_invalid_result); |
| 1231 | 1242 |
| 1232 CHECK_ROUND_RESULT(round); | 1243 CHECK_ROUND_RESULT(round); |
| 1233 CHECK_ROUND_RESULT(floor); | 1244 CHECK_ROUND_RESULT(floor); |
| 1234 CHECK_ROUND_RESULT(ceil); | 1245 CHECK_ROUND_RESULT(ceil); |
| 1235 CHECK_ROUND_RESULT(cvt); | 1246 CHECK_ROUND_RESULT(cvt); |
| 1236 } | 1247 } |
| 1237 | 1248 |
| 1238 | 1249 |
| 1239 TEST(MIPS15) { | 1250 TEST(MIPS15) { |
| 1240 // Test chaining of label usages within instructions (issue 1644). | 1251 // Test chaining of label usages within instructions (issue 1644). |
| 1241 CcTest::InitializeVM(); | 1252 CcTest::InitializeVM(); |
| 1242 Isolate* isolate = CcTest::i_isolate(); | 1253 Isolate* isolate = CcTest::i_isolate(); |
| 1243 HandleScope scope(isolate); | 1254 HandleScope scope(isolate); |
| 1244 Assembler assm(isolate, NULL, 0); | 1255 Assembler assm(isolate, NULL, 0); |
| 1245 | 1256 |
| 1246 Label target; | 1257 Label target; |
| 1247 __ beq(v0, v1, &target); | 1258 __ beq(v0, v1, &target); |
| 1248 __ nop(); | 1259 __ nop(); |
| 1249 __ bne(v0, v1, &target); | 1260 __ bne(v0, v1, &target); |
| 1250 __ nop(); | 1261 __ nop(); |
| 1251 __ bind(&target); | 1262 __ bind(&target); |
| 1252 __ nop(); | 1263 __ nop(); |
| 1253 } | 1264 } |
| 1254 | 1265 |
| 1266 |
| 1267 // ----- mips64 tests ----------------------------------------------- |
| 1268 |
| 1269 TEST(MIPS16) { |
| 1270 // Test 64-bit memory loads and stores. |
| 1271 CcTest::InitializeVM(); |
| 1272 Isolate* isolate = CcTest::i_isolate(); |
| 1273 HandleScope scope(isolate); |
| 1274 |
| 1275 typedef struct { |
| 1276 int64_t r1; |
| 1277 int64_t r2; |
| 1278 int64_t r3; |
| 1279 int64_t r4; |
| 1280 int64_t r5; |
| 1281 int64_t r6; |
| 1282 uint32_t ui; |
| 1283 int32_t si; |
| 1284 } T; |
| 1285 T t; |
| 1286 |
| 1287 Assembler assm(isolate, NULL, 0); |
| 1288 Label L, C; |
| 1289 |
| 1290 // Basic 32-bit word load/store, with un-signed data. |
| 1291 __ lw(a4, MemOperand(a0, OFFSET_OF(T, ui)) ); |
| 1292 __ sw(a4, MemOperand(a0, OFFSET_OF(T, r1)) ); |
| 1293 |
| 1294 // Check that the data got zero-extended into 64-bit a4. |
| 1295 __ sd(a4, MemOperand(a0, OFFSET_OF(T, r2)) ); |
| 1296 |
| 1297 // Basic 32-bit word load/store, with SIGNED data. |
| 1298 __ lw(a5, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 1299 __ sw(a5, MemOperand(a0, OFFSET_OF(T, r3)) ); |
| 1300 |
| 1301 // Check that the data got sign-extended into 64-bit a4. |
| 1302 __ sd(a5, MemOperand(a0, OFFSET_OF(T, r4)) ); |
| 1303 |
| 1304 // 32-bit UNSIGNED word load/store, with SIGNED data. |
| 1305 __ lwu(a6, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 1306 __ sw(a6, MemOperand(a0, OFFSET_OF(T, r5)) ); |
| 1307 |
| 1308 // Check that the data got zero-extended into 64-bit a4. |
| 1309 __ sd(a6, MemOperand(a0, OFFSET_OF(T, r6)) ); |
| 1310 |
| 1311 // lh with positive data. |
| 1312 __ lh(a5, MemOperand(a0, OFFSET_OF(T, ui)) ); |
| 1313 __ sw(a5, MemOperand(a0, OFFSET_OF(T, r2)) ); |
| 1314 |
| 1315 // lh with negative data. |
| 1316 __ lh(a6, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 1317 __ sw(a6, MemOperand(a0, OFFSET_OF(T, r3)) ); |
| 1318 |
| 1319 // lhu with negative data. |
| 1320 __ lhu(a7, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 1321 __ sw(a7, MemOperand(a0, OFFSET_OF(T, r4)) ); |
| 1322 |
| 1323 // lb with negative data. |
| 1324 __ lb(t0, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 1325 __ sw(t0, MemOperand(a0, OFFSET_OF(T, r5)) ); |
| 1326 |
| 1327 // // sh writes only 1/2 of word. |
| 1328 __ lui(t1, 0x3333); |
| 1329 __ ori(t1, t1, 0x3333); |
| 1330 __ sw(t1, MemOperand(a0, OFFSET_OF(T, r6)) ); |
| 1331 __ lhu(t1, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 1332 __ sh(t1, MemOperand(a0, OFFSET_OF(T, r6)) ); |
| 1333 |
| 1334 __ jr(ra); |
| 1335 __ nop(); |
| 1336 |
| 1337 CodeDesc desc; |
| 1338 assm.GetCode(&desc); |
| 1339 Handle<Code> code = isolate->factory()->NewCode( |
| 1340 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1341 F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1342 t.ui = 0x44332211; |
| 1343 t.si = 0x99aabbcc; |
| 1344 t.r1 = 0x1111111111111111; |
| 1345 t.r2 = 0x2222222222222222; |
| 1346 t.r3 = 0x3333333333333333; |
| 1347 t.r4 = 0x4444444444444444; |
| 1348 t.r5 = 0x5555555555555555; |
| 1349 t.r6 = 0x6666666666666666; |
| 1350 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 1351 USE(dummy); |
| 1352 |
| 1353 // Unsigned data, 32 & 64. |
| 1354 CHECK_EQ(0x1111111144332211L, t.r1); |
| 1355 CHECK_EQ(0x0000000000002211L, t.r2); |
| 1356 |
| 1357 // Signed data, 32 & 64. |
| 1358 CHECK_EQ(0x33333333ffffbbccL, t.r3); |
| 1359 CHECK_EQ(0xffffffff0000bbccL, t.r4); |
| 1360 |
| 1361 // Signed data, 32 & 64. |
| 1362 CHECK_EQ(0x55555555ffffffccL, t.r5); |
| 1363 CHECK_EQ(0x000000003333bbccL, t.r6); |
| 1364 } |
| 1365 |
| 1255 #undef __ | 1366 #undef __ |
| OLD | NEW |