00095 {
00096
int raw;
00097
int nextLoadReg = 0;
00098
int nextLoadValue = 0;
00099
00100
00101
00102
if (!machine->ReadMem(registers[PCReg], 4, &raw))
00103
return;
00104 instr->
value = raw;
00105 instr->
Decode();
00106
00107
if (
DebugIsEnabled(
'm')) {
00108
struct OpString *str = &opStrings[instr->
opCode];
00109
00110
ASSERT(instr->
opCode <= MaxOpcode);
00111 printf(
"At PC = 0x%x: ", registers[PCReg]);
00112 printf(str->string, TypeToReg(str->args[0], instr),
00113 TypeToReg(str->args[1], instr), TypeToReg(str->args[2], instr));
00114 printf(
"\n");
00115 }
00116
00117
00118
int pcAfter =
registers[
NextPCReg] + 4;
00119
int sum, diff, tmp, value;
00120
unsigned int rs, rt, imm;
00121
00122
00123
switch (instr->
opCode) {
00124
00125
case OP_ADD:
00126 sum = registers[instr->
rs] + registers[instr->
rt];
00127
if (!((registers[instr->
rs] ^ registers[instr->
rt]) &
SIGN_BIT) &&
00128 ((registers[instr->
rs] ^ sum) &
SIGN_BIT)) {
00129
RaiseException(OverflowException, 0);
00130
return;
00131 }
00132 registers[instr->
rd] = sum;
00133
break;
00134
00135
case OP_ADDI:
00136 sum = registers[instr->
rs] + instr->
extra;
00137
if (!((registers[instr->
rs] ^ instr->
extra) &
SIGN_BIT) &&
00138 ((instr->
extra ^ sum) &
SIGN_BIT)) {
00139
RaiseException(OverflowException, 0);
00140
return;
00141 }
00142 registers[instr->
rt] = sum;
00143
break;
00144
00145
case OP_ADDIU:
00146 registers[instr->
rt] = registers[instr->
rs] + instr->
extra;
00147
break;
00148
00149
case OP_ADDU:
00150 registers[instr->
rd] = registers[instr->
rs] + registers[instr->
rt];
00151
break;
00152
00153
case OP_AND:
00154 registers[instr->
rd] = registers[instr->
rs] & registers[instr->
rt];
00155
break;
00156
00157
case OP_ANDI:
00158 registers[instr->
rt] = registers[instr->
rs] & (instr->
extra & 0xffff);
00159
break;
00160
00161
case OP_BEQ:
00162
if (registers[instr->
rs] == registers[instr->
rt])
00163 pcAfter = registers[
NextPCReg] +
IndexToAddr(instr->
extra);
00164
break;
00165
00166
case OP_BGEZAL:
00167 registers[
R31] = registers[
NextPCReg] + 4;
00168
case OP_BGEZ:
00169
if (!(registers[instr->
rs] &
SIGN_BIT))
00170 pcAfter = registers[
NextPCReg] +
IndexToAddr(instr->
extra);
00171
break;
00172
00173
case OP_BGTZ:
00174
if (registers[instr->
rs] > 0)
00175 pcAfter = registers[
NextPCReg] +
IndexToAddr(instr->
extra);
00176
break;
00177
00178
case OP_BLEZ:
00179
if (registers[instr->
rs] <= 0)
00180 pcAfter = registers[
NextPCReg] +
IndexToAddr(instr->
extra);
00181
break;
00182
00183
case OP_BLTZAL:
00184 registers[
R31] = registers[
NextPCReg] + 4;
00185
case OP_BLTZ:
00186
if (registers[instr->
rs] &
SIGN_BIT)
00187 pcAfter = registers[
NextPCReg] +
IndexToAddr(instr->
extra);
00188
break;
00189
00190
case OP_BNE:
00191
if (registers[instr->
rs] != registers[instr->
rt])
00192 pcAfter = registers[
NextPCReg] +
IndexToAddr(instr->
extra);
00193
break;
00194
00195
case OP_DIV:
00196
if (registers[instr->
rt] == 0) {
00197 registers[
LoReg] = 0;
00198 registers[
HiReg] = 0;
00199 }
else {
00200 registers[
LoReg] = registers[instr->
rs] / registers[instr->
rt];
00201 registers[
HiReg] = registers[instr->
rs] % registers[instr->
rt];
00202 }
00203
break;
00204
00205
case OP_DIVU:
00206 rs = (
unsigned int) registers[instr->
rs];
00207 rt = (
unsigned int) registers[instr->
rt];
00208
if (rt == 0) {
00209 registers[
LoReg] = 0;
00210 registers[
HiReg] = 0;
00211 }
else {
00212 tmp = rs / rt;
00213 registers[
LoReg] = (
int) tmp;
00214 tmp = rs % rt;
00215 registers[
HiReg] = (
int) tmp;
00216 }
00217
break;
00218
00219
case OP_JAL:
00220 registers[
R31] = registers[
NextPCReg] + 4;
00221
case OP_J:
00222 pcAfter = (pcAfter & 0xf0000000) |
IndexToAddr(instr->
extra);
00223
break;
00224
00225
case OP_JALR:
00226 registers[instr->
rd] = registers[
NextPCReg] + 4;
00227
case OP_JR:
00228 pcAfter = registers[instr->
rs];
00229
break;
00230
00231
case OP_LB:
00232
case OP_LBU:
00233 tmp = registers[instr->
rs] + instr->
extra;
00234
if (!machine->ReadMem(tmp, 1, &value))
00235
return;
00236
00237
if ((value & 0x80) && (instr->
opCode ==
OP_LB))
00238 value |= 0xffffff00;
00239
else
00240 value &= 0xff;
00241 nextLoadReg = instr->
rt;
00242 nextLoadValue = value;
00243
break;
00244
00245
case OP_LH:
00246
case OP_LHU:
00247 tmp = registers[instr->
rs] + instr->
extra;
00248
if (tmp & 0x1) {
00249
RaiseException(AddressErrorException, tmp);
00250
return;
00251 }
00252
if (!machine->ReadMem(tmp, 2, &value))
00253
return;
00254
00255
if ((value & 0x8000) && (instr->
opCode ==
OP_LH))
00256 value |= 0xffff0000;
00257
else
00258 value &= 0xffff;
00259 nextLoadReg = instr->
rt;
00260 nextLoadValue = value;
00261
break;
00262
00263
case OP_LUI:
00264
DEBUG(
'm',
"Executing: LUI r%d,%d\n", instr->
rt, instr->
extra);
00265 registers[instr->
rt] = instr->
extra << 16;
00266
break;
00267
00268
case OP_LW:
00269 tmp = registers[instr->
rs] + instr->
extra;
00270
if (tmp & 0x3) {
00271
RaiseException(AddressErrorException, tmp);
00272
return;
00273 }
00274
if (!machine->ReadMem(tmp, 4, &value))
00275
return;
00276 nextLoadReg = instr->
rt;
00277 nextLoadValue = value;
00278
break;
00279
00280
case OP_LWL:
00281 tmp = registers[instr->
rs] + instr->
extra;
00282
00283
00284
00285
00286
ASSERT((tmp & 0x3) == 0);
00287
00288
if (!machine->ReadMem(tmp, 4, &value))
00289
return;
00290
if (registers[
LoadReg] == instr->
rt)
00291 nextLoadValue = registers[
LoadValueReg];
00292
else
00293 nextLoadValue = registers[instr->
rt];
00294
switch (tmp & 0x3) {
00295
case 0:
00296 nextLoadValue = value;
00297
break;
00298
case 1:
00299 nextLoadValue = (nextLoadValue & 0xff) | (value << 8);
00300
break;
00301
case 2:
00302 nextLoadValue = (nextLoadValue & 0xffff) | (value << 16);
00303
break;
00304
case 3:
00305 nextLoadValue = (nextLoadValue & 0xffffff) | (value << 24);
00306
break;
00307 }
00308 nextLoadReg = instr->
rt;
00309
break;
00310
00311
case OP_LWR:
00312 tmp = registers[instr->
rs] + instr->
extra;
00313
00314
00315
00316
00317
ASSERT((tmp & 0x3) == 0);
00318
00319
if (!machine->ReadMem(tmp, 4, &value))
00320
return;
00321
if (registers[
LoadReg] == instr->
rt)
00322 nextLoadValue = registers[
LoadValueReg];
00323
else
00324 nextLoadValue = registers[instr->
rt];
00325
switch (tmp & 0x3) {
00326
case 0:
00327 nextLoadValue = (nextLoadValue & 0xffffff00) |
00328 ((value >> 24) & 0xff);
00329
break;
00330
case 1:
00331 nextLoadValue = (nextLoadValue & 0xffff0000) |
00332 ((value >> 16) & 0xffff);
00333
break;
00334
case 2:
00335 nextLoadValue = (nextLoadValue & 0xff000000)
00336 | ((value >> 8) & 0xffffff);
00337
break;
00338
case 3:
00339 nextLoadValue = value;
00340
break;
00341 }
00342 nextLoadReg = instr->
rt;
00343
break;
00344
00345
case OP_MFHI:
00346 registers[instr->
rd] = registers[
HiReg];
00347
break;
00348
00349
case OP_MFLO:
00350 registers[instr->
rd] = registers[
LoReg];
00351
break;
00352
00353
case OP_MTHI:
00354 registers[
HiReg] = registers[instr->
rs];
00355
break;
00356
00357
case OP_MTLO:
00358 registers[
LoReg] = registers[instr->
rs];
00359
break;
00360
00361
case OP_MULT:
00362 Mult(registers[instr->
rs], registers[instr->
rt], TRUE,
00363 ®isters[HiReg], ®isters[LoReg]);
00364
break;
00365
00366
case OP_MULTU:
00367 Mult(registers[instr->
rs], registers[instr->
rt], FALSE,
00368 ®isters[HiReg], ®isters[LoReg]);
00369
break;
00370
00371
case OP_NOR:
00372 registers[instr->
rd] = ~(registers[instr->
rs] | registers[instr->
rt]);
00373
break;
00374
00375
case OP_OR:
00376 registers[instr->
rd] = registers[instr->
rs] | registers[instr->
rs];
00377
break;
00378
00379
case OP_ORI:
00380 registers[instr->
rt] = registers[instr->
rs] | (instr->
extra & 0xffff);
00381
break;
00382
00383
case OP_SB:
00384
if (!machine->WriteMem((
unsigned)
00385 (registers[instr->
rs] + instr->
extra), 1, registers[instr->
rt]))
00386
return;
00387
break;
00388
00389
case OP_SH:
00390
if (!machine->WriteMem((
unsigned)
00391 (registers[instr->
rs] + instr->
extra), 2, registers[instr->
rt]))
00392
return;
00393
break;
00394
00395
case OP_SLL:
00396 registers[instr->
rd] = registers[instr->
rt] << instr->
extra;
00397
break;
00398
00399
case OP_SLLV:
00400 registers[instr->
rd] = registers[instr->
rt] <<
00401 (registers[instr->
rs] & 0x1f);
00402
break;
00403
00404
case OP_SLT:
00405
if (registers[instr->
rs] < registers[instr->
rt])
00406 registers[instr->
rd] = 1;
00407
else
00408 registers[instr->
rd] = 0;
00409
break;
00410
00411
case OP_SLTI:
00412
if (registers[instr->
rs] < instr->
extra)
00413 registers[instr->
rt] = 1;
00414
else
00415 registers[instr->
rt] = 0;
00416
break;
00417
00418
case OP_SLTIU:
00419 rs = registers[instr->
rs];
00420 imm = instr->
extra;
00421
if (rs < imm)
00422 registers[instr->
rt] = 1;
00423
else
00424 registers[instr->
rt] = 0;
00425
break;
00426
00427
case OP_SLTU:
00428 rs = registers[instr->
rs];
00429 rt = registers[instr->
rt];
00430
if (rs < rt)
00431 registers[instr->
rd] = 1;
00432
else
00433 registers[instr->
rd] = 0;
00434
break;
00435
00436
case OP_SRA:
00437 registers[instr->
rd] = registers[instr->
rt] >> instr->
extra;
00438
break;
00439
00440
case OP_SRAV:
00441 registers[instr->
rd] = registers[instr->
rt] >>
00442 (registers[instr->
rs] & 0x1f);
00443
break;
00444
00445
case OP_SRL:
00446 tmp = registers[instr->
rt];
00447 tmp >>= instr->
extra;
00448 registers[instr->
rd] = tmp;
00449
break;
00450
00451
case OP_SRLV:
00452 tmp = registers[instr->
rt];
00453 tmp >>= (registers[instr->
rs] & 0x1f);
00454 registers[instr->
rd] = tmp;
00455
break;
00456
00457
case OP_SUB:
00458 diff = registers[instr->
rs] - registers[instr->
rt];
00459
if (((registers[instr->
rs] ^ registers[instr->
rt]) &
SIGN_BIT) &&
00460 ((registers[instr->
rs] ^ diff) &
SIGN_BIT)) {
00461
RaiseException(OverflowException, 0);
00462
return;
00463 }
00464 registers[instr->
rd] = diff;
00465
break;
00466
00467
case OP_SUBU:
00468 registers[instr->
rd] = registers[instr->
rs] - registers[instr->
rt];
00469
break;
00470
00471
case OP_SW:
00472
if (!machine->WriteMem((
unsigned)
00473 (registers[instr->
rs] + instr->
extra), 4, registers[instr->
rt]))
00474
return;
00475
break;
00476
00477
case OP_SWL:
00478 tmp = registers[instr->
rs] + instr->
extra;
00479
00480
00481
00482
ASSERT((tmp & 0x3) == 0);
00483
00484
if (!machine->ReadMem((tmp & ~0x3), 4, &value))
00485
return;
00486
switch (tmp & 0x3) {
00487
case 0:
00488 value = registers[instr->
rt];
00489
break;
00490
case 1:
00491 value = (value & 0xff000000) | ((registers[instr->
rt] >> 8) &
00492 0xffffff);
00493
break;
00494
case 2:
00495 value = (value & 0xffff0000) | ((registers[instr->
rt] >> 16) &
00496 0xffff);
00497
break;
00498
case 3:
00499 value = (value & 0xffffff00) | ((registers[instr->
rt] >> 24) &
00500 0xff);
00501
break;
00502 }
00503
if (!machine->WriteMem((tmp & ~0x3), 4, value))
00504
return;
00505
break;
00506
00507
case OP_SWR:
00508 tmp = registers[instr->
rs] + instr->
extra;
00509
00510
00511
00512
ASSERT((tmp & 0x3) == 0);
00513
00514
if (!machine->ReadMem((tmp & ~0x3), 4, &value))
00515
return;
00516
switch (tmp & 0x3) {
00517
case 0:
00518 value = (value & 0xffffff) | (registers[instr->
rt] << 24);
00519
break;
00520
case 1:
00521 value = (value & 0xffff) | (registers[instr->
rt] << 16);
00522
break;
00523
case 2:
00524 value = (value & 0xff) | (registers[instr->
rt] << 8);
00525
break;
00526
case 3:
00527 value = registers[instr->
rt];
00528
break;
00529 }
00530
if (!machine->WriteMem((tmp & ~0x3), 4, value))
00531
return;
00532
break;
00533
00534
case OP_SYSCALL:
00535
RaiseException(SyscallException, 0);
00536
return;
00537
00538
case OP_XOR:
00539 registers[instr->
rd] = registers[instr->
rs] ^ registers[instr->
rt];
00540
break;
00541
00542
case OP_XORI:
00543 registers[instr->
rt] = registers[instr->
rs] ^ (instr->
extra & 0xffff);
00544
break;
00545
00546
case OP_RES:
00547
case OP_UNIMP:
00548
RaiseException(IllegalInstrException, 0);
00549
return;
00550
00551
default:
00552
ASSERT(FALSE);
00553 }
00554
00555
00556
00557
00558
DelayedLoad(nextLoadReg, nextLoadValue);
00559
00560
00561 registers[
PrevPCReg] = registers[
PCReg];
00562
00563 registers[
PCReg] = registers[
NextPCReg];
00564 registers[
NextPCReg] = pcAfter;
00565 }