diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_dec.cpp | 11 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_dec.h | 216 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 282 |
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 | ||
| 199 | const ISEITEM arm_exclusion_code[] = { | 202 | const 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 | ||
| 104 | int decode_arm_instr(uint32_t instr, int32_t *idx); | 70 | int decode_arm_instr(uint32_t instr, int32_t *idx); |
| 105 | 71 | ||
| 106 | enum DECODE_STATUS { | 72 | enum DECODE_STATUS { |
| 107 | DECODE_SUCCESS, | 73 | DECODE_SUCCESS, |
| 108 | DECODE_FAILURE | 74 | DECODE_FAILURE |
| 109 | }; | 75 | }; |
| 110 | 76 | ||
| 111 | struct instruction_set_encoding_item { | 77 | struct 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 | ||
| 118 | typedef struct instruction_set_encoding_item ISEITEM; | 84 | typedef 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 | |
| 125 | inline int get_reg_count(uint32_t instr){ | 91 | inline 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 | ||
| 136 | enum ARMVER { | 102 | enum 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[]; | ||
| 151 | extern const ISEITEM arm_instruction[]; | 117 | extern 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 | ||
| 1106 | typedef struct _pkh_inst { | 1104 | typedef 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 | ||
| 1113 | typedef arm_inst * ARM_INST_PTR; | 1111 | typedef 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 | |||
| 1744 | ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) | 1741 | ARM_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 | } |
| 1761 | ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) | 1755 | ARM_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 | 1759 | ARM_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 | 1763 | ARM_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 | } |
| 1778 | ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) | 1767 | ARM_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 | } |
| 2624 | ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) | 2613 | ARM_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 | } |
| 2641 | ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) | 2628 | ARM_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 | 2632 | ARM_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 | 2636 | ARM_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 | } |
| 2658 | ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) | 2640 | ARM_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 | } |