summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp11
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.h216
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp282
-rw-r--r--src/core/hle/service/fs/archive.cpp6
-rw-r--r--src/core/loader/elf.cpp2
5 files changed, 286 insertions, 231 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp
index 333b40f54..0927eece1 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp
@@ -136,7 +136,6 @@ const ISEITEM arm_instruction[] = {
136 { "pkhbt", 2, 6, 20, 27, 0x00000068, 4, 6, 0x00000001 }, 136 { "pkhbt", 2, 6, 20, 27, 0x00000068, 4, 6, 0x00000001 },
137 { "smul", 3, 4, 20, 27, 0x00000016, 7, 7, 0x00000001, 4, 4, 0x00000000 }, 137 { "smul", 3, 4, 20, 27, 0x00000016, 7, 7, 0x00000001, 4, 4, 0x00000000 },
138 { "smlalxy", 3, 4, 20, 27, 0x00000014, 7, 7, 0x00000001, 4, 4, 0x00000000 }, 138 { "smlalxy", 3, 4, 20, 27, 0x00000014, 7, 7, 0x00000001, 4, 4, 0x00000000 },
139 // {"smlal" , 2 , 4 , 21, 27, 0x00000007, 4, 7, 0x00000009},
140 { "smla", 3, 4, 20, 27, 0x00000010, 7, 7, 0x00000001, 4, 4, 0x00000000 }, 139 { "smla", 3, 4, 20, 27, 0x00000010, 7, 7, 0x00000001, 4, 4, 0x00000000 },
141 { "mcrr", 1, 6, 20, 27, 0x000000c4 }, 140 { "mcrr", 1, 6, 20, 27, 0x000000c4 },
142 { "mrrc", 1, 6, 20, 27, 0x000000c5 }, 141 { "mrrc", 1, 6, 20, 27, 0x000000c5 },
@@ -194,6 +193,10 @@ const ISEITEM arm_instruction[] = {
194 { "ldc", 2, 0, 25, 27, 0x00000006, 20, 20, 0x00000001 }, 193 { "ldc", 2, 0, 25, 27, 0x00000006, 20, 20, 0x00000001 },
195 { "swi", 1, 0, 24, 27, 0x0000000f }, 194 { "swi", 1, 0, 24, 27, 0x0000000f },
196 { "bbl", 1, 0, 25, 27, 0x00000005 }, 195 { "bbl", 1, 0, 25, 27, 0x00000005 },
196 { "ldrexd", 2, ARMV6K, 20, 27, 0x0000001B, 4, 7, 0x00000009 },
197 { "strexd", 2, ARMV6K, 20, 27, 0x0000001A, 4, 7, 0x00000009 },
198 { "ldrexh", 2, ARMV6K, 20, 27, 0x0000001F, 4, 7, 0x00000009 },
199 { "strexh", 2, ARMV6K, 20, 27, 0x0000001E, 4, 7, 0x00000009 },
197}; 200};
198 201
199const ISEITEM arm_exclusion_code[] = { 202const ISEITEM arm_exclusion_code[] = {
@@ -383,6 +386,11 @@ const ISEITEM arm_exclusion_code[] = {
383 { "ldc", 0, 0, 0 }, 386 { "ldc", 0, 0, 0 },
384 { "swi", 0, 0, 0 }, 387 { "swi", 0, 0, 0 },
385 { "bbl", 0, 0, 0 }, 388 { "bbl", 0, 0, 0 },
389 { "ldrexd", 0, ARMV6K, 0 },
390 { "strexd", 0, ARMV6K, 0 },
391 { "ldrexh", 0, ARMV6K, 0 },
392 { "strexh", 0, ARMV6K, 0 },
393
386 { "bl_1_thumb", 0, INVALID, 0 }, // Should be table[-4] 394 { "bl_1_thumb", 0, INVALID, 0 }, // Should be table[-4]
387 { "bl_2_thumb", 0, INVALID, 0 }, // Should be located at the end of the table[-3] 395 { "bl_2_thumb", 0, INVALID, 0 }, // Should be located at the end of the table[-3]
388 { "blx_1_thumb", 0, INVALID, 0 }, // Should be located at table[-2] 396 { "blx_1_thumb", 0, INVALID, 0 }, // Should be located at table[-2]
@@ -395,6 +403,7 @@ int decode_arm_instr(uint32_t instr, int32_t *idx) {
395 int ret = DECODE_FAILURE; 403 int ret = DECODE_FAILURE;
396 int i = 0; 404 int i = 0;
397 int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM); 405 int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM);
406
398 for (i = 0; i < instr_slots; i++) { 407 for (i = 0; i < instr_slots; i++) {
399 n = arm_instruction[i].attribute_value; 408 n = arm_instruction[i].attribute_value;
400 base = 0; 409 base = 0;
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h
index 70eb96e93..58784aeea 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.h
+++ b/src/core/arm/dyncom/arm_dyncom_dec.h
@@ -1,153 +1,117 @@
1/* Copyright (C) 1// Copyright 2012 Michael Kang, 2015 Citra Emulator Project
2* 2012 - Michael.Kang blackfin.kang@gmail.com 2// Licensed under GPLv2 or any later version
3* This program is free software; you can redistribute it and/or 3// Refer to the license.txt file included.
4* modify it under the terms of the GNU General Public License 4
5* as published by the Free Software Foundation; either version 2 5#pragma once
6* of the License, or (at your option) any later version. 6
7* 7#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1))
8* This program is distributed in the hope that it will be useful, 8#define BIT(n) ((instr >> (n)) & 1)
9* but WITHOUT ANY WARRANTY; without even the implied warranty of 9#define BAD do { printf("meet BAD at %s, instr is %x\n", __FUNCTION__, instr ); } while(0);
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10#define ptr_N cpu->ptr_N
11* GNU General Public License for more details. 11#define ptr_Z cpu->ptr_Z
12* 12#define ptr_C cpu->ptr_C
13* You should have received a copy of the GNU General Public License 13#define ptr_V cpu->ptr_V
14* along with this program; if not, write to the Free Software 14#define ptr_I cpu->ptr_I
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 15#define ptr_T cpu->ptr_T
16* 16#define ptr_CPSR cpu->ptr_gpr[16]
17*/ 17
18 18// For MUL instructions
19/** 19#define RDHi ((instr >> 16) & 0xF)
20* @file arm_dyncom_dec.h 20#define RDLo ((instr >> 12) & 0xF)
21* @brief Some common utility for arm instruction decoder 21#define MUL_RD ((instr >> 16) & 0xF)
22* @author Michael.Kang blackfin.kang@gmail.com 22#define MUL_RN ((instr >> 12) & 0xF)
23* @version 7849 23#define RS ((instr >> 8) & 0xF)
24* @date 2012-03-15 24#define RD ((instr >> 12) & 0xF)
25*/ 25#define RN ((instr >> 16) & 0xF)
26 26#define RM (instr & 0xF)
27#ifndef __ARM_DYNCOM_DEC__ 27
28#define __ARM_DYNCOM_DEC__ 28// CP15 registers
29 29#define OPCODE_1 BITS(21, 23)
30#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1)) 30#define CRn BITS(16, 19)
31#define BIT(n) ((instr >> (n)) & 1) 31#define CRm BITS(0, 3)
32#define BAD do{printf("meet BAD at %s, instr is %x\n", __FUNCTION__, instr ); /*exit(0);*/}while(0); 32#define OPCODE_2 BITS(5, 7)
33#define ptr_N cpu->ptr_N 33
34#define ptr_Z cpu->ptr_Z 34#define I BIT(25)
35#define ptr_C cpu->ptr_C 35#define S BIT(20)
36#define ptr_V cpu->ptr_V 36
37#define ptr_I cpu->ptr_I 37#define SHIFT BITS(5,6)
38#define ptr_T cpu->ptr_T 38#define SHIFT_IMM BITS(7,11)
39#define ptr_CPSR cpu->ptr_gpr[16] 39#define IMMH BITS(8,11)
40 40#define IMML BITS(0,3)
41/* for MUL instructions */ 41
42/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */ 42#define LSPBIT BIT(24)
43#define RDHi ((instr >> 16) & 0xF) 43#define LSUBIT BIT(23)
44/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */ 44#define LSBBIT BIT(22)
45#define RDLo ((instr >> 12) & 0xF) 45#define LSWBIT BIT(21)
46/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */ 46#define LSLBIT BIT(20)
47#define MUL_RD ((instr >> 16) & 0xF) 47#define LSSHBITS BITS(5,6)
48/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */ 48#define OFFSET12 BITS(0,11)
49#define MUL_RN ((instr >> 12) & 0xF) 49#define SBIT BIT(20)
50/*xxxx xxxx xxxx xxxx xxxx 1111 xxxx xxxx */ 50#define DESTReg (BITS (12, 15))
51#define RS ((instr >> 8) & 0xF) 51
52 52// They are in unused state, give a corrent value when using
53/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */
54#define RD ((instr >> 12) & 0xF)
55/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */
56#define RN ((instr >> 16) & 0xF)
57/*xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1111 */
58#define RM (instr & 0xF)
59
60/* CP15 registers */
61#define OPCODE_1 BITS(21, 23)
62#define CRn BITS(16, 19)
63#define CRm BITS(0, 3)
64#define OPCODE_2 BITS(5, 7)
65
66/*xxxx xx1x xxxx xxxx xxxx xxxx xxxx xxxx */
67#define I BIT(25)
68/*xxxx xxxx xxx1 xxxx xxxx xxxx xxxx xxxx */
69#define S BIT(20)
70
71#define SHIFT BITS(5,6)
72#define SHIFT_IMM BITS(7,11)
73#define IMMH BITS(8,11)
74#define IMML BITS(0,3)
75
76#define LSPBIT BIT(24)
77#define LSUBIT BIT(23)
78#define LSBBIT BIT(22)
79#define LSWBIT BIT(21)
80#define LSLBIT BIT(20)
81#define LSSHBITS BITS(5,6)
82#define OFFSET12 BITS(0,11)
83#define SBIT BIT(20)
84#define DESTReg (BITS (12, 15))
85
86/* they are in unused state, give a corrent value when using */
87#define IS_V5E 0 53#define IS_V5E 0
88#define IS_V5 0 54#define IS_V5 0
89#define IS_V6 0 55#define IS_V6 0
90#define LHSReg 0 56#define LHSReg 0
91 57
92/* temp define the using the pc reg need implement a flow */ 58// Temp define the using the pc reg need implement a flow
93#define STORE_CHECK_RD_PC ADD(R(RD), CONST(INSTR_SIZE * 2)) 59#define STORE_CHECK_RD_PC ADD(R(RD), CONST(INSTR_SIZE * 2))
94 60
95#define OPERAND operand(cpu,instr,bb,NULL) 61#define OPERAND operand(cpu,instr,bb,NULL)
96#define SCO_OPERAND(sco) operand(cpu,instr,bb,sco) 62#define SCO_OPERAND(sco) operand(cpu,instr,bb,sco)
97#define BOPERAND boperand(instr) 63#define BOPERAND boperand(instr)
98 64
99#define CHECK_RN_PC (RN==15? ADD(AND(R(RN), CONST(~0x1)), CONST(INSTR_SIZE * 2)):R(RN)) 65#define CHECK_RN_PC (RN == 15 ? ADD(AND(R(RN), CONST(~0x1)), CONST(INSTR_SIZE * 2)) : R(RN))
100#define CHECK_RN_PC_WA (RN==15? ADD(AND(R(RN), CONST(~0x3)), CONST(INSTR_SIZE * 2)):R(RN)) 66#define CHECK_RN_PC_WA (RN == 15 ? ADD(AND(R(RN), CONST(~0x3)), CONST(INSTR_SIZE * 2)) : R(RN))
101 67
102#define GET_USER_MODE() (OR(ICMP_EQ(R(MODE_REG), CONST(USER32MODE)), ICMP_EQ(R(MODE_REG), CONST(SYSTEM32MODE)))) 68#define GET_USER_MODE() (OR(ICMP_EQ(R(MODE_REG), CONST(USER32MODE)), ICMP_EQ(R(MODE_REG), CONST(SYSTEM32MODE))))
103 69
104int decode_arm_instr(uint32_t instr, int32_t *idx); 70int decode_arm_instr(uint32_t instr, int32_t *idx);
105 71
106enum DECODE_STATUS { 72enum DECODE_STATUS {
107 DECODE_SUCCESS, 73 DECODE_SUCCESS,
108 DECODE_FAILURE 74 DECODE_FAILURE
109}; 75};
110 76
111struct instruction_set_encoding_item { 77struct instruction_set_encoding_item {
112 const char *name; 78 const char *name;
113 int attribute_value; 79 int attribute_value;
114 int version; 80 int version;
115 u32 content[21]; 81 u32 content[21];
116}; 82};
117 83
118typedef struct instruction_set_encoding_item ISEITEM; 84typedef struct instruction_set_encoding_item ISEITEM;
119 85
120#define RECORD_WB(value, flag) {cpu->dyncom_engine->wb_value = value;cpu->dyncom_engine->wb_flag = flag;} 86#define RECORD_WB(value, flag) { cpu->dyncom_engine->wb_value = value;cpu->dyncom_engine->wb_flag = flag; }
121#define INIT_WB(wb_value, wb_flag) RECORD_WB(wb_value, wb_flag) 87#define INIT_WB(wb_value, wb_flag) RECORD_WB(wb_value, wb_flag)
122 88
123#define EXECUTE_WB(base_reg) {if(cpu->dyncom_engine->wb_flag) \ 89#define EXECUTE_WB(base_reg) { if(cpu->dyncom_engine->wb_flag) LET(base_reg, cpu->dyncom_engine->wb_value); }
124 LET(base_reg, cpu->dyncom_engine->wb_value);} 90
125inline int get_reg_count(uint32_t instr){ 91inline int get_reg_count(uint32_t instr) {
126 int i = BITS(0,15); 92 int i = BITS(0, 15);
127 int count = 0; 93 int count = 0;
128 while(i){ 94 while (i) {
129 if(i & 1) 95 if (i & 1)
130 count ++; 96 count++;
131 i = i >> 1; 97 i = i >> 1;
132 } 98 }
133 return count; 99 return count;
134} 100}
135 101
136enum ARMVER { 102enum ARMVER {
137 INVALID = 0, 103 INVALID = 0,
138 ARMALL, 104 ARMALL,
139 ARMV4, 105 ARMV4,
140 ARMV4T, 106 ARMV4T,
141 ARMV5T, 107 ARMV5T,
142 ARMV5TE, 108 ARMV5TE,
143 ARMV5TEJ, 109 ARMV5TEJ,
144 ARMV6, 110 ARMV6,
145 ARM1176JZF_S, 111 ARM1176JZF_S,
146 ARMVFP2, 112 ARMVFP2,
147 ARMVFP3 113 ARMVFP3,
114 ARMV6K,
148}; 115};
149 116
150//extern const INSTRACT arm_instruction_action[];
151extern const ISEITEM arm_instruction[]; 117extern const ISEITEM arm_instruction[];
152
153#endif
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 662b92579..a37e6c94e 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -622,9 +622,7 @@ void LdnStM(DecrementAfter)(arm_processor *cpu, unsigned int inst, unsigned int
622 } 622 }
623 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 623 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
624 unsigned int start_addr = rn - count * 4 + 4; 624 unsigned int start_addr = rn - count * 4 + 4;
625 unsigned int end_addr = rn;
626 625
627 virt_addr = end_addr;
628 virt_addr = start_addr; 626 virt_addr = start_addr;
629 627
630 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) { 628 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
@@ -1104,10 +1102,10 @@ typedef struct _blx_1_thumb {
1104}blx_1_thumb; 1102}blx_1_thumb;
1105 1103
1106typedef struct _pkh_inst { 1104typedef struct _pkh_inst {
1107 u32 Rm; 1105 unsigned int Rm;
1108 u32 Rn; 1106 unsigned int Rn;
1109 u32 Rd; 1107 unsigned int Rd;
1110 u8 imm; 1108 unsigned char imm;
1111} pkh_inst; 1109} pkh_inst;
1112 1110
1113typedef arm_inst * ARM_INST_PTR; 1111typedef arm_inst * ARM_INST_PTR;
@@ -1740,40 +1738,31 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index)
1740 1738
1741 return inst_base; 1739 return inst_base;
1742} 1740}
1743
1744ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) 1741ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index)
1745{ 1742{
1746 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1743 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1747 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1744 generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component;
1748 1745
1749 inst_base->cond = BITS(inst, 28, 31); 1746 inst_base->cond = BITS(inst, 28, 31);
1750 inst_base->idx = index; 1747 inst_base->idx = index;
1751 inst_base->br = NON_BRANCH; 1748 inst_base->br = (BITS(inst, 12, 15) == 15) ? INDIRECT_BRANCH : NON_BRANCH; // Branch if dest is R15
1752 1749
1753 inst_cream->inst = inst; 1750 inst_cream->Rn = BITS(inst, 16, 19);
1754 //inst_cream->get_addr = get_calc_addr_op(inst); 1751 inst_cream->Rd = BITS(inst, 12, 15);
1755 1752
1756 if (BITS(inst, 12, 15) == 15) {
1757 inst_base->br = INDIRECT_BRANCH;
1758 }
1759 return inst_base; 1753 return inst_base;
1760} 1754}
1761ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) 1755ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index)
1762{ 1756{
1763 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1757 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
1764 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1758}
1765 1759ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index)
1766 inst_base->cond = BITS(inst, 28, 31); 1760{
1767 inst_base->idx = index; 1761 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
1768 inst_base->br = NON_BRANCH; 1762}
1769 1763ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index)
1770 inst_cream->inst = inst; 1764{
1771 inst_cream->get_addr = get_calc_addr_op(inst); 1765 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
1772
1773 if (BITS(inst, 12, 15) == 15) {
1774 inst_base->br = INDIRECT_BRANCH;
1775 }
1776 return inst_base;
1777} 1766}
1778ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) 1767ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index)
1779{ 1768{
@@ -2651,37 +2640,30 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){
2651} 2640}
2652ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) 2641ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index)
2653{ 2642{
2654 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2643 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
2655 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2644 generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component;
2656 2645
2657 inst_base->cond = BITS(inst, 28, 31); 2646 inst_base->cond = BITS(inst, 28, 31);
2658 inst_base->idx = index; 2647 inst_base->idx = index;
2659 inst_base->br = NON_BRANCH; 2648 inst_base->br = NON_BRANCH;
2660 2649
2661 inst_cream->inst = inst; 2650 inst_cream->Rn = BITS(inst, 16, 19);
2662 inst_cream->get_addr = get_calc_addr_op(inst); 2651 inst_cream->Rd = BITS(inst, 12, 15);
2652 inst_cream->Rm = BITS(inst, 0, 3);
2663 2653
2664 if (BITS(inst, 12, 15) == 15) {
2665 inst_base->br = INDIRECT_BRANCH;
2666 }
2667 return inst_base; 2654 return inst_base;
2668} 2655}
2669ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) 2656ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index)
2670{ 2657{
2671 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2658 return INTERPRETER_TRANSLATE(strex)(inst, index);
2672 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2659}
2673 2660ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index)
2674 inst_base->cond = BITS(inst, 28, 31); 2661{
2675 inst_base->idx = index; 2662 return INTERPRETER_TRANSLATE(strex)(inst, index);
2676 inst_base->br = NON_BRANCH; 2663}
2677 2664ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index)
2678 inst_cream->inst = inst; 2665{
2679 inst_cream->get_addr = get_calc_addr_op(inst); 2666 return INTERPRETER_TRANSLATE(strex)(inst, index);
2680
2681 if (BITS(inst, 12, 15) == 15) {
2682 inst_base->br = INDIRECT_BRANCH;
2683 }
2684 return inst_base;
2685} 2667}
2686ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) 2668ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index)
2687{ 2669{
@@ -3383,6 +3365,11 @@ const transop_fp_t arm_instruction_trans[] = {
3383 INTERPRETER_TRANSLATE(ldc), 3365 INTERPRETER_TRANSLATE(ldc),
3384 INTERPRETER_TRANSLATE(swi), 3366 INTERPRETER_TRANSLATE(swi),
3385 INTERPRETER_TRANSLATE(bbl), 3367 INTERPRETER_TRANSLATE(bbl),
3368 INTERPRETER_TRANSLATE(ldrexd),
3369 INTERPRETER_TRANSLATE(strexd),
3370 INTERPRETER_TRANSLATE(ldrexh),
3371 INTERPRETER_TRANSLATE(strexh),
3372
3386 // All the thumb instructions should be placed the end of table 3373 // All the thumb instructions should be placed the end of table
3387 INTERPRETER_TRANSLATE(b_2_thumb), 3374 INTERPRETER_TRANSLATE(b_2_thumb),
3388 INTERPRETER_TRANSLATE(b_cond_thumb), 3375 INTERPRETER_TRANSLATE(b_cond_thumb),
@@ -3579,6 +3566,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
3579 #define CRm inst_cream->crm 3566 #define CRm inst_cream->crm
3580 #define CP15_REG(n) cpu->CP15[CP15(n)] 3567 #define CP15_REG(n) cpu->CP15[CP15(n)]
3581 #define RD cpu->Reg[inst_cream->Rd] 3568 #define RD cpu->Reg[inst_cream->Rd]
3569 #define RD2 cpu->Reg[inst_cream->Rd + 1]
3582 #define RN cpu->Reg[inst_cream->Rn] 3570 #define RN cpu->Reg[inst_cream->Rn]
3583 #define RM cpu->Reg[inst_cream->Rm] 3571 #define RM cpu->Reg[inst_cream->Rm]
3584 #define RS cpu->Reg[inst_cream->Rs] 3572 #define RS cpu->Reg[inst_cream->Rs]
@@ -3790,14 +3778,18 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
3790 case 182: goto LDC_INST; \ 3778 case 182: goto LDC_INST; \
3791 case 183: goto SWI_INST; \ 3779 case 183: goto SWI_INST; \
3792 case 184: goto BBL_INST; \ 3780 case 184: goto BBL_INST; \
3793 case 185: goto B_2_THUMB ; \ 3781 case 185: goto LDREXD_INST; \
3794 case 186: goto B_COND_THUMB ; \ 3782 case 186: goto STREXD_INST; \
3795 case 187: goto BL_1_THUMB ; \ 3783 case 187: goto LDREXH_INST; \
3796 case 188: goto BL_2_THUMB ; \ 3784 case 188: goto STREXH_INST; \
3797 case 189: goto BLX_1_THUMB ; \ 3785 case 189: goto B_2_THUMB ; \
3798 case 190: goto DISPATCH; \ 3786 case 190: goto B_COND_THUMB ; \
3799 case 191: goto INIT_INST_LENGTH; \ 3787 case 191: goto BL_1_THUMB ; \
3800 case 192: goto END; \ 3788 case 192: goto BL_2_THUMB ; \
3789 case 193: goto BLX_1_THUMB ; \
3790 case 194: goto DISPATCH; \
3791 case 195: goto INIT_INST_LENGTH; \
3792 case 196: goto END; \
3801 } 3793 }
3802#endif 3794#endif
3803 3795
@@ -3858,8 +3850,9 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
3858 &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST, 3850 &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST,
3859 &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST, 3851 &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST,
3860 &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST,&&MSR_INST, 3852 &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST,&&MSR_INST,
3861 &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST,&&SWI_INST,&&BBL_INST,&&B_2_THUMB, &&B_COND_THUMB, 3853 &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST,&&SWI_INST,&&BBL_INST,&&LDREXD_INST,
3862 &&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH,&&INIT_INST_LENGTH,&&END 3854 &&STREXD_INST,&&LDREXH_INST,&&STREXH_INST,&&B_2_THUMB, &&B_COND_THUMB,&&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH,
3855 &&INIT_INST_LENGTH,&&END
3863 }; 3856 };
3864#endif 3857#endif
3865 arm_inst * inst_base; 3858 arm_inst * inst_base;
@@ -4460,45 +4453,84 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4460 4453
4461 LDREX_INST: 4454 LDREX_INST:
4462 { 4455 {
4463 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4456 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4464 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4457 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4465 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 4458 unsigned int read_addr = RN;
4466 4459
4467 unsigned int value = Memory::Read32(addr); 4460 add_exclusive_addr(cpu, read_addr);
4468
4469 add_exclusive_addr(cpu, addr);
4470 cpu->exclusive_state = 1; 4461 cpu->exclusive_state = 1;
4471 4462
4472 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4463 RD = Memory::Read32(read_addr);
4473 if (BITS(inst_cream->inst, 12, 15) == 15) { 4464 if (inst_cream->Rd == 15) {
4474 INC_PC(sizeof(ldst_inst)); 4465 INC_PC(sizeof(generic_arm_inst));
4475 goto DISPATCH; 4466 goto DISPATCH;
4476 } 4467 }
4477 } 4468 }
4478 cpu->Reg[15] += GET_INST_SIZE(cpu); 4469 cpu->Reg[15] += GET_INST_SIZE(cpu);
4479 INC_PC(sizeof(ldst_inst)); 4470 INC_PC(sizeof(generic_arm_inst));
4480 FETCH_INST; 4471 FETCH_INST;
4481 GOTO_NEXT_INST; 4472 GOTO_NEXT_INST;
4482 } 4473 }
4483 LDREXB_INST: 4474 LDREXB_INST:
4484 { 4475 {
4485 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4476 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4486 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4477 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4487 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 4478 unsigned int read_addr = RN;
4488 4479
4489 unsigned int value = Memory::Read8(addr); 4480 add_exclusive_addr(cpu, read_addr);
4481 cpu->exclusive_state = 1;
4482
4483 RD = Memory::Read8(read_addr);
4484 if (inst_cream->Rd == 15) {
4485 INC_PC(sizeof(generic_arm_inst));
4486 goto DISPATCH;
4487 }
4488 }
4489 cpu->Reg[15] += GET_INST_SIZE(cpu);
4490 INC_PC(sizeof(generic_arm_inst));
4491 FETCH_INST;
4492 GOTO_NEXT_INST;
4493 }
4494 LDREXH_INST:
4495 {
4496 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4497 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4498 unsigned int read_addr = RN;
4490 4499
4491 add_exclusive_addr(cpu, addr); 4500 add_exclusive_addr(cpu, read_addr);
4492 cpu->exclusive_state = 1; 4501 cpu->exclusive_state = 1;
4493 4502
4494 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4503 RD = Memory::Read16(read_addr);
4495 if (BITS(inst_cream->inst, 12, 15) == 15) { 4504 if (inst_cream->Rd == 15) {
4496 INC_PC(sizeof(ldst_inst)); 4505 INC_PC(sizeof(generic_arm_inst));
4497 goto DISPATCH; 4506 goto DISPATCH;
4498 } 4507 }
4499 } 4508 }
4500 cpu->Reg[15] += GET_INST_SIZE(cpu); 4509 cpu->Reg[15] += GET_INST_SIZE(cpu);
4501 INC_PC(sizeof(ldst_inst)); 4510 INC_PC(sizeof(generic_arm_inst));
4511 FETCH_INST;
4512 GOTO_NEXT_INST;
4513 }
4514 LDREXD_INST:
4515 {
4516 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4517 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4518 unsigned int read_addr = RN;
4519
4520 add_exclusive_addr(cpu, read_addr);
4521 cpu->exclusive_state = 1;
4522 // TODO(bunnei): Do we need to also make [read_addr + 4] exclusive?
4523
4524 RD = Memory::Read32(read_addr);
4525 RD2 = Memory::Read32(read_addr + 4);
4526
4527 if (inst_cream->Rd == 15) {
4528 INC_PC(sizeof(generic_arm_inst));
4529 goto DISPATCH;
4530 }
4531 }
4532 cpu->Reg[15] += GET_INST_SIZE(cpu);
4533 INC_PC(sizeof(generic_arm_inst));
4502 FETCH_INST; 4534 FETCH_INST;
4503 GOTO_NEXT_INST; 4535 GOTO_NEXT_INST;
4504 } 4536 }
@@ -5823,46 +5855,96 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5823 } 5855 }
5824 STREX_INST: 5856 STREX_INST:
5825 { 5857 {
5826 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5858 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
5859
5827 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5860 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5828 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 5861 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
5829 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)];
5830 5862
5831 int dest_reg = BITS(inst_cream->inst, 12, 15); 5863 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
5832 if((exclusive_detect(cpu, addr) == 0) && (cpu->exclusive_state == 1)){ 5864 remove_exclusive(cpu, write_addr);
5833 remove_exclusive(cpu, addr);
5834 cpu->Reg[dest_reg] = 0;
5835 cpu->exclusive_state = 0; 5865 cpu->exclusive_state = 0;
5836 5866
5837 Memory::Write32(addr, value); 5867 Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]);
5868 RD = 0;
5838 } else { 5869 } else {
5839 // Failed to write due to mutex access 5870 // Failed to write due to mutex access
5840 cpu->Reg[dest_reg] = 1; 5871 RD = 1;
5841 } 5872 }
5842 } 5873 }
5843 cpu->Reg[15] += GET_INST_SIZE(cpu); 5874 cpu->Reg[15] += GET_INST_SIZE(cpu);
5844 INC_PC(sizeof(ldst_inst)); 5875 INC_PC(sizeof(generic_arm_inst));
5845 FETCH_INST; 5876 FETCH_INST;
5846 GOTO_NEXT_INST; 5877 GOTO_NEXT_INST;
5847 } 5878 }
5848 STREXB_INST: 5879 STREXB_INST:
5849 { 5880 {
5850 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5881 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
5882
5851 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5883 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5852 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 5884 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
5853 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)] & 0xff; 5885
5854 int dest_reg = BITS(inst_cream->inst, 12, 15); 5886 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
5855 if((exclusive_detect(cpu, addr) == 0) && (cpu->exclusive_state == 1)){ 5887 remove_exclusive(cpu, write_addr);
5856 remove_exclusive(cpu, addr);
5857 cpu->Reg[dest_reg] = 0;
5858 cpu->exclusive_state = 0; 5888 cpu->exclusive_state = 0;
5859 Memory::Write8(addr, value); 5889
5890 Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]);
5891 RD = 0;
5860 } else { 5892 } else {
5861 cpu->Reg[dest_reg] = 1; 5893 // Failed to write due to mutex access
5894 RD = 1;
5862 } 5895 }
5863 } 5896 }
5864 cpu->Reg[15] += GET_INST_SIZE(cpu); 5897 cpu->Reg[15] += GET_INST_SIZE(cpu);
5865 INC_PC(sizeof(ldst_inst)); 5898 INC_PC(sizeof(generic_arm_inst));
5899 FETCH_INST;
5900 GOTO_NEXT_INST;
5901 }
5902 STREXD_INST:
5903 {
5904 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
5905
5906 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5907 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
5908
5909 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
5910 remove_exclusive(cpu, write_addr);
5911 cpu->exclusive_state = 0;
5912 // TODO(bunnei): Remove exclusive from [write_addr + 4] if we implement this in LDREXD
5913
5914 Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]);
5915 Memory::Write32(write_addr + 4, cpu->Reg[inst_cream->Rm + 1]);
5916 RD = 0;
5917 }
5918 else {
5919 // Failed to write due to mutex access
5920 RD = 1;
5921 }
5922 }
5923 cpu->Reg[15] += GET_INST_SIZE(cpu);
5924 INC_PC(sizeof(generic_arm_inst));
5925 FETCH_INST;
5926 GOTO_NEXT_INST;
5927 }
5928 STREXH_INST:
5929 {
5930 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
5931
5932 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5933 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
5934
5935 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
5936 remove_exclusive(cpu, write_addr);
5937 cpu->exclusive_state = 0;
5938
5939 Memory::Write16(write_addr, cpu->Reg[inst_cream->Rm]);
5940 RD = 0;
5941 } else {
5942 // Failed to write due to mutex access
5943 RD = 1;
5944 }
5945 }
5946 cpu->Reg[15] += GET_INST_SIZE(cpu);
5947 INC_PC(sizeof(generic_arm_inst));
5866 FETCH_INST; 5948 FETCH_INST;
5867 GOTO_NEXT_INST; 5949 GOTO_NEXT_INST;
5868 } 5950 }
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index f19ca3a9f..9a91bcb8b 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -63,7 +63,7 @@ enum class DirectoryCommand : u32 {
63class Archive { 63class Archive {
64public: 64public:
65 Archive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) 65 Archive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code)
66 : backend(std::move(backend)), id_code(id_code) { 66 : id_code(id_code), backend(std::move(backend)) {
67 } 67 }
68 68
69 std::string GetName() const { return "Archive: " + backend->GetName(); } 69 std::string GetName() const { return "Archive: " + backend->GetName(); }
@@ -75,7 +75,7 @@ public:
75class File : public Kernel::Session { 75class File : public Kernel::Session {
76public: 76public:
77 File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) 77 File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path)
78 : backend(std::move(backend)), path(path) { 78 : path(path), backend(std::move(backend)) {
79 } 79 }
80 80
81 std::string GetName() const override { return "Path: " + path.DebugStr(); } 81 std::string GetName() const override { return "Path: " + path.DebugStr(); }
@@ -160,7 +160,7 @@ public:
160class Directory : public Kernel::Session { 160class Directory : public Kernel::Session {
161public: 161public:
162 Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path) 162 Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path)
163 : backend(std::move(backend)), path(path) { 163 : path(path), backend(std::move(backend)) {
164 } 164 }
165 165
166 std::string GetName() const override { return "Directory: " + path.DebugStr(); } 166 std::string GetName() const override { return "Directory: " + path.DebugStr(); }
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 354335014..3ca60c072 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -222,7 +222,7 @@ public:
222 int GetSectionSize(SectionID section) const { return sections[section].sh_size; } 222 int GetSectionSize(SectionID section) const { return sections[section].sh_size; }
223 SectionID GetSectionByName(const char *name, int firstSection = 0) const; //-1 for not found 223 SectionID GetSectionByName(const char *name, int firstSection = 0) const; //-1 for not found
224 224
225 bool DidRelocate() { 225 bool DidRelocate() const {
226 return relocate; 226 return relocate;
227 } 227 }
228}; 228};