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

Unified 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 side-by-side diff with in-line comments
Download patch
« runtime/vm/simulator_mips.h ('K') | « runtime/vm/simulator_mips.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/simulator_mips.cc
===================================================================
--- runtime/vm/simulator_mips.cc (revision 19704)
+++ runtime/vm/simulator_mips.cc (working copy)
@@ -102,14 +102,89 @@
void Simulator::DecodeSpecial(Instr* instr) {
switch (instr->FunctionField()) {
+ case ADDU: {
+ ASSERT(instr->SaField() == 0);
+ // Format(instr, "addu 'rd, 'rs, 'rt");
+ int32_t rs_val = get_register(instr->RsField());
+ int32_t rt_val = get_register(instr->RtField());
+ set_register(instr->RdField(), rs_val + rt_val);
+ break;
+ }
+ case AND: {
+ ASSERT(instr->SaField() == 0);
+ // Format(instr, "and 'rd, 'rs, 'rt");
+ int32_t rs_val = get_register(instr->RsField());
+ int32_t rt_val = get_register(instr->RtField());
+ set_register(instr->RdField(), rs_val & rt_val);
+ break;
+ }
+ case DIV: {
+ ASSERT(instr->RdField() == 0);
+ ASSERT(instr->SaField() == 0);
+ // Format(instr, "div 'rs, 'rt");
+ int32_t rs_val = get_register(instr->RsField());
+ int32_t rt_val = get_register(instr->RtField());
+ if (rt_val == 0) {
+ // Results are unpredictable
+ set_hi_register(0);
+ set_lo_register(0);
+ return;
regis 2013/03/08 21:09:03 Why return instead of break? Maybe we should drop
+ }
+
+ if ((rs_val == static_cast<int32_t>(0x80000000)) &&
+ (rt_val == static_cast<int32_t>(0xffffffff))) {
+ set_lo_register(0x80000000);
+ set_hi_register(0);
+ } else {
+ set_lo_register(rs_val / rt_val);
+ set_hi_register(rs_val % rt_val);
+ }
+ break;
+ }
+ case DIVU: {
+ ASSERT(instr->RdField() == 0);
+ ASSERT(instr->SaField() == 0);
+ // Format(instr, "divu 'rs, 'rt");
+ uint32_t rs_val = get_register(instr->RsField());
+ uint32_t rt_val = get_register(instr->RtField());
+ if (rt_val == 0) {
+ // Results are unpredictable
+ set_hi_register(0);
+ set_lo_register(0);
+ return;
regis 2013/03/08 21:09:03 ditto
+ }
+
+ set_lo_register(rs_val / rt_val);
+ set_hi_register(rs_val % rt_val);
+ break;
+ }
+ case MFHI: {
+ ASSERT(instr->RsField() == 0);
+ ASSERT(instr->RtField() == 0);
+ ASSERT(instr->SaField() == 0);
+ // Format(instr, "mfhi 'rd");
+ set_register(instr->RdField(), get_hi_register());
+ break;
+ }
+ case MFLO: {
+ ASSERT(instr->RsField() == 0);
+ ASSERT(instr->RtField() == 0);
+ ASSERT(instr->SaField() == 0);
+ // Format(instr, "mflo 'rd");
+ set_register(instr->RdField(), get_lo_register());
+ break;
+ }
case SLL: {
+ ASSERT(instr->RsField() == 0);
if ((instr->RdField() == R0) &&
(instr->RtField() == R0) &&
(instr->SaField() == 0)) {
// Format(instr, "nop");
// Nothing to be done for NOP.
} else {
- Format(instr, "sll 'rd, 'rt, 'sa");
+ int32_t rt_val = get_register(instr->RtField());
+ int sa = instr->SaField();
+ set_register(instr->RdField(), rt_val << sa);
}
break;
}
@@ -132,12 +207,84 @@
}
+void Simulator::DecodeSpecial2(Instr* instr) {
+ switch (instr->FunctionField()) {
+ case CLO: {
+ ASSERT(instr->SaField() == 0);
+ ASSERT(instr->RtField() == instr->RdField());
+ // Format(instr, "clo 'rd, 'rs");
+ int32_t rs_val = get_register(instr->RsField());
+ int32_t bitcount = 0;
+ while (rs_val < 0) {
+ bitcount++;
+ rs_val <<= 1;
+ }
+ set_register(instr->RdField(), bitcount);
+ break;
+ }
+ case CLZ: {
+ ASSERT(instr->SaField() == 0);
+ ASSERT(instr->RtField() == instr->RdField());
+ // Format(instr, "clz 'rd, 'rs");
+ int32_t rs_val = get_register(instr->RsField());
+ int32_t bitcount = 0;
+ if (rs_val != 0) {
+ while (rs_val > 0) {
+ bitcount++;
+ rs_val <<= 1;
+ }
+ } else {
+ bitcount = 32;
+ }
+ set_register(instr->RdField(), bitcount);
+ break;
+ }
+ default: {
+ OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits());
+ UNREACHABLE();
+ break;
+ }
+ }
+}
+
+
void Simulator::InstructionDecode(Instr* instr) {
switch (instr->OpcodeField()) {
case SPECIAL: {
DecodeSpecial(instr);
break;
}
+ case SPECIAL2: {
+ DecodeSpecial2(instr);
+ break;
+ }
+ case ADDI: {
+ // Format(instr, "addi 'rt, 'rs, 'immu");
+ int32_t rs_val = get_register(instr->RsField());
+ int32_t imm_val = instr->SImmField();
+ int32_t res = rs_val + imm_val;
+ // Rt is not set on overflow
regis 2013/03/08 21:09:03 period
+ if (!(((res < 0) && (rs_val > 0) && (imm_val > 0)) ||
+ ((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
+ set_register(instr->RtField(), res);
+ }
+ break;
+ }
+ case ADDIU: {
+ // Format(instr, "addiu 'rt, 'rs, 'immu");
+ int32_t rs_val = get_register(instr->RsField());
+ int32_t imm_val = instr->SImmField();
+ int32_t res = rs_val + imm_val;
+ // Rt is set even on overflow
regis 2013/03/08 21:09:03 period
+ set_register(instr->RtField(), res);
+ break;
+ }
+ case ANDI: {
+ // Format(instr, "andi 'rt, 'rs, 'immu");
+ int32_t rs_val = get_register(instr->RsField());
+ set_register(instr->RtField(), rs_val & instr->UImmField());
+ break;
+ }
case ORI: {
// Format(instr, "ori 'rt, 'rs, 'immu");
int32_t rs_val = get_register(instr->RsField());
« 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