summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
3 files changed, 282 insertions, 227 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 bc55a082f..5f09d8580 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{
@@ -2623,37 +2612,30 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){
2623} 2612}
2624ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) 2613ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index)
2625{ 2614{
2626 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2615 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
2627 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2616 generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component;
2628 2617
2629 inst_base->cond = BITS(inst, 28, 31); 2618 inst_base->cond = BITS(inst, 28, 31);
2630 inst_base->idx = index; 2619 inst_base->idx = index;
2631 inst_base->br = NON_BRANCH; 2620 inst_base->br = NON_BRANCH;
2632 2621
2633 inst_cream->inst = inst; 2622 inst_cream->Rn = BITS(inst, 16, 19);
2634 inst_cream->get_addr = get_calc_addr_op(inst); 2623 inst_cream->Rd = BITS(inst, 12, 15);
2624 inst_cream->Rm = BITS(inst, 0, 3);
2635 2625
2636 if (BITS(inst, 12, 15) == 15) {
2637 inst_base->br = INDIRECT_BRANCH;
2638 }
2639 return inst_base; 2626 return inst_base;
2640} 2627}
2641ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) 2628ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index)
2642{ 2629{
2643 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2630 return INTERPRETER_TRANSLATE(strex)(inst, index);
2644 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2631}
2645 2632ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index)
2646 inst_base->cond = BITS(inst, 28, 31); 2633{
2647 inst_base->idx = index; 2634 return INTERPRETER_TRANSLATE(strex)(inst, index);
2648 inst_base->br = NON_BRANCH; 2635}
2649 2636ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index)
2650 inst_cream->inst = inst; 2637{
2651 inst_cream->get_addr = get_calc_addr_op(inst); 2638 return INTERPRETER_TRANSLATE(strex)(inst, index);
2652
2653 if (BITS(inst, 12, 15) == 15) {
2654 inst_base->br = INDIRECT_BRANCH;
2655 }
2656 return inst_base;
2657} 2639}
2658ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) 2640ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index)
2659{ 2641{
@@ -3355,6 +3337,11 @@ const transop_fp_t arm_instruction_trans[] = {
3355 INTERPRETER_TRANSLATE(ldc), 3337 INTERPRETER_TRANSLATE(ldc),
3356 INTERPRETER_TRANSLATE(swi), 3338 INTERPRETER_TRANSLATE(swi),
3357 INTERPRETER_TRANSLATE(bbl), 3339 INTERPRETER_TRANSLATE(bbl),
3340 INTERPRETER_TRANSLATE(ldrexd),
3341 INTERPRETER_TRANSLATE(strexd),
3342 INTERPRETER_TRANSLATE(ldrexh),
3343 INTERPRETER_TRANSLATE(strexh),
3344
3358 // All the thumb instructions should be placed the end of table 3345 // All the thumb instructions should be placed the end of table
3359 INTERPRETER_TRANSLATE(b_2_thumb), 3346 INTERPRETER_TRANSLATE(b_2_thumb),
3360 INTERPRETER_TRANSLATE(b_cond_thumb), 3347 INTERPRETER_TRANSLATE(b_cond_thumb),
@@ -3551,6 +3538,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
3551 #define CRm inst_cream->crm 3538 #define CRm inst_cream->crm
3552 #define CP15_REG(n) cpu->CP15[CP15(n)] 3539 #define CP15_REG(n) cpu->CP15[CP15(n)]
3553 #define RD cpu->Reg[inst_cream->Rd] 3540 #define RD cpu->Reg[inst_cream->Rd]
3541 #define RD2 cpu->Reg[inst_cream->Rd + 1]
3554 #define RN cpu->Reg[inst_cream->Rn] 3542 #define RN cpu->Reg[inst_cream->Rn]
3555 #define RM cpu->Reg[inst_cream->Rm] 3543 #define RM cpu->Reg[inst_cream->Rm]
3556 #define RS cpu->Reg[inst_cream->Rs] 3544 #define RS cpu->Reg[inst_cream->Rs]
@@ -3762,14 +3750,18 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
3762 case 182: goto LDC_INST; \ 3750 case 182: goto LDC_INST; \
3763 case 183: goto SWI_INST; \ 3751 case 183: goto SWI_INST; \
3764 case 184: goto BBL_INST; \ 3752 case 184: goto BBL_INST; \
3765 case 185: goto B_2_THUMB ; \ 3753 case 185: goto LDREXD_INST; \
3766 case 186: goto B_COND_THUMB ; \ 3754 case 186: goto STREXD_INST; \
3767 case 187: goto BL_1_THUMB ; \ 3755 case 187: goto LDREXH_INST; \
3768 case 188: goto BL_2_THUMB ; \ 3756 case 188: goto STREXH_INST; \
3769 case 189: goto BLX_1_THUMB ; \ 3757 case 189: goto B_2_THUMB ; \
3770 case 190: goto DISPATCH; \ 3758 case 190: goto B_COND_THUMB ; \
3771 case 191: goto INIT_INST_LENGTH; \ 3759 case 191: goto BL_1_THUMB ; \
3772 case 192: goto END; \ 3760 case 192: goto BL_2_THUMB ; \
3761 case 193: goto BLX_1_THUMB ; \
3762 case 194: goto DISPATCH; \
3763 case 195: goto INIT_INST_LENGTH; \
3764 case 196: goto END; \
3773 } 3765 }
3774#endif 3766#endif
3775 3767
@@ -3830,8 +3822,9 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
3830 &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST, 3822 &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST,
3831 &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST, 3823 &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST,
3832 &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST,&&MSR_INST, 3824 &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST,&&MSR_INST,
3833 &&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, 3825 &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST,&&SWI_INST,&&BBL_INST,&&LDREXD_INST,
3834 &&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH,&&INIT_INST_LENGTH,&&END 3826 &&STREXD_INST,&&LDREXH_INST,&&STREXH_INST,&&B_2_THUMB, &&B_COND_THUMB,&&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH,
3827 &&INIT_INST_LENGTH,&&END
3835 }; 3828 };
3836#endif 3829#endif
3837 arm_inst * inst_base; 3830 arm_inst * inst_base;
@@ -4432,45 +4425,84 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4432 4425
4433 LDREX_INST: 4426 LDREX_INST:
4434 { 4427 {
4435 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4428 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4436 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4429 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4437 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 4430 unsigned int read_addr = RN;
4438 4431
4439 unsigned int value = Memory::Read32(addr); 4432 add_exclusive_addr(cpu, read_addr);
4440
4441 add_exclusive_addr(cpu, addr);
4442 cpu->exclusive_state = 1; 4433 cpu->exclusive_state = 1;
4443 4434
4444 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4435 RD = Memory::Read32(read_addr);
4445 if (BITS(inst_cream->inst, 12, 15) == 15) { 4436 if (inst_cream->Rd == 15) {
4446 INC_PC(sizeof(ldst_inst)); 4437 INC_PC(sizeof(generic_arm_inst));
4447 goto DISPATCH; 4438 goto DISPATCH;
4448 } 4439 }
4449 } 4440 }
4450 cpu->Reg[15] += GET_INST_SIZE(cpu); 4441 cpu->Reg[15] += GET_INST_SIZE(cpu);
4451 INC_PC(sizeof(ldst_inst)); 4442 INC_PC(sizeof(generic_arm_inst));
4452 FETCH_INST; 4443 FETCH_INST;
4453 GOTO_NEXT_INST; 4444 GOTO_NEXT_INST;
4454 } 4445 }
4455 LDREXB_INST: 4446 LDREXB_INST:
4456 { 4447 {
4457 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4448 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4458 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4449 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4459 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 4450 unsigned int read_addr = RN;
4460 4451
4461 unsigned int value = Memory::Read8(addr); 4452 add_exclusive_addr(cpu, read_addr);
4453 cpu->exclusive_state = 1;
4454
4455 RD = Memory::Read8(read_addr);
4456 if (inst_cream->Rd == 15) {
4457 INC_PC(sizeof(generic_arm_inst));
4458 goto DISPATCH;
4459 }
4460 }
4461 cpu->Reg[15] += GET_INST_SIZE(cpu);
4462 INC_PC(sizeof(generic_arm_inst));
4463 FETCH_INST;
4464 GOTO_NEXT_INST;
4465 }
4466 LDREXH_INST:
4467 {
4468 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4469 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4470 unsigned int read_addr = RN;
4462 4471
4463 add_exclusive_addr(cpu, addr); 4472 add_exclusive_addr(cpu, read_addr);
4464 cpu->exclusive_state = 1; 4473 cpu->exclusive_state = 1;
4465 4474
4466 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4475 RD = Memory::Read16(read_addr);
4467 if (BITS(inst_cream->inst, 12, 15) == 15) { 4476 if (inst_cream->Rd == 15) {
4468 INC_PC(sizeof(ldst_inst)); 4477 INC_PC(sizeof(generic_arm_inst));
4469 goto DISPATCH; 4478 goto DISPATCH;
4470 } 4479 }
4471 } 4480 }
4472 cpu->Reg[15] += GET_INST_SIZE(cpu); 4481 cpu->Reg[15] += GET_INST_SIZE(cpu);
4473 INC_PC(sizeof(ldst_inst)); 4482 INC_PC(sizeof(generic_arm_inst));
4483 FETCH_INST;
4484 GOTO_NEXT_INST;
4485 }
4486 LDREXD_INST:
4487 {
4488 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4489 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4490 unsigned int read_addr = RN;
4491
4492 add_exclusive_addr(cpu, read_addr);
4493 cpu->exclusive_state = 1;
4494 // TODO(bunnei): Do we need to also make [read_addr + 4] exclusive?
4495
4496 RD = Memory::Read32(read_addr);
4497 RD2 = Memory::Read32(read_addr + 4);
4498
4499 if (inst_cream->Rd == 15) {
4500 INC_PC(sizeof(generic_arm_inst));
4501 goto DISPATCH;
4502 }
4503 }
4504 cpu->Reg[15] += GET_INST_SIZE(cpu);
4505 INC_PC(sizeof(generic_arm_inst));
4474 FETCH_INST; 4506 FETCH_INST;
4475 GOTO_NEXT_INST; 4507 GOTO_NEXT_INST;
4476 } 4508 }
@@ -5762,46 +5794,96 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5762 } 5794 }
5763 STREX_INST: 5795 STREX_INST:
5764 { 5796 {
5765 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5797 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
5798
5766 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5799 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5767 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 5800 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
5768 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)];
5769 5801
5770 int dest_reg = BITS(inst_cream->inst, 12, 15); 5802 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
5771 if((exclusive_detect(cpu, addr) == 0) && (cpu->exclusive_state == 1)){ 5803 remove_exclusive(cpu, write_addr);
5772 remove_exclusive(cpu, addr);
5773 cpu->Reg[dest_reg] = 0;
5774 cpu->exclusive_state = 0; 5804 cpu->exclusive_state = 0;
5775 5805
5776 Memory::Write32(addr, value); 5806 Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]);
5807 RD = 0;
5777 } else { 5808 } else {
5778 // Failed to write due to mutex access 5809 // Failed to write due to mutex access
5779 cpu->Reg[dest_reg] = 1; 5810 RD = 1;
5780 } 5811 }
5781 } 5812 }
5782 cpu->Reg[15] += GET_INST_SIZE(cpu); 5813 cpu->Reg[15] += GET_INST_SIZE(cpu);
5783 INC_PC(sizeof(ldst_inst)); 5814 INC_PC(sizeof(generic_arm_inst));
5784 FETCH_INST; 5815 FETCH_INST;
5785 GOTO_NEXT_INST; 5816 GOTO_NEXT_INST;
5786 } 5817 }
5787 STREXB_INST: 5818 STREXB_INST:
5788 { 5819 {
5789 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5820 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
5821
5790 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5822 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5791 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 5823 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
5792 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)] & 0xff; 5824
5793 int dest_reg = BITS(inst_cream->inst, 12, 15); 5825 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
5794 if((exclusive_detect(cpu, addr) == 0) && (cpu->exclusive_state == 1)){ 5826 remove_exclusive(cpu, write_addr);
5795 remove_exclusive(cpu, addr);
5796 cpu->Reg[dest_reg] = 0;
5797 cpu->exclusive_state = 0; 5827 cpu->exclusive_state = 0;
5798 Memory::Write8(addr, value); 5828
5829 Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]);
5830 RD = 0;
5799 } else { 5831 } else {
5800 cpu->Reg[dest_reg] = 1; 5832 // Failed to write due to mutex access
5833 RD = 1;
5801 } 5834 }
5802 } 5835 }
5803 cpu->Reg[15] += GET_INST_SIZE(cpu); 5836 cpu->Reg[15] += GET_INST_SIZE(cpu);
5804 INC_PC(sizeof(ldst_inst)); 5837 INC_PC(sizeof(generic_arm_inst));
5838 FETCH_INST;
5839 GOTO_NEXT_INST;
5840 }
5841 STREXD_INST:
5842 {
5843 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
5844
5845 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5846 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
5847
5848 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
5849 remove_exclusive(cpu, write_addr);
5850 cpu->exclusive_state = 0;
5851 // TODO(bunnei): Remove exclusive from [write_addr + 4] if we implement this in LDREXD
5852
5853 Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]);
5854 Memory::Write32(write_addr + 4, cpu->Reg[inst_cream->Rm + 1]);
5855 RD = 0;
5856 }
5857 else {
5858 // Failed to write due to mutex access
5859 RD = 1;
5860 }
5861 }
5862 cpu->Reg[15] += GET_INST_SIZE(cpu);
5863 INC_PC(sizeof(generic_arm_inst));
5864 FETCH_INST;
5865 GOTO_NEXT_INST;
5866 }
5867 STREXH_INST:
5868 {
5869 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
5870
5871 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5872 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
5873
5874 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) {
5875 remove_exclusive(cpu, write_addr);
5876 cpu->exclusive_state = 0;
5877
5878 Memory::Write16(write_addr, cpu->Reg[inst_cream->Rm]);
5879 RD = 0;
5880 } else {
5881 // Failed to write due to mutex access
5882 RD = 1;
5883 }
5884 }
5885 cpu->Reg[15] += GET_INST_SIZE(cpu);
5886 INC_PC(sizeof(generic_arm_inst));
5805 FETCH_INST; 5887 FETCH_INST;
5806 GOTO_NEXT_INST; 5888 GOTO_NEXT_INST;
5807 } 5889 }