3 changed files with 282 additions and 227 deletions
-
11src/core/arm/dyncom/arm_dyncom_dec.cpp
-
216src/core/arm/dyncom/arm_dyncom_dec.h
-
282src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@ -1,153 +1,117 @@ |
|||||
/* Copyright (C) |
|
||||
* 2012 - Michael.Kang blackfin.kang@gmail.com |
|
||||
* This program is free software; you can redistribute it and/or |
|
||||
* modify it under the terms of the GNU General Public License |
|
||||
* as published by the Free Software Foundation; either version 2 |
|
||||
* of the License, or (at your option) any later version. |
|
||||
* |
|
||||
* This program is distributed in the hope that it will be useful, |
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
* GNU General Public License for more details. |
|
||||
* |
|
||||
* You should have received a copy of the GNU General Public License |
|
||||
* along with this program; if not, write to the Free Software |
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
/** |
|
||||
* @file arm_dyncom_dec.h |
|
||||
* @brief Some common utility for arm instruction decoder |
|
||||
* @author Michael.Kang blackfin.kang@gmail.com |
|
||||
* @version 7849 |
|
||||
* @date 2012-03-15 |
|
||||
*/ |
|
||||
|
|
||||
#ifndef __ARM_DYNCOM_DEC__ |
|
||||
#define __ARM_DYNCOM_DEC__ |
|
||||
|
|
||||
#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1)) |
|
||||
#define BIT(n) ((instr >> (n)) & 1) |
|
||||
#define BAD do{printf("meet BAD at %s, instr is %x\n", __FUNCTION__, instr ); /*exit(0);*/}while(0); |
|
||||
#define ptr_N cpu->ptr_N |
|
||||
#define ptr_Z cpu->ptr_Z |
|
||||
#define ptr_C cpu->ptr_C |
|
||||
#define ptr_V cpu->ptr_V |
|
||||
#define ptr_I cpu->ptr_I |
|
||||
#define ptr_T cpu->ptr_T |
|
||||
#define ptr_CPSR cpu->ptr_gpr[16] |
|
||||
|
|
||||
/* for MUL instructions */ |
|
||||
/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */ |
|
||||
#define RDHi ((instr >> 16) & 0xF) |
|
||||
/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */ |
|
||||
#define RDLo ((instr >> 12) & 0xF) |
|
||||
/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */ |
|
||||
#define MUL_RD ((instr >> 16) & 0xF) |
|
||||
/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */ |
|
||||
#define MUL_RN ((instr >> 12) & 0xF) |
|
||||
/*xxxx xxxx xxxx xxxx xxxx 1111 xxxx xxxx */ |
|
||||
#define RS ((instr >> 8) & 0xF) |
|
||||
|
|
||||
/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */ |
|
||||
#define RD ((instr >> 12) & 0xF) |
|
||||
/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */ |
|
||||
#define RN ((instr >> 16) & 0xF) |
|
||||
/*xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1111 */ |
|
||||
#define RM (instr & 0xF) |
|
||||
|
|
||||
/* CP15 registers */ |
|
||||
#define OPCODE_1 BITS(21, 23) |
|
||||
#define CRn BITS(16, 19) |
|
||||
#define CRm BITS(0, 3) |
|
||||
#define OPCODE_2 BITS(5, 7) |
|
||||
|
|
||||
/*xxxx xx1x xxxx xxxx xxxx xxxx xxxx xxxx */ |
|
||||
#define I BIT(25) |
|
||||
/*xxxx xxxx xxx1 xxxx xxxx xxxx xxxx xxxx */ |
|
||||
#define S BIT(20) |
|
||||
|
|
||||
#define SHIFT BITS(5,6) |
|
||||
#define SHIFT_IMM BITS(7,11) |
|
||||
#define IMMH BITS(8,11) |
|
||||
#define IMML BITS(0,3) |
|
||||
|
|
||||
#define LSPBIT BIT(24) |
|
||||
#define LSUBIT BIT(23) |
|
||||
#define LSBBIT BIT(22) |
|
||||
#define LSWBIT BIT(21) |
|
||||
#define LSLBIT BIT(20) |
|
||||
#define LSSHBITS BITS(5,6) |
|
||||
#define OFFSET12 BITS(0,11) |
|
||||
#define SBIT BIT(20) |
|
||||
#define DESTReg (BITS (12, 15)) |
|
||||
|
|
||||
/* they are in unused state, give a corrent value when using */ |
|
||||
|
// Copyright 2012 Michael Kang, 2015 Citra Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1)) |
||||
|
#define BIT(n) ((instr >> (n)) & 1) |
||||
|
#define BAD do { printf("meet BAD at %s, instr is %x\n", __FUNCTION__, instr ); } while(0); |
||||
|
#define ptr_N cpu->ptr_N |
||||
|
#define ptr_Z cpu->ptr_Z |
||||
|
#define ptr_C cpu->ptr_C |
||||
|
#define ptr_V cpu->ptr_V |
||||
|
#define ptr_I cpu->ptr_I |
||||
|
#define ptr_T cpu->ptr_T |
||||
|
#define ptr_CPSR cpu->ptr_gpr[16] |
||||
|
|
||||
|
// For MUL instructions |
||||
|
#define RDHi ((instr >> 16) & 0xF) |
||||
|
#define RDLo ((instr >> 12) & 0xF) |
||||
|
#define MUL_RD ((instr >> 16) & 0xF) |
||||
|
#define MUL_RN ((instr >> 12) & 0xF) |
||||
|
#define RS ((instr >> 8) & 0xF) |
||||
|
#define RD ((instr >> 12) & 0xF) |
||||
|
#define RN ((instr >> 16) & 0xF) |
||||
|
#define RM (instr & 0xF) |
||||
|
|
||||
|
// CP15 registers |
||||
|
#define OPCODE_1 BITS(21, 23) |
||||
|
#define CRn BITS(16, 19) |
||||
|
#define CRm BITS(0, 3) |
||||
|
#define OPCODE_2 BITS(5, 7) |
||||
|
|
||||
|
#define I BIT(25) |
||||
|
#define S BIT(20) |
||||
|
|
||||
|
#define SHIFT BITS(5,6) |
||||
|
#define SHIFT_IMM BITS(7,11) |
||||
|
#define IMMH BITS(8,11) |
||||
|
#define IMML BITS(0,3) |
||||
|
|
||||
|
#define LSPBIT BIT(24) |
||||
|
#define LSUBIT BIT(23) |
||||
|
#define LSBBIT BIT(22) |
||||
|
#define LSWBIT BIT(21) |
||||
|
#define LSLBIT BIT(20) |
||||
|
#define LSSHBITS BITS(5,6) |
||||
|
#define OFFSET12 BITS(0,11) |
||||
|
#define SBIT BIT(20) |
||||
|
#define DESTReg (BITS (12, 15)) |
||||
|
|
||||
|
// They are in unused state, give a corrent value when using |
||||
#define IS_V5E 0 |
#define IS_V5E 0 |
||||
#define IS_V5 0 |
#define IS_V5 0 |
||||
#define IS_V6 0 |
#define IS_V6 0 |
||||
#define LHSReg 0 |
#define LHSReg 0 |
||||
|
|
||||
/* temp define the using the pc reg need implement a flow */ |
|
||||
#define STORE_CHECK_RD_PC ADD(R(RD), CONST(INSTR_SIZE * 2)) |
|
||||
|
// Temp define the using the pc reg need implement a flow |
||||
|
#define STORE_CHECK_RD_PC ADD(R(RD), CONST(INSTR_SIZE * 2)) |
||||
|
|
||||
#define OPERAND operand(cpu,instr,bb,NULL) |
|
||||
#define SCO_OPERAND(sco) operand(cpu,instr,bb,sco) |
|
||||
#define BOPERAND boperand(instr) |
|
||||
|
#define OPERAND operand(cpu,instr,bb,NULL) |
||||
|
#define SCO_OPERAND(sco) operand(cpu,instr,bb,sco) |
||||
|
#define BOPERAND boperand(instr) |
||||
|
|
||||
#define CHECK_RN_PC (RN==15? ADD(AND(R(RN), CONST(~0x1)), CONST(INSTR_SIZE * 2)):R(RN)) |
|
||||
#define CHECK_RN_PC_WA (RN==15? ADD(AND(R(RN), CONST(~0x3)), CONST(INSTR_SIZE * 2)):R(RN)) |
|
||||
|
#define CHECK_RN_PC (RN == 15 ? ADD(AND(R(RN), CONST(~0x1)), CONST(INSTR_SIZE * 2)) : R(RN)) |
||||
|
#define CHECK_RN_PC_WA (RN == 15 ? ADD(AND(R(RN), CONST(~0x3)), CONST(INSTR_SIZE * 2)) : R(RN)) |
||||
|
|
||||
#define GET_USER_MODE() (OR(ICMP_EQ(R(MODE_REG), CONST(USER32MODE)), ICMP_EQ(R(MODE_REG), CONST(SYSTEM32MODE)))) |
|
||||
|
#define GET_USER_MODE() (OR(ICMP_EQ(R(MODE_REG), CONST(USER32MODE)), ICMP_EQ(R(MODE_REG), CONST(SYSTEM32MODE)))) |
||||
|
|
||||
int decode_arm_instr(uint32_t instr, int32_t *idx); |
int decode_arm_instr(uint32_t instr, int32_t *idx); |
||||
|
|
||||
enum DECODE_STATUS { |
enum DECODE_STATUS { |
||||
DECODE_SUCCESS, |
|
||||
DECODE_FAILURE |
|
||||
|
DECODE_SUCCESS, |
||||
|
DECODE_FAILURE |
||||
}; |
}; |
||||
|
|
||||
struct instruction_set_encoding_item { |
struct instruction_set_encoding_item { |
||||
const char *name; |
|
||||
int attribute_value; |
|
||||
int version; |
|
||||
u32 content[21]; |
|
||||
|
const char *name; |
||||
|
int attribute_value; |
||||
|
int version; |
||||
|
u32 content[21]; |
||||
}; |
}; |
||||
|
|
||||
typedef struct instruction_set_encoding_item ISEITEM; |
typedef struct instruction_set_encoding_item ISEITEM; |
||||
|
|
||||
#define RECORD_WB(value, flag) {cpu->dyncom_engine->wb_value = value;cpu->dyncom_engine->wb_flag = flag;} |
|
||||
|
#define RECORD_WB(value, flag) { cpu->dyncom_engine->wb_value = value;cpu->dyncom_engine->wb_flag = flag; } |
||||
#define INIT_WB(wb_value, wb_flag) RECORD_WB(wb_value, wb_flag) |
#define INIT_WB(wb_value, wb_flag) RECORD_WB(wb_value, wb_flag) |
||||
|
|
||||
#define EXECUTE_WB(base_reg) {if(cpu->dyncom_engine->wb_flag) \ |
|
||||
LET(base_reg, cpu->dyncom_engine->wb_value);} |
|
||||
inline int get_reg_count(uint32_t instr){ |
|
||||
int i = BITS(0,15); |
|
||||
int count = 0; |
|
||||
while(i){ |
|
||||
if(i & 1) |
|
||||
count ++; |
|
||||
i = i >> 1; |
|
||||
} |
|
||||
return count; |
|
||||
|
#define EXECUTE_WB(base_reg) { if(cpu->dyncom_engine->wb_flag) LET(base_reg, cpu->dyncom_engine->wb_value); } |
||||
|
|
||||
|
inline int get_reg_count(uint32_t instr) { |
||||
|
int i = BITS(0, 15); |
||||
|
int count = 0; |
||||
|
while (i) { |
||||
|
if (i & 1) |
||||
|
count++; |
||||
|
i = i >> 1; |
||||
|
} |
||||
|
return count; |
||||
} |
} |
||||
|
|
||||
enum ARMVER { |
enum ARMVER { |
||||
INVALID = 0, |
|
||||
ARMALL, |
|
||||
ARMV4, |
|
||||
ARMV4T, |
|
||||
ARMV5T, |
|
||||
ARMV5TE, |
|
||||
ARMV5TEJ, |
|
||||
ARMV6, |
|
||||
ARM1176JZF_S, |
|
||||
ARMVFP2, |
|
||||
ARMVFP3 |
|
||||
|
INVALID = 0, |
||||
|
ARMALL, |
||||
|
ARMV4, |
||||
|
ARMV4T, |
||||
|
ARMV5T, |
||||
|
ARMV5TE, |
||||
|
ARMV5TEJ, |
||||
|
ARMV6, |
||||
|
ARM1176JZF_S, |
||||
|
ARMVFP2, |
||||
|
ARMVFP3, |
||||
|
ARMV6K, |
||||
}; |
}; |
||||
|
|
||||
//extern const INSTRACT arm_instruction_action[]; |
|
||||
extern const ISEITEM arm_instruction[]; |
extern const ISEITEM arm_instruction[]; |
||||
|
|
||||
#endif |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue