OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, the Dartino project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE.md file. |
| 4 |
| 5 #ifndef SRC_VM_ASSEMBLER_MIPS_H_ |
| 6 #define SRC_VM_ASSEMBLER_MIPS_H_ |
| 7 |
| 8 #ifndef SRC_VM_ASSEMBLER_H_ |
| 9 #error Do not include assembler_mips.h directly; use assembler.h instead. |
| 10 #endif |
| 11 |
| 12 #include "src/shared/assert.h" |
| 13 #include "src/shared/utils.h" |
| 14 |
| 15 namespace dartino { |
| 16 |
| 17 enum Register { |
| 18 ZR = 0, |
| 19 AT = 1, |
| 20 V0 = 2, |
| 21 V1 = 3, |
| 22 A0 = 4, |
| 23 A1 = 5, |
| 24 A2 = 6, |
| 25 A3 = 7, |
| 26 T0 = 8, |
| 27 T1 = 9, |
| 28 T2 = 10, |
| 29 T3 = 11, |
| 30 T4 = 12, |
| 31 T5 = 13, |
| 32 T6 = 14, |
| 33 T7 = 15, |
| 34 S0 = 16, |
| 35 S1 = 17, |
| 36 S2 = 18, |
| 37 S3 = 19, |
| 38 S4 = 20, |
| 39 S5 = 21, |
| 40 S6 = 22, |
| 41 S7 = 23, |
| 42 T8 = 24, |
| 43 T9 = 25, |
| 44 K0 = 26, // mips kernel reserved register. DO NOT USE. |
| 45 K1 = 27, // mips kernel reserved register. DO NOT USE. |
| 46 GP = 28, |
| 47 SP = 29, |
| 48 FP = 30, |
| 49 RA = 31, |
| 50 }; |
| 51 |
| 52 enum ScaleFactor { |
| 53 TIMES_1 = 0, |
| 54 TIMES_2 = 1, |
| 55 TIMES_4 = 2, |
| 56 TIMES_WORD_SIZE = TIMES_4, |
| 57 TIMES_8 = 3 |
| 58 }; |
| 59 enum ShiftType { SLL, SRL, SLLV, SRLV, SRA, SRAV }; |
| 60 |
| 61 enum Condition { |
| 62 F = 0, // False |
| 63 T = 1, // True |
| 64 UN = 2, // Unordered |
| 65 OR = 3, // Ordered |
| 66 EQ = 4, // Equal |
| 67 NEQ = 5, // Not Equal |
| 68 UEQ = 6, // Unordered or Equal |
| 69 OLG = 7, // Ordered or Less than or Greater Than |
| 70 OLT = 8, // Ordered Less Than |
| 71 UGE = 9, // Unordered or Greater Than or Equal |
| 72 ULT = 10, // Unordered or Less Than |
| 73 OGE = 11, // Ordered Greater Than or Equal |
| 74 OLE = 12, // Ordered Less Than or Equal |
| 75 UGT = 13, // Unordered or Greater Than |
| 76 ULE = 14, // Unordered or Less Than or Equal |
| 77 OGT = 15, // Ordered Greater Than |
| 78 SF = 16, // Signaling False |
| 79 ST = 17, // Signaling True |
| 80 NGLE = 18, // Not Greater Than or Less Than or Equal |
| 81 GLE = 19, // Greater Than, or Less Than or Equal |
| 82 SEQ = 20, // Signaling Equal |
| 83 SNE = 21, // Signaling Not Equal |
| 84 NGL = 22, // Not Greater Than or Less Than |
| 85 GL = 23, // Greater Than or Less Than |
| 86 LT = 24, // Less Than |
| 87 NLT = 25, // Not Less Than |
| 88 NGE = 26, // Not Greater Than |
| 89 GE = 27, // Greater Than or Equal |
| 90 LE = 28, // Less Than or Equal |
| 91 NLE = 29, // Not Less Than or Equal |
| 92 NGT = 30, // Not Greater Than |
| 93 GT = 31, // Greater Than |
| 94 }; |
| 95 |
| 96 class Immediate { |
| 97 public: |
| 98 explicit Immediate(int32_t value) : value_(value) {} |
| 99 int32_t value() const { return value_; } |
| 100 |
| 101 private: |
| 102 const int32_t value_; |
| 103 }; |
| 104 |
| 105 class Address { |
| 106 public: |
| 107 Address(Register base, int32_t offset) |
| 108 : base_(base), offset_(offset) {} |
| 109 |
| 110 Register base() const { return base_; } |
| 111 int32_t offset() const { return offset_; } |
| 112 |
| 113 private: |
| 114 const Register base_; |
| 115 const int32_t offset_; |
| 116 }; |
| 117 |
| 118 |
| 119 class Label { |
| 120 public: |
| 121 Label() : position_(-1) {} |
| 122 |
| 123 // Returns the position for a label. Positions are assigned on first use. |
| 124 int position() { |
| 125 if (position_ == -1) position_ = position_counter_++; |
| 126 return position_; |
| 127 } |
| 128 |
| 129 private: |
| 130 int position_; |
| 131 static int position_counter_; |
| 132 }; |
| 133 |
| 134 #define INSTRUCTION_0(name, format) \ |
| 135 void name() { Print(format); } |
| 136 |
| 137 #define INSTRUCTION_1(name, format, t0) \ |
| 138 void name(t0 a0) { Print(format, Wrap(a0)); } |
| 139 |
| 140 #define INSTRUCTION_2(name, format, t0, t1) \ |
| 141 void name(t0 a0, t1 a1) { Print(format, Wrap(a0), Wrap(a1)); } |
| 142 |
| 143 #define INSTRUCTION_3(name, format, t0, t1, t2) \ |
| 144 void name(t0 a0, t1 a1, t2 a2) { \ |
| 145 Print(format, Wrap(a0), Wrap(a1), Wrap(a2)); \ |
| 146 } |
| 147 |
| 148 #define INSTRUCTION_4(name, format, t0, t1, t2, t3) \ |
| 149 void name(t0 a0, t1 a1, t2 a2, t3 a3) { \ |
| 150 Print(format, Wrap(a0), Wrap(a1), Wrap(a2), Wrap(a3)); \ |
| 151 } |
| 152 |
| 153 class Assembler { |
| 154 public: |
| 155 INSTRUCTION_3(add, "add %r, %r, %r", Register, Register, Register); |
| 156 INSTRUCTION_3(addi, "addi %r, %r, %i", Register, Register, const Immediate&); |
| 157 INSTRUCTION_3(addu, "addu %r, %r, %r", Register, Register, Register); |
| 158 INSTRUCTION_3(addiu, "addiu %r, %r, %i", Register, Register, |
| 159 const Immediate&); |
| 160 |
| 161 INSTRUCTION_3(andi, "andi %r, %r, %i", Register, Register, const Immediate&); |
| 162 INSTRUCTION_3(and_, "and %r, %r, %r", Register, Register, Register); |
| 163 |
| 164 INSTRUCTION_0(break_, "break"); |
| 165 |
| 166 INSTRUCTION_1(b, "b %s", const char*); |
| 167 INSTRUCTION_1(b, "b %l", Label*); |
| 168 INSTRUCTION_2(b, "b%c %l", Condition, Label*); |
| 169 INSTRUCTION_4(b, "b%c %r, %r, %l", Condition, Register, Register, Label*); |
| 170 INSTRUCTION_4(b, "b%c %r, %r, %s", Condition, Register, Register, |
| 171 const char*); |
| 172 |
| 173 INSTRUCTION_1(jal, "jal %s", const char*); |
| 174 INSTRUCTION_1(jalr, "jalr %r", Register); |
| 175 INSTRUCTION_1(jr, "jr %r", Register); |
| 176 |
| 177 INSTRUCTION_2(la, "la %r, %s", Register, const char*); |
| 178 INSTRUCTION_2(la, "la %r, %l", Register, Label*); |
| 179 INSTRUCTION_2(li, "li %r, %i", Register, const Immediate&); |
| 180 INSTRUCTION_2(lui, "lui %r, %i", Register, const Immediate&); |
| 181 |
| 182 INSTRUCTION_2(lb, "lb %r, %a", Register, const Address&); |
| 183 INSTRUCTION_2(lbu, "lbu %r, %a", Register, const Address&); |
| 184 INSTRUCTION_2(lw, "lw %r, %a", Register, const Address&); |
| 185 INSTRUCTION_2(lw, "lw %r, %s", Register, const char*); |
| 186 |
| 187 INSTRUCTION_2(move, "move %r, %r", Register, Register); |
| 188 INSTRUCTION_2(mult, "mult %r, %r", Register, Register); |
| 189 |
| 190 INSTRUCTION_1(mfhi, "mfhi %r", Register); |
| 191 INSTRUCTION_1(mflo, "mflo %r", Register); |
| 192 |
| 193 INSTRUCTION_0(nop, "nop"); |
| 194 INSTRUCTION_2(not_, "nor %r, %r, $0", Register, Register); |
| 195 |
| 196 INSTRUCTION_3(or_, "or %r, %r, %r", Register, Register, Register); |
| 197 |
| 198 INSTRUCTION_3(sll, "sll %r, %r, %i", Register, Register, const Immediate&); |
| 199 INSTRUCTION_3(sllv, "sllv %r, %r, %r", Register, Register, Register); |
| 200 INSTRUCTION_3(sra, "sra %r, %r, %i", Register, Register, const Immediate&); |
| 201 INSTRUCTION_3(srav, "srav %r, %r, %r", Register, Register, Register); |
| 202 INSTRUCTION_3(srl, "srl %r, %r, %i", Register, Register, const Immediate&); |
| 203 |
| 204 INSTRUCTION_3(slt, "slt %r, %r, %r", Register, Register, Register); |
| 205 INSTRUCTION_3(sltu, "sltu %r, %r, %r", Register, Register, Register); |
| 206 |
| 207 |
| 208 INSTRUCTION_3(sub, "sub %r, %r, %r", Register, Register, Register); |
| 209 INSTRUCTION_3(subi, "addi %r, %r, -%i", Register, Register, const Immediate&); |
| 210 INSTRUCTION_3(subu, "subu %r, %r, %r", Register, Register, Register); |
| 211 |
| 212 INSTRUCTION_0(syscall, "syscall"); |
| 213 |
| 214 INSTRUCTION_2(sb, "sb %r, %a", Register, const Address&); |
| 215 INSTRUCTION_2(sw, "sw %r, %a", Register, const Address&); |
| 216 |
| 217 INSTRUCTION_3(xor_, "xor %r, %r, %r", Register, Register, Register); |
| 218 |
| 219 |
| 220 // Align what follows to a 2^power address. |
| 221 void AlignToPowerOfTwo(int power); |
| 222 |
| 223 void Bind(const char* prefix, const char* name); |
| 224 void Bind(Label* label); |
| 225 |
| 226 void DefineLong(const char* name); |
| 227 |
| 228 void SwitchToText(); |
| 229 |
| 230 void BindWithPowerOfTwoAlignment(const char* name, int power); |
| 231 void SwitchToData(); |
| 232 |
| 233 const char* LabelPrefix(); |
| 234 |
| 235 private: |
| 236 void Print(const char* format, ...); |
| 237 void PrintAddress(const Address* address); |
| 238 |
| 239 Condition Wrap(Condition condition) { return condition; } |
| 240 Register Wrap(Register reg) { return reg; } |
| 241 const char* Wrap(const char* label) { return label; } |
| 242 Label* Wrap(Label* label) { return label; } |
| 243 const Immediate* Wrap(const Immediate& immediate) { return &immediate; } |
| 244 const Address* Wrap(const Address& address) { return &address; } |
| 245 }; |
| 246 |
| 247 #undef INSTRUCTION_0 |
| 248 #undef INSTRUCTION_1 |
| 249 #undef INSTRUCTION_2 |
| 250 #undef INSTRUCTION_3 |
| 251 #undef INSTRUCTION_4 |
| 252 |
| 253 } // namespace dartino |
| 254 |
| 255 #endif // SRC_VM_ASSEMBLER_MIPS_H_ |
OLD | NEW |