aboutsummaryrefslogtreecommitdiffstats
path: root/target-arm
diff options
context:
space:
mode:
authorVladimir Chtchetkine <vchtchetkine@google.com>2010-04-02 11:03:19 -0700
committerVladimir Chtchetkine <vchtchetkine@google.com>2010-04-02 11:03:19 -0700
commita1204591a52bf668ee72c86f98f53189621572a2 (patch)
tree18794edb58c684c3db8878450a4c1bf257d9873b /target-arm
parent0d6e3e2b1510319f218d8b6f1590f25079d4fc4a (diff)
downloadexternal_qemu-a1204591a52bf668ee72c86f98f53189621572a2.zip
external_qemu-a1204591a52bf668ee72c86f98f53189621572a2.tar.gz
external_qemu-a1204591a52bf668ee72c86f98f53189621572a2.tar.bz2
Revert change I7af83e21c64d217c6b28bf6cb5ee2e2f23182c95 to fix Froyo build.
Apparently, that change that supposedly fixed AT-related ARMv7 bug broke DexOpt step in the build process, resulting in trashed files that crash the device. Rolling this change back to fix Froyo, until cause of the DexOpt breaking has been found and fixed Change-Id: I33b417fcbd65767f7cfe60f5fb5ffa32610b4852
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/it_helper.h83
-rw-r--r--target-arm/translate.c64
2 files changed, 24 insertions, 123 deletions
diff --git a/target-arm/it_helper.h b/target-arm/it_helper.h
deleted file mode 100644
index 7982174..0000000
--- a/target-arm/it_helper.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Copyright (C) 2007-2010 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** 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.
-*/
-
-/*
- * Contains implementation of helper routines for IT block support.
- */
-
-#ifndef QEMU_TARGET_ARM_IT_HELPER_H
-#define QEMU_TARGET_ARM_IT_HELPER_H
-
-/* Gets condition bits from ITSTATE.
- * Return:
- * ITSTATE condition bits in the low 4 bits of the returned value.
- */
-static inline uint8_t
-itstate_cond(uint8_t itstate)
-{
- return (itstate >> 4) & 0xf;
-}
-
-/* Checks if ITSTATE defines the last instruction in an IT block.
- * Param:
- * itstate - ITSTATE for an instruction in an IT block.
- * Return:
- * boolean: 1 if an instruction is the last instruction in its IT block,
- * or zero if there are more instruction in the IT block.
- */
-static inline int
-itstate_is_last_it_insn(uint8_t itstate)
-{
- return (itstate & 0x7) == 0;
-}
-
-/* Checks if ITSTATE suggests that an IT block instruction is being translated.
- * Return:
- * boolean: 1 if an IT block instruction is being translated, or zero if
- * a "normal" instruction is being translated.
- */
-static inline int
-itstate_is_in_it_block(uint8_t itstate)
-{
- return (itstate & 0xff) != 0;
-}
-
-/* Advances ITSTATE to the next instruction in an IT block.
- * Param:
- * itstate - ITSTATE of the currently executing instruction.
- * Retunn:
- * ITSTATE for the next instruction in an IT block, or zero is currently
- * executing instruction was the last IT block instruction.
- */
-static inline uint8_t
-itstate_advance(uint8_t itstate)
-{
- if (itstate_is_last_it_insn(itstate)) {
- return 0;
- } else {
- return (itstate & 0xe0) | ((itstate & 0xf) << 1);
- }
-}
-
-/* Checks if given THUMB instruction is an IT instruction.
- * Param:
- * insn - THUMB instruction to check.
- * Return:
- * boolean: 1 if instruction is IT instruction, or zero otherwise.
- */
-static inline int
-is_it_insn(uint16_t insn)
-{
- return (insn & 0xff00) == 0xbf00 && (insn & 0x000f) != 0;
-}
-
-#endif // QEMU_TARGET_ARM_IT_HELPER_H
diff --git a/target-arm/translate.c b/target-arm/translate.c
index ca04700..84600f7 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -30,7 +30,6 @@
#include "disas.h"
#include "tcg-op.h"
#include "qemu-log.h"
-#include "it_helper.h"
#ifdef CONFIG_TRACE
#include "trace.h"
@@ -58,15 +57,8 @@ typedef struct DisasContext {
int condlabel;
/* Thumb-2 condtional execution bits. */
int condexec_mask;
- /* Set to 1 iff currently translated instruction is IT instruction.
- * This flag is then used to properly adjust condexec_mask field after
- * instruction has been translated*/
- int is_it_insn;
- /* Set to 1 iff condexec_mask should be updated to CPU's condexec_bits.
- * This flag is set to 1 if condexec_mask field has changed as the result
- * of an instruction translation, so it must be saved to CPU's condexec_bits
- * field after translated instruction has been executed. */
- int save_condexec_mask;
+ int condexec_cond;
+ int condexec_mask_prev; /* mask at start of instruction/block */
struct TranslationBlock *tb;
int singlestep_enabled;
int thumb;
@@ -3532,11 +3524,16 @@ static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
static inline void
gen_set_condexec (DisasContext *s)
{
- if (s->save_condexec_mask) {
+ if (s->condexec_mask) {
+ uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
TCGv tmp = new_tmp();
- tcg_gen_movi_i32(tmp, s->condexec_mask);
+ tcg_gen_movi_i32(tmp, val);
+ store_cpu_field(tmp, condexec_bits);
+ }
+ else if (s->condexec_mask_prev != 0) {
+ TCGv tmp = new_tmp();
+ tcg_gen_movi_i32(tmp, 0);
store_cpu_field(tmp, condexec_bits);
- s->save_condexec_mask = 0;
}
}
@@ -8183,12 +8180,10 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
TCGv tmp2;
TCGv addr;
- if (itstate_is_in_it_block(s->condexec_mask)) {
- /* We're translating an IT block instruction. Make it branch as
- * requried by the current ITSTATE. */
- const uint32_t it_cond = itstate_cond(s->condexec_mask);
+ if (s->condexec_mask) {
+ cond = s->condexec_cond;
s->condlabel = gen_new_label();
- gen_test_cc(it_cond ^ 1, s->condlabel);
+ gen_test_cc(cond ^ 1, s->condlabel);
s->condjmp = 1;
}
@@ -8707,9 +8702,8 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
break;
}
/* If Then. */
- s->condexec_mask = insn & 0xff;
- /* Let the translator know that this was an IT instruction. */
- s->is_it_insn = 1;
+ s->condexec_cond = (insn >> 4) & 0xe;
+ s->condexec_mask = insn & 0x1f;
/* No actual code generated for this insn, just setup state. */
break;
@@ -8885,11 +8879,9 @@ static inline void gen_intermediate_code_internal(CPUState *env,
dc->singlestep_enabled = env->singlestep_enabled;
dc->condjmp = 0;
dc->thumb = env->thumb;
- if (!search_pc) {
- /* Store current ITSTATE value. */
- tb->itstate = env->condexec_bits;
- }
- dc->condexec_mask = tb->itstate;
+ dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
+ dc->condexec_mask_prev = dc->condexec_mask;
+ dc->condexec_cond = env->condexec_bits >> 4;
#if !defined(CONFIG_USER_ONLY)
if (IS_M(env)) {
dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
@@ -8924,9 +8916,6 @@ static inline void gen_intermediate_code_internal(CPUState *env,
#endif
do {
- /* Clear IT related flags at the beginning of insn translation. */
- dc->save_condexec_mask = 0;
- dc->is_it_insn = 0;
#ifdef CONFIG_USER_ONLY
/* Intercept jump to the magic kernel page. */
if (dc->pc >= 0xffff0000) {
@@ -8986,13 +8975,13 @@ static inline void gen_intermediate_code_internal(CPUState *env,
if (env->thumb) {
disas_thumb_insn(env, dc);
+ dc->condexec_mask_prev = dc->condexec_mask;
if (dc->condexec_mask) {
- /* We just translated an IT-related instruction. We must save
- * updated ITSTATE into CPU's condexec_bits field at the end
- * this instruction translation. */
- dc->save_condexec_mask = 1;
- if (!dc->is_it_insn) {
- dc->condexec_mask = itstate_advance(dc->condexec_mask);
+ dc->condexec_cond = (dc->condexec_cond & 0xe)
+ | ((dc->condexec_mask >> 4) & 1);
+ dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
+ if (dc->condexec_mask == 0) {
+ dc->condexec_cond = 0;
}
}
} else {
@@ -9008,11 +8997,6 @@ static inline void gen_intermediate_code_internal(CPUState *env,
gen_set_label(dc->condlabel);
dc->condjmp = 0;
}
-
- /* Update CPU's condexec_bits after we've moved beyond executed
- * command for both, "fall through" and "branch" cases. */
- gen_set_condexec(dc);
-
/* Translation stops when a conditional branch is encountered.
* Otherwise the subsequent code could get translated several times.
* Also stop translation when a page boundary is reached. This