Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: runtime/vm/simulator_mips.cc

Issue 12545024: Adds a few MIPS arithmetic instructions to the simulator, assembler, disassembler (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« runtime/vm/disassembler_mips.cc ('K') | « runtime/vm/simulator_mips.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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 file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 // Only build the simulator if not compiling for real MIPS hardware. 8 // Only build the simulator if not compiling for real MIPS hardware.
9 #if !defined(HOST_ARCH_MIPS) 9 #if !defined(HOST_ARCH_MIPS)
10 10
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 return reinterpret_cast<uword>(stack_) + 93 return reinterpret_cast<uword>(stack_) +
94 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); 94 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer);
95 } 95 }
96 96
97 97
98 void Simulator::Format(Instr* instr, const char* format) { 98 void Simulator::Format(Instr* instr, const char* format) {
99 OS::PrintErr("Simulator - unknown instruction: %s\n", format); 99 OS::PrintErr("Simulator - unknown instruction: %s\n", format);
100 UNIMPLEMENTED(); 100 UNIMPLEMENTED();
101 } 101 }
102 102
103
104 bool Simulator::OverflowFrom(int32_t alu_out,
105 int32_t left, int32_t right, bool addition) {
106 bool overflow;
107 if (addition) {
108 // Operands have the same sign.
109 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
110 // And operands and result have different sign.
111 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
112 } else {
113 // Operands have different signs.
114 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
115 // And first operand and result have different signs.
116 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
117 }
118 return overflow;
119 }
120
121
103 void Simulator::DecodeSpecial(Instr* instr) { 122 void Simulator::DecodeSpecial(Instr* instr) {
104 switch (instr->FunctionField()) { 123 switch (instr->FunctionField()) {
124 case ADDU: {
125 ASSERT(instr->SaField() == 0);
126 // Format(instr, "addu 'rd, 'rs, 'rt");
127 int32_t rs_val = get_register(instr->RsField());
128 int32_t rt_val = get_register(instr->RtField());
129 set_register(instr->RdField(), rs_val + rt_val);
130 break;
131 }
132 case AND: {
133 ASSERT(instr->SaField() == 0);
134 // Format(instr, "and 'rd, 'rs, 'rt");
135 int32_t rs_val = get_register(instr->RsField());
136 int32_t rt_val = get_register(instr->RtField());
137 set_register(instr->RdField(), rs_val & rt_val);
138 break;
139 }
140 case DIV: {
141 ASSERT(instr->RdField() == 0);
142 ASSERT(instr->SaField() == 0);
143 // Format(instr, "div 'rs, 'rt");
144 int32_t rs_val = get_register(instr->RsField());
145 int32_t rt_val = get_register(instr->RtField());
146 if (rt_val == 0) {
147 // Results are unpredictable.
148 set_hi_register(0);
149 set_lo_register(0);
150 // TODO(zra): Drop into the debugger here.
151 break;
152 }
153
154 if ((rs_val == static_cast<int32_t>(0x80000000)) &&
155 (rt_val == static_cast<int32_t>(0xffffffff))) {
156 set_lo_register(0x80000000);
157 set_hi_register(0);
158 } else {
159 set_lo_register(rs_val / rt_val);
160 set_hi_register(rs_val % rt_val);
161 }
162 break;
163 }
164 case DIVU: {
165 ASSERT(instr->RdField() == 0);
166 ASSERT(instr->SaField() == 0);
167 // Format(instr, "divu 'rs, 'rt");
168 uint32_t rs_val = get_register(instr->RsField());
169 uint32_t rt_val = get_register(instr->RtField());
170 if (rt_val == 0) {
171 // Results are unpredictable.
172 set_hi_register(0);
173 set_lo_register(0);
174 // TODO(zra): Drop into the debugger here.
175 break;
176 }
177
178 set_lo_register(rs_val / rt_val);
179 set_hi_register(rs_val % rt_val);
180 break;
181 }
182 case MFHI: {
183 ASSERT(instr->RsField() == 0);
184 ASSERT(instr->RtField() == 0);
185 ASSERT(instr->SaField() == 0);
186 // Format(instr, "mfhi 'rd");
187 set_register(instr->RdField(), get_hi_register());
188 break;
189 }
190 case MFLO: {
191 ASSERT(instr->RsField() == 0);
192 ASSERT(instr->RtField() == 0);
193 ASSERT(instr->SaField() == 0);
194 // Format(instr, "mflo 'rd");
195 set_register(instr->RdField(), get_lo_register());
196 break;
197 }
105 case SLL: { 198 case SLL: {
199 ASSERT(instr->RsField() == 0);
106 if ((instr->RdField() == R0) && 200 if ((instr->RdField() == R0) &&
107 (instr->RtField() == R0) && 201 (instr->RtField() == R0) &&
108 (instr->SaField() == 0)) { 202 (instr->SaField() == 0)) {
109 // Format(instr, "nop"); 203 // Format(instr, "nop");
110 // Nothing to be done for NOP. 204 // Nothing to be done for NOP.
111 } else { 205 } else {
112 Format(instr, "sll 'rd, 'rt, 'sa"); 206 int32_t rt_val = get_register(instr->RtField());
207 int sa = instr->SaField();
208 set_register(instr->RdField(), rt_val << sa);
113 } 209 }
114 break; 210 break;
115 } 211 }
116 case JR: { 212 case JR: {
117 ASSERT(instr->RtField() == R0); 213 ASSERT(instr->RtField() == R0);
118 ASSERT(instr->RdField() == R0); 214 ASSERT(instr->RdField() == R0);
119 ASSERT(!delay_slot_); 215 ASSERT(!delay_slot_);
120 // Format(instr, "jr'hint 'rs"); 216 // Format(instr, "jr'hint 'rs");
121 uword next_pc = get_register(instr->RsField()); 217 uword next_pc = get_register(instr->RsField());
122 ExecuteDelaySlot(); 218 ExecuteDelaySlot();
123 pc_ = next_pc - Instr::kInstrSize; // Account for regular PC increment. 219 pc_ = next_pc - Instr::kInstrSize; // Account for regular PC increment.
124 break; 220 break;
125 } 221 }
126 default: { 222 default: {
127 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits()); 223 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits());
128 UNREACHABLE(); 224 UNREACHABLE();
129 break; 225 break;
130 } 226 }
131 } 227 }
132 } 228 }
133 229
134 230
231 void Simulator::DecodeSpecial2(Instr* instr) {
232 switch (instr->FunctionField()) {
233 case CLO: {
234 ASSERT(instr->SaField() == 0);
235 ASSERT(instr->RtField() == instr->RdField());
236 // Format(instr, "clo 'rd, 'rs");
237 int32_t rs_val = get_register(instr->RsField());
238 int32_t bitcount = 0;
239 while (rs_val < 0) {
240 bitcount++;
241 rs_val <<= 1;
242 }
243 set_register(instr->RdField(), bitcount);
244 break;
245 }
246 case CLZ: {
247 ASSERT(instr->SaField() == 0);
248 ASSERT(instr->RtField() == instr->RdField());
249 // Format(instr, "clz 'rd, 'rs");
250 int32_t rs_val = get_register(instr->RsField());
251 int32_t bitcount = 0;
252 if (rs_val != 0) {
253 while (rs_val > 0) {
254 bitcount++;
255 rs_val <<= 1;
256 }
257 } else {
258 bitcount = 32;
259 }
260 set_register(instr->RdField(), bitcount);
261 break;
262 }
263 default: {
264 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits());
265 UNREACHABLE();
266 break;
267 }
268 }
269 }
270
271
135 void Simulator::InstructionDecode(Instr* instr) { 272 void Simulator::InstructionDecode(Instr* instr) {
136 switch (instr->OpcodeField()) { 273 switch (instr->OpcodeField()) {
137 case SPECIAL: { 274 case SPECIAL: {
138 DecodeSpecial(instr); 275 DecodeSpecial(instr);
139 break; 276 break;
140 } 277 }
278 case SPECIAL2: {
279 DecodeSpecial2(instr);
280 break;
281 }
282 case ADDI: {
283 // Format(instr, "addi 'rt, 'rs, 'immu");
284 int32_t rs_val = get_register(instr->RsField());
285 int32_t imm_val = instr->SImmField();
286 int32_t res = rs_val + imm_val;
287 // Rt is not set on overflow.
288 if (!OverflowFrom(res, rs_val, imm_val, true)) {
289 set_register(instr->RtField(), res);
Ivan Posva 2013/03/11 06:03:27 Shouldn't this also dispatch to a trap handler?
zra 2013/03/11 15:46:03 Yes. I've added a TODO for myself that I'll fill i
290 }
291 break;
292 }
293 case ADDIU: {
294 // Format(instr, "addiu 'rt, 'rs, 'immu");
295 int32_t rs_val = get_register(instr->RsField());
296 int32_t imm_val = instr->SImmField();
297 int32_t res = rs_val + imm_val;
298 // Rt is set even on overflow.
299 set_register(instr->RtField(), res);
300 break;
301 }
302 case ANDI: {
303 // Format(instr, "andi 'rt, 'rs, 'immu");
304 int32_t rs_val = get_register(instr->RsField());
305 set_register(instr->RtField(), rs_val & instr->UImmField());
306 break;
307 }
308 case LUI: {
309 ASSERT(instr->RsField() == 0);
310 set_register(instr->RtField(), instr->UImmField() << 16);
311 break;
312 }
141 case ORI: { 313 case ORI: {
142 // Format(instr, "ori 'rt, 'rs, 'immu"); 314 // Format(instr, "ori 'rt, 'rs, 'immu");
143 int32_t rs_val = get_register(instr->RsField()); 315 int32_t rs_val = get_register(instr->RsField());
144 set_register(instr->RtField(), rs_val | instr->UImmField()); 316 set_register(instr->RtField(), rs_val | instr->UImmField());
145 break; 317 break;
146 } 318 }
147 default: { 319 default: {
148 OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits()); 320 OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits());
149 UNREACHABLE(); 321 UNREACHABLE();
150 break; 322 break;
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 // Restore the SP register and return R1:R0. 443 // Restore the SP register and return R1:R0.
272 set_register(SP, sp_before_call); 444 set_register(SP, sp_before_call);
273 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); 445 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1));
274 } 446 }
275 447
276 } // namespace dart 448 } // namespace dart
277 449
278 #endif // !defined(HOST_ARCH_MIPS) 450 #endif // !defined(HOST_ARCH_MIPS)
279 451
280 #endif // defined TARGET_ARCH_MIPS 452 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« runtime/vm/disassembler_mips.cc ('K') | « runtime/vm/simulator_mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698