📄 arm2x86_other.c
字号:
#include "armdefs.h"
#include "arm2x86_self.h"
uint8_t *
get_op_addq_T0_T1_eax_T2(int *len)
{
unsigned int begin=0,end=0;
OP_BEGIN("get_op_addq_T0_T1_eax_T2");
__asm__ __volatile__ ("addl %eax, %"AREG_T0);
__asm__ __volatile__ ("adcl %"AREG_T2", %"AREG_T1);
OP_END("get_op_addq_T0_T1_eax_T2");
*len = end - begin;
return((uint8_t *)begin);
}
uint8_t *
get_op_b_offset(int *len)
{
unsigned int begin=0,end=0;
OP_BEGIN("get_op_b_offset");
st->Reg[15] += INT32_MAX;
OP_END("get_op_b_offset");
*len = end - begin;
if (*len <= sizeof(INT32_MAX)) {
return(NULL);
}
else {
*len -= sizeof(ULONG_MAX);
}
return((uint8_t *)begin);
}
uint8_t *
get_op_bl_offset(int *len)
{
unsigned int begin=0,end=0;
OP_BEGIN("get_op_bl_offset");
//st->Reg[14] = st->Reg[15] + 4;
st->Reg[14] = st->Reg[15];
wmb();
st->Reg[15] += INT32_MAX;
OP_END("get_op_bl_offset");
*len = end - begin;
if (*len <= sizeof(INT32_MAX)) {
return(NULL);
}
else {
*len -= sizeof(ULONG_MAX);
}
return((uint8_t *)begin);
}
//teawater add check thumb 2005.07.21-------------------------------------------
uint8_t *
get_op_bx_T1(int *len)
{
unsigned int begin=0,end=0;
OP_BEGIN("get_op_bx_T1");
if (T1 & 1) {
//thumb XXX
st->TFlag = 1;
st->Reg[15] = (T1 & 0xfffffffe) + 2;
st->trap = TRAP_UNPREDICTABLE;
}
else {
//arm
st->TFlag = 0;
st->Reg[15] = (T1 & 0xfffffffc) + 4;
}
OP_END("get_op_bx_T1");
*len = end - begin;
return((uint8_t *)begin);
}
uint8_t *
get_op_blx_T1(int *len)
{
unsigned int begin=0,end=0;
OP_BEGIN("get_op_blx_T1");
if (T1 & 1) {
//thumb XXX
st->TFlag = 1;
st->Reg[14] = st->Reg[15];
st->Reg[15] = (T1 & 0xfffffffe) + 2;
st->trap = TRAP_UNPREDICTABLE;
}
else {
//arm
st->TFlag = 0;
st->Reg[14] = st->Reg[15];
st->Reg[15] = (T1 & 0xfffffffc) + 4;
}
OP_END("get_op_blx_T1");
*len = end - begin;
return((uint8_t *)begin);
}
//AJ2D--------------------------------------------------------------------------
op_table_t op_addq_T0_T1_eax_T2;
op_table_t op_b_offset;
op_table_t op_bl_offset;
//teawater add check thumb 2005.07.21-------------------------------------------
op_table_t op_bx_T1;
op_table_t op_blx_T1;
//AJ2D--------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
void
arm2x86_get_op_mul(ARMul_State *state, ARMword insn, uint8_t **tbpp, int *plen)
{
ARMword rd, rn, rs, rm;
rd = (insn >> 16) & 0xf;
rn = (insn >> 12) & 0xf;
rs = (insn >> 8) & 0xf;
rm = (insn) & 0xf;
if (!(insn & (1 << 23))) {
//32 bit
//mul
gen_op_movl_Tx_reg(state, tbpp, plen, 0, rs);
gen_op_movl_Tx_reg(state, tbpp, plen, 1, rm);
GEN_OP(*tbpp, *plen, op_mul_T0_T1);
if (insn & (1 << 21)) {
//mla
gen_op_movl_Tx_reg(state, tbpp, plen, 1, rn);
GEN_OP(*tbpp, *plen, op_addl_T0_T1);
}
if (insn & (1 << 20)) {
//set cpsr nf
GEN_OP(*tbpp, *plen, op_logic_T0_sn);
GEN_OP(*tbpp, *plen, op_set_nf);
//set cpsr zf
GEN_OP(*tbpp, *plen, op_logic_T0_sz);
GEN_OP(*tbpp, *plen, op_set_zf);
}
gen_op_movl_reg_Tx(state, tbpp, plen, rd, 0);
if (rd == 15) {
state->trap = 1;
}
}
else {
//64 bit
gen_op_movl_Tx_reg(state, tbpp, plen, 0, rs);
gen_op_movl_Tx_reg(state, tbpp, plen, 1, rm);
if (insn & (1 << 22)) {
//smull
GEN_OP(*tbpp, *plen, op_smull_T0_T1);
}
else {
//umull
GEN_OP(*tbpp, *plen, op_umull_T0_T1);
}
if (insn & (1 << 21)) {
//smlal if smull
//umlal if umull
gen_op_movl_Tx_reg(state, tbpp, plen, 2, rn);
GEN_OP(*tbpp, *plen, op_movl_eax_T2);
gen_op_movl_Tx_reg(state, tbpp, plen, 2, rd);
GEN_OP(*tbpp, *plen, op_addq_T0_T1_eax_T2);
}
if (insn & (1 << 20)) {
//set cpsr nf
GEN_OP(*tbpp, *plen, op_logic_T0_sn);
GEN_OP(*tbpp, *plen, op_set_nf);
//set cpsr zf
GEN_OP(*tbpp, *plen, op_logic_T0_sz);
GEN_OP(*tbpp, *plen, op_set_zf);
}
gen_op_movl_reg_Tx(state, tbpp, plen, rn, 0);
gen_op_movl_reg_Tx(state, tbpp, plen, rd, 1);
if (rn == 15 || rd == 15) {
state->trap = 1;
}
}
}
void
arm2x86_get_op_swp(ARMul_State *state, ARMword insn, uint8_t **tbpp, int *plen)
{
ARMword rd, rn, rm;
rn = (insn >> 16) & 0xf;
rd = (insn >> 12) & 0xf;
rm = (insn) & 0xf;
gen_op_movl_Tx_reg(state, tbpp, plen, 0, rm);
gen_op_movl_Tx_reg(state, tbpp, plen, 1, rn);
if (insn & (1 << 22)) {
//swpb
//ldrb T2 from T1
GEN_OP(*tbpp, *plen, op_ldrb_T2_T1);
//strb T0 to T1
GEN_OP(*tbpp, *plen, op_strb_T0_T1);
}
else {
//swp
//ldr T2 from T1
GEN_OP(*tbpp, *plen, op_ldr_T2_T1);
//str T0 to T1
GEN_OP(*tbpp, *plen, op_str_T0_T1);
}
gen_op_movl_reg_Tx(state, tbpp, plen, rd, 2);
}
void
arm2x86_get_op_insn_undef(ARMul_State *state, ARMword insn, uint8_t **tbpp, int *plen)
{
gen_op_movl_trap_im_use_T2(state, tbpp, plen, TRAP_INSN_UNDEF);
state->trap = 1;
}
void
arm2x86_get_op_ldrstr(ARMul_State *state, ARMword insn, uint8_t **tbpp, int *plen)
{
ARMword rn = (insn >> 16) & 0xf;
ARMword rd = (insn >> 12) & 0xf;
gen_op_movl_Tx_reg(state, tbpp, plen, 1, rn);
if (insn & (1 << 24)) { //P
gen_op_add_data_offset(state, tbpp, plen, insn);
}
if (insn & (1 << 20)) { //L
if (insn & (1 << 22)) { //B
//ldrb
GEN_OP(*tbpp, *plen, op_ldrb_T0_T1);
}
else {
//ldr
GEN_OP(*tbpp, *plen, op_ldr_T0_T1);
}
//if (!state->is_XScale) {
if (state->abort_model > 1) {
gen_op_test_dataabort_im(state, tbpp, plen, op_movl_reg_Tx[0][rd].len);
}
gen_op_movl_reg_Tx(state, tbpp, plen, rd, 0);
}
else {
gen_op_movl_Tx_reg(state, tbpp, plen, 0, rd);
if (insn & (1 << 22)) { //B
//strb
GEN_OP(*tbpp, *plen, op_strb_T0_T1);
}
else {
//str
GEN_OP(*tbpp, *plen, op_str_T0_T1);
}
}
if (!(insn & (1 << 24))) { //!P
gen_op_add_data_offset(state, tbpp, plen, insn);
gen_op_movl_reg_Tx(state, tbpp, plen, rn, 1);
}
else if (insn & (1 << 21)) { //P & W
gen_op_movl_reg_Tx(state, tbpp, plen, rn, 1);
}
//if (!state->is_XScale) {
if (state->abort_model > 1) {
GEN_OP(*tbpp, *plen, op_test_dataabort_ret);
}
}
void
arm2x86_get_op_ldmstm(ARMul_State *state, ARMword insn, uint8_t **tbpp, int *plen)
{
int i, n;
ARMword rn = (insn >> 16) & 0xf;
if (rn == 15) {
gen_op_movl_trap_im_use_T2(state, tbpp, plen, TRAP_UNPREDICTABLE);
state->trap = 1;
return;
}
if (insn & (1 << 22)) { //S ("^")
if (!(insn & (1 << 15)) && (insn & (1 << 21))) {
gen_op_movl_trap_im_use_T2(state, tbpp, plen, TRAP_UNPREDICTABLE);
state->trap = 1;
return;
}
GEN_OP(*tbpp, *plen, op_test_cpsr_ret_UNP);
}
gen_op_movl_Tx_reg(state, tbpp, plen, 1, rn);
n = 0;
for(i=0;i<16;i++) {
if (insn & (1 << i)) {
if (i == 15 && (insn & (1 << 20))) {
//have pc & L
state->trap = 1;
if (insn & (1 << 22)) {
//S
gen_op_movl_trap_im_use_T2(state, tbpp, plen, TRAP_SETS_R15);
}
}
n++;
}
}
if (n == 0) {
//compute total size ("If bits[15:0] are all zero, the result is UNPREDICTABLE" arm_arm)
gen_op_movl_trap_im_use_T2(state, tbpp, plen, TRAP_UNPREDICTABLE);
state->trap = 1;
return;
}
if (insn & (1 << 23)) { //U
//i increment
if (insn & (1 << 24)) { //P
//b before
gen_op_addl_T1_im(state, tbpp, plen, 4);
}
else {
//a after
}
}
else {
//d decrement
if (insn & (1 << 24)) { //P
//b before
gen_op_addl_T1_im(state, tbpp, plen, (-(n * 4)));
}
else {
//a after
if (n != 1) {
gen_op_addl_T1_im(state, tbpp, plen, (-((n - 1) * 4)));
}
}
}
gen_op_movl_Tx_im(state, tbpp, plen, 0, insn & 0xffff);
if (insn & (1 << 20)) { //L
//ldm
if (insn & (1 << 22) && !state->trap) { //S ("^") & don't have pc
GEN_OP(*tbpp, *plen, op_ldm_user_T1_T0);
}
else {
GEN_OP(*tbpp, *plen, op_ldm_T1_T0);
}
}
else {
//stm
if (insn & (1 << 22)) { //S ("^")
GEN_OP(*tbpp, *plen, op_stm_user_T1_T0);
}
else {
GEN_OP(*tbpp, *plen, op_stm_T1_T0);
}
}
if (insn & (1 << 21)) { //W
//write back
//if (!state->is_XScale) {
if (state->abort_model > 1) {
gen_op_test_dataabort_im(state, tbpp, plen, op_addl_T1_im.len + sizeof(ARMword) + op_movl_reg_Tx[0][rn].len);
}
if (insn & (1 << 23)) { //U
//i increment
if (insn & (1 << 24)) { //P
//b before
}
else {
//a after
gen_op_addl_T1_im(state, tbpp, plen, 4);
}
}
else {
//d decrement
if (insn & (1 << 24)) { //P
//b before
if (n != 1) {
gen_op_addl_T1_im(state, tbpp, plen, (-((n - 1) * 4)));
}
}
else {
//a after
gen_op_addl_T1_im(state, tbpp, plen, (-(n * 4)));
}
}
gen_op_movl_reg_Tx(state, tbpp, plen, rn, 1);
}
//if (!state->is_XScale) {
if (state->abort_model > 1) {
GEN_OP(*tbpp, *plen, op_test_dataabort_ret);
}
}
void
arm2x86_get_op_bbl(ARMul_State *state, ARMword insn, uint8_t **tbpp, int *plen)
{
int offset = ((((int)insn << 8) >> 8) << 2) + 4;
if (insn & (1 << 24)) {
//bl
gen_op_bl_offset(state, tbpp, plen, (ARMword)offset);
}
else {
//b
gen_op_b_offset(state, tbpp, plen, (ARMword)offset);
}
}
void
arm2x86_get_op_ldcstc(ARMul_State *state, ARMword insn, uint8_t **tbpp, int *plen)
{
ARMword rn = (insn >> 16) & 0xf;
//ARMword crd = (insn >> 12) & 0xf;
//ARMword cp = (insn >> 8) & 0xf;
//XXX teawater:howto deal with N
gen_op_movl_Tx_reg(state, tbpp, plen, 1, rn);
if (insn & (1 << 24)) //P
gen_op_add_imm_offset(state, tbpp, plen, insn);
gen_op_movl_Tx_im(state, tbpp, plen, 0, insn);
if (insn & (1 << 20)) { //L
//ldc
GEN_OP(*tbpp, *plen, op_ldc_T0_T1);
}
else {
//stc
GEN_OP(*tbpp, *plen, op_stc_T0_T1);
}
if (!(insn & (1 << 24))) { //!P
gen_op_add_imm_offset(state, tbpp, plen, insn);
gen_op_movl_reg_Tx(state, tbpp, plen, rn, 1);
}
else if (insn & (1 << 21)) { //P & W
gen_op_movl_reg_Tx(state, tbpp, plen, rn, 1);
}
}
void
arm2x86_get_op_cdp_mrcmcr(ARMul_State *state, ARMword insn, uint8_t **tbpp, int *plen)
{
gen_op_movl_Tx_im(state, tbpp, plen, 0, insn);
//put cp_num to T1
gen_op_movl_Tx_im(state, tbpp, plen, 1, (insn >> 8) & 0xf);
if (insn & (1 << 4)) {
if (insn & (1 << 20)) { //L
//mrc
GEN_OP(*tbpp, *plen, op_mrc_T0_T1);
}
else {
//mcr
GEN_OP(*tbpp, *plen, op_mcr_T0_T1);
}
}
else {
//cdp
GEN_OP(*tbpp, *plen, op_cdp_T0_T1);
}
}
void
arm2x86_get_op_swi(ARMul_State *state, ARMword insn, uint8_t **tbpp, int *plen)
{
gen_op_movl_trap_im_use_T2(state, tbpp, plen, TRAP_SWI);
state->trap = 1;
}
arm2x86_get_other_op_t *arm2x86_get_other_op[16] = {
arm2x86_get_op_mul,
arm2x86_get_op_swp,
arm2x86_get_op_insn_undef,
arm2x86_get_op_insn_undef,
arm2x86_get_op_ldrstr,
arm2x86_get_op_ldrstr,
arm2x86_get_op_ldrstr,
arm2x86_get_op_ldrstr,
arm2x86_get_op_ldmstm,
arm2x86_get_op_ldmstm,
arm2x86_get_op_bbl,
arm2x86_get_op_bbl,
arm2x86_get_op_ldcstc,
arm2x86_get_op_ldcstc,
arm2x86_get_op_cdp_mrcmcr,
arm2x86_get_op_swi,
};
//--------------------------------------------------------------------------------------------------
int
arm2x86_other_init()
{
op_addq_T0_T1_eax_T2.op = get_op_addq_T0_T1_eax_T2(&op_addq_T0_T1_eax_T2.len);
if (op_addq_T0_T1_eax_T2.len <= 0)
return(-1);
op_b_offset.op = get_op_b_offset(&op_b_offset.len);
if (op_b_offset.len <= 0)
return(-1);
op_bl_offset.op = get_op_bl_offset(&op_bl_offset.len);
if (op_bl_offset.len <= 0)
return(-1);
//teawater add check thumb 2005.07.21-------------------------------------------
op_bx_T1.op = get_op_bx_T1(&op_bx_T1.len);
if (op_bx_T1.len <= 0)
return(-1);
op_blx_T1.op = get_op_blx_T1(&op_blx_T1.len);
if (op_blx_T1.len <= 0)
return(-1);
//AJ2D--------------------------------------------------------------------------
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -