提交 32f70d76 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20170320' into staging

target-arm queue:
 * fix MSR/MRS decoding for M profile CPUs

# gpg: Signature made Mon 20 Mar 2017 12:53:26 GMT
# gpg:                using RSA key 0x3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20170320:
  arm: Fix APSR writes via M profile MSR
  arm: Enforce should-be-1 bits in MRS decoding
  arm: Don't decode MRS(banked) or MSR(banked) for M profile
  arm: HVC and SMC encodings don't exist for M profile
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
......@@ -8548,8 +8548,18 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
}
}
void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
{
void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
{
/* We're passed bits [11..0] of the instruction; extract
* SYSm and the mask bits.
* Invalid combinations of SYSm and mask are UNPREDICTABLE;
* we choose to treat them as if the mask bits were valid.
* NB that the pseudocode 'mask' variable is bits [11..10],
* whereas ours is [11..8].
*/
uint32_t mask = extract32(maskreg, 8, 4);
uint32_t reg = extract32(maskreg, 0, 8);
if (arm_current_el(env) == 0 && reg > 7) {
/* only xPSR sub-fields may be written by unprivileged */
return;
......@@ -8558,8 +8568,16 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
switch (reg) {
case 0 ... 7: /* xPSR sub-fields */
/* only APSR is actually writable */
if (reg & 4) {
xpsr_write(env, val, 0xf8000000); /* APSR */
if (!(reg & 4)) {
uint32_t apsrmask = 0;
if (mask & 8) {
apsrmask |= 0xf8000000; /* APSR NZCVQ */
}
if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
apsrmask |= 0x000f0000; /* APSR GE[3:0] */
}
xpsr_write(env, val, apsrmask);
}
break;
case 8: /* MSP */
......
......@@ -10377,6 +10377,9 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
goto illegal_op;
if (insn & (1 << 26)) {
if (arm_dc_feature(s, ARM_FEATURE_M)) {
goto illegal_op;
}
if (!(insn & (1 << 20))) {
/* Hypervisor call (v7) */
int imm16 = extract32(insn, 16, 4) << 12
......@@ -10400,7 +10403,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
case 0: /* msr cpsr. */
if (arm_dc_feature(s, ARM_FEATURE_M)) {
tmp = load_reg(s, rn);
addr = tcg_const_i32(insn & 0xff);
/* the constant is the mask and SYSm fields */
addr = tcg_const_i32(insn & 0xfff);
gen_helper_v7m_msr(cpu_env, addr, tmp);
tcg_temp_free_i32(addr);
tcg_temp_free_i32(tmp);
......@@ -10497,7 +10501,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
gen_exception_return(s, tmp);
break;
case 6: /* MRS */
if (extract32(insn, 5, 1)) {
if (extract32(insn, 5, 1) &&
!arm_dc_feature(s, ARM_FEATURE_M)) {
/* MRS (banked) */
int sysm = extract32(insn, 16, 4) |
(extract32(insn, 4, 1) << 4);
......@@ -10506,6 +10511,14 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
break;
}
if (extract32(insn, 16, 4) != 0xf) {
goto illegal_op;
}
if (!arm_dc_feature(s, ARM_FEATURE_M) &&
extract32(insn, 0, 8) != 0) {
goto illegal_op;
}
/* mrs cpsr */
tmp = tcg_temp_new_i32();
if (arm_dc_feature(s, ARM_FEATURE_M)) {
......@@ -10518,7 +10531,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
store_reg(s, rd, tmp);
break;
case 7: /* MRS */
if (extract32(insn, 5, 1)) {
if (extract32(insn, 5, 1) &&
!arm_dc_feature(s, ARM_FEATURE_M)) {
/* MRS (banked) */
int sysm = extract32(insn, 16, 4) |
(extract32(insn, 4, 1) << 4);
......@@ -10532,6 +10546,12 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
goto illegal_op;
}
if (extract32(insn, 16, 4) != 0xf ||
extract32(insn, 0, 8) != 0) {
goto illegal_op;
}
tmp = load_cpu_field(spsr);
store_reg(s, rd, tmp);
break;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册