blob: 0f5f2fe199fe2f63ee979eea7323ab531131afe6 [file] [log] [blame]
jeffhao7fbee072012-08-24 17:56:54 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Ian Rogers166db042013-07-26 12:05:57 -070017#ifndef ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
18#define ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
jeffhao7fbee072012-08-24 17:56:54 -070019
20#include <vector>
Elliott Hughes76160052012-12-12 16:31:20 -080021
22#include "base/macros.h"
jeffhao7fbee072012-08-24 17:56:54 -070023#include "constants_mips.h"
24#include "globals.h"
25#include "managed_register_mips.h"
Ian Rogers166db042013-07-26 12:05:57 -070026#include "utils/assembler.h"
jeffhao7fbee072012-08-24 17:56:54 -070027#include "offsets.h"
28#include "utils.h"
29
30namespace art {
31namespace mips {
32#if 0
33class Operand {
34 public:
35 uint8_t mod() const {
36 return (encoding_at(0) >> 6) & 3;
37 }
38
39 Register rm() const {
40 return static_cast<Register>(encoding_at(0) & 7);
41 }
42
43 ScaleFactor scale() const {
44 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
45 }
46
47 Register index() const {
48 return static_cast<Register>((encoding_at(1) >> 3) & 7);
49 }
50
51 Register base() const {
52 return static_cast<Register>(encoding_at(1) & 7);
53 }
54
55 int8_t disp8() const {
56 CHECK_GE(length_, 2);
57 return static_cast<int8_t>(encoding_[length_ - 1]);
58 }
59
60 int32_t disp32() const {
61 CHECK_GE(length_, 5);
62 int32_t value;
63 memcpy(&value, &encoding_[length_ - 4], sizeof(value));
64 return value;
65 }
66
67 bool IsRegister(Register reg) const {
68 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
69 && ((encoding_[0] & 0x07) == reg); // Register codes match.
70 }
71
72 protected:
73 // Operand can be sub classed (e.g: Address).
74 Operand() : length_(0) { }
75
76 void SetModRM(int mod, Register rm) {
77 CHECK_EQ(mod & ~3, 0);
78 encoding_[0] = (mod << 6) | rm;
79 length_ = 1;
80 }
81
82 void SetSIB(ScaleFactor scale, Register index, Register base) {
83 CHECK_EQ(length_, 1);
84 CHECK_EQ(scale & ~3, 0);
85 encoding_[1] = (scale << 6) | (index << 3) | base;
86 length_ = 2;
87 }
88
89 void SetDisp8(int8_t disp) {
90 CHECK(length_ == 1 || length_ == 2);
91 encoding_[length_++] = static_cast<uint8_t>(disp);
92 }
93
94 void SetDisp32(int32_t disp) {
95 CHECK(length_ == 1 || length_ == 2);
96 int disp_size = sizeof(disp);
97 memmove(&encoding_[length_], &disp, disp_size);
98 length_ += disp_size;
99 }
100
101 private:
102 byte length_;
103 byte encoding_[6];
104 byte padding_;
105
106 explicit Operand(Register reg) { SetModRM(3, reg); }
107
108 // Get the operand encoding byte at the given index.
109 uint8_t encoding_at(int index) const {
110 CHECK_GE(index, 0);
111 CHECK_LT(index, length_);
112 return encoding_[index];
113 }
114
115 friend class MipsAssembler;
116
jeffhao7fbee072012-08-24 17:56:54 -0700117 DISALLOW_COPY_AND_ASSIGN(Operand);
jeffhao7fbee072012-08-24 17:56:54 -0700118};
119
120
121class Address : public Operand {
122 public:
123 Address(Register base, int32_t disp) {
124 Init(base, disp);
125 }
126
127 Address(Register base, Offset disp) {
128 Init(base, disp.Int32Value());
129 }
130
131 Address(Register base, FrameOffset disp) {
132 CHECK_EQ(base, ESP);
133 Init(ESP, disp.Int32Value());
134 }
135
136 Address(Register base, MemberOffset disp) {
137 Init(base, disp.Int32Value());
138 }
139
140 void Init(Register base, int32_t disp) {
141 if (disp == 0 && base != EBP) {
142 SetModRM(0, base);
143 if (base == ESP) SetSIB(TIMES_1, ESP, base);
144 } else if (disp >= -128 && disp <= 127) {
145 SetModRM(1, base);
146 if (base == ESP) SetSIB(TIMES_1, ESP, base);
147 SetDisp8(disp);
148 } else {
149 SetModRM(2, base);
150 if (base == ESP) SetSIB(TIMES_1, ESP, base);
151 SetDisp32(disp);
152 }
153 }
154
155
156 Address(Register index, ScaleFactor scale, int32_t disp) {
157 CHECK_NE(index, ESP); // Illegal addressing mode.
158 SetModRM(0, ESP);
159 SetSIB(scale, index, EBP);
160 SetDisp32(disp);
161 }
162
163 Address(Register base, Register index, ScaleFactor scale, int32_t disp) {
164 CHECK_NE(index, ESP); // Illegal addressing mode.
165 if (disp == 0 && base != EBP) {
166 SetModRM(0, ESP);
167 SetSIB(scale, index, base);
168 } else if (disp >= -128 && disp <= 127) {
169 SetModRM(1, ESP);
170 SetSIB(scale, index, base);
171 SetDisp8(disp);
172 } else {
173 SetModRM(2, ESP);
174 SetSIB(scale, index, base);
175 SetDisp32(disp);
176 }
177 }
178
179 static Address Absolute(uword addr) {
180 Address result;
181 result.SetModRM(0, EBP);
182 result.SetDisp32(addr);
183 return result;
184 }
185
186 static Address Absolute(ThreadOffset addr) {
187 return Absolute(addr.Int32Value());
188 }
189
190 private:
191 Address() {}
192
jeffhao7fbee072012-08-24 17:56:54 -0700193 DISALLOW_COPY_AND_ASSIGN(Address);
jeffhao7fbee072012-08-24 17:56:54 -0700194};
195
196#endif
197
198enum LoadOperandType {
199 kLoadSignedByte,
200 kLoadUnsignedByte,
201 kLoadSignedHalfword,
202 kLoadUnsignedHalfword,
203 kLoadWord,
204 kLoadWordPair,
205 kLoadSWord,
206 kLoadDWord
207};
208
209enum StoreOperandType {
210 kStoreByte,
211 kStoreHalfword,
212 kStoreWord,
213 kStoreWordPair,
214 kStoreSWord,
215 kStoreDWord
216};
217
218class MipsAssembler : public Assembler {
219 public:
220 MipsAssembler() {}
221 virtual ~MipsAssembler() {}
222
223 // Emit Machine Instructions.
224 void Add(Register rd, Register rs, Register rt);
225 void Addu(Register rd, Register rs, Register rt);
226 void Addi(Register rt, Register rs, uint16_t imm16);
227 void Addiu(Register rt, Register rs, uint16_t imm16);
228 void Sub(Register rd, Register rs, Register rt);
229 void Subu(Register rd, Register rs, Register rt);
230 void Mult(Register rs, Register rt);
231 void Multu(Register rs, Register rt);
232 void Div(Register rs, Register rt);
233 void Divu(Register rs, Register rt);
234
235 void And(Register rd, Register rs, Register rt);
236 void Andi(Register rt, Register rs, uint16_t imm16);
237 void Or(Register rd, Register rs, Register rt);
238 void Ori(Register rt, Register rs, uint16_t imm16);
239 void Xor(Register rd, Register rs, Register rt);
240 void Xori(Register rt, Register rs, uint16_t imm16);
241 void Nor(Register rd, Register rs, Register rt);
242
243 void Sll(Register rd, Register rs, int shamt);
244 void Srl(Register rd, Register rs, int shamt);
245 void Sra(Register rd, Register rs, int shamt);
246 void Sllv(Register rd, Register rs, Register rt);
247 void Srlv(Register rd, Register rs, Register rt);
248 void Srav(Register rd, Register rs, Register rt);
249
250 void Lb(Register rt, Register rs, uint16_t imm16);
251 void Lh(Register rt, Register rs, uint16_t imm16);
252 void Lw(Register rt, Register rs, uint16_t imm16);
253 void Lbu(Register rt, Register rs, uint16_t imm16);
254 void Lhu(Register rt, Register rs, uint16_t imm16);
255 void Lui(Register rt, uint16_t imm16);
256 void Mfhi(Register rd);
257 void Mflo(Register rd);
258
259 void Sb(Register rt, Register rs, uint16_t imm16);
260 void Sh(Register rt, Register rs, uint16_t imm16);
261 void Sw(Register rt, Register rs, uint16_t imm16);
262
263 void Slt(Register rd, Register rs, Register rt);
264 void Sltu(Register rd, Register rs, Register rt);
265 void Slti(Register rt, Register rs, uint16_t imm16);
266 void Sltiu(Register rt, Register rs, uint16_t imm16);
267
268 void Beq(Register rt, Register rs, uint16_t imm16);
269 void Bne(Register rt, Register rs, uint16_t imm16);
270 void J(uint32_t address);
271 void Jal(uint32_t address);
272 void Jr(Register rs);
273 void Jalr(Register rs);
274
275 void AddS(FRegister fd, FRegister fs, FRegister ft);
276 void SubS(FRegister fd, FRegister fs, FRegister ft);
277 void MulS(FRegister fd, FRegister fs, FRegister ft);
278 void DivS(FRegister fd, FRegister fs, FRegister ft);
279 void AddD(DRegister fd, DRegister fs, DRegister ft);
280 void SubD(DRegister fd, DRegister fs, DRegister ft);
281 void MulD(DRegister fd, DRegister fs, DRegister ft);
282 void DivD(DRegister fd, DRegister fs, DRegister ft);
283 void MovS(FRegister fd, FRegister fs);
284 void MovD(DRegister fd, DRegister fs);
285
286 void Mfc1(Register rt, FRegister fs);
287 void Mtc1(FRegister ft, Register rs);
288 void Lwc1(FRegister ft, Register rs, uint16_t imm16);
289 void Ldc1(DRegister ft, Register rs, uint16_t imm16);
290 void Swc1(FRegister ft, Register rs, uint16_t imm16);
291 void Sdc1(DRegister ft, Register rs, uint16_t imm16);
292
293 void Break();
jeffhao07030602012-09-26 14:33:14 -0700294 void Nop();
jeffhao7fbee072012-08-24 17:56:54 -0700295 void Move(Register rt, Register rs);
296 void Clear(Register rt);
297 void Not(Register rt, Register rs);
298 void Mul(Register rd, Register rs, Register rt);
299 void Div(Register rd, Register rs, Register rt);
300 void Rem(Register rd, Register rs, Register rt);
301
302 void AddConstant(Register rt, Register rs, int32_t value);
303 void LoadImmediate(Register rt, int32_t value);
304
305 void EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, size_t size);
306 void LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset);
307 void LoadSFromOffset(FRegister reg, Register base, int32_t offset);
308 void LoadDFromOffset(DRegister reg, Register base, int32_t offset);
309 void StoreToOffset(StoreOperandType type, Register reg, Register base, int32_t offset);
310 void StoreFToOffset(FRegister reg, Register base, int32_t offset);
311 void StoreDToOffset(DRegister reg, Register base, int32_t offset);
312
313#if 0
314 MipsAssembler* lock();
315
316 void mfence();
317
318 MipsAssembler* fs();
319
320 //
321 // Macros for High-level operations.
322 //
323
324 void AddImmediate(Register reg, const Immediate& imm);
325
326 void LoadDoubleConstant(XmmRegister dst, double value);
327
328 void DoubleNegate(XmmRegister d);
329 void FloatNegate(XmmRegister f);
330
331 void DoubleAbs(XmmRegister reg);
332
333 void LockCmpxchgl(const Address& address, Register reg) {
334 lock()->cmpxchgl(address, reg);
335 }
336
337 //
338 // Misc. functionality
339 //
340 int PreferredLoopAlignment() { return 16; }
341 void Align(int alignment, int offset);
342
343 // Debugging and bringup support.
344 void Stop(const char* message);
345#endif
346
347 // Emit data (e.g. encoded instruction or immediate) to the instruction stream.
348 void Emit(int32_t value);
349 void EmitBranch(Register rt, Register rs, Label* label, bool equal);
350 void EmitJump(Label* label, bool link);
351 void Bind(Label* label, bool is_jump);
352
353 //
354 // Overridden common assembler high-level functionality
355 //
356
357 // Emit code that will create an activation on the stack
358 virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
359 const std::vector<ManagedRegister>& callee_save_regs,
360 const std::vector<ManagedRegister>& entry_spills);
361
362 // Emit code that will remove an activation from the stack
363 virtual void RemoveFrame(size_t frame_size,
364 const std::vector<ManagedRegister>& callee_save_regs);
365
366 virtual void IncreaseFrameSize(size_t adjust);
367 virtual void DecreaseFrameSize(size_t adjust);
368
369 // Store routines
370 virtual void Store(FrameOffset offs, ManagedRegister msrc, size_t size);
371 virtual void StoreRef(FrameOffset dest, ManagedRegister msrc);
372 virtual void StoreRawPtr(FrameOffset dest, ManagedRegister msrc);
373
374 virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
375 ManagedRegister mscratch);
376
377 virtual void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
378 ManagedRegister mscratch);
379
380 virtual void StoreStackOffsetToThread(ThreadOffset thr_offs,
381 FrameOffset fr_offs,
382 ManagedRegister mscratch);
383
384 virtual void StoreStackPointerToThread(ThreadOffset thr_offs);
385
386 virtual void StoreSpanning(FrameOffset dest, ManagedRegister msrc,
387 FrameOffset in_off, ManagedRegister mscratch);
388
389 // Load routines
390 virtual void Load(ManagedRegister mdest, FrameOffset src, size_t size);
391
392 virtual void Load(ManagedRegister mdest, ThreadOffset src, size_t size);
393
394 virtual void LoadRef(ManagedRegister dest, FrameOffset src);
395
396 virtual void LoadRef(ManagedRegister mdest, ManagedRegister base,
397 MemberOffset offs);
398
399 virtual void LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
400 Offset offs);
401
402 virtual void LoadRawPtrFromThread(ManagedRegister mdest,
403 ThreadOffset offs);
404
405 // Copying routines
406 virtual void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size);
407
408 virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
409 ManagedRegister mscratch);
410
411 virtual void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
412 ManagedRegister mscratch);
413
414 virtual void CopyRef(FrameOffset dest, FrameOffset src,
415 ManagedRegister mscratch);
416
417 virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size);
418
419 virtual void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
420 ManagedRegister mscratch, size_t size);
421
422 virtual void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
423 ManagedRegister mscratch, size_t size);
424
425 virtual void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset,
426 ManagedRegister mscratch, size_t size);
427
428 virtual void Copy(ManagedRegister dest, Offset dest_offset,
429 ManagedRegister src, Offset src_offset,
430 ManagedRegister mscratch, size_t size);
431
432 virtual void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
433 ManagedRegister mscratch, size_t size);
434
435 virtual void MemoryBarrier(ManagedRegister);
436
437 // Sign extension
438 virtual void SignExtend(ManagedRegister mreg, size_t size);
439
440 // Zero extension
441 virtual void ZeroExtend(ManagedRegister mreg, size_t size);
442
443 // Exploit fast access in managed code to Thread::Current()
444 virtual void GetCurrentThread(ManagedRegister tr);
445 virtual void GetCurrentThread(FrameOffset dest_offset,
446 ManagedRegister mscratch);
447
448 // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the
449 // value is null and null_allowed. in_reg holds a possibly stale reference
450 // that can be used to avoid loading the SIRT entry to see if the value is
451 // NULL.
452 virtual void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset,
453 ManagedRegister in_reg, bool null_allowed);
454
455 // Set up out_off to hold a Object** into the SIRT, or to be NULL if the
456 // value is null and null_allowed.
457 virtual void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset,
458 ManagedRegister mscratch, bool null_allowed);
459
460 // src holds a SIRT entry (Object**) load this into dst
461 virtual void LoadReferenceFromSirt(ManagedRegister dst,
462 ManagedRegister src);
463
464 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
465 // know that src may not be null.
466 virtual void VerifyObject(ManagedRegister src, bool could_be_null);
467 virtual void VerifyObject(FrameOffset src, bool could_be_null);
468
469 // Call to address held at [base+offset]
470 virtual void Call(ManagedRegister base, Offset offset,
471 ManagedRegister mscratch);
472 virtual void Call(FrameOffset base, Offset offset,
473 ManagedRegister mscratch);
474 virtual void Call(ThreadOffset offset, ManagedRegister mscratch);
475
jeffhao7fbee072012-08-24 17:56:54 -0700476 // Generate code to check if Thread::Current()->exception_ is non-null
477 // and branch to a ExceptionSlowPath if it is.
478 virtual void ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust);
479
480 private:
481 void EmitR(int opcode, Register rs, Register rt, Register rd, int shamt, int funct);
482 void EmitI(int opcode, Register rs, Register rt, uint16_t imm);
483 void EmitJ(int opcode, int address);
484 void EmitFR(int opcode, int fmt, FRegister ft, FRegister fs, FRegister fd, int funct);
485 void EmitFI(int opcode, int fmt, FRegister rt, uint16_t imm);
486
487 int32_t EncodeBranchOffset(int offset, int32_t inst, bool is_jump);
488 int DecodeBranchOffset(int32_t inst, bool is_jump);
489
490 DISALLOW_COPY_AND_ASSIGN(MipsAssembler);
491};
492
493// Slowpath entered when Thread::Current()->_exception is non-null
494class MipsExceptionSlowPath : public SlowPath {
495 public:
496 explicit MipsExceptionSlowPath(MipsManagedRegister scratch, size_t stack_adjust)
497 : scratch_(scratch), stack_adjust_(stack_adjust) {}
498 virtual void Emit(Assembler *sp_asm);
499 private:
500 const MipsManagedRegister scratch_;
501 const size_t stack_adjust_;
502};
503
jeffhao7fbee072012-08-24 17:56:54 -0700504} // namespace mips
505} // namespace art
506
Ian Rogers166db042013-07-26 12:05:57 -0700507#endif // ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_