target-arm: Implement MRS (banked) and MSR (banked) instructions

Starting with the ARMv7 Virtualization Extensions, the A32 and T32
instruction sets provide instructions "MSR (banked)" and "MRS
(banked)" which can be used to access registers for a mode other
than the current one:
* R<m>_<mode>
* ELR_hyp
* SPSR_<mode>

Implement the missing instructions.

Backports commit 8bfd0550be821cf27d71444e2af350de3c3d2ee3 from qemu
This commit is contained in:
Peter Maydell 2018-02-21 21:43:19 -05:00 committed by Lioncash
parent d561d28827
commit 8309945dcc
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
17 changed files with 450 additions and 3 deletions

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_aarch64
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_aarch64
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_aarch64
#define gen_helper_mrs_banked gen_helper_mrs_banked_aarch64
#define gen_helper_msr_banked gen_helper_msr_banked_aarch64
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_aarch64
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_aarch64
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_aarch64
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_aarch64
#define helper_le_stq_mmu helper_le_stq_mmu_aarch64
#define helper_le_stw_mmu helper_le_stw_mmu_aarch64
#define helper_mrs_banked helper_mrs_banked_aarch64
#define helper_msa_ld_b helper_msa_ld_b_aarch64
#define helper_msa_ld_d helper_msa_ld_d_aarch64
#define helper_msa_ld_h helper_msa_ld_h_aarch64
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_aarch64
#define helper_msa_st_h helper_msa_st_h_aarch64
#define helper_msa_st_w helper_msa_st_w_aarch64
#define helper_msr_banked helper_msr_banked_aarch64
#define helper_msr_i_pstate helper_msr_i_pstate_aarch64
#define helper_neon_abd_f32 helper_neon_abd_f32_aarch64
#define helper_neon_abdl_s16 helper_neon_abdl_s16_aarch64

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_aarch64eb
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_aarch64eb
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_aarch64eb
#define gen_helper_mrs_banked gen_helper_mrs_banked_aarch64eb
#define gen_helper_msr_banked gen_helper_msr_banked_aarch64eb
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_aarch64eb
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_aarch64eb
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_aarch64eb
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_aarch64eb
#define helper_le_stq_mmu helper_le_stq_mmu_aarch64eb
#define helper_le_stw_mmu helper_le_stw_mmu_aarch64eb
#define helper_mrs_banked helper_mrs_banked_aarch64eb
#define helper_msa_ld_b helper_msa_ld_b_aarch64eb
#define helper_msa_ld_d helper_msa_ld_d_aarch64eb
#define helper_msa_ld_h helper_msa_ld_h_aarch64eb
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_aarch64eb
#define helper_msa_st_h helper_msa_st_h_aarch64eb
#define helper_msa_st_w helper_msa_st_w_aarch64eb
#define helper_msr_banked helper_msr_banked_aarch64eb
#define helper_msr_i_pstate helper_msr_i_pstate_aarch64eb
#define helper_neon_abd_f32 helper_neon_abd_f32_aarch64eb
#define helper_neon_abdl_s16 helper_neon_abdl_s16_aarch64eb

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_arm
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_arm
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_arm
#define gen_helper_mrs_banked gen_helper_mrs_banked_arm
#define gen_helper_msr_banked gen_helper_msr_banked_arm
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_arm
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_arm
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_arm
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_arm
#define helper_le_stq_mmu helper_le_stq_mmu_arm
#define helper_le_stw_mmu helper_le_stw_mmu_arm
#define helper_mrs_banked helper_mrs_banked_arm
#define helper_msa_ld_b helper_msa_ld_b_arm
#define helper_msa_ld_d helper_msa_ld_d_arm
#define helper_msa_ld_h helper_msa_ld_h_arm
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_arm
#define helper_msa_st_h helper_msa_st_h_arm
#define helper_msa_st_w helper_msa_st_w_arm
#define helper_msr_banked helper_msr_banked_arm
#define helper_msr_i_pstate helper_msr_i_pstate_arm
#define helper_neon_abd_f32 helper_neon_abd_f32_arm
#define helper_neon_abdl_s16 helper_neon_abdl_s16_arm

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_armeb
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_armeb
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_armeb
#define gen_helper_mrs_banked gen_helper_mrs_banked_armeb
#define gen_helper_msr_banked gen_helper_msr_banked_armeb
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_armeb
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_armeb
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_armeb
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_armeb
#define helper_le_stq_mmu helper_le_stq_mmu_armeb
#define helper_le_stw_mmu helper_le_stw_mmu_armeb
#define helper_mrs_banked helper_mrs_banked_armeb
#define helper_msa_ld_b helper_msa_ld_b_armeb
#define helper_msa_ld_d helper_msa_ld_d_armeb
#define helper_msa_ld_h helper_msa_ld_h_armeb
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_armeb
#define helper_msa_st_h helper_msa_st_h_armeb
#define helper_msa_st_w helper_msa_st_w_armeb
#define helper_msr_banked helper_msr_banked_armeb
#define helper_msr_i_pstate helper_msr_i_pstate_armeb
#define helper_neon_abd_f32 helper_neon_abd_f32_armeb
#define helper_neon_abdl_s16 helper_neon_abdl_s16_armeb

