[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 14/76] target-arm: A64: Implement MRS/MSR/SYS/SYSL
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 14/76] target-arm: A64: Implement MRS/MSR/SYS/SYSL |
Date: |
Tue, 7 Jan 2014 20:03:10 +0000 |
The AArch64 equivalent of the traditional AArch32
cp15 coprocessor registers is the set of instructions
MRS/MSR/SYS/SYSL, which cover between them both true
system registers and the "operations with side effects"
such as cache maintenance which in AArch32 are mixed
in with other cp15 registers. Implement these instructions
to look in the cpregs hashtable for the register or
operation.
Since we don't yet populate the cpregs hashtable with
any registers with the "AA64" bit set, everything will
still UNDEF at this point.
MSR/MRS is the first user of is_jmp = DISAS_UPDATE, so
fix an infelicity in its handling where the main loop
was requiring the caller to do the update of PC rather
than just doing it itself.
Signed-off-by: Peter Maydell <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
---
target-arm/translate-a64.c | 112 +++++++++++++++++++++++++++++++++------------
1 file changed, 82 insertions(+), 30 deletions(-)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index e35d2f3..7a9ee82 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -733,28 +733,88 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
unsupported_encoding(s, insn);
}
-/* C5.6.204 SYS */
-static void handle_sys(DisasContext *s, uint32_t insn, unsigned int l,
- unsigned int op1, unsigned int op2,
+/* C5.6.129 MRS - move from system register
+ * C5.6.131 MSR (register) - move to system register
+ * C5.6.204 SYS
+ * C5.6.205 SYSL
+ * These are all essentially the same insn in 'read' and 'write'
+ * versions, with varying op0 fields.
+ */
+static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
+ unsigned int op0, unsigned int op1, unsigned int op2,
unsigned int crn, unsigned int crm, unsigned int rt)
{
- unsupported_encoding(s, insn);
-}
+ const ARMCPRegInfo *ri;
+ TCGv_i64 tcg_rt;
-/* C5.6.129 MRS - move from system register */
-static void handle_mrs(DisasContext *s, uint32_t insn, unsigned int op0,
- unsigned int op1, unsigned int op2,
- unsigned int crn, unsigned int crm, unsigned int rt)
-{
- unsupported_encoding(s, insn);
-}
+ ri = get_arm_cp_reginfo(s->cp_regs,
+ ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP,
+ crn, crm, op0, op1, op2));
-/* C5.6.131 MSR (register) - move to system register */
-static void handle_msr(DisasContext *s, uint32_t insn, unsigned int op0,
- unsigned int op1, unsigned int op2,
- unsigned int crn, unsigned int crm, unsigned int rt)
-{
- unsupported_encoding(s, insn);
+ if (!ri) {
+ /* Unknown register */
+ unallocated_encoding(s);
+ return;
+ }
+
+ /* Check access permissions */
+ if (!cp_access_ok(s->current_pl, ri, isread)) {
+ unallocated_encoding(s);
+ return;
+ }
+
+ /* Handle special cases first */
+ switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
+ case ARM_CP_NOP:
+ return;
+ default:
+ break;
+ }
+
+ if (use_icount && (ri->type & ARM_CP_IO)) {
+ gen_io_start();
+ }
+
+ tcg_rt = cpu_reg(s, rt);
+
+ if (isread) {
+ if (ri->type & ARM_CP_CONST) {
+ tcg_gen_movi_i64(tcg_rt, ri->resetvalue);
+ } else if (ri->readfn) {
+ TCGv_ptr tmpptr;
+ gen_a64_set_pc_im(s->pc - 4);
+ tmpptr = tcg_const_ptr(ri);
+ gen_helper_get_cp_reg64(tcg_rt, cpu_env, tmpptr);
+ tcg_temp_free_ptr(tmpptr);
+ } else {
+ tcg_gen_ld_i64(tcg_rt, cpu_env, ri->fieldoffset);
+ }
+ } else {
+ if (ri->type & ARM_CP_CONST) {
+ /* If not forbidden by access permissions, treat as WI */
+ return;
+ } else if (ri->writefn) {
+ TCGv_ptr tmpptr;
+ gen_a64_set_pc_im(s->pc - 4);
+ tmpptr = tcg_const_ptr(ri);
+ gen_helper_set_cp_reg64(cpu_env, tmpptr, tcg_rt);
+ tcg_temp_free_ptr(tmpptr);
+ } else {
+ tcg_gen_st_i64(tcg_rt, cpu_env, ri->fieldoffset);
+ }
+ }
+
+ if (use_icount && (ri->type & ARM_CP_IO)) {
+ /* I/O operations must end the TB here (whether read or write) */
+ gen_io_end();
+ s->is_jmp = DISAS_UPDATE;
+ } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
+ /* We default to ending the TB on a coprocessor register write,
+ * but allow this to be suppressed by the register definition
+ * (usually only necessary to work around guest bugs).
+ */
+ s->is_jmp = DISAS_UPDATE;
+ }
}
/* C3.2.4 System
@@ -795,17 +855,7 @@ static void disas_system(DisasContext *s, uint32_t insn)
}
return;
}
-
- if (op0 == 1) {
- /* C5.6.204 SYS */
- handle_sys(s, insn, l, op1, op2, crn, crm, rt);
- } else if (l) { /* op0 > 1 */
- /* C5.6.129 MRS - move from system register */
- handle_mrs(s, insn, op0, op1, op2, crn, crm, rt);
- } else {
- /* C5.6.131 MSR (register) - move to system register */
- handle_msr(s, insn, op0, op1, op2, crn, crm, rt);
- }
+ handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
}
/* C3.2.3 Exception generation
@@ -3098,8 +3148,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
gen_goto_tb(dc, 1, dc->pc);
break;
default:
- case DISAS_JUMP:
case DISAS_UPDATE:
+ gen_a64_set_pc_im(dc->pc);
+ /* fall through */
+ case DISAS_JUMP:
/* indicate that the hash table must be used to find the next TB */
tcg_gen_exit_tb(0);
break;
--
1.8.5
- [Qemu-devel] [PULL 16/76] target-arm: Widen thread-local register state fields to 64 bits, (continued)
- [Qemu-devel] [PULL 16/76] target-arm: Widen thread-local register state fields to 64 bits, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 21/76] target-arm: A64: support for ld/st/cl exclusive, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 02/76] target-arm: A64: add support for ld/st unsigned imm, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 15/76] target-arm: A64: Implement minimal set of EL0-visible sysregs, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 04/76] target-arm: A64: add support for ld/st with index, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 08/76] target-arm: A64: implement SVC, BRK, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 74/76] target-arm: A64: Add floating-point<->integer conversion instructions, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 32/76] target-arm: A64: Add support for floating point compare, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 37/76] char/cadence_uart: Add missing uart_update_state, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 14/76] target-arm: A64: Implement MRS/MSR/SYS/SYSL,
Peter Maydell <=
- [Qemu-devel] [PULL 22/76] linux-user: AArch64: define TARGET_CLONE_BACKWARDS, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 57/76] softfloat: Fix float64_to_uint64, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 30/76] target-arm: A64: Add "Floating-point data-processing (3 source)" insns, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 33/76] target-arm: A64: Add support for floating point conditional compare, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 38/76] char/cadence_uart: Fix reset., Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 24/76] .travis.yml: Add aarch64-* targets, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 27/76] target-arm: A64: Fix vector register access on bigendian hosts, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 50/76] target-arm: fix build with gcc 4.8.2, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 39/76] char/cadence_uart: s/r_fifo/rx_fifo, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 31/76] target-arm: A64: Add fmov (scalar, immediate) instruction, Peter Maydell, 2014/01/07