summaryrefslogtreecommitdiffstats
path: root/target/arm/translate.c
diff options
context:
space:
mode:
authorRichard Henderson2019-09-04 21:30:26 +0200
committerPeter Maydell2019-09-05 14:23:03 +0200
commit52f83b9c68bdde8d3da5f49292d3561bd474651d (patch)
tree2e24e54d3fb9e631f4c32f4ca31d8fa9eef8d9bb /target/arm/translate.c
parenttarget/arm: Convert Clear-Exclusive, Barriers (diff)
downloadqemu-52f83b9c68bdde8d3da5f49292d3561bd474651d.tar.gz
qemu-52f83b9c68bdde8d3da5f49292d3561bd474651d.tar.xz
qemu-52f83b9c68bdde8d3da5f49292d3561bd474651d.zip
target/arm: Convert CPS (privileged)
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20190904193059.26202-37-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r--target/arm/translate.c91
1 files changed, 40 insertions, 51 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 364b51c2a6..664ea281f8 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10145,6 +10145,44 @@ static bool trans_SRS(DisasContext *s, arg_SRS *a)
return true;
}
+static bool trans_CPS(DisasContext *s, arg_CPS *a)
+{
+ uint32_t mask, val;
+
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
+ return false;
+ }
+ if (IS_USER(s)) {
+ /* Implemented as NOP in user mode. */
+ return true;
+ }
+ /* TODO: There are quite a lot of UNPREDICTABLE argument combinations. */
+
+ mask = val = 0;
+ if (a->imod & 2) {
+ if (a->A) {
+ mask |= CPSR_A;
+ }
+ if (a->I) {
+ mask |= CPSR_I;
+ }
+ if (a->F) {
+ mask |= CPSR_F;
+ }
+ if (a->imod & 1) {
+ val |= mask;
+ }
+ }
+ if (a->M) {
+ mask |= CPSR_M;
+ val |= a->mode;
+ }
+ if (mask) {
+ gen_set_psr_im(s, mask, 0, val);
+ }
+ return true;
+}
+
/*
* Clear-Exclusive, Barriers
*/
@@ -10321,31 +10359,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
ARCH(5TE);
} else if ((insn & 0x0f000010) == 0x0e000010) {
/* Additional coprocessor register transfer. */
- } else if ((insn & 0x0ff10020) == 0x01000000) {
- uint32_t mask;
- uint32_t val;
- /* cps (privileged) */
- if (IS_USER(s))
- return;
- mask = val = 0;
- if (insn & (1 << 19)) {
- if (insn & (1 << 8))
- mask |= CPSR_A;
- if (insn & (1 << 7))
- mask |= CPSR_I;
- if (insn & (1 << 6))
- mask |= CPSR_F;
- if (insn & (1 << 18))
- val |= mask;
- }
- if (insn & (1 << 17)) {
- mask |= CPSR_M;
- val |= (insn & 0x1f);
- }
- if (mask) {
- gen_set_psr_im(s, mask, 0, val);
- }
- return;
}
goto illegal_op;
}
@@ -10454,7 +10467,6 @@ static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn)
/* Translate a 32-bit thumb instruction. */
static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
{
- uint32_t imm, offset;
uint32_t rd, rn, rm, rs;
TCGv_i32 tmp;
TCGv_i32 addr;
@@ -10730,31 +10742,8 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
case 0: /* msr cpsr, in decodetree */
case 1: /* msr spsr, in decodetree */
goto illegal_op;
- case 2: /* cps, nop-hint. */
- /* nop hints in decodetree */
- /* Implemented as NOP in user mode. */
- if (IS_USER(s))
- break;
- offset = 0;
- imm = 0;
- if (insn & (1 << 10)) {
- if (insn & (1 << 7))
- offset |= CPSR_A;
- if (insn & (1 << 6))
- offset |= CPSR_I;
- if (insn & (1 << 5))
- offset |= CPSR_F;
- if (insn & (1 << 9))
- imm = CPSR_A | CPSR_I | CPSR_F;
- }
- if (insn & (1 << 8)) {
- offset |= 0x1f;
- imm |= (insn & 0x1f);
- }
- if (offset) {
- gen_set_psr_im(s, offset, 0, imm);
- }
- break;
+ case 2: /* cps, nop-hint, in decodetree */
+ goto illegal_op;
case 3: /* Special control operations, in decodetree */
case 4: /* bxj, in decodetree */
goto illegal_op;