OLD | NEW |
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 972 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 } | 983 } |
984 default: { | 984 default: { |
985 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits()); | 985 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits()); |
986 UnimplementedInstruction(instr); | 986 UnimplementedInstruction(instr); |
987 break; | 987 break; |
988 } | 988 } |
989 } | 989 } |
990 } | 990 } |
991 | 991 |
992 | 992 |
| 993 void Simulator::DoBranch(Instr* instr, bool taken, bool likely) { |
| 994 ASSERT(!delay_slot_); |
| 995 int32_t imm_val = instr->SImmField() << 2; |
| 996 |
| 997 uword next_pc; |
| 998 if (taken) { |
| 999 // imm_val is added to the address of the instruction following the branch. |
| 1000 next_pc = pc_ + imm_val + Instr::kInstrSize; |
| 1001 if (likely) { |
| 1002 ExecuteDelaySlot(); |
| 1003 } |
| 1004 } else { |
| 1005 next_pc = pc_ + (2 * Instr::kInstrSize); // Next after delay slot. |
| 1006 } |
| 1007 if (!likely) { |
| 1008 ExecuteDelaySlot(); |
| 1009 } |
| 1010 pc_ = next_pc - Instr::kInstrSize; |
| 1011 |
| 1012 return; |
| 1013 } |
| 1014 |
| 1015 |
| 1016 void Simulator::DecodeRegImm(Instr* instr) { |
| 1017 ASSERT(instr->OpcodeField() == REGIMM); |
| 1018 switch (instr->RegImmFnField()) { |
| 1019 case BGEZ: { |
| 1020 // Format(instr, "bgez 'rs, 'dest"); |
| 1021 int32_t rs_val = get_register(instr->RsField()); |
| 1022 DoBranch(instr, rs_val >= 0, false); |
| 1023 break; |
| 1024 } |
| 1025 case BGEZL: { |
| 1026 // Format(instr, "bgezl 'rs, 'dest"); |
| 1027 int32_t rs_val = get_register(instr->RsField()); |
| 1028 DoBranch(instr, rs_val >= 0, true); |
| 1029 break; |
| 1030 } |
| 1031 case BLTZ: { |
| 1032 // Format(instr, "bltz 'rs, 'dest"); |
| 1033 int32_t rs_val = get_register(instr->RsField()); |
| 1034 DoBranch(instr, rs_val < 0, false); |
| 1035 break; |
| 1036 } |
| 1037 case BLTZL: { |
| 1038 // Format(instr, "bltzl 'rs, 'dest"); |
| 1039 int32_t rs_val = get_register(instr->RsField()); |
| 1040 DoBranch(instr, rs_val < 0, true); |
| 1041 break; |
| 1042 } |
| 1043 default: { |
| 1044 OS::PrintErr("DecodeRegImm: 0x%x\n", instr->InstructionBits()); |
| 1045 UnimplementedInstruction(instr); |
| 1046 break; |
| 1047 } |
| 1048 } |
| 1049 } |
| 1050 |
| 1051 |
993 void Simulator::InstructionDecode(Instr* instr) { | 1052 void Simulator::InstructionDecode(Instr* instr) { |
994 switch (instr->OpcodeField()) { | 1053 switch (instr->OpcodeField()) { |
995 case SPECIAL: { | 1054 case SPECIAL: { |
996 DecodeSpecial(instr); | 1055 DecodeSpecial(instr); |
997 break; | 1056 break; |
998 } | 1057 } |
999 case SPECIAL2: { | 1058 case SPECIAL2: { |
1000 DecodeSpecial2(instr); | 1059 DecodeSpecial2(instr); |
1001 break; | 1060 break; |
1002 } | 1061 } |
| 1062 case REGIMM: { |
| 1063 DecodeRegImm(instr); |
| 1064 break; |
| 1065 } |
1003 case ADDIU: { | 1066 case ADDIU: { |
1004 // Format(instr, "addiu 'rt, 'rs, 'imms"); | 1067 // Format(instr, "addiu 'rt, 'rs, 'imms"); |
1005 int32_t rs_val = get_register(instr->RsField()); | 1068 int32_t rs_val = get_register(instr->RsField()); |
1006 int32_t imm_val = instr->SImmField(); | 1069 int32_t imm_val = instr->SImmField(); |
1007 int32_t res = rs_val + imm_val; | 1070 int32_t res = rs_val + imm_val; |
1008 // Rt is set even on overflow. | 1071 // Rt is set even on overflow. |
1009 set_register(instr->RtField(), res); | 1072 set_register(instr->RtField(), res); |
1010 break; | 1073 break; |
1011 } | 1074 } |
1012 case ANDI: { | 1075 case ANDI: { |
1013 // Format(instr, "andi 'rt, 'rs, 'immu"); | 1076 // Format(instr, "andi 'rt, 'rs, 'immu"); |
1014 int32_t rs_val = get_register(instr->RsField()); | 1077 int32_t rs_val = get_register(instr->RsField()); |
1015 set_register(instr->RtField(), rs_val & instr->UImmField()); | 1078 set_register(instr->RtField(), rs_val & instr->UImmField()); |
1016 break; | 1079 break; |
1017 } | 1080 } |
| 1081 case BEQ: { |
| 1082 // Format(instr, "beq 'rs, 'rt, 'dest"); |
| 1083 int32_t rs_val = get_register(instr->RsField()); |
| 1084 int32_t rt_val = get_register(instr->RtField()); |
| 1085 DoBranch(instr, rs_val == rt_val, false); |
| 1086 break; |
| 1087 } |
| 1088 case BEQL: { |
| 1089 // Format(instr, "beql 'rs, 'rt, 'dest"); |
| 1090 int32_t rs_val = get_register(instr->RsField()); |
| 1091 int32_t rt_val = get_register(instr->RtField()); |
| 1092 DoBranch(instr, rs_val == rt_val, true); |
| 1093 break; |
| 1094 } |
| 1095 case BGTZ: { |
| 1096 ASSERT(instr->RtField() == R0); |
| 1097 // Format(instr, "bgtz 'rs, 'dest"); |
| 1098 int32_t rs_val = get_register(instr->RsField()); |
| 1099 DoBranch(instr, rs_val > 0, false); |
| 1100 break; |
| 1101 } |
| 1102 case BGTZL: { |
| 1103 ASSERT(instr->RtField() == R0); |
| 1104 // Format(instr, "bgtzl 'rs, 'dest"); |
| 1105 int32_t rs_val = get_register(instr->RsField()); |
| 1106 DoBranch(instr, rs_val > 0, true); |
| 1107 break; |
| 1108 } |
| 1109 case BLEZ: { |
| 1110 ASSERT(instr->RtField() == R0); |
| 1111 // Format(instr, "blez 'rs, 'dest"); |
| 1112 int32_t rs_val = get_register(instr->RsField()); |
| 1113 DoBranch(instr, rs_val <= 0, false); |
| 1114 break; |
| 1115 } |
| 1116 case BLEZL: { |
| 1117 ASSERT(instr->RtField() == R0); |
| 1118 // Format(instr, "blezl 'rs, 'dest"); |
| 1119 int32_t rs_val = get_register(instr->RsField()); |
| 1120 DoBranch(instr, rs_val <= 0, true); |
| 1121 break; |
| 1122 } |
| 1123 case BNE: { |
| 1124 // Format(instr, "bne 'rs, 'rt, 'dest"); |
| 1125 int32_t rs_val = get_register(instr->RsField()); |
| 1126 int32_t rt_val = get_register(instr->RtField()); |
| 1127 DoBranch(instr, rs_val != rt_val, false); |
| 1128 break; |
| 1129 } |
| 1130 case BNEL: { |
| 1131 // Format(instr, "bnel 'rs, 'rt, 'dest"); |
| 1132 int32_t rs_val = get_register(instr->RsField()); |
| 1133 int32_t rt_val = get_register(instr->RtField()); |
| 1134 DoBranch(instr, rs_val != rt_val, true); |
| 1135 break; |
| 1136 } |
1018 case LB: { | 1137 case LB: { |
1019 // Format(instr, "lb 'rt, 'imms('rs)"); | 1138 // Format(instr, "lb 'rt, 'imms('rs)"); |
1020 int32_t base_val = get_register(instr->RsField()); | 1139 int32_t base_val = get_register(instr->RsField()); |
1021 int32_t imm_val = instr->SImmField(); | 1140 int32_t imm_val = instr->SImmField(); |
1022 uword addr = base_val + imm_val; | 1141 uword addr = base_val + imm_val; |
1023 if (Simulator::IsIllegalAddress(addr)) { | 1142 if (Simulator::IsIllegalAddress(addr)) { |
1024 HandleIllegalAccess(addr, instr); | 1143 HandleIllegalAccess(addr, instr); |
1025 } else { | 1144 } else { |
1026 int32_t res = ReadB(addr); | 1145 int32_t res = ReadB(addr); |
1027 set_register(instr->RtField(), res); | 1146 set_register(instr->RtField(), res); |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1268 // Restore the SP register and return R1:R0. | 1387 // Restore the SP register and return R1:R0. |
1269 set_register(SP, sp_before_call); | 1388 set_register(SP, sp_before_call); |
1270 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); | 1389 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); |
1271 } | 1390 } |
1272 | 1391 |
1273 } // namespace dart | 1392 } // namespace dart |
1274 | 1393 |
1275 #endif // !defined(HOST_ARCH_MIPS) | 1394 #endif // !defined(HOST_ARCH_MIPS) |
1276 | 1395 |
1277 #endif // defined TARGET_ARCH_MIPS | 1396 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |