mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-03 23:28:48 +00:00 
			
		
		
		
	dyncom: Make Load/Store instructions support big endian
This commit is contained in:
		
							parent
							
								
									f280806214
								
							
						
					
					
						commit
						9fdb311d6e
					
				
					 7 changed files with 204 additions and 81 deletions
				
			
		| 
						 | 
				
			
			@ -18,7 +18,6 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armmmu.h"
 | 
			
		||||
#include "core/arm/skyeye_common/arm_regformat.h"
 | 
			
		||||
#include "core/arm/skyeye_common/skyeye_defs.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -356,3 +355,5 @@ extern u16 ARMul_UnsignedSaturatedSub16(u16, u16);
 | 
			
		|||
extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
 | 
			
		||||
extern u32 ARMul_SignedSatQ(s32, u8, bool*);
 | 
			
		||||
extern u32 ARMul_UnsignedSatQ(s32, u8, bool*);
 | 
			
		||||
 | 
			
		||||
extern bool InBigEndianMode(ARMul_State*);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,9 @@
 | 
			
		|||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/mem_map.h"
 | 
			
		||||
#include "core/arm/skyeye_common/armdefs.h"
 | 
			
		||||
 | 
			
		||||
// Register numbers in the MMU
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -54,3 +57,55 @@ enum
 | 
			
		|||
	XSCALE_CP15_AUX_CONTROL = 1,
 | 
			
		||||
	XSCALE_CP15_COPRO_ACCESS = 15,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Reads data in big/little endian format based on the
 | 
			
		||||
// state of the E (endian) bit in the emulated CPU's APSR.
 | 
			
		||||
