OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 #include "src/compiler/code-generator-impl.h" | 6 #include "src/compiler/code-generator-impl.h" |
7 #include "src/compiler/gap-resolver.h" | 7 #include "src/compiler/gap-resolver.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
10 #include "src/mips/macro-assembler-mips.h" | 10 #include "src/mips/macro-assembler-mips.h" |
11 #include "src/scopes.h" | 11 #include "src/scopes.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 namespace compiler { | 15 namespace compiler { |
16 | 16 |
17 #define __ masm()-> | 17 #define __ masm()-> |
18 | 18 |
19 | 19 |
20 // TODO(plind): Possibly avoid using these lithium names. | 20 // TODO(plind): Possibly avoid using these lithium names. |
21 #define kScratchReg kLithiumScratchReg | 21 #define kScratchReg kLithiumScratchReg |
22 #define kCompareReg kLithiumScratchReg2 | 22 #define kCompareReg kLithiumScratchReg2 |
| 23 #define kScratchReg2 kLithiumScratchReg2 |
23 #define kScratchDoubleReg kLithiumScratchDouble | 24 #define kScratchDoubleReg kLithiumScratchDouble |
24 | 25 |
25 | 26 |
26 // TODO(plind): consider renaming these macros. | 27 // TODO(plind): consider renaming these macros. |
27 #define TRACE_MSG(msg) \ | 28 #define TRACE_MSG(msg) \ |
28 PrintF("code_gen: \'%s\' in function %s at line %d\n", msg, __FUNCTION__, \ | 29 PrintF("code_gen: \'%s\' in function %s at line %d\n", msg, __FUNCTION__, \ |
29 __LINE__) | 30 __LINE__) |
30 | 31 |
31 #define TRACE_UNIMPL() \ | 32 #define TRACE_UNIMPL() \ |
32 PrintF("UNIMPLEMENTED code_generator_mips: %s at line %d\n", __FUNCTION__, \ | 33 PrintF("UNIMPLEMENTED code_generator_mips: %s at line %d\n", __FUNCTION__, \ |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 public: | 156 public: |
156 OutOfLineLoadInteger(CodeGenerator* gen, Register result) | 157 OutOfLineLoadInteger(CodeGenerator* gen, Register result) |
157 : OutOfLineCode(gen), result_(result) {} | 158 : OutOfLineCode(gen), result_(result) {} |
158 | 159 |
159 void Generate() FINAL { __ mov(result_, zero_reg); } | 160 void Generate() FINAL { __ mov(result_, zero_reg); } |
160 | 161 |
161 private: | 162 private: |
162 Register const result_; | 163 Register const result_; |
163 }; | 164 }; |
164 | 165 |
| 166 |
| 167 class OutOfLineRound : public OutOfLineCode { |
| 168 public: |
| 169 OutOfLineRound(CodeGenerator* gen, DoubleRegister result) |
| 170 : OutOfLineCode(gen), result_(result) {} |
| 171 |
| 172 void Generate() FINAL { |
| 173 // Handle rounding to zero case where sign has to be preserved. |
| 174 // High bits of double input already in kScratchReg. |
| 175 __ srl(at, kScratchReg, 31); |
| 176 __ sll(at, at, 31); |
| 177 __ Mthc1(at, result_); |
| 178 } |
| 179 |
| 180 private: |
| 181 DoubleRegister const result_; |
| 182 }; |
| 183 |
| 184 |
| 185 class OutOfLineTruncate FINAL : public OutOfLineRound { |
| 186 public: |
| 187 OutOfLineTruncate(CodeGenerator* gen, DoubleRegister result) |
| 188 : OutOfLineRound(gen, result) {} |
| 189 }; |
| 190 |
| 191 |
| 192 class OutOfLineFloor FINAL : public OutOfLineRound { |
| 193 public: |
| 194 OutOfLineFloor(CodeGenerator* gen, DoubleRegister result) |
| 195 : OutOfLineRound(gen, result) {} |
| 196 }; |
| 197 |
| 198 |
| 199 class OutOfLineCeil FINAL : public OutOfLineRound { |
| 200 public: |
| 201 OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) |
| 202 : OutOfLineRound(gen, result) {} |
| 203 }; |
| 204 |
165 } // namespace | 205 } // namespace |
166 | 206 |
167 | 207 |
168 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ | 208 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ |
169 do { \ | 209 do { \ |
170 auto result = i.Output##width##Register(); \ | 210 auto result = i.Output##width##Register(); \ |
171 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ | 211 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ |
172 if (instr->InputAt(0)->IsRegister()) { \ | 212 if (instr->InputAt(0)->IsRegister()) { \ |
173 auto offset = i.InputRegister(0); \ | 213 auto offset = i.InputRegister(0); \ |
174 __ Branch(USE_DELAY_SLOT, ool->entry(), hs, offset, i.InputOperand(1)); \ | 214 __ Branch(USE_DELAY_SLOT, ool->entry(), hs, offset, i.InputOperand(1)); \ |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 } else { \ | 272 } else { \ |
233 auto offset = i.InputOperand(0).immediate(); \ | 273 auto offset = i.InputOperand(0).immediate(); \ |
234 auto value = i.InputRegister(2); \ | 274 auto value = i.InputRegister(2); \ |
235 __ Branch(&done, ls, i.InputRegister(1), Operand(offset)); \ | 275 __ Branch(&done, ls, i.InputRegister(1), Operand(offset)); \ |
236 __ asm_instr(value, MemOperand(i.InputRegister(3), offset)); \ | 276 __ asm_instr(value, MemOperand(i.InputRegister(3), offset)); \ |
237 } \ | 277 } \ |
238 __ bind(&done); \ | 278 __ bind(&done); \ |
239 } while (0) | 279 } while (0) |
240 | 280 |
241 | 281 |
| 282 #define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(asm_instr, operation) \ |
| 283 do { \ |
| 284 auto ool = \ |
| 285 new (zone()) OutOfLine##operation(this, i.OutputDoubleRegister()); \ |
| 286 Label done; \ |
| 287 __ Mfhc1(kScratchReg, i.InputDoubleRegister(0)); \ |
| 288 __ Ext(at, kScratchReg, HeapNumber::kExponentShift, \ |
| 289 HeapNumber::kExponentBits); \ |
| 290 __ Branch(USE_DELAY_SLOT, &done, hs, at, \ |
| 291 Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits)); \ |
| 292 __ mov_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ |
| 293 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ |
| 294 __ Move(at, kScratchReg2, i.OutputDoubleRegister()); \ |
| 295 __ or_(at, at, kScratchReg2); \ |
| 296 __ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \ |
| 297 __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \ |
| 298 __ bind(ool->exit()); \ |
| 299 __ bind(&done); \ |
| 300 } while (0) |
| 301 |
| 302 |
242 // Assembles an instruction after register allocation, producing machine code. | 303 // Assembles an instruction after register allocation, producing machine code. |
243 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 304 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
244 MipsOperandConverter i(this, instr); | 305 MipsOperandConverter i(this, instr); |
245 InstructionCode opcode = instr->opcode(); | 306 InstructionCode opcode = instr->opcode(); |
246 | 307 |
247 switch (ArchOpcodeField::decode(opcode)) { | 308 switch (ArchOpcodeField::decode(opcode)) { |
248 case kArchCallCodeObject: { | 309 case kArchCallCodeObject: { |
249 EnsureSpaceForLazyDeopt(); | 310 EnsureSpaceForLazyDeopt(); |
250 if (instr->InputAt(0)->IsImmediate()) { | 311 if (instr->InputAt(0)->IsImmediate()) { |
251 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 312 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 FrameScope scope(masm(), StackFrame::MANUAL); | 461 FrameScope scope(masm(), StackFrame::MANUAL); |
401 __ PrepareCallCFunction(0, 2, kScratchReg); | 462 __ PrepareCallCFunction(0, 2, kScratchReg); |
402 __ MovToFloatParameters(i.InputDoubleRegister(0), | 463 __ MovToFloatParameters(i.InputDoubleRegister(0), |
403 i.InputDoubleRegister(1)); | 464 i.InputDoubleRegister(1)); |
404 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), | 465 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), |
405 0, 2); | 466 0, 2); |
406 // Move the result in the double result register. | 467 // Move the result in the double result register. |
407 __ MovFromFloatResult(i.OutputDoubleRegister()); | 468 __ MovFromFloatResult(i.OutputDoubleRegister()); |
408 break; | 469 break; |
409 } | 470 } |
| 471 case kMipsFloat64Floor: { |
| 472 ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(floor_l_d, Floor); |
| 473 break; |
| 474 } |
| 475 case kMipsFloat64Ceil: { |
| 476 ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(ceil_l_d, Ceil); |
| 477 break; |
| 478 } |
| 479 case kMipsFloat64RoundTruncate: { |
| 480 ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(trunc_l_d, Truncate); |
| 481 break; |
| 482 } |
410 case kMipsSqrtD: { | 483 case kMipsSqrtD: { |
411 __ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); | 484 __ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
412 break; | 485 break; |
413 } | 486 } |
414 case kMipsCvtSD: { | 487 case kMipsCvtSD: { |
415 __ cvt_s_d(i.OutputSingleRegister(), i.InputDoubleRegister(0)); | 488 __ cvt_s_d(i.OutputSingleRegister(), i.InputDoubleRegister(0)); |
416 break; | 489 break; |
417 } | 490 } |
418 case kMipsCvtDS: { | 491 case kMipsCvtDS: { |
419 __ cvt_d_s(i.OutputDoubleRegister(), i.InputSingleRegister(0)); | 492 __ cvt_d_s(i.OutputDoubleRegister(), i.InputSingleRegister(0)); |
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 } | 1176 } |
1104 } | 1177 } |
1105 MarkLazyDeoptSite(); | 1178 MarkLazyDeoptSite(); |
1106 } | 1179 } |
1107 | 1180 |
1108 #undef __ | 1181 #undef __ |
1109 | 1182 |
1110 } // namespace compiler | 1183 } // namespace compiler |
1111 } // namespace internal | 1184 } // namespace internal |
1112 } // namespace v8 | 1185 } // namespace v8 |
OLD | NEW |