View file

@ -811,6 +811,8 @@ symbols = (
'gen_helper_iwmmxt_unpacklul',
'gen_helper_iwmmxt_unpackluw',
'gen_helper_iwmmxt_unpacklw',
'gen_helper_mrs_banked',
'gen_helper_msr_banked',
'gen_helper_neon_abd_f32',
'gen_helper_neon_abdl_s16',
'gen_helper_neon_abdl_s32',
@ -1553,6 +1555,7 @@ symbols = (
'helper_le_stl_mmu',
'helper_le_stq_mmu',
'helper_le_stw_mmu',
'helper_mrs_banked',
'helper_msa_ld_b',
'helper_msa_ld_d',
'helper_msa_ld_h',
@ -1561,6 +1564,7 @@ symbols = (
'helper_msa_st_d',
'helper_msa_st_h',
'helper_msa_st_w',
'helper_msr_banked',
'helper_msr_i_pstate',
'helper_neon_abd_f32',
'helper_neon_abdl_s16',

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_m68k
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_m68k
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_m68k
#define gen_helper_mrs_banked gen_helper_mrs_banked_m68k
#define gen_helper_msr_banked gen_helper_msr_banked_m68k
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_m68k
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_m68k
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_m68k
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_m68k
#define helper_le_stq_mmu helper_le_stq_mmu_m68k
#define helper_le_stw_mmu helper_le_stw_mmu_m68k
#define helper_mrs_banked helper_mrs_banked_m68k
#define helper_msa_ld_b helper_msa_ld_b_m68k
#define helper_msa_ld_d helper_msa_ld_d_m68k
#define helper_msa_ld_h helper_msa_ld_h_m68k
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_m68k
#define helper_msa_st_h helper_msa_st_h_m68k
#define helper_msa_st_w helper_msa_st_w_m68k
#define helper_msr_banked helper_msr_banked_m68k
#define helper_msr_i_pstate helper_msr_i_pstate_m68k
#define helper_neon_abd_f32 helper_neon_abd_f32_m68k
#define helper_neon_abdl_s16 helper_neon_abdl_s16_m68k

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_mips
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_mips
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_mips
#define gen_helper_mrs_banked gen_helper_mrs_banked_mips
#define gen_helper_msr_banked gen_helper_msr_banked_mips
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_mips
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_mips
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_mips
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_mips
#define helper_le_stq_mmu helper_le_stq_mmu_mips
#define helper_le_stw_mmu helper_le_stw_mmu_mips
#define helper_mrs_banked helper_mrs_banked_mips
#define helper_msa_ld_b helper_msa_ld_b_mips
#define helper_msa_ld_d helper_msa_ld_d_mips
#define helper_msa_ld_h helper_msa_ld_h_mips
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_mips
#define helper_msa_st_h helper_msa_st_h_mips
#define helper_msa_st_w helper_msa_st_w_mips
#define helper_msr_banked helper_msr_banked_mips
#define helper_msr_i_pstate helper_msr_i_pstate_mips
#define helper_neon_abd_f32 helper_neon_abd_f32_mips
#define helper_neon_abdl_s16 helper_neon_abdl_s16_mips

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_mips64
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_mips64
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_mips64
#define gen_helper_mrs_banked gen_helper_mrs_banked_mips64
#define gen_helper_msr_banked gen_helper_msr_banked_mips64
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_mips64
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_mips64
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_mips64
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_mips64
#define helper_le_stq_mmu helper_le_stq_mmu_mips64
#define helper_le_stw_mmu helper_le_stw_mmu_mips64
#define helper_mrs_banked helper_mrs_banked_mips64
#define helper_msa_ld_b helper_msa_ld_b_mips64
#define helper_msa_ld_d helper_msa_ld_d_mips64
#define helper_msa_ld_h helper_msa_ld_h_mips64
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_mips64
#define helper_msa_st_h helper_msa_st_h_mips64
#define helper_msa_st_w helper_msa_st_w_mips64
#define helper_msr_banked helper_msr_banked_mips64
#define helper_msr_i_pstate helper_msr_i_pstate_mips64
#define helper_neon_abd_f32 helper_neon_abd_f32_mips64
#define helper_neon_abdl_s16 helper_neon_abdl_s16_mips64

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_mips64el
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_mips64el
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_mips64el
#define gen_helper_mrs_banked gen_helper_mrs_banked_mips64el
#define gen_helper_msr_banked gen_helper_msr_banked_mips64el
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_mips64el
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_mips64el
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_mips64el
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_mips64el
#define helper_le_stq_mmu helper_le_stq_mmu_mips64el
#define helper_le_stw_mmu helper_le_stw_mmu_mips64el
#define helper_mrs_banked helper_mrs_banked_mips64el
#define helper_msa_ld_b helper_msa_ld_b_mips64el
#define helper_msa_ld_d helper_msa_ld_d_mips64el
#define helper_msa_ld_h helper_msa_ld_h_mips64el
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_mips64el
#define helper_msa_st_h helper_msa_st_h_mips64el
#define helper_msa_st_w helper_msa_st_w_mips64el
#define helper_msr_banked helper_msr_banked_mips64el
#define helper_msr_i_pstate helper_msr_i_pstate_mips64el
#define helper_neon_abd_f32 helper_neon_abd_f32_mips64el
#define helper_neon_abdl_s16 helper_neon_abdl_s16_mips64el

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_mipsel
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_mipsel
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_mipsel
#define gen_helper_mrs_banked gen_helper_mrs_banked_mipsel
#define gen_helper_msr_banked gen_helper_msr_banked_mipsel
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_mipsel
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_mipsel
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_mipsel
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_mipsel
#define helper_le_stq_mmu helper_le_stq_mmu_mipsel
#define helper_le_stw_mmu helper_le_stw_mmu_mipsel
#define helper_mrs_banked helper_mrs_banked_mipsel
#define helper_msa_ld_b helper_msa_ld_b_mipsel
#define helper_msa_ld_d helper_msa_ld_d_mipsel
#define helper_msa_ld_h helper_msa_ld_h_mipsel
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_mipsel
#define helper_msa_st_h helper_msa_st_h_mipsel
#define helper_msa_st_w helper_msa_st_w_mipsel
#define helper_msr_banked helper_msr_banked_mipsel
#define helper_msr_i_pstate helper_msr_i_pstate_mipsel
#define helper_neon_abd_f32 helper_neon_abd_f32_mipsel
#define helper_neon_abdl_s16 helper_neon_abdl_s16_mipsel

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_powerpc
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_powerpc
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_powerpc
#define gen_helper_mrs_banked gen_helper_mrs_banked_powerpc
#define gen_helper_msr_banked gen_helper_msr_banked_powerpc
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_powerpc
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_powerpc
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_powerpc
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_powerpc
#define helper_le_stq_mmu helper_le_stq_mmu_powerpc
#define helper_le_stw_mmu helper_le_stw_mmu_powerpc
#define helper_mrs_banked helper_mrs_banked_powerpc
#define helper_msa_ld_b helper_msa_ld_b_powerpc
#define helper_msa_ld_d helper_msa_ld_d_powerpc
#define helper_msa_ld_h helper_msa_ld_h_powerpc
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_powerpc
#define helper_msa_st_h helper_msa_st_h_powerpc
#define helper_msa_st_w helper_msa_st_w_powerpc
#define helper_msr_banked helper_msr_banked_powerpc
#define helper_msr_i_pstate helper_msr_i_pstate_powerpc
#define helper_neon_abd_f32 helper_neon_abd_f32_powerpc
#define helper_neon_abdl_s16 helper_neon_abdl_s16_powerpc

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_sparc
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_sparc
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_sparc
#define gen_helper_mrs_banked gen_helper_mrs_banked_sparc
#define gen_helper_msr_banked gen_helper_msr_banked_sparc
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_sparc
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_sparc
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_sparc
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_sparc
#define helper_le_stq_mmu helper_le_stq_mmu_sparc
#define helper_le_stw_mmu helper_le_stw_mmu_sparc
#define helper_mrs_banked helper_mrs_banked_sparc
#define helper_msa_ld_b helper_msa_ld_b_sparc
#define helper_msa_ld_d helper_msa_ld_d_sparc
#define helper_msa_ld_h helper_msa_ld_h_sparc
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_sparc
#define helper_msa_st_h helper_msa_st_h_sparc
#define helper_msa_st_w helper_msa_st_w_sparc
#define helper_msr_banked helper_msr_banked_sparc
#define helper_msr_i_pstate helper_msr_i_pstate_sparc
#define helper_neon_abd_f32 helper_neon_abd_f32_sparc
#define helper_neon_abdl_s16 helper_neon_abdl_s16_sparc

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_sparc64
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_sparc64
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_sparc64
#define gen_helper_mrs_banked gen_helper_mrs_banked_sparc64
#define gen_helper_msr_banked gen_helper_msr_banked_sparc64
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_sparc64
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_sparc64
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_sparc64
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_sparc64
#define helper_le_stq_mmu helper_le_stq_mmu_sparc64
#define helper_le_stw_mmu helper_le_stw_mmu_sparc64
#define helper_mrs_banked helper_mrs_banked_sparc64
#define helper_msa_ld_b helper_msa_ld_b_sparc64
#define helper_msa_ld_d helper_msa_ld_d_sparc64
#define helper_msa_ld_h helper_msa_ld_h_sparc64
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_sparc64
#define helper_msa_st_h helper_msa_st_h_sparc64
#define helper_msa_st_w helper_msa_st_w_sparc64
#define helper_msr_banked helper_msr_banked_sparc64
#define helper_msr_i_pstate helper_msr_i_pstate_sparc64
#define helper_neon_abd_f32 helper_neon_abd_f32_sparc64
#define helper_neon_abdl_s16 helper_neon_abdl_s16_sparc64

View file

@ -80,6 +80,9 @@ DEF_HELPER_1(exception_return, void, env)
DEF_HELPER_2(get_r13_banked, i32, env, i32)
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
DEF_HELPER_3(mrs_banked, i32, env, i32, i32)
DEF_HELPER_4(msr_banked, void, env, i32, i32, i32)
DEF_HELPER_2(get_user_reg, i32, env, i32)
DEF_HELPER_3(set_user_reg, void, env, i32, i32)

View file

@ -494,6 +494,134 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
}
}
static void msr_mrs_banked_exc_checks(CPUARMState *env, uint32_t tgtmode,
uint32_t regno)
{
/* Raise an exception if the requested access is one of the UNPREDICTABLE
* cases; otherwise return. This broadly corresponds to the pseudocode
* BankedRegisterAccessValid() and SPSRAccessValid(),
* except that we have already handled some cases at translate time.
*/
int curmode = env->uncached_cpsr & CPSR_M;
if (curmode == tgtmode) {
goto undef;
}
if (tgtmode == ARM_CPU_MODE_USR) {
switch (regno) {
case 8 ... 12:
if (curmode != ARM_CPU_MODE_FIQ) {
goto undef;
}
break;
case 13:
if (curmode == ARM_CPU_MODE_SYS) {
goto undef;
}
break;
case 14:
if (curmode == ARM_CPU_MODE_HYP || curmode == ARM_CPU_MODE_SYS) {
goto undef;
}
break;
default:
break;
}
}
if (tgtmode == ARM_CPU_MODE_HYP) {
switch (regno) {
case 17: /* ELR_Hyp */
if (curmode != ARM_CPU_MODE_HYP && curmode != ARM_CPU_MODE_MON) {
goto undef;
}
break;
default:
if (curmode != ARM_CPU_MODE_MON) {
goto undef;
}
break;
}
}
return;
undef:
raise_exception(env, EXCP_UDEF, syn_uncategorized(),
exception_target_el(env));
}
void HELPER(msr_banked)(CPUARMState *env, uint32_t value, uint32_t tgtmode,
uint32_t regno)
{
msr_mrs_banked_exc_checks(env, tgtmode, regno);
switch (regno) {
case 16: /* SPSRs */
env->banked_spsr[bank_number(tgtmode)] = value;
break;
case 17: /* ELR_Hyp */
env->elr_el[2] = value;
break;
case 13:
env->banked_r13[bank_number(tgtmode)] = value;
break;
case 14:
env->banked_r14[bank_number(tgtmode)] = value;
break;
case 8:
case 9:
case 10:
case 11:
case 12:
switch (tgtmode) {
case ARM_CPU_MODE_USR:
env->usr_regs[regno - 8] = value;
break;
case ARM_CPU_MODE_FIQ:
env->fiq_regs[regno - 8] = value;
break;
default:
g_assert_not_reached();
}
break;
default:
g_assert_not_reached();
}
}
uint32_t HELPER(mrs_banked)(CPUARMState *env, uint32_t tgtmode, uint32_t regno)
{
msr_mrs_banked_exc_checks(env, tgtmode, regno);
switch (regno) {
case 16: /* SPSRs */
return env->banked_spsr[bank_number(tgtmode)];
case 17: /* ELR_Hyp */
return env->elr_el[2];
case 13:
return env->banked_r13[bank_number(tgtmode)];
case 14:
return env->banked_r14[bank_number(tgtmode)];
case 8:
case 9:
case 10:
case 11:
case 12:
switch (tgtmode) {
case ARM_CPU_MODE_USR:
return env->usr_regs[regno - 8];
case ARM_CPU_MODE_FIQ:
return env->fiq_regs[regno - 8];
default:
g_assert_not_reached();
}
default:
g_assert_not_reached();
}
}
void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
uint32_t isread)
{

View file

@ -4264,6 +4264,215 @@ static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val
return gen_set_psr(s, mask, spsr, tmp);
}
static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
int *tgtmode, int *regno)
{
/* Decode the r and sysm fields of MSR/MRS banked accesses into
* the target mode and register number, and identify the various
* unpredictable cases.
* MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
* + executed in user mode
* + using R15 as the src/dest register
* + accessing an unimplemented register
* + accessing a register that's inaccessible at current PL/security state*
* + accessing a register that you could access with a different insn
* We choose to UNDEF in all these cases.
* Since we don't know which of the various AArch32 modes we are in
* we have to defer some checks to runtime.
* Accesses to Monitor mode registers from Secure EL1 (which implies
* that EL3 is AArch64) must trap to EL3.
*
* If the access checks fail this function will emit code to take
* an exception and return false. Otherwise it will return true,
* and set *tgtmode and *regno appropriately.
*/
int exc_target = default_exception_el(s);
/* These instructions are present only in ARMv8, or in ARMv7 with the
* Virtualization Extensions.
*/
if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
!arm_dc_feature(s, ARM_FEATURE_EL2)) {
goto undef;
}
if (IS_USER(s) || rn == 15) {
goto undef;
}
/* The table in the v8 ARM ARM section F5.2.3 describes the encoding
* of registers into (r, sysm).
*/
if (r) {
/* SPSRs for other modes */
switch (sysm) {
case 0xe: /* SPSR_fiq */
*tgtmode = ARM_CPU_MODE_FIQ;
break;
case 0x10: /* SPSR_irq */
*tgtmode = ARM_CPU_MODE_IRQ;
break;
case 0x12: /* SPSR_svc */
*tgtmode = ARM_CPU_MODE_SVC;
break;
case 0x14: /* SPSR_abt */
*tgtmode = ARM_CPU_MODE_ABT;
break;
case 0x16: /* SPSR_und */
*tgtmode = ARM_CPU_MODE_UND;
break;
case 0x1c: /* SPSR_mon */
*tgtmode = ARM_CPU_MODE_MON;
break;
case 0x1e: /* SPSR_hyp */
*tgtmode = ARM_CPU_MODE_HYP;
break;
default: /* unallocated */
goto undef;
}
/* We arbitrarily assign SPSR a register number of 16. */
*regno = 16;
} else {
/* general purpose registers for other modes */
switch (sysm) {
case 0x0: /* 0b00xxx : r8_usr ... r14_usr */
case 0x1:
case 0x2:
case 0x3:
case 0x4:
case 0x5:
case 0x6:
*tgtmode = ARM_CPU_MODE_USR;
*regno = sysm + 8;
break;
case 0x8: /* 0b01xxx : r8_fiq ... r14_fiq */
case 0x9:
case 0xa:
case 0xb:
case 0xc:
case 0xd:
case 0xe:
*tgtmode = ARM_CPU_MODE_FIQ;
*regno = sysm;
break;
case 0x10: /* 0b1000x : r14_irq, r13_irq */
case 0x11:
*tgtmode = ARM_CPU_MODE_IRQ;
*regno = sysm & 1 ? 13 : 14;
break;
case 0x12: /* 0b1001x : r14_svc, r13_svc */
case 0x13:
*tgtmode = ARM_CPU_MODE_SVC;
*regno = sysm & 1 ? 13 : 14;
break;
case 0x14: /* 0b1010x : r14_abt, r13_abt */
case 0x15:
*tgtmode = ARM_CPU_MODE_ABT;
*regno = sysm & 1 ? 13 : 14;
break;
case 0x16: /* 0b1011x : r14_und, r13_und */
case 0x17:
*tgtmode = ARM_CPU_MODE_UND;
*regno = sysm & 1 ? 13 : 14;
break;
case 0x1c: /* 0b1110x : r14_mon, r13_mon */
case 0x1d:
*tgtmode = ARM_CPU_MODE_MON;
*regno = sysm & 1 ? 13 : 14;
break;
case 0x1e: /* 0b1111x : elr_hyp, r13_hyp */
case 0x1f:
*tgtmode = ARM_CPU_MODE_HYP;
/* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
*regno = sysm & 1 ? 13 : 17;
break;
default: /* unallocated */
goto undef;
}
}
/* Catch the 'accessing inaccessible register' cases we can detect
* at translate time.
*/
switch (*tgtmode) {
case ARM_CPU_MODE_MON:
if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
goto undef;
}
if (s->current_el == 1) {
/* If we're in Secure EL1 (which implies that EL3 is AArch64)
* then accesses to Mon registers trap to EL3
*/
exc_target = 3;
goto undef;
}
break;
case ARM_CPU_MODE_HYP:
/* Note that we can forbid accesses from EL2 here because they
* must be from Hyp mode itself
*/
if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 3) {
goto undef;
}
break;
default:
break;
}
return true;
undef:
/* If we get here then some access check did not pass */
gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), exc_target);
return false;
}
static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
int tgtmode = 0, regno = 0;
if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
return;
}
/* Sync state because msr_banked() can raise exceptions */
gen_set_condexec(s);
gen_set_pc_im(s, s->pc - 4);
tcg_reg = load_reg(s, rn);
tcg_tgtmode = tcg_const_i32(tcg_ctx, tgtmode);
tcg_regno = tcg_const_i32(tcg_ctx, regno);
gen_helper_msr_banked(tcg_ctx, tcg_ctx->cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
tcg_temp_free_i32(tcg_ctx, tcg_tgtmode);
tcg_temp_free_i32(tcg_ctx, tcg_regno);
tcg_temp_free_i32(tcg_ctx, tcg_reg);
s->is_jmp = DISAS_UPDATE;
}
static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
int tgtmode = 0, regno = 0;
if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
return;
}
/* Sync state because mrs_banked() can raise exceptions */
gen_set_condexec(s);
gen_set_pc_im(s, s->pc - 4);
tcg_reg = tcg_temp_new_i32(tcg_ctx);
tcg_tgtmode = tcg_const_i32(tcg_ctx, tgtmode);
tcg_regno = tcg_const_i32(tcg_ctx, regno);
gen_helper_mrs_banked(tcg_ctx, tcg_reg, tcg_ctx->cpu_env, tcg_tgtmode, tcg_regno);
tcg_temp_free_i32(tcg_ctx, tcg_tgtmode);
tcg_temp_free_i32(tcg_ctx, tcg_regno);
store_reg(s, rn, tcg_reg);
s->is_jmp = DISAS_UPDATE;
}
/* Generate an old-style exception return. Marks pc as dead. */
static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
{
@ -8157,7 +8366,26 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq
sh = (insn >> 4) & 0xf;
rm = insn & 0xf;
switch (sh) {
case 0x0: /* move program status register */
case 0x0: /* MSR, MRS */
if (insn & (1 << 9)) {
/* MSR (banked) and MRS (banked) */
int sysm = extract32(insn, 16, 4) |
(extract32(insn, 8, 1) << 4);
int r = extract32(insn, 22, 1);
if (op1 & 1) {
/* MSR (banked) */
gen_msr_banked(s, r, sysm, rm);
} else {
/* MRS (banked) */
int rd = extract32(insn, 12, 4);
gen_mrs_banked(s, r, sysm, rd);
}
break;
}
/* MSR, MRS (for PSRs) */
if (op1 & 1) {
/* PSR = reg */
tmp = load_reg(s, rm);
@ -10264,6 +10492,18 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
if (arm_dc_feature(s, ARM_FEATURE_M)) {
goto illegal_op;
}
if (extract32(insn, 5, 1)) {
/* MSR (banked) */
int sysm = extract32(insn, 8, 4) |
(extract32(insn, 4, 1) << 4);
int r = op & 1;
gen_msr_banked(s, r, sysm, rm);
break;
}
/* MSR (for PSRs) */
tmp = load_reg(s, rn);
if (gen_set_psr(s,
msr_mask(s, (insn >> 8) & 0xf, op == 1),
@ -10336,7 +10576,17 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
tcg_gen_subi_i32(tcg_ctx, tmp, tmp, insn & 0xff);
gen_exception_return(s, tmp);
break;
case 6: /* mrs cpsr. */
case 6: /* MRS */
if (extract32(insn, 5, 1)) {
/* MRS (banked) */
int sysm = extract32(insn, 16, 4) |
(extract32(insn, 4, 1) << 4);
gen_mrs_banked(s, 0, sysm, rd);
break;
}
/* mrs cpsr */
tmp = tcg_temp_new_i32(tcg_ctx);
if (arm_dc_feature(s, ARM_FEATURE_M)) {
addr = tcg_const_i32(tcg_ctx, insn & 0xff);
@ -10347,7 +10597,17 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
}
store_reg(s, rd, tmp);
break;
case 7: /* mrs spsr. */
case 7: /* MRS */
if (extract32(insn, 5, 1)) {
/* MRS (banked) */
int sysm = extract32(insn, 16, 4) |
(extract32(insn, 4, 1) << 4);
gen_mrs_banked(s, 1, sysm, rd);
break;
}
/* mrs spsr. */
/* Not accessible in user mode. */
if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
goto illegal_op;

View file

@ -805,6 +805,8 @@
#define gen_helper_iwmmxt_unpacklul gen_helper_iwmmxt_unpacklul_x86_64
#define gen_helper_iwmmxt_unpackluw gen_helper_iwmmxt_unpackluw_x86_64
#define gen_helper_iwmmxt_unpacklw gen_helper_iwmmxt_unpacklw_x86_64
#define gen_helper_mrs_banked gen_helper_mrs_banked_x86_64
#define gen_helper_msr_banked gen_helper_msr_banked_x86_64
#define gen_helper_neon_abd_f32 gen_helper_neon_abd_f32_x86_64
#define gen_helper_neon_abdl_s16 gen_helper_neon_abdl_s16_x86_64
#define gen_helper_neon_abdl_s32 gen_helper_neon_abdl_s32_x86_64
@ -1547,6 +1549,7 @@
#define helper_le_stl_mmu helper_le_stl_mmu_x86_64
#define helper_le_stq_mmu helper_le_stq_mmu_x86_64
#define helper_le_stw_mmu helper_le_stw_mmu_x86_64
#define helper_mrs_banked helper_mrs_banked_x86_64
#define helper_msa_ld_b helper_msa_ld_b_x86_64
#define helper_msa_ld_d helper_msa_ld_d_x86_64
#define helper_msa_ld_h helper_msa_ld_h_x86_64
@ -1555,6 +1558,7 @@
#define helper_msa_st_d helper_msa_st_d_x86_64
#define helper_msa_st_h helper_msa_st_h_x86_64
#define helper_msa_st_w helper_msa_st_w_x86_64
#define helper_msr_banked helper_msr_banked_x86_64
#define helper_msr_i_pstate helper_msr_i_pstate_x86_64
#define helper_neon_abd_f32 helper_neon_abd_f32_x86_64
#define helper_neon_abdl_s16 helper_neon_abdl_s16_x86_64