summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2015-03-19 21:37:43 -0400
committerGravatar bunnei2015-03-19 21:37:43 -0400
commit1981aa3d7e8c230f05999393a891c89105575b12 (patch)
tree0f2e2db10ba2b96bda11b4538aaaba7cdbd3536b
parentMerge pull request #667 from archshift/wut (diff)
parentdyncom: Make Load/Store instructions support big endian (diff)
downloadyuzu-1981aa3d7e8c230f05999393a891c89105575b12.tar.gz
yuzu-1981aa3d7e8c230f05999393a891c89105575b12.tar.xz
yuzu-1981aa3d7e8c230f05999393a891c89105575b12.zip
Merge pull request #659 from lioncash/setend
Implement SETEND.
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp150
-rw-r--r--src/core/arm/interpreter/armsupp.cpp6
-rw-r--r--src/core/arm/skyeye_common/armdefs.h3
-rw-r--r--src/core/arm/skyeye_common/armmmu.h55
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp102
-rw-r--r--src/core/mem_map.h1
-rw-r--r--src/core/mem_map_funcs.cpp6
7 files changed, 240 insertions, 83 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index d953adba9..cfa6de8fc 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -1075,6 +1075,10 @@ typedef struct _swp_inst {
1075 unsigned int Rm; 1075 unsigned int Rm;
1076} swp_inst; 1076} swp_inst;
1077 1077
1078typedef struct setend_inst {
1079 unsigned int set_bigend;
1080} setend_inst;
1081
1078typedef struct _b_2_thumb { 1082typedef struct _b_2_thumb {
1079 unsigned int imm; 1083 unsigned int imm;
1080}b_2_thumb; 1084}b_2_thumb;
@@ -2283,7 +2287,20 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index)
2283 return inst_base; 2287 return inst_base;
2284} 2288}
2285 2289
2286static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SETEND"); } 2290static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index)
2291{
2292 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst));
2293 setend_inst* const inst_cream = (setend_inst*)inst_base->component;
2294
2295 inst_base->cond = AL;
2296 inst_base->idx = index;
2297 inst_base->br = NON_BRANCH;
2298 inst_base->load_r15 = 0;
2299
2300 inst_cream->set_bigend = BIT(inst, 9);
2301
2302 return inst_base;
2303}
2287 2304
2288static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) 2305static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index)
2289{ 2306{
@@ -4345,30 +4362,30 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4345 if (BIT(inst, 22) && !BIT(inst, 15)) { 4362 if (BIT(inst, 22) && !BIT(inst, 15)) {
4346 for (int i = 0; i < 13; i++) { 4363 for (int i = 0; i < 13; i++) {
4347 if(BIT(inst, i)) { 4364 if(BIT(inst, i)) {
4348 cpu->Reg[i] = Memory::Read32(addr); 4365 cpu->Reg[i] = ReadMemory32(cpu, addr);
4349 addr += 4; 4366 addr += 4;
4350 } 4367 }
4351 } 4368 }
4352 if (BIT(inst, 13)) { 4369 if (BIT(inst, 13)) {
4353 if (cpu->Mode == USER32MODE) 4370 if (cpu->Mode == USER32MODE)
4354 cpu->Reg[13] = Memory::Read32(addr); 4371 cpu->Reg[13] = ReadMemory32(cpu, addr);
4355 else 4372 else
4356 cpu->Reg_usr[0] = Memory::Read32(addr); 4373 cpu->Reg_usr[0] = ReadMemory32(cpu, addr);
4357 4374
4358 addr += 4; 4375 addr += 4;
4359 } 4376 }
4360 if (BIT(inst, 14)) { 4377 if (BIT(inst, 14)) {
4361 if (cpu->Mode == USER32MODE) 4378 if (cpu->Mode == USER32MODE)
4362 cpu->Reg[14] = Memory::Read32(addr); 4379 cpu->Reg[14] = ReadMemory32(cpu, addr);
4363 else 4380 else
4364 cpu->Reg_usr[1] = Memory::Read32(addr); 4381 cpu->Reg_usr[1] = ReadMemory32(cpu, addr);
4365 4382
4366 addr += 4; 4383 addr += 4;
4367 } 4384 }
4368 } else if (!BIT(inst, 22)) { 4385 } else if (!BIT(inst, 22)) {
4369 for(int i = 0; i < 16; i++ ){ 4386 for(int i = 0; i < 16; i++ ){
4370 if(BIT(inst, i)){ 4387 if(BIT(inst, i)){
4371 unsigned int ret = Memory::Read32(addr); 4388 unsigned int ret = ReadMemory32(cpu, addr);
4372 4389
4373 // For armv5t, should enter thumb when bits[0] is non-zero. 4390 // For armv5t, should enter thumb when bits[0] is non-zero.
4374 if(i == 15){ 4391 if(i == 15){
@@ -4383,7 +4400,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4383 } else if (BIT(inst, 22) && BIT(inst, 15)) { 4400 } else if (BIT(inst, 22) && BIT(inst, 15)) {
4384 for(int i = 0; i < 15; i++ ){ 4401 for(int i = 0; i < 15; i++ ){
4385 if(BIT(inst, i)){ 4402 if(BIT(inst, i)){
4386 cpu->Reg[i] = Memory::Read32(addr); 4403 cpu->Reg[i] = ReadMemory32(cpu, addr);
4387 addr += 4; 4404 addr += 4;
4388 } 4405 }
4389 } 4406 }
@@ -4394,7 +4411,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4394 LOAD_NZCVT; 4411 LOAD_NZCVT;
4395 } 4412 }
4396 4413
4397 cpu->Reg[15] = Memory::Read32(addr); 4414 cpu->Reg[15] = ReadMemory32(cpu, addr);
4398 } 4415 }
4399 4416
4400 if (BIT(inst, 15)) { 4417 if (BIT(inst, 15)) {
@@ -4428,20 +4445,18 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4428 LDR_INST: 4445 LDR_INST:
4429 { 4446 {
4430 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4447 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4431 //if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4448 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4432 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4433 4449
4434 unsigned int value = Memory::Read32(addr); 4450 unsigned int value = ReadMemory32(cpu, addr);
4435 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4451 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4436 4452
4437 if (BITS(inst_cream->inst, 12, 15) == 15) { 4453 if (BITS(inst_cream->inst, 12, 15) == 15) {
4438 // For armv5t, should enter thumb when bits[0] is non-zero. 4454 // For armv5t, should enter thumb when bits[0] is non-zero.
4439 cpu->TFlag = value & 0x1; 4455 cpu->TFlag = value & 0x1;
4440 cpu->Reg[15] &= 0xFFFFFFFE; 4456 cpu->Reg[15] &= 0xFFFFFFFE;
4441 INC_PC(sizeof(ldst_inst)); 4457 INC_PC(sizeof(ldst_inst));
4442 goto DISPATCH; 4458 goto DISPATCH;
4443 } 4459 }
4444 //}
4445 4460
4446 cpu->Reg[15] += GET_INST_SIZE(cpu); 4461 cpu->Reg[15] += GET_INST_SIZE(cpu);
4447 INC_PC(sizeof(ldst_inst)); 4462 INC_PC(sizeof(ldst_inst));
@@ -4454,7 +4469,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4454 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4469 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4455 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); 4470 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4456 4471
4457 unsigned int value = Memory::Read32(addr); 4472 unsigned int value = ReadMemory32(cpu, addr);
4458 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4473 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4459 4474
4460 if (BITS(inst_cream->inst, 12, 15) == 15) { 4475 if (BITS(inst_cream->inst, 12, 15) == 15) {
@@ -4537,8 +4552,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4537 // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0) 4552 // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0)
4538 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); 4553 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4539 4554
4540 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = Memory::Read32(addr); 4555 // The 3DS doesn't have LPAE (Large Physical Access Extension), so it
4541 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = Memory::Read32(addr + 4); 4556 // wouldn't do this as a single read.
4557 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = ReadMemory32(cpu, addr);
4558 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = ReadMemory32(cpu, addr + 4);
4542 4559
4543 // No dispatch since this operation should not modify R15 4560 // No dispatch since this operation should not modify R15
4544 } 4561 }
@@ -4557,7 +4574,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4557 add_exclusive_addr(cpu, read_addr); 4574 add_exclusive_addr(cpu, read_addr);
4558 cpu->exclusive_state = 1; 4575 cpu->exclusive_state = 1;
4559 4576
4560 RD = Memory::Read32(read_addr); 4577 RD = ReadMemory32(cpu, read_addr);
4561 if (inst_cream->Rd == 15) { 4578 if (inst_cream->Rd == 15) {
4562 INC_PC(sizeof(generic_arm_inst)); 4579 INC_PC(sizeof(generic_arm_inst));
4563 goto DISPATCH; 4580 goto DISPATCH;
@@ -4597,7 +4614,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4597 add_exclusive_addr(cpu, read_addr); 4614 add_exclusive_addr(cpu, read_addr);
4598 cpu->exclusive_state = 1; 4615 cpu->exclusive_state = 1;
4599 4616
4600 RD = Memory::Read16(read_addr); 4617 RD = ReadMemory16(cpu, read_addr);
4601 if (inst_cream->Rd == 15) { 4618 if (inst_cream->Rd == 15) {
4602 INC_PC(sizeof(generic_arm_inst)); 4619 INC_PC(sizeof(generic_arm_inst));
4603 goto DISPATCH; 4620 goto DISPATCH;
@@ -4617,8 +4634,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4617 add_exclusive_addr(cpu, read_addr); 4634 add_exclusive_addr(cpu, read_addr);
4618 cpu->exclusive_state = 1; 4635 cpu->exclusive_state = 1;
4619 4636
4620 RD = Memory::Read32(read_addr); 4637 RD = ReadMemory32(cpu, read_addr);
4621 RD2 = Memory::Read32(read_addr + 4); 4638 RD2 = ReadMemory32(cpu, read_addr + 4);
4622 4639
4623 if (inst_cream->Rd == 15) { 4640 if (inst_cream->Rd == 15) {
4624 INC_PC(sizeof(generic_arm_inst)); 4641 INC_PC(sizeof(generic_arm_inst));
@@ -4635,7 +4652,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4635 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { 4652 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
4636 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 4653 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
4637 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); 4654 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4638 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = Memory::Read16(addr); 4655
4656 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ReadMemory16(cpu, addr);
4639 if (BITS(inst_cream->inst, 12, 15) == 15) { 4657 if (BITS(inst_cream->inst, 12, 15) == 15) {
4640 INC_PC(sizeof(ldst_inst)); 4658 INC_PC(sizeof(ldst_inst));
4641 goto DISPATCH; 4659 goto DISPATCH;
@@ -4671,7 +4689,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4671 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { 4689 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
4672 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 4690 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
4673 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); 4691 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4674 unsigned int value = Memory::Read16(addr); 4692
4693 unsigned int value = ReadMemory16(cpu, addr);
4675 if (BIT(value, 15)) { 4694 if (BIT(value, 15)) {
4676 value |= 0xffff0000; 4695 value |= 0xffff0000;
4677 } 4696 }
@@ -4692,7 +4711,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4692 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 4711 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
4693 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); 4712 inst_cream->get_addr(cpu, inst_cream->inst, addr, 1);
4694 4713
4695 unsigned int value = Memory::Read32(addr); 4714 unsigned int value = ReadMemory32(cpu, addr);
4696 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4715 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4697 4716
4698 if (BITS(inst_cream->inst, 12, 15) == 15) { 4717 if (BITS(inst_cream->inst, 12, 15) == 15) {
@@ -5521,6 +5540,23 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5521 } 5540 }
5522 5541
5523 SETEND_INST: 5542 SETEND_INST:
5543 {
5544 // SETEND is unconditional
5545 setend_inst* const inst_cream = (setend_inst*)inst_base->component;
5546 const bool big_endian = (inst_cream->set_bigend == 1);
5547
5548 if (big_endian)
5549 cpu->Cpsr |= (1 << 9);
5550 else
5551 cpu->Cpsr &= ~(1 << 9);
5552
5553 LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE");
5554
5555 cpu->Reg[15] += GET_INST_SIZE(cpu);
5556 INC_PC(sizeof(setend_inst));
5557 FETCH_INST;
5558 GOTO_NEXT_INST;
5559 }
5524 5560
5525 SHADD8_INST: 5561 SHADD8_INST:
5526 SHADD16_INST: 5562 SHADD16_INST:
@@ -5976,36 +6012,36 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5976 if (BIT(inst_cream->inst, 22) == 1) { 6012 if (BIT(inst_cream->inst, 22) == 1) {
5977 for (int i = 0; i < 13; i++) { 6013 for (int i = 0; i < 13; i++) {
5978 if (BIT(inst_cream->inst, i)) { 6014 if (BIT(inst_cream->inst, i)) {
5979 Memory::Write32(addr, cpu->Reg[i]); 6015 WriteMemory32(cpu, addr, cpu->Reg[i]);
5980 addr += 4; 6016 addr += 4;
5981 } 6017 }
5982 } 6018 }
5983 if (BIT(inst_cream->inst, 13)) { 6019 if (BIT(inst_cream->inst, 13)) {
5984 if (cpu->Mode == USER32MODE) 6020 if (cpu->Mode == USER32MODE)
5985 Memory::Write32(addr, cpu->Reg[13]); 6021 WriteMemory32(cpu, addr, cpu->Reg[13]);
5986 else 6022 else
5987 Memory::Write32(addr, cpu->Reg_usr[0]); 6023 WriteMemory32(cpu, addr, cpu->Reg_usr[0]);
5988 6024
5989 addr += 4; 6025 addr += 4;
5990 } 6026 }
5991 if (BIT(inst_cream->inst, 14)) { 6027 if (BIT(inst_cream->inst, 14)) {
5992 if (cpu->Mode == USER32MODE) 6028 if (cpu->Mode == USER32MODE)
5993 Memory::Write32(addr, cpu->Reg[14]); 6029 WriteMemory32(cpu, addr, cpu->Reg[14]);
5994 else 6030 else
5995 Memory::Write32(addr, cpu->Reg_usr[1]); 6031 WriteMemory32(cpu, addr, cpu->Reg_usr[1]);
5996 6032
5997 addr += 4; 6033 addr += 4;
5998 } 6034 }
5999 if (BIT(inst_cream->inst, 15)) { 6035 if (BIT(inst_cream->inst, 15)) {
6000 Memory::Write32(addr, cpu->Reg_usr[1] + 8); 6036 WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8);
6001 } 6037 }
6002 } else { 6038 } else {
6003 for (int i = 0; i < 15; i++) { 6039 for (int i = 0; i < 15; i++) {
6004 if (BIT(inst_cream->inst, i)) { 6040 if (BIT(inst_cream->inst, i)) {
6005 if (i == Rn) 6041 if (i == Rn)
6006 Memory::Write32(addr, old_RN); 6042 WriteMemory32(cpu, addr, old_RN);
6007 else 6043 else
6008 Memory::Write32(addr, cpu->Reg[i]); 6044 WriteMemory32(cpu, addr, cpu->Reg[i]);
6009 6045
6010 addr += 4; 6046 addr += 4;
6011 } 6047 }
@@ -6013,7 +6049,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6013 6049
6014 // Check PC reg 6050 // Check PC reg
6015 if (BIT(inst_cream->inst, 15)) 6051 if (BIT(inst_cream->inst, 15))
6016 Memory::Write32(addr, cpu->Reg_usr[1] + 8); 6052 WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8);
6017 } 6053 }
6018 } 6054 }
6019 cpu->Reg[15] += GET_INST_SIZE(cpu); 6055 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -6046,7 +6082,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6046 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); 6082 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
6047 6083
6048 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; 6084 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
6049 Memory::Write32(addr, value); 6085 WriteMemory32(cpu, addr, value);
6050 } 6086 }
6051 cpu->Reg[15] += GET_INST_SIZE(cpu); 6087 cpu->Reg[15] += GET_INST_SIZE(cpu);
6052 INC_PC(sizeof(ldst_inst)); 6088 INC_PC(sizeof(ldst_inst));
@@ -6109,10 +6145,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6109 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 6145 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
6110 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); 6146 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
6111 6147
6112 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; 6148 // The 3DS doesn't have the Large Physical Access Extension (LPAE)
6113 Memory::Write32(addr, value); 6149 // so STRD wouldn't store these as a single write.
6114 value = cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]; 6150 WriteMemory32(cpu, addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]);
6115 Memory::Write32(addr + 4, value); 6151 WriteMemory32(cpu, addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]);
6116 } 6152 }
6117 cpu->Reg[15] += GET_INST_SIZE(cpu); 6153 cpu->Reg[15] += GET_INST_SIZE(cpu);
6118 INC_PC(sizeof(ldst_inst)); 6154 INC_PC(sizeof(ldst_inst));
@@ -6129,7 +6165,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6129 remove_exclusive(cpu, write_addr); 6165 remove_exclusive(cpu, write_addr);
6130 cpu->exclusive_state = 0; 6166 cpu->exclusive_state = 0;
6131 6167
6132 Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]); 6168 WriteMemory32(cpu, write_addr, RM);
6133 RD = 0; 6169 RD = 0;
6134 } else { 6170 } else {
6135 // Failed to write due to mutex access 6171 // Failed to write due to mutex access
@@ -6173,8 +6209,16 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6173 remove_exclusive(cpu, write_addr); 6209 remove_exclusive(cpu, write_addr);
6174 cpu->exclusive_state = 0; 6210 cpu->exclusive_state = 0;
6175 6211
6176 Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]); 6212 const u32 rt = cpu->Reg[inst_cream->Rm + 0];
6177 Memory::Write32(write_addr + 4, cpu->Reg[inst_cream->Rm + 1]); 6213 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
6214 u64 value;
6215
6216 if (InBigEndianMode(cpu))
6217 value = (((u64)rt << 32) | rt2);
6218 else
6219 value = (((u64)rt2 << 32) | rt);
6220
6221 WriteMemory64(cpu, write_addr, value);
6178 RD = 0; 6222 RD = 0;
6179 } 6223 }
6180 else { 6224 else {
@@ -6197,7 +6241,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6197 remove_exclusive(cpu, write_addr); 6241 remove_exclusive(cpu, write_addr);
6198 cpu->exclusive_state = 0; 6242 cpu->exclusive_state = 0;
6199 6243
6200 Memory::Write16(write_addr, cpu->Reg[inst_cream->Rm]); 6244 WriteMemory16(cpu, write_addr, RM);
6201 RD = 0; 6245 RD = 0;
6202 } else { 6246 } else {
6203 // Failed to write due to mutex access 6247 // Failed to write due to mutex access
@@ -6216,7 +6260,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6216 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); 6260 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
6217 6261
6218 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; 6262 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
6219 Memory::Write16(addr, value); 6263 WriteMemory16(cpu, addr, value);
6220 } 6264 }
6221 cpu->Reg[15] += GET_INST_SIZE(cpu); 6265 cpu->Reg[15] += GET_INST_SIZE(cpu);
6222 INC_PC(sizeof(ldst_inst)); 6266 INC_PC(sizeof(ldst_inst));
@@ -6230,7 +6274,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6230 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); 6274 inst_cream->get_addr(cpu, inst_cream->inst, addr, 0);
6231 6275
6232 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; 6276 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
6233 Memory::Write32(addr, value); 6277 WriteMemory32(cpu, addr, value);
6234 } 6278 }
6235 cpu->Reg[15] += GET_INST_SIZE(cpu); 6279 cpu->Reg[15] += GET_INST_SIZE(cpu);
6236 INC_PC(sizeof(ldst_inst)); 6280 INC_PC(sizeof(ldst_inst));
@@ -6289,8 +6333,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6289 swp_inst* inst_cream = (swp_inst*)inst_base->component; 6333 swp_inst* inst_cream = (swp_inst*)inst_base->component;
6290 6334
6291 addr = RN; 6335 addr = RN;
6292 unsigned int value = Memory::Read32(addr); 6336 unsigned int value = ReadMemory32(cpu, addr);
6293 Memory::Write32(addr, RM); 6337 WriteMemory32(cpu, addr, RM);
6294 6338
6295 RD = value; 6339 RD = value;
6296 } 6340 }
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index ed4f6c2a2..aca2bfbbd 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -201,3 +201,9 @@ u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
201 *saturation_occurred = false; 201 *saturation_occurred = false;
202 return (u32)value; 202 return (u32)value;
203} 203}
204
205// Whether or not the given CPU is in big endian mode (E bit is set)
206bool InBigEndianMode(ARMul_State* cpu)
207{
208 return (cpu->Cpsr & (1 << 9)) != 0;
209}
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index 16f3ac86c..c1a19fecc 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -18,7 +18,6 @@
18#pragma once 18#pragma once
19 19
20#include "common/common_types.h" 20#include "common/common_types.h"
21#include "core/arm/skyeye_common/armmmu.h"
22#include "core/arm/skyeye_common/arm_regformat.h" 21#include "core/arm/skyeye_common/arm_regformat.h"
23#include "core/arm/skyeye_common/skyeye_defs.h" 22#include "core/arm/skyeye_common/skyeye_defs.h"
24 23
@@ -356,3 +355,5 @@ extern u16 ARMul_UnsignedSaturatedSub16(u16, u16);
356extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); 355extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
357extern u32 ARMul_SignedSatQ(s32, u8, bool*); 356extern u32 ARMul_SignedSatQ(s32, u8, bool*);
358extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); 357extern u32 ARMul_UnsignedSatQ(s32, u8, bool*);
358
359extern bool InBigEndianMode(ARMul_State*);
diff --git a/src/core/arm/skyeye_common/armmmu.h b/src/core/arm/skyeye_common/armmmu.h
index 6e54142ee..0f9eadafa 100644
--- a/src/core/arm/skyeye_common/armmmu.h
+++ b/src/core/arm/skyeye_common/armmmu.h
@@ -20,6 +20,9 @@
20 20
21#pragma once 21#pragma once
22 22
23#include "core/mem_map.h"
24#include "core/arm/skyeye_common/armdefs.h"
25
23// Register numbers in the MMU 26// Register numbers in the MMU
24enum 27enum
25{ 28{
@@ -54,3 +57,55 @@ enum
54 XSCALE_CP15_AUX_CONTROL = 1, 57 XSCALE_CP15_AUX_CONTROL = 1,
55 XSCALE_CP15_COPRO_ACCESS = 15, 58 XSCALE_CP15_COPRO_ACCESS = 15,
56}; 59};
60
61// Reads data in big/little endian format based on the
62// state of the E (endian) bit in the emulated CPU's APSR.
63inline u16 ReadMemory16(ARMul_State* cpu, u32 address) {
64 u16 data = Memory::Read16(address);
65
66 if (InBigEndianMode(cpu))
67 data = Common::swap16(data);
68
69 return data;
70}
71
72inline u32 ReadMemory32(ARMul_State* cpu, u32 address) {
73 u32 data = Memory::Read32(address);
74
75 if (InBigEndianMode(cpu))
76 data = Common::swap32(data);
77
78 return data;
79}
80
81inline u64 ReadMemory64(ARMul_State* cpu, u32 address) {
82 u64 data = Memory::Read64(address);
83
84 if (InBigEndianMode(cpu))
85 data = Common::swap64(data);
86
87 return data;
88}
89
90// Writes data in big/little endian format based on the
91// state of the E (endian) bit in the emulated CPU's APSR.
92inline void WriteMemory16(ARMul_State* cpu, u32 address, u16 data) {
93 if (InBigEndianMode(cpu))
94 data = Common::swap16(data);
95
96 Memory::Write16(address, data);
97}
98
99inline void WriteMemory32(ARMul_State* cpu, u32 address, u32 data) {
100 if (InBigEndianMode(cpu))
101 data = Common::swap32(data);
102
103 Memory::Write32(address, data);
104}
105
106inline void WriteMemory64(ARMul_State* cpu, u32 address, u64 data) {
107 if (InBigEndianMode(cpu))
108 data = Common::swap64(data);
109
110 Memory::Write64(address, data);
111}
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index b9b96c388..368b5a25d 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -1388,12 +1388,20 @@ VSTR_INST:
1388 1388
1389 if (inst_cream->single) 1389 if (inst_cream->single)
1390 { 1390 {
1391 Memory::Write32(addr, cpu->ExtReg[inst_cream->d]); 1391 WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d]);
1392 } 1392 }
1393 else 1393 else
1394 { 1394 {
1395 Memory::Write32(addr, cpu->ExtReg[inst_cream->d*2]); 1395 const u32 word1 = cpu->ExtReg[inst_cream->d*2+0];
1396 Memory::Write32(addr + 4, cpu->ExtReg[inst_cream->d*2+1]); 1396 const u32 word2 = cpu->ExtReg[inst_cream->d*2+1];
1397
1398 if (InBigEndianMode(cpu)) {
1399 WriteMemory32(cpu, addr + 0, word2);
1400 WriteMemory32(cpu, addr + 4, word1);
1401 } else {
1402 WriteMemory32(cpu, addr + 0, word1);
1403 WriteMemory32(cpu, addr + 4, word2);
1404 }
1397 } 1405 }
1398 } 1406 }
1399 cpu->Reg[15] += GET_INST_SIZE(cpu); 1407 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -1447,17 +1455,27 @@ VPUSH_INST:
1447 { 1455 {
1448 if (inst_cream->single) 1456 if (inst_cream->single)
1449 { 1457 {
1450 Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]); 1458 WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]);
1451 addr += 4; 1459 addr += 4;
1452 } 1460 }
1453 else 1461 else
1454 { 1462 {
1455 Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]); 1463 const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
1456 Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]); 1464 const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
1465
1466 if (InBigEndianMode(cpu)) {
1467 WriteMemory32(cpu, addr + 0, word2);
1468 WriteMemory32(cpu, addr + 4, word1);
1469 } else {
1470 WriteMemory32(cpu, addr + 0, word1);
1471 WriteMemory32(cpu, addr + 4, word2);
1472 }
1473
1457 addr += 8; 1474 addr += 8;
1458 } 1475 }
1459 } 1476 }
1460 cpu->Reg[R13] = cpu->Reg[R13] - inst_cream->imm32; 1477
1478 cpu->Reg[R13] -= inst_cream->imm32;
1461 } 1479 }
1462 cpu->Reg[15] += GET_INST_SIZE(cpu); 1480 cpu->Reg[15] += GET_INST_SIZE(cpu);
1463 INC_PC(sizeof(vpush_inst)); 1481 INC_PC(sizeof(vpush_inst));
@@ -1516,13 +1534,22 @@ VSTM_INST: /* encoding 1 */
1516 { 1534 {
1517 if (inst_cream->single) 1535 if (inst_cream->single)
1518 { 1536 {
1519 Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]); 1537 WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]);
1520 addr += 4; 1538 addr += 4;
1521 } 1539 }
1522 else 1540 else
1523 { 1541 {
1524 Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]); 1542 const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
1525 Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]); 1543 const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
1544
1545 if (InBigEndianMode(cpu)) {
1546 WriteMemory32(cpu, addr + 0, word2);
1547 WriteMemory32(cpu, addr + 4, word1);
1548 } else {
1549 WriteMemory32(cpu, addr + 0, word1);
1550 WriteMemory32(cpu, addr + 4, word2);
1551 }
1552
1526 addr += 8; 1553 addr += 8;
1527 } 1554 }
1528 } 1555 }
@@ -1575,8 +1602,6 @@ VPOP_INST:
1575 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1602 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1576 CHECK_VFP_ENABLED; 1603 CHECK_VFP_ENABLED;
1577 1604
1578 unsigned int value1, value2;
1579
1580 vpop_inst *inst_cream = (vpop_inst *)inst_base->component; 1605 vpop_inst *inst_cream = (vpop_inst *)inst_base->component;
1581 1606
1582 addr = cpu->Reg[R13]; 1607 addr = cpu->Reg[R13];
@@ -1585,20 +1610,26 @@ VPOP_INST:
1585 { 1610 {
1586 if (inst_cream->single) 1611 if (inst_cream->single)
1587 { 1612 {
1588 value1 = Memory::Read32(addr); 1613 cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr);
1589 cpu->ExtReg[inst_cream->d+i] = value1;
1590 addr += 4; 1614 addr += 4;
1591 } 1615 }
1592 else 1616 else
1593 { 1617 {
1594 value1 = Memory::Read32(addr); 1618 const u32 word1 = ReadMemory32(cpu, addr + 0);
1595 value2 = Memory::Read32(addr + 4); 1619 const u32 word2 = ReadMemory32(cpu, addr + 4);
1596 cpu->ExtReg[(inst_cream->d+i)*2] = value1; 1620
1597 cpu->ExtReg[(inst_cream->d+i)*2 + 1] = value2; 1621 if (InBigEndianMode(cpu)) {
1622 cpu->ExtReg[(inst_cream->d+i)*2+0] = word2;
1623 cpu->ExtReg[(inst_cream->d+i)*2+1] = word1;
1624 } else {
1625 cpu->ExtReg[(inst_cream->d+i)*2+0] = word1;
1626 cpu->ExtReg[(inst_cream->d+i)*2+1] = word2;
1627 }
1628
1598 addr += 8; 1629 addr += 8;
1599 } 1630 }
1600 } 1631 }
1601 cpu->Reg[R13] = cpu->Reg[R13] + inst_cream->imm32; 1632 cpu->Reg[R13] += inst_cream->imm32;
1602 } 1633 }
1603 cpu->Reg[15] += GET_INST_SIZE(cpu); 1634 cpu->Reg[15] += GET_INST_SIZE(cpu);
1604 INC_PC(sizeof(vpop_inst)); 1635 INC_PC(sizeof(vpop_inst));
@@ -1653,16 +1684,20 @@ VLDR_INST:
1653 1684
1654 if (inst_cream->single) 1685 if (inst_cream->single)
1655 { 1686 {
1656 cpu->ExtReg[inst_cream->d] = Memory::Read32(addr); 1687 cpu->ExtReg[inst_cream->d] = ReadMemory32(cpu, addr);
1657 } 1688 }
1658 else 1689 else
1659 { 1690 {
1660 unsigned int word1, word2; 1691 const u32 word1 = ReadMemory32(cpu, addr + 0);
1661 word1 = Memory::Read32(addr); 1692 const u32 word2 = ReadMemory32(cpu, addr + 4);
1662 word2 = Memory::Read32(addr + 4); 1693
1663 1694 if (InBigEndianMode(cpu)) {
1664 cpu->ExtReg[inst_cream->d*2] = word1; 1695 cpu->ExtReg[inst_cream->d*2+0] = word2;
1665 cpu->ExtReg[inst_cream->d*2+1] = word2; 1696 cpu->ExtReg[inst_cream->d*2+1] = word1;
1697 } else {
1698 cpu->ExtReg[inst_cream->d*2+0] = word1;
1699 cpu->ExtReg[inst_cream->d*2+1] = word2;
1700 }
1666 } 1701 }
1667 } 1702 }
1668 cpu->Reg[15] += GET_INST_SIZE(cpu); 1703 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -1722,13 +1757,22 @@ VLDM_INST:
1722 { 1757 {
1723 if (inst_cream->single) 1758 if (inst_cream->single)
1724 { 1759 {
1725 cpu->ExtReg[inst_cream->d+i] = Memory::Read32(addr); 1760 cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr);
1726 addr += 4; 1761 addr += 4;
1727 } 1762 }
1728 else 1763 else
1729 { 1764 {
1730 cpu->ExtReg[(inst_cream->d+i)*2] = Memory::Read32(addr); 1765 const u32 word1 = ReadMemory32(cpu, addr + 0);
1731 cpu->ExtReg[(inst_cream->d+i)*2 + 1] = Memory::Read32(addr + 4); 1766 const u32 word2 = ReadMemory32(cpu, addr + 4);
1767
1768 if (InBigEndianMode(cpu)) {
1769 cpu->ExtReg[(inst_cream->d+i)*2+0] = word2;
1770 cpu->ExtReg[(inst_cream->d+i)*2+1] = word1;
1771 } else {
1772 cpu->ExtReg[(inst_cream->d+i)*2+0] = word1;
1773 cpu->ExtReg[(inst_cream->d+i)*2+1] = word2;
1774 }
1775
1732 addr += 8; 1776 addr += 8;
1733 } 1777 }
1734 } 1778 }
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index 8f4f21fec..bce99dffa 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -147,6 +147,7 @@ inline void Write(VAddr addr, T data);
147u8 Read8(VAddr addr); 147u8 Read8(VAddr addr);
148u16 Read16(VAddr addr); 148u16 Read16(VAddr addr);
149u32 Read32(VAddr addr); 149u32 Read32(VAddr addr);
150u64 Read64(VAddr addr);
150 151
151u32 Read8_ZX(VAddr addr); 152u32 Read8_ZX(VAddr addr);
152u32 Read16_ZX(VAddr addr); 153u32 Read16_ZX(VAddr addr);
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index 48f61db4e..a161a8204 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -245,6 +245,12 @@ u32 Read32(const VAddr addr) {
245 return (u32)data; 245 return (u32)data;
246} 246}
247 247
248u64 Read64(const VAddr addr) {
249 u64_le data = 0;
250 Read<u64_le>(data, addr);
251 return (u64)data;
252}
253
248u32 Read8_ZX(const VAddr addr) { 254u32 Read8_ZX(const VAddr addr) {
249 return (u32)Read8(addr); 255 return (u32)Read8(addr);
250} 256}