diff options
author | Alex Bennée <alex@bennee.com> | 2013-11-28 11:18:53 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2013-11-30 20:37:09 +0000 |
commit | 5ea4f23b93858efb04f5adaaf0f3384a6b05fc35 (patch) | |
tree | 6b6e3a086deff84534f71b1c3d06c354022314c2 | |
parent | 5f45d8cefe0bdf03ba5d7841af7f62d5940cab77 (diff) |
target-arm: aarch64: add support for stp (store pair)
This patch support basic GPR based store-pair instructions and includes
the generic do_gpr_st() function for store routines.
from Alexander Graf <agraf@suse.de> aarch64 series 11/60
---
v2 -> v3:
- use extract32/sextract32 instead of get_bits and get_sbits
- drop get_reg()
- open code get_reg()
v3 -> v4
- split from bigger patch (non vector)
- better naming?
-rw-r--r-- | target-arm/translate-a64.c | 123 |
1 files changed, 121 insertions, 2 deletions
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index cedfccd137..b7c64ae217 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -111,6 +111,13 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, cpu_fprintf(f, "\n"); } + +static int get_mem_index(DisasContext *s) +{ + /* XXX only user mode for now */ + return 1; +} + void gen_a64_set_pc_im(uint64_t val) { tcg_gen_movi_i64(cpu_pc, val); @@ -953,10 +960,122 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn) unsupported_encoding(s, insn); } -/* Load/store pair (all forms) */ +/* + C5.6.177 STP (Store Pair - non vector) + + 31 30 29 26 25 23 22 21 15 14 10 9 5 4 0 + +-----+-----------+-------+--+-----------------------------+ + | opc | 1 0 1 0 0 | index | 0| imm7 | Rt2 | Rn | Rt | + +-----+-----------+-------+--+-------+-------+------+------+ + + opc = 00 -> 32 bit, 10 -> 64 bit + index_mode = 01 -> post-index + 11 -> pre-index + 10 -> signed-offset + Rt, Rt2 = general purpose registers to be stored + Rn = general purpose register containing address + imm7 = signed offset (multiple of 4 or 8 depending on size) + */ +static void handle_gpr_stp(DisasContext *s, uint32_t insn) +{ + int rt = extract32(insn, 0, 5); + int rn = extract32(insn, 5, 5); + int rt2 = extract32(insn, 10, 5); + int offset = sextract32(insn, 15, 7); + int type = extract32(insn, 23, 2); + int is_32bit = !extract32(insn, 30, 2); + + TCGv_i64 tcg_rt = cpu_reg(s, rt); + TCGv_i64 tcg_rt2 = cpu_reg(s, rt2); + TCGv_i64 tcg_addr; /* calculated address */ + bool postindex = false; + bool wback = false; + int size = is_32bit ? 2 : 3; + + switch (type) { + case 1: /* STP (post-index) */ + postindex = true; + wback = true; + break; + case 2: /* STP (signed offset), rn not updated */ + postindex = false; + break; + case 3: /* STP (pre-index) */ + postindex = false; + wback = true; + break; + default: /* Failed decoder tree? */ + unallocated_encoding(s); + break; + } + + offset <<= size; + + tcg_addr = tcg_temp_new_i64(); + if (rn == 31) { + /* XXX CheckSPAlignment - may fault */ + } + tcg_gen_mov_i64(tcg_addr, cpu_reg_sp(s, rn)); + + if (!postindex) { + tcg_gen_addi_i64(tcg_addr, tcg_addr, offset); + } + + do_gpr_st(s, tcg_rt, tcg_addr, size); + tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size); + do_gpr_st(s, tcg_rt2, tcg_addr, size); + // XXX - this could be more optimal? + tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size); + + if (wback) { + if (postindex) { + tcg_gen_addi_i64(tcg_addr, tcg_addr, offset); + } + tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr); + } + + tcg_temp_free_i64(tcg_addr); +} + + +/* C2.2.3 Load/store pair (all non vector forms) + + 31 30 29 26 25 23 22 21 15 14 10 9 5 4 0 + +-----+-----------+-------+--+-----------------------------+ + | opc | 1 0 1 0 0 | index | L| imm7 | Rt2 | Rn | Rt1 | + +-----+-----------+-------+--+-------+-------+------+------+ + + opc = 00 -> 32 bit, 10 -> 64 bit, 01 -> LDPSW + L = 0 -> Store, 1 -> Load + index = 01 -> post-index + 11 -> pre-index + 10 -> signed-index + + The following instructions are defined in: + C5.6.81 LDP (Load pair) + C5.6.82 LDPSW (Load pair of registers signed word) + C5.6.177 STP (Store Pair) + + 31 30 29 22 21 15 14 10 9 5 4 0 + +-----+--------------+-----------------------------+ + | 0 1 | index_mode | imm7 | Rt2 | Rn | Rt1 | + +-----+--------------+-------+-------+------+------+ + + opc = 00 -> 32 bit, 10 -> 64 bit + index_mode = 10100011 -> post-index + 10100111 -> pre-index + 10100101 -> signed offset + + */ static void disas_ldst_pair(DisasContext *s, uint32_t insn) { - unsupported_encoding(s, insn); + int is_load = extract32(insn, 22, 1); + + if (is_load) { + unsupported_encoding(s, insn); + } else { + handle_gpr_stp(s, insn); + } } /* Load/store register (all forms) */ |