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

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/simulator_mips.h ('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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 void Simulator::DecodeSpecial(Instr* instr) { 103 void Simulator::DecodeSpecial(Instr* instr) {
104 switch (instr->FunctionField()) { 104 switch (instr->FunctionField()) {
105 case ADDU: {
106 ASSERT(instr->SaField() == 0);
107 // Format(instr, "addu 'rd, 'rs, 'rt");
108 int32_t rs_val = get_register(instr->RsField());
109 int32_t rt_val = get_register(instr->RtField());
110 set_register(instr->RdField(), rs_val + rt_val);
111 break;
112 }
113 case AND: {
114 ASSERT(instr->SaField() == 0);
115 // Format(instr, "and 'rd, 'rs, 'rt");
116 int32_t rs_val = get_register(instr->RsField());
117 int32_t rt_val = get_register(instr->RtField());
118 set_register(instr->RdField(), rs_val & rt_val);
119 break;
120 }
121 case DIV: {
122 ASSERT(instr->RdField() == 0);
123 ASSERT(instr->SaField() == 0);
124 // Format(instr, "div 'rs, 'rt");
125 int32_t rs_val = get_register(instr->RsField());
126 int32_t rt_val = get_register(instr->RtField());
127 if (rt_val == 0) {
128 // Results are unpredictable
129 set_hi_register(0);
130 set_lo_register(0);
131 return;
regis 2013/03/08 21:09:03 Why return instead of break? Maybe we should drop
132 }
133
134 if ((rs_val == static_cast<int32_t>(0x80000000)) &&
135 (rt_val == static_cast<int32_t>(0xffffffff))) {
136 set_lo_register(0x80000000);
137 set_hi_register(0);
138 } else {
139 set_lo_register(rs_val / rt_val);
140 set_hi_register(rs_val % rt_val);
141 }
142 break;
143 }
144 case DIVU: {
145 ASSERT(instr->RdField() == 0);
146 ASSERT(instr->SaField() == 0);
147 // Format(instr, "divu 'rs, 'rt");
148 uint32_t rs_val = get_register(instr->RsField());
149 uint32_t rt_val = get_register(instr->RtField());
150 if (rt_val == 0) {
151 // Results are unpredictable
152 set_hi_register(0);
153 set_lo_register(0);
154 return;
regis 2013/03/08 21:09:03 ditto
155 }
156
157 set_lo_register(rs_val / rt_val);
158 set_hi_register(rs_val % rt_val);
159 break;
160 }
161 case MFHI: {
162 ASSERT(instr->RsField() == 0);
163 ASSERT(instr->RtField() == 0);
164 ASSERT(instr->SaField() == 0);
165 // Format(instr, "mfhi 'rd");
166 set_register(instr->RdField(), get_hi_register());
167 break;
168 }
169 case MFLO: {
170 ASSERT(instr->RsField() == 0);
171 ASSERT(instr->RtField() == 0);
172 ASSERT(instr->SaField() == 0);
173 // Format(instr, "mflo 'rd");
174 set_register(instr->RdField(), get_lo_register());
175 break;
176 }
105 case SLL: { 177 case SLL: {
178 ASSERT(instr->RsField() == 0);
106 if ((instr->RdField() == R0) && 179 if ((instr->RdField() == R0) &&
107 (instr->RtField() == R0) && 180 (instr->RtField() == R0) &&
108 (instr->SaField() == 0)) { 181 (instr->SaField() == 0)) {
109 // Format(instr, "nop"); 182 // Format(instr, "nop");
110 // Nothing to be done for NOP. 183 // Nothing to be done for NOP.
111 } else { 184 } else {
112 Format(instr, "sll 'rd, 'rt, 'sa"); 185 int32_t rt_val = get_register(instr->RtField());
186 int sa = instr->SaField();
187 set_register(instr->RdField(), rt_val << sa);
113 } 188 }
114 break; 189 break;
115 } 190 }
116 case JR: { 191 case JR: {
117 ASSERT(instr->RtField() == R0); 192 ASSERT(instr->RtField() == R0);
118 ASSERT(instr->RdField() == R0); 193 ASSERT(instr->RdField() == R0);
119 ASSERT(!delay_slot_); 194 ASSERT(!delay_slot_);
120 // Format(instr, "jr'hint 'rs"); 195 // Format(instr, "jr'hint 'rs");
121 uword next_pc = get_register(instr->RsField()); 196 uword next_pc = get_register(instr->RsField());
122 ExecuteDelaySlot(); 197 ExecuteDelaySlot();
123 pc_ = next_pc - Instr::kInstrSize; // Account for regular PC increment. 198 pc_ = next_pc - Instr::kInstrSize; // Account for regular PC increment.
124 break; 199 break;
125 } 200 }
126 default: { 201 default: {
127 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits()); 202 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits());
128 UNREACHABLE(); 203 UNREACHABLE();
129 break; 204 break;
130 } 205 }
131 } 206 }
132 } 207 }
133 208
134 209
210 void Simulator::DecodeSpecial2(Instr* instr) {
211 switch (instr->FunctionField()) {
212 case CLO: {
213 ASSERT(instr->SaField() == 0);
214 ASSERT(instr->RtField() == instr->RdField());
215 // Format(instr, "clo 'rd, 'rs");
216 int32_t rs_val = get_register(instr->RsField());
217 int32_t bitcount = 0;
218 while (rs_val < 0) {
219 bitcount++;
220 rs_val <<= 1;
221 }
222 set_register(instr->RdField(), bitcount);
223 break;
224 }
225 case CLZ: {
226 ASSERT(instr->SaField() == 0);
227 ASSERT(instr->RtField() == instr->RdField());
228 // Format(instr, "clz 'rd, 'rs");
229 int32_t rs_val = get_register(instr->RsField());
230 int32_t bitcount = 0;
231 if (rs_val != 0) {
232 while (rs_val > 0) {
233 bitcount++;
234 rs_val <<= 1;
235 }
236 } else {
237 bitcount = 32;
238 }
239 set_register(instr->RdField(), bitcount);
240 break;
241 }
242 default: {
243 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits());
244 UNREACHABLE();
245 break;
246 }
247 }
248 }
249
250
135 void Simulator::InstructionDecode(Instr* instr) { 251 void Simulator::InstructionDecode(Instr* instr) {
136 switch (instr->OpcodeField()) { 252 switch (instr->OpcodeField()) {
137 case SPECIAL: { 253 case SPECIAL: {
138 DecodeSpecial(instr); 254 DecodeSpecial(instr);
139 break; 255 break;
140 } 256 }
257 case SPECIAL2: {
258 DecodeSpecial2(instr);
259 break;
260 }
261 case ADDI: {
262 // Format(instr, "addi 'rt, 'rs, 'immu");
263 int32_t rs_val = get_register(instr->RsField());
264 int32_t imm_val = instr->SImmField();
265 int32_t res = rs_val + imm_val;
266 // Rt is not set on overflow
regis 2013/03/08 21:09:03 period
267 if (!(((res < 0) && (rs_val > 0) && (imm_val > 0)) ||
268 ((res > 0) && (rs_val < 0) && (imm_val < 0)))) {
regis 2013/03/08 21:09:03 Is this correct? Can't you produce an overflow wit
269 set_register(instr->RtField(), res);
270 }
271 break;
272 }
273 case ADDIU: {
274 // Format(instr, "addiu 'rt, 'rs, 'immu");
275 int32_t rs_val = get_register(instr->RsField());
276 int32_t imm_val = instr->SImmField();
277 int32_t res = rs_val + imm_val;
278 // Rt is set even on overflow
regis 2013/03/08 21:09:03 period
279 set_register(instr->RtField(), res);
280 break;
281 }
282 case ANDI: {
283 // Format(instr, "andi 'rt, 'rs, 'immu");
284 int32_t rs_val = get_register(instr->RsField());
285 set_register(instr->RtField(), rs_val & instr->UImmField());
286 break;
287 }
141 case ORI: { 288 case ORI: {
142 // Format(instr, "ori 'rt, 'rs, 'immu"); 289 // Format(instr, "ori 'rt, 'rs, 'immu");
143 int32_t rs_val = get_register(instr->RsField()); 290 int32_t rs_val = get_register(instr->RsField());
144 set_register(instr->RtField(), rs_val | instr->UImmField()); 291 set_register(instr->RtField(), rs_val | instr->UImmField());
145 break; 292 break;
146 } 293 }
147 default: { 294 default: {
148 OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits()); 295 OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits());
149 UNREACHABLE(); 296 UNREACHABLE();
150 break; 297 break;
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 // Restore the SP register and return R1:R0. 418 // Restore the SP register and return R1:R0.
272 set_register(SP, sp_before_call); 419 set_register(SP, sp_before_call);
273 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); 420 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1));
274 } 421 }
275 422
276 } // namespace dart 423 } // namespace dart
277 424
278 #endif // !defined(HOST_ARCH_MIPS) 425 #endif // !defined(HOST_ARCH_MIPS)
279 426
280 #endif // defined TARGET_ARCH_MIPS 427 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« runtime/vm/simulator_mips.h ('K') | « runtime/vm/simulator_mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698