OLD | NEW |
1 //===- subzero/src/IceAssemblerMIPS32.h - Assembler for MIPS ----*- C++ -*-===// | 1 //===- subzero/src/IceAssemblerMIPS32.h - Assembler for MIPS ----*- C++ -*-===// |
2 // | 2 // |
3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
4 // for details. All rights reserved. Use of this source code is governed by a | |
5 // BSD-style license that can be found in the LICENSE file. | |
6 // | |
7 // Modified by the Subzero authors. | |
8 // | |
9 //===----------------------------------------------------------------------===// | |
10 // | |
11 // The Subzero Code Generator | 3 // The Subzero Code Generator |
12 // | 4 // |
13 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
14 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
15 // | 7 // |
16 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
17 /// | 9 /// |
18 /// \file | 10 /// \file |
19 /// \brief Declares the Assembler class for MIPS32. | 11 /// \brief Declares the Assembler class for MIPS32. |
20 /// | 12 /// |
21 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
22 | 14 |
23 #ifndef SUBZERO_SRC_ICEASSEMBLERMIPS32_H | 15 #ifndef SUBZERO_SRC_ICEASSEMBLERMIPS32_H |
24 #define SUBZERO_SRC_ICEASSEMBLERMIPS32_H | 16 #define SUBZERO_SRC_ICEASSEMBLERMIPS32_H |
25 | 17 |
26 #include "IceAssembler.h" | 18 #include "IceAssembler.h" |
27 #include "IceDefs.h" | 19 #include "IceDefs.h" |
28 #include "IceFixups.h" | 20 #include "IceFixups.h" |
| 21 #include "IceInstMIPS32.h" |
| 22 #include "IceTargetLowering.h" |
29 | 23 |
30 namespace Ice { | 24 namespace Ice { |
31 namespace MIPS32 { | 25 namespace MIPS32 { |
32 | 26 |
| 27 using IValueT = uint32_t; |
| 28 using IOffsetT = int32_t; |
| 29 |
33 class AssemblerMIPS32 : public Assembler { | 30 class AssemblerMIPS32 : public Assembler { |
34 AssemblerMIPS32(const AssemblerMIPS32 &) = delete; | 31 AssemblerMIPS32(const AssemblerMIPS32 &) = delete; |
35 AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete; | 32 AssemblerMIPS32 &operator=(const AssemblerMIPS32 &) = delete; |
36 | 33 |
37 public: | 34 public: |
38 explicit AssemblerMIPS32(bool use_far_branches = false) | 35 explicit AssemblerMIPS32(bool use_far_branches = false) |
39 : Assembler(Asm_MIPS32) { | 36 : Assembler(Asm_MIPS32) { |
40 // This mode is only needed and implemented for MIPS32 and ARM. | 37 // This mode is only needed and implemented for MIPS32 and ARM. |
41 assert(!use_far_branches); | 38 assert(!use_far_branches); |
42 (void)use_far_branches; | 39 (void)use_far_branches; |
43 } | 40 } |
44 ~AssemblerMIPS32() override = default; | 41 ~AssemblerMIPS32() override { |
| 42 if (BuildDefs::asserts()) { |
| 43 for (const Label *Label : CfgNodeLabels) { |
| 44 Label->finalCheck(); |
| 45 } |
| 46 for (const Label *Label : LocalLabels) { |
| 47 Label->finalCheck(); |
| 48 } |
| 49 } |
| 50 } |
| 51 |
| 52 void trap(); |
| 53 |
| 54 void nop(); |
| 55 |
| 56 void emitRtRsImm16(IValueT Opcode, const Operand *OpRt, const Operand *OpRs, |
| 57 const uint32_t Imm, const char *InsnName); |
| 58 |
| 59 void emitRdRtSa(IValueT Opcode, const Operand *OpRd, const Operand *OpRt, |
| 60 const uint32_t Sa, const char *InsnName); |
| 61 |
| 62 void emitRdRsRt(IValueT Opcode, const Operand *OpRd, const Operand *OpRs, |
| 63 const Operand *OpRt, const char *InsnName); |
| 64 |
| 65 void emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, |
| 66 const Operand *OpRt, IOffsetT Offset); |
| 67 |
| 68 void addiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); |
| 69 |
| 70 void slti(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); |
| 71 |
| 72 void sltiu(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); |
| 73 |
| 74 void and_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); |
| 75 |
| 76 void andi(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); |
| 77 |
| 78 void or_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); |
| 79 |
| 80 void ori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); |
| 81 |
| 82 void xor_(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); |
| 83 |
| 84 void xori(const Operand *OpRt, const Operand *OpRs, const uint32_t Imm); |
| 85 |
| 86 void sll(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa); |
| 87 |
| 88 void srl(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa); |
| 89 |
| 90 void sra(const Operand *OpRd, const Operand *OpRt, const uint32_t Sa); |
| 91 |
| 92 void move(const Operand *OpRd, const Operand *OpRs); |
| 93 |
| 94 void addu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); |
| 95 |
| 96 void slt(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); |
| 97 |
| 98 void sltu(const Operand *OpRd, const Operand *OpRs, const Operand *OpRt); |
| 99 |
| 100 void sw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset); |
| 101 |
| 102 void lw(const Operand *OpRt, const Operand *OpBase, const uint32_t Offset); |
| 103 |
| 104 void ret(void); |
| 105 |
| 106 void b(Label *TargetLabel); |
| 107 |
| 108 void bcc(const CondMIPS32::Cond Cond, const Operand *OpRs, |
| 109 const Operand *OpRt, Label *TargetLabel); |
| 110 |
| 111 void bzc(const CondMIPS32::Cond Cond, const Operand *OpRs, |
| 112 Label *TargetLabel); |
45 | 113 |
46 void alignFunction() override { | 114 void alignFunction() override { |
47 llvm::report_fatal_error("Not yet implemented."); | 115 const SizeT Align = 1 << getBundleAlignLog2Bytes(); |
| 116 SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align); |
| 117 constexpr SizeT InstSize = sizeof(IValueT); |
| 118 assert(BytesNeeded % InstMIPS32::InstSize == 0); |
| 119 while (BytesNeeded > 0) { |
| 120 trap(); |
| 121 BytesNeeded -= InstSize; |
| 122 } |
48 } | 123 } |
49 | 124 |
50 SizeT getBundleAlignLog2Bytes() const override { return 4; } | 125 SizeT getBundleAlignLog2Bytes() const override { return 4; } |
51 | 126 |
52 const char *getAlignDirective() const override { return ".p2alignl"; } | 127 const char *getAlignDirective() const override { return ".p2alignl"; } |
53 | 128 |
54 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override { | 129 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override; |
55 // TODO(reed kotler) . Find out what this should be. | 130 |
56 static const uint8_t Padding[] = {0xE7, 0xFE, 0xDE, 0xF0}; | 131 void padWithNop(intptr_t Padding) override; |
57 return llvm::ArrayRef<uint8_t>(Padding, 4); | 132 |
| 133 void bind(Label *label); |
| 134 |
| 135 void emitTextInst(const std::string &Text, SizeT InstSize); |
| 136 |
| 137 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override { |
| 138 assert(NodeNumber < CfgNodeLabels.size()); |
| 139 return CfgNodeLabels[NodeNumber]; |
58 } | 140 } |
59 | 141 |
60 void padWithNop(intptr_t Padding) override { | 142 Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) { |
61 (void)Padding; | 143 return getOrCreateLabel(NodeNumber, CfgNodeLabels); |
62 llvm::report_fatal_error("Not yet implemented."); | |
63 } | 144 } |
64 | 145 |
65 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override { | 146 Label *getOrCreateLocalLabel(SizeT Number) { |
66 (void)NodeNumber; | 147 return getOrCreateLabel(Number, LocalLabels); |
67 llvm_unreachable("Not yet implemented."); | |
68 } | |
69 | |
70 void bindCfgNodeLabel(const CfgNode *) override { | |
71 llvm::report_fatal_error("Not yet implemented."); | |
72 } | 148 } |
73 | 149 |
74 bool fixupIsPCRel(FixupKind Kind) const override { | 150 bool fixupIsPCRel(FixupKind Kind) const override { |
75 (void)Kind; | 151 (void)Kind; |
76 llvm::report_fatal_error("Not yet implemented."); | 152 llvm::report_fatal_error("Not yet implemented."); |
77 } | 153 } |
78 | 154 |
79 static bool classof(const Assembler *Asm) { | 155 static bool classof(const Assembler *Asm) { |
80 return Asm->getKind() == Asm_MIPS32; | 156 return Asm->getKind() == Asm_MIPS32; |
81 } | 157 } |
82 | 158 |
83 private: | 159 private: |
84 ENABLE_MAKE_UNIQUE; | 160 ENABLE_MAKE_UNIQUE; |
| 161 |
| 162 using LabelVector = std::vector<Label *>; |
| 163 LabelVector CfgNodeLabels; |
| 164 LabelVector LocalLabels; |
| 165 |
| 166 // Returns the offset encoded in the branch instruction Inst. |
| 167 static IOffsetT decodeBranchOffset(IValueT Inst); |
| 168 |
| 169 Label *getOrCreateLabel(SizeT Number, LabelVector &Labels); |
| 170 |
| 171 void bindCfgNodeLabel(const CfgNode *) override; |
| 172 |
| 173 void emitInst(IValueT Value) { |
| 174 AssemblerBuffer::EnsureCapacity _(&Buffer); |
| 175 Buffer.emit<IValueT>(Value); |
| 176 } |
85 }; | 177 }; |
86 | 178 |
87 } // end of namespace MIPS32 | 179 } // end of namespace MIPS32 |
88 } // end of namespace Ice | 180 } // end of namespace Ice |
89 | 181 |
90 #endif // SUBZERO_SRC_ICEASSEMBLERMIPS32_H | 182 #endif // SUBZERO_SRC_ICEASSEMBLERMIPS32_H |
OLD | NEW |