Index: src/arm/simulator-arm.cc |
=================================================================== |
--- src/arm/simulator-arm.cc (revision 2364) |
+++ src/arm/simulator-arm.cc (working copy) |
@@ -1080,25 +1080,41 @@ |
// multiply instruction or extra loads and stores |
if (instr->Bits(7, 4) == 9) { |
if (instr->Bit(24) == 0) { |
- // Multiply instructions have Rd in a funny place. |
- int rd = instr->RnField(); |
+ // Raw field decoding here. Multiply instructions have their Rd in |
+ // funny places. |
+ int rn = instr->RnField(); |
int rm = instr->RmField(); |
int rs = instr->RsField(); |
int32_t rs_val = get_register(rs); |
int32_t rm_val = get_register(rm); |
if (instr->Bit(23) == 0) { |
if (instr->Bit(21) == 0) { |
+ // The MUL instruction description (A 4.1.33) refers to Rd as being |
+ // the destination for the operation, but it confusingly uses the |
+ // Rn field to encode it. |
// Format(instr, "mul'cond's 'rn, 'rm, 'rs"); |
+ int rd = rn; // Remap the rn field to the Rd register. |
int32_t alu_out = rm_val * rs_val; |
set_register(rd, alu_out); |
if (instr->HasS()) { |
SetNZFlags(alu_out); |
} |
} else { |
- UNIMPLEMENTED(); // mla is not used by V8. |
+ // mla is not currently being used by V8. |
+ Format(instr, "mla'cond's 'rd, 'rm, 'rs, 'rn"); |
Erik Corry
2009/07/07 08:14:16
Should be 'rn 'rm 'rs 'rd for similar reasons to t
iposva
2009/07/08 21:33:26
Fixed by copying the whole block out of the disass
|
} |
} else { |
- // Format(instr, "'um'al'cond's 'rn, 'rd, 'rs, 'rm"); |
+ // The signed/long multiply instructions use the terms RdHi and RdLo |
+ // when referring to the target registers. They are mapped to the Rn |
+ // and Rd fields as follows: |
+ // RdLo == Rd |
+ // RdHi == Rn (This is confusingly stored in variable rd here |
+ // because the mul instruction from above uses the |
+ // Rn field to encode the Rd register. Good luck figuring |
+ // this out without reading the ARM instruction manual |
+ // at a very detailed level.) |
+ // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm"); |
+ int rd_hi = rn; // Remap the rn field to the RdHi register. |
int rd_lo = instr->RdField(); |
int32_t hi_res = 0; |
int32_t lo_res = 0; |
@@ -1117,7 +1133,7 @@ |
lo_res = static_cast<int32_t>(result & 0xffffffff); |
} |
set_register(rd_lo, lo_res); |
- set_register(rd, hi_res); |
+ set_register(rd_hi, hi_res); |
if (instr->HasS()) { |
UNIMPLEMENTED(); |
} |