inline u16 ReadMemory16(ARMul_State* cpu, u32 address) {
 | 
			
		||||
    u16 data = Memory::Read16(address);
 | 
			
		||||
 | 
			
		||||
    if (InBigEndianMode(cpu))
 | 
			
		||||
        data = Common::swap16(data);
 | 
			
		||||
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u32 ReadMemory32(ARMul_State* cpu, u32 address) {
 | 
			
		||||
    u32 data = Memory::Read32(address);
 | 
			
		||||
 | 
			
		||||
    if (InBigEndianMode(cpu))
 | 
			
		||||
        data = Common::swap32(data);
 | 
			
		||||
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline u64 ReadMemory64(ARMul_State* cpu, u32 address) {
 | 
			
		||||
    u64 data = Memory::Read64(address);
 | 
			
		||||
 | 
			
		||||
    if (InBigEndianMode(cpu))
 | 
			
		||||
        data = Common::swap64(data);
 | 
			
		||||
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Writes data in big/little endian format based on the
 | 
			
		||||
// state of the E (endian) bit in the emulated CPU's APSR.
 | 
			
		||||
inline void WriteMemory16(ARMul_State* cpu, u32 address, u16 data) {
 | 
			
		||||
    if (InBigEndianMode(cpu))
 | 
			
		||||
        data = Common::swap16(data);
 | 
			
		||||
 | 
			
		||||
    Memory::Write16(address, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void WriteMemory32(ARMul_State* cpu, u32 address, u32 data) {
 | 
			
		||||
    if (InBigEndianMode(cpu))
 | 
			
		||||
        data = Common::swap32(data);
 | 
			
		||||
 | 
			
		||||
    Memory::Write32(address, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void WriteMemory64(ARMul_State* cpu, u32 address, u64 data) {
 | 
			
		||||
    if (InBigEndianMode(cpu))
 | 
			
		||||
        data = Common::swap64(data);
 | 
			
		||||
 | 
			
		||||
    Memory::Write64(address, data);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1388,12 +1388,20 @@ VSTR_INST:
 | 
			
		|||
 | 
			
		||||
        if (inst_cream->single)
 | 
			
		||||
        {
 | 
			
		||||
            Memory::Write32(addr, cpu->ExtReg[inst_cream->d]);
 | 
			
		||||
            WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d]);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            Memory::Write32(addr, cpu->ExtReg[inst_cream->d*2]);
 | 
			
		||||
            Memory::Write32(addr + 4, cpu->ExtReg[inst_cream->d*2+1]);
 | 
			
		||||
            const u32 word1 = cpu->ExtReg[inst_cream->d*2+0];
 | 
			
		||||
            const u32 word2 = cpu->ExtReg[inst_cream->d*2+1];
 | 
			
		||||
 | 
			
		||||
            if (InBigEndianMode(cpu)) {
 | 
			
		||||
                WriteMemory32(cpu, addr + 0, word2);
 | 
			
		||||
                WriteMemory32(cpu, addr + 4, word1);
 | 
			
		||||
            } else {
 | 
			
		||||
                WriteMemory32(cpu, addr + 0, word1);
 | 
			
		||||
                WriteMemory32(cpu, addr + 4, word2);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    cpu->Reg[15] += GET_INST_SIZE(cpu);
 | 
			
		||||
| 
						 | 
				
			
			@ -1447,17 +1455,27 @@ VPUSH_INST:
 | 
			
		|||
        {
 | 
			
		||||
            if (inst_cream->single)
 | 
			
		||||
            {
 | 
			
		||||
                Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]);
 | 
			
		||||
                WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]);
 | 
			
		||||
                addr += 4;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]);
 | 
			
		||||
                Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]);
 | 
			
		||||
                const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
 | 
			
		||||
                const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
 | 
			
		||||
 | 
			
		||||
                if (InBigEndianMode(cpu)) {
 | 
			
		||||
                    WriteMemory32(cpu, addr + 0, word2);
 | 
			
		||||
                    WriteMemory32(cpu, addr + 4, word1);
 | 
			
		||||
                } else {
 | 
			
		||||
                    WriteMemory32(cpu, addr + 0, word1);
 | 
			
		||||
                    WriteMemory32(cpu, addr + 4, word2);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                addr += 8;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        cpu->Reg[R13] = cpu->Reg[R13] - inst_cream->imm32;
 | 
			
		||||
 | 
			
		||||
        cpu->Reg[R13] -= inst_cream->imm32;
 | 
			
		||||
    }
 | 
			
		||||
    cpu->Reg[15] += GET_INST_SIZE(cpu);
 | 
			
		||||
    INC_PC(sizeof(vpush_inst));
 | 
			
		||||
| 
						 | 
				
			
			@ -1516,13 +1534,22 @@ VSTM_INST: /* encoding 1 */
 | 
			
		|||
        {
 | 
			
		||||
            if (inst_cream->single)
 | 
			
		||||
            {
 | 
			
		||||
                Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]);
 | 
			
		||||
                WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]);
 | 
			
		||||
                addr += 4;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]);
 | 
			
		||||
                Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]);
 | 
			
		||||
                const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
 | 
			
		||||
                const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
 | 
			
		||||
 | 
			
		||||
                if (InBigEndianMode(cpu)) {
 | 
			
		||||
                    WriteMemory32(cpu, addr + 0, word2);
 | 
			
		||||
                    WriteMemory32(cpu, addr + 4, word1);
 | 
			
		||||
                } else {
 | 
			
		||||
                    WriteMemory32(cpu, addr + 0, word1);
 | 
			
		||||
                    WriteMemory32(cpu, addr + 4, word2);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                addr += 8;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1575,8 +1602,6 @@ VPOP_INST:
 | 
			
		|||
    if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
 | 
			
		||||
        CHECK_VFP_ENABLED;
 | 
			
		||||
 | 
			
		||||
        unsigned int value1, value2;
 | 
			
		||||
 | 
			
		||||
        vpop_inst *inst_cream = (vpop_inst *)inst_base->component;
 | 
			
		||||
 | 
			
		||||
        addr = cpu->Reg[R13];
 | 
			
		||||
| 
						 | 
				
			
			@ -1585,20 +1610,26 @@ VPOP_INST:
 | 
			
		|||
        {
 | 
			
		||||
            if (inst_cream->single)
 | 
			
		||||
            {
 | 
			
		||||
                value1 = Memory::Read32(addr);
 | 
			
		||||
                cpu->ExtReg[inst_cream->d+i] = value1;
 | 
			
		||||
                cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr);
 | 
			
		||||
                addr += 4;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                value1 = Memory::Read32(addr);
 | 
			
		||||
                value2 = Memory::Read32(addr + 4);
 | 
			
		||||
                cpu->ExtReg[(inst_cream->d+i)*2] = value1;
 | 
			
		||||
                cpu->ExtReg[(inst_cream->d+i)*2 + 1] = value2;
 | 
			
		||||
                const u32 word1 = ReadMemory32(cpu, addr + 0);
 | 
			
		||||
                const u32 word2 = ReadMemory32(cpu, addr + 4);
 | 
			
		||||
 | 
			
		||||
                if (InBigEndianMode(cpu)) {
 | 
			
		||||
                    cpu->ExtReg[(inst_cream->d+i)*2+0] = word2;
 | 
			
		||||
                    cpu->ExtReg[(inst_cream->d+i)*2+1] = word1;
 | 
			
		||||
                } else {
 | 
			
		||||
                    cpu->ExtReg[(inst_cream->d+i)*2+0] = word1;
 | 
			
		||||
                    cpu->ExtReg[(inst_cream->d+i)*2+1] = word2;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                addr += 8;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        cpu->Reg[R13] = cpu->Reg[R13] + inst_cream->imm32;
 | 
			
		||||
        cpu->Reg[R13] += inst_cream->imm32;
 | 
			
		||||
    }
 | 
			
		||||
    cpu->Reg[15] += GET_INST_SIZE(cpu);
 | 
			
		||||
    INC_PC(sizeof(vpop_inst));
 | 
			
		||||
| 
						 | 
				
			
			@ -1653,16 +1684,20 @@ VLDR_INST:
 | 
			
		|||
 | 
			
		||||
        if (inst_cream->single)
 | 
			
		||||
        {
 | 
			
		||||
            cpu->ExtReg[inst_cream->d] = Memory::Read32(addr);
 | 
			
		||||
            cpu->ExtReg[inst_cream->d] = ReadMemory32(cpu, addr);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            unsigned int word1, word2;
 | 
			
		||||
            word1 = Memory::Read32(addr);
 | 
			
		||||
            word2 = Memory::Read32(addr + 4);
 | 
			
		||||
            const u32 word1 = ReadMemory32(cpu, addr + 0);
 | 
			
		||||
            const u32 word2 = ReadMemory32(cpu, addr + 4);
 | 
			
		||||
 | 
			
		||||
            cpu->ExtReg[inst_cream->d*2] = word1;
 | 
			
		||||
            cpu->ExtReg[inst_cream->d*2+1] = word2;
 | 
			
		||||
            if (InBigEndianMode(cpu)) {
 | 
			
		||||
                cpu->ExtReg[inst_cream->d*2+0] = word2;
 | 
			
		||||
                cpu->ExtReg[inst_cream->d*2+1] = word1;
 | 
			
		||||
            } else {
 | 
			
		||||
                cpu->ExtReg[inst_cream->d*2+0] = word1;
 | 
			
		||||
                cpu->ExtReg[inst_cream->d*2+1] = word2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    cpu->Reg[15] += GET_INST_SIZE(cpu);
 | 
			
		||||
| 
						 | 
				
			
			@ -1722,13 +1757,22 @@ VLDM_INST:
 | 
			
		|||
        {
 | 
			
		||||
            if (inst_cream->single)
 | 
			
		||||
            {
 | 
			
		||||
                cpu->ExtReg[inst_cream->d+i] = Memory::Read32(addr);
 | 
			
		||||
                cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr);
 | 
			
		||||
                addr += 4;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                cpu->ExtReg[(inst_cream->d+i)*2] = Memory::Read32(addr);
 | 
			
		||||
                cpu->ExtReg[(inst_cream->d+i)*2 + 1] = Memory::Read32(addr + 4);
 | 
			
		||||
                const u32 word1 = ReadMemory32(cpu, addr + 0);
 | 
			
		||||
                const u32 word2 = ReadMemory32(cpu, addr + 4);
 | 
			
		||||
 | 
			
		||||
                if (InBigEndianMode(cpu)) {
 | 
			
		||||
                    cpu->ExtReg[(inst_cream->d+i)*2+0] = word2;
 | 
			
		||||
                    cpu->ExtReg[(inst_cream->d+i)*2+1] = word1;
 | 
			
		||||
                } else {
 | 
			
		||||
                    cpu->ExtReg[(inst_cream->d+i)*2+0] = word1;
 | 
			
		||||
                    cpu->ExtReg[(inst_cream->d+i)*2+1] = word2;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                addr += 8;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue