sim-card
/
qemu
Archived
10
0
Fork 0

ARM TCG conversion 12/16.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4149 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
pbrook 2008-03-31 03:47:48 +00:00
parent 5e3f878ad6
commit 8984bd2e83
7 changed files with 277 additions and 330 deletions

View File

@ -61,13 +61,6 @@ static inline int cpu_halted(CPUState *env) {
/* In op_helper.c */
void helper_set_cp(CPUState *, uint32_t, uint32_t);
uint32_t helper_get_cp(CPUState *, uint32_t);
void helper_set_cp15(CPUState *, uint32_t, uint32_t);
uint32_t helper_get_cp15(CPUState *, uint32_t);
uint32_t helper_v7m_mrs(CPUState *env, int reg);
void helper_v7m_msr(CPUState *env, int reg, uint32_t val);
void helper_mark_exclusive(CPUARMState *, uint32_t addr);
int helper_test_exclusive(CPUARMState *, uint32_t addr);
void helper_clrex(CPUARMState *env);

View File

@ -470,38 +470,38 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
}
/* These should probably raise undefined insn exceptions. */
void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
{
int op1 = (insn >> 8) & 0xf;
cpu_abort(env, "cp%i insn %08x\n", op1, insn);
return;
}
uint32_t helper_get_cp(CPUState *env, uint32_t insn)
uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
{
int op1 = (insn >> 8) & 0xf;
cpu_abort(env, "cp%i insn %08x\n", op1, insn);
return 0;
}
void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
{
cpu_abort(env, "cp15 insn %08x\n", insn);
}
uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
{
cpu_abort(env, "cp15 insn %08x\n", insn);
return 0;
}
/* These should probably raise undefined insn exceptions. */
void helper_v7m_msr(CPUState *env, int reg, uint32_t val)
void HELPER(v7m_msr)(CPUState *env, uint32_t reg, uint32_t val)
{
cpu_abort(env, "v7m_mrs %d\n", reg);
}
uint32_t helper_v7m_mrs(CPUState *env, int reg)
uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
{
cpu_abort(env, "v7m_mrs %d\n", reg);
return 0;
@ -1191,7 +1191,7 @@ void helper_clrex(CPUState *env)
env->mmon_addr = -1;
}
void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
{
int cp_num = (insn >> 8) & 0xf;
int cp_info = (insn >> 5) & 7;
@ -1203,7 +1203,7 @@ void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
cp_info, src, operand, val);
}
uint32_t helper_get_cp(CPUState *env, uint32_t insn)
uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
{
int cp_num = (insn >> 8) & 0xf;
int cp_info = (insn >> 5) & 7;
@ -1246,7 +1246,7 @@ static uint32_t extended_mpu_ap_bits(uint32_t val)
return ret;
}
void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
{
int op1;
int op2;
@ -1530,7 +1530,7 @@ bad_reg:
(insn >> 16) & 0xf, crm, op1, op2);
}
uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
{
int op1;
int op2;
@ -1803,7 +1803,7 @@ uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
return env->banked_r13[bank_number(mode)];
}
uint32_t helper_v7m_mrs(CPUState *env, int reg)
uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
{
switch (reg) {
case 0: /* APSR */
@ -1840,7 +1840,7 @@ uint32_t helper_v7m_mrs(CPUState *env, int reg)
}
}
void helper_v7m_msr(CPUState *env, int reg, uint32_t val)
void HELPER(v7m_msr)(CPUState *env, uint32_t reg, uint32_t val)
{
switch (reg) {
case 0: /* APSR */

View File

@ -118,6 +118,15 @@ DEF_HELPER_0_0(wfi, void, (void))
DEF_HELPER_0_2(cpsr_write, void, (uint32_t, uint32_t))
DEF_HELPER_1_0(cpsr_read, uint32_t, (void))
DEF_HELPER_0_3(v7m_msr, void, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_2(v7m_mrs, uint32_t, (CPUState *, uint32_t))
DEF_HELPER_0_3(set_cp15, void, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_2(get_cp15, uint32_t, (CPUState *, uint32_t))
DEF_HELPER_0_3(set_cp, void, (CPUState *, uint32_t, uint32_t))
DEF_HELPER_1_2(get_cp, uint32_t, (CPUState *, uint32_t))
DEF_HELPER_1_2(get_r13_banked, uint32_t, (CPUState *, uint32_t))
DEF_HELPER_0_3(set_r13_banked, void, (CPUState *, uint32_t, uint32_t))
@ -187,6 +196,20 @@ DEF_HELPER_1_2(rsqrte_f32, float32, (float32, CPUState *))
DEF_HELPER_1_2(recpe_u32, uint32_t, (uint32_t, CPUState *))
DEF_HELPER_1_2(rsqrte_u32, uint32_t, (uint32_t, CPUState *))
DEF_HELPER_1_2(add_cc, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_1_2(adc_cc, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_1_2(sub_cc, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_1_2(sbc_cc, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_1_2(shl, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_1_2(shr, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_1_2(sar, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_1_2(ror, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_1_2(shl_cc, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_1_2(shr_cc, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_1_2(sar_cc, uint32_t, (uint32_t, uint32_t))
DEF_HELPER_1_2(ror_cc, uint32_t, (uint32_t, uint32_t))
#undef DEF_HELPER
#undef DEF_HELPER_0_0
#undef DEF_HELPER_0_1

View File

@ -20,66 +20,6 @@
*/
#include "exec.h"
void OPPROTO op_addl_T0_T1_cc(void)
{
unsigned int src1;
src1 = T0;
T0 += T1;
env->NZF = T0;
env->CF = T0 < src1;
env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
}
void OPPROTO op_adcl_T0_T1_cc(void)
{
unsigned int src1;
src1 = T0;
if (!env->CF) {
T0 += T1;
env->CF = T0 < src1;
} else {
T0 += T1 + 1;
env->CF = T0 <= src1;
}
env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
env->NZF = T0;
FORCE_RET();
}
#define OPSUB(sub, sbc, res, T0, T1) \
\
void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \
{ \
unsigned int src1; \
src1 = T0; \
T0 -= T1; \
env->NZF = T0; \
env->CF = src1 >= T1; \
env->VF = (src1 ^ T1) & (src1 ^ T0); \
res = T0; \
} \
\
void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \
{ \
unsigned int src1; \
src1 = T0; \
if (!env->CF) { \
T0 = T0 - T1 - 1; \
env->CF = src1 > T1; \
} else { \
T0 = T0 - T1; \
env->CF = src1 >= T1; \
} \
env->VF = (src1 ^ T1) & (src1 ^ T0); \
env->NZF = T0; \
res = T0; \
FORCE_RET(); \
}
OPSUB(sub, sbc, T0, T0, T1)
OPSUB(rsb, rsc, T0, T1, T0)
/* memory access */
#define MEMSUFFIX _raw
@ -92,164 +32,6 @@ OPSUB(rsb, rsc, T0, T1, T0)
#include "op_mem.h"
#endif
void OPPROTO op_clrex(void)
{
cpu_lock();
helper_clrex(env);
cpu_unlock();
}
/* T1 based, use T0 as shift count */
void OPPROTO op_shll_T1_T0(void)
{
int shift;
shift = T0 & 0xff;
if (shift >= 32)
T1 = 0;
else
T1 = T1 << shift;
FORCE_RET();
}
void OPPROTO op_shrl_T1_T0(void)
{
int shift;
shift = T0 & 0xff;
if (shift >= 32)
T1 = 0;
else
T1 = (uint32_t)T1 >> shift;
FORCE_RET();
}
void OPPROTO op_sarl_T1_T0(void)
{
int shift;
shift = T0 & 0xff;
if (shift >= 32)
shift = 31;
T1 = (int32_t)T1 >> shift;
}
void OPPROTO op_rorl_T1_T0(void)
{
int shift;
shift = T0 & 0x1f;
if (shift) {
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
}
FORCE_RET();
}
/* T1 based, use T0 as shift count and compute CF */
void OPPROTO op_shll_T1_T0_cc(void)
{
int shift;
shift = T0 & 0xff;
if (shift >= 32) {
if (shift == 32)
env->CF = T1 & 1;
else
env->CF = 0;
T1 = 0;
} else if (shift != 0) {
env->CF = (T1 >> (32 - shift)) & 1;
T1 = T1 << shift;
}
FORCE_RET();
}
void OPPROTO op_shrl_T1_T0_cc(void)
{
int shift;
shift = T0 & 0xff;
if (shift >= 32) {
if (shift == 32)
env->CF = (T1 >> 31) & 1;
else
env->CF = 0;
T1 = 0;
} else if (shift != 0) {
env->CF = (T1 >> (shift - 1)) & 1;
T1 = (uint32_t)T1 >> shift;
}
FORCE_RET();
}
void OPPROTO op_sarl_T1_T0_cc(void)
{
int shift;
shift = T0 & 0xff;
if (shift >= 32) {
env->CF = (T1 >> 31) & 1;
T1 = (int32_t)T1 >> 31;
} else if (shift != 0) {
env->CF = (T1 >> (shift - 1)) & 1;
T1 = (int32_t)T1 >> shift;
}
FORCE_RET();
}
void OPPROTO op_rorl_T1_T0_cc(void)
{
int shift1, shift;
shift1 = T0 & 0xff;
shift = shift1 & 0x1f;
if (shift == 0) {
if (shift1 != 0)
env->CF = (T1 >> 31) & 1;
} else {
env->CF = (T1 >> (shift - 1)) & 1;
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
}
FORCE_RET();
}
void OPPROTO op_movl_cp_T0(void)
{
helper_set_cp(env, PARAM1, T0);
FORCE_RET();
}
void OPPROTO op_movl_T0_cp(void)
{
T0 = helper_get_cp(env, PARAM1);
FORCE_RET();
}
void OPPROTO op_movl_cp15_T0(void)
{
helper_set_cp15(env, PARAM1, T0);
FORCE_RET();
}
void OPPROTO op_movl_T0_cp15(void)
{
T0 = helper_get_cp15(env, PARAM1);
FORCE_RET();
}
void OPPROTO op_v7m_mrs_T0(void)
{
T0 = helper_v7m_mrs(env, PARAM1);
}
void OPPROTO op_v7m_msr_T0(void)
{
helper_v7m_msr(env, PARAM1, T0);
}
void OPPROTO op_movl_T0_sp(void)
{
if (PARAM1 == env->v7m.current_sp)
T0 = env->regs[13];
else
T0 = env->v7m.other_sp;
FORCE_RET();
}
#include "op_neon.h"
/* iwMMXt support */

View File

@ -304,3 +304,151 @@ void HELPER(set_user_reg)(uint32_t regno, uint32_t val)
}
}
/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
The only way to do that in TCG is a conditional branch, which clobbers
all our temporaries. For now implement these as helper functions. */
uint32_t HELPER (add_cc)(uint32_t a, uint32_t b)
{
uint32_t result;
result = T0 + T1;
env->NZF = result;
env->CF = result < a;
env->VF = (a ^ b ^ -1) & (a ^ result);
return result;
}
uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
{
uint32_t result;
if (!env->CF) {
result = a + b;
env->CF = result < a;
} else {
result = a + b + 1;
env->CF = result <= a;
}
env->VF = (a ^ b ^ -1) & (a ^ result);
env->NZF = result;
return result;
}
uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
{
uint32_t result;
result = a - b;
env->NZF = result;
env->CF = a >= b;
env->VF = (a ^ b) & (a ^ result);
return result;
}
uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
{
uint32_t result;
if (!env->CF) {
result = a - b - 1;
env->CF = a > b;
} else {
result = a - b;
env->CF = a >= b;
}
env->VF = (a ^ b) & (a ^ result);
env->NZF = result;
return result;
}
/* Similarly for variable shift instructions. */
uint32_t HELPER(shl)(uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32)
return 0;
return x << shift;
}
uint32_t HELPER(shr)(uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32)
return 0;
return (uint32_t)x >> shift;
}
uint32_t HELPER(sar)(uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32)
shift = 31;
return (int32_t)x >> shift;
}
uint32_t HELPER(ror)(uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift == 0)
return x;
return (x >> shift) | (x << (32 - shift));
}
uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32) {
if (shift == 32)
env->CF = x & 1;
else
env->CF = 0;
return 0;
} else if (shift != 0) {
env->CF = (x >> (32 - shift)) & 1;
return x << shift;
}
return x;
}
uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32) {
if (shift == 32)
env->CF = (x >> 31) & 1;
else
env->CF = 0;
return 0;
} else if (shift != 0) {
env->CF = (x >> (shift - 1)) & 1;
return x >> shift;
}
return x;
}
uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i)
{
int shift = i & 0xff;
if (shift >= 32) {
env->CF = (x >> 31) & 1;
return (int32_t)x >> 31;
} else if (shift != 0) {
env->CF = (x >> (shift - 1)) & 1;
return (int32_t)x >> shift;
}
return x;
}
uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
{
int shift1, shift;
shift1 = i & 0xff;
shift = shift1 & 0x1f;
if (shift == 0) {
if (shift1 != 0)
env->CF = (x >> 31) & 1;
return x;
} else {
env->CF = (x >> (shift - 1)) & 1;
return ((uint32_t)x >> shift) | (x << (32 - shift));
}
}

View File

@ -1,24 +1,5 @@
/* ARM memory operations. */
/* Swap T0 with memory at address T1. */
/* ??? Is this exception safe? */
#define MEM_SWP_OP(name, lname) \
void OPPROTO glue(op_swp##name,MEMSUFFIX)(void) \
{ \
uint32_t tmp; \
cpu_lock(); \
tmp = glue(ld##lname,MEMSUFFIX)(T1); \
glue(st##name,MEMSUFFIX)(T1, T0); \
T0 = tmp; \
cpu_unlock(); \
FORCE_RET(); \
}
MEM_SWP_OP(b, ub)
MEM_SWP_OP(l, l)
#undef MEM_SWP_OP
/* Load-locked, store exclusive. */
#define EXCLUSIVE_OP(suffix, ldsuffix) \
void OPPROTO glue(op_ld##suffix##ex,MEMSUFFIX)(void) \

View File

@ -201,6 +201,13 @@ static void store_reg(DisasContext *s, int reg, TCGv var)
#define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
#define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
#define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
#define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
#define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
#define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
#define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
#define gen_op_rscl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[1], cpu_T[0])
#define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
#define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
#define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
@ -538,6 +545,27 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
}
};
static inline void gen_arm_shift_reg(TCGv var, int shiftop,
TCGv shift, int flags)
{
if (flags) {
switch (shiftop) {
case 0: gen_helper_shl_cc(var, var, shift); break;
case 1: gen_helper_shr_cc(var, var, shift); break;
case 2: gen_helper_sar_cc(var, var, shift); break;
case 3: gen_helper_ror_cc(var, var, shift); break;
}
} else {
switch (shiftop) {
case 0: gen_helper_shl(var, var, shift); break;
case 1: gen_helper_shr(var, var, shift); break;
case 2: gen_helper_sar(var, var, shift); break;
case 3: gen_helper_ror(var, var, shift); break;
}
}
dead_tmp(shift);
}
#define PAS_OP(pfx) \
switch (op2) { \
case 0: gen_pas_helper(glue(pfx,add16)); break; \
@ -746,20 +774,6 @@ const uint8_t table_logic_cc[16] = {
1, /* mvn */
};
static GenOpFunc *gen_shift_T1_T0[4] = {
gen_op_shll_T1_T0,
gen_op_shrl_T1_T0,
gen_op_sarl_T1_T0,
gen_op_rorl_T1_T0,
};
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
gen_op_shll_T1_T0_cc,
gen_op_shrl_T1_T0_cc,
gen_op_sarl_T1_T0_cc,
gen_op_rorl_T1_T0_cc,
};
/* Set PC and Thumb state from an immediate address. */
static inline void gen_bx_im(DisasContext *s, uint32_t addr)
{
@ -2249,6 +2263,7 @@ static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
instruction is not defined. */
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
{
TCGv tmp;
uint32_t rd = (insn >> 12) & 0xf;
uint32_t cp = (insn >> 8) & 0xf;
if (IS_USER(s)) {
@ -2258,17 +2273,16 @@ static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
if (insn & ARM_CP_RW_BIT) {
if (!env->cp[cp].cp_read)
return 1;
gen_op_movl_T0_im((uint32_t) s->pc);
gen_set_pc_T0();
gen_op_movl_T0_cp(insn);
gen_movl_reg_T0(s, rd);
gen_set_pc_im(s->pc);
tmp = new_tmp();
gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
store_reg(s, rd, tmp);
} else {
if (!env->cp[cp].cp_write)
return 1;
gen_op_movl_T0_im((uint32_t) s->pc);
gen_set_pc_T0();
gen_movl_T0_reg(s, rd);
gen_op_movl_cp_T0(insn);
gen_set_pc_im(s->pc);
tmp = load_reg(s, rd);
gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
}
return 0;
}
@ -2298,6 +2312,7 @@ static int cp15_user_ok(uint32_t insn)
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
{
uint32_t rd;
TCGv tmp;
/* M profile cores use memory mapped registers instead of cp15. */
if (arm_feature(env, ARM_FEATURE_M))
@ -2321,20 +2336,23 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
if ((insn & 0x0fff0fff) == 0x0e070f90
|| (insn & 0x0fff0fff) == 0x0e070f58) {
/* Wait for interrupt. */
gen_op_movl_T0_im((long)s->pc);
gen_set_pc_T0();
gen_set_pc_im(s->pc);
s->is_jmp = DISAS_WFI;
return 0;
}
rd = (insn >> 12) & 0xf;
if (insn & ARM_CP_RW_BIT) {
gen_op_movl_T0_cp15(insn);
tmp = new_tmp();
gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
/* If the destination register is r15 then sets condition codes. */
if (rd != 15)
gen_movl_reg_T0(s, rd);
store_reg(s, rd, tmp);
else
dead_tmp(tmp);
} else {
gen_movl_T0_reg(s, rd);
gen_op_movl_cp15_T0(insn);
tmp = load_reg(s, rd);
gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
dead_tmp(tmp);
/* Normally we would always end the TB here, but Linux
* arch/arm/mach-pxa/sleep.S expects two instructions following
* an MMU enable to execute from cache. Imitate this behaviour. */
@ -3052,12 +3070,10 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
tb = s->tb;
if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
tcg_gen_goto_tb(n);
gen_op_movl_T0_im(dest);
gen_set_pc_T0();
gen_set_pc_im(dest);
tcg_gen_exit_tb((long)tb + n);
} else {
gen_op_movl_T0_im(dest);
gen_set_pc_T0();
gen_set_pc_im(dest);
tcg_gen_exit_tb(0);
}
}
@ -3173,8 +3189,7 @@ static void gen_nop_hint(DisasContext *s, int val)
{
switch (val) {
case 3: /* wfi */
gen_op_movl_T0_im((long)s->pc);
gen_set_pc_T0();
gen_set_pc_im(s->pc);
s->is_jmp = DISAS_WFI;
break;
case 2: /* wfe */
@ -5770,12 +5785,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
} else {
rs = (insn >> 8) & 0xf;
gen_movl_T0_reg(s, rs);
if (logic_cc) {
gen_shift_T1_T0_cc[shiftop]();
} else {
gen_shift_T1_T0[shiftop]();
}
tmp = load_reg(s, rs);
gen_arm_shift_reg(cpu_T[1], shiftop, tmp, logic_cc);
}
}
if (op1 != 0x0f && op1 != 0x0d) {
@ -5977,14 +5988,20 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
/* SWP instruction */
rm = (insn) & 0xf;
gen_movl_T0_reg(s, rm);
gen_movl_T1_reg(s, rn);
/* ??? This is not really atomic. However we know
we never have multiple CPUs running in parallel,
so it is good enough. */
addr = load_reg(s, rn);
tmp = load_reg(s, rm);
if (insn & (1 << 22)) {
gen_ldst(swpb, s);
tmp2 = gen_ld8u(addr, IS_USER(s));
gen_st8(tmp, addr, IS_USER(s));
} else {
gen_ldst(swpl, s);
tmp2 = gen_ld32(addr, IS_USER(s));
gen_st32(tmp, addr, IS_USER(s));
}
gen_movl_reg_T0(s, rd);
dead_tmp(addr);
store_reg(s, rd, tmp2);
}
}
} else {
@ -6903,18 +6920,16 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
goto illegal_op;
switch (op) {
case 0: /* Register controlled shift. */
gen_movl_T0_reg(s, rm);
gen_movl_T1_reg(s, rn);
tmp = load_reg(s, rn);
tmp2 = load_reg(s, rm);
if ((insn & 0x70) != 0)
goto illegal_op;
op = (insn >> 21) & 3;
if (insn & (1 << 20)) {
gen_shift_T1_T0_cc[op]();
gen_op_logic_T1_cc();
} else {
gen_shift_T1_T0[op]();
}
gen_movl_reg_T1(s, rd);
logic_cc = (insn & (1 << 20)) != 0;
gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
if (logic_cc)
gen_logic_CC(tmp);
store_reg(s, rd, tmp);
break;
case 1: /* Sign/zero extend. */
tmp = load_reg(s, rm);
@ -7208,8 +7223,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
switch (op) {
case 0: /* msr cpsr. */
if (IS_M(env)) {
gen_op_v7m_msr_T0(insn & 0xff);
gen_movl_reg_T0(s, rn);
tmp = load_reg(s, rn);
addr = tcg_const_i32(insn & 0xff);
gen_helper_v7m_msr(cpu_env, addr, tmp);
gen_lookup_tb(s);
break;
}
@ -7276,12 +7292,14 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
/* Unpredictable in user mode. */
goto illegal_op;
case 6: /* mrs cpsr. */
tmp = new_tmp();
if (IS_M(env)) {
gen_op_v7m_mrs_T0(insn & 0xff);
addr = tcg_const_i32(insn & 0xff);
gen_helper_v7m_mrs(tmp, cpu_env, addr);
} else {
gen_helper_cpsr_read(cpu_T[0]);
gen_helper_cpsr_read(tmp);
}
gen_movl_reg_T0(s, rd);
store_reg(s, rd, tmp);
break;
case 7: /* mrs spsr. */
/* Not accessible in user mode. */
@ -7753,25 +7771,25 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
break;
case 0x2: /* lsl */
if (s->condexec_mask) {
gen_op_shll_T1_T0();
gen_helper_shl(cpu_T[1], cpu_T[1], cpu_T[0]);
} else {
gen_op_shll_T1_T0_cc();
gen_helper_shl_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
gen_op_logic_T1_cc();
}
break;
case 0x3: /* lsr */
if (s->condexec_mask) {
gen_op_shrl_T1_T0();
gen_helper_shr(cpu_T[1], cpu_T[1], cpu_T[0]);
} else {
gen_op_shrl_T1_T0_cc();
gen_helper_shr_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
gen_op_logic_T1_cc();
}
break;
case 0x4: /* asr */
if (s->condexec_mask) {
gen_op_sarl_T1_T0();
gen_helper_sar(cpu_T[1], cpu_T[1], cpu_T[0]);
} else {
gen_op_sarl_T1_T0_cc();
gen_helper_sar_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
gen_op_logic_T1_cc();
}
break;
@ -7789,9 +7807,9 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
break;
case 0x7: /* ror */
if (s->condexec_mask) {
gen_op_rorl_T1_T0();
gen_helper_ror(cpu_T[1], cpu_T[1], cpu_T[0]);
} else {
gen_op_rorl_T1_T0_cc();
gen_helper_ror_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
gen_op_logic_T1_cc();
}
break;
@ -8118,15 +8136,17 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
if (IS_USER(s))
break;
if (IS_M(env)) {
val = (insn & (1 << 4)) != 0;
gen_op_movl_T0_im(val);
tmp = tcg_const_i32((insn & (1 << 4)) != 0);
/* PRIMASK */
if (insn & 1)
gen_op_v7m_msr_T0(16);
if (insn & 1) {
addr = tcg_const_i32(16);
gen_helper_v7m_msr(cpu_env, addr, tmp);
}
/* FAULTMASK */
if (insn & 2)
gen_op_v7m_msr_T0(17);
if (insn & 2) {
addr = tcg_const_i32(17);
gen_helper_v7m_msr(cpu_env, addr, tmp);
}
gen_lookup_tb(s);
} else {
if (insn & (1 << 4))