~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

Viewing changes to debian/patches/ubuntu/arm64/0048-target-arm-A64-add-support-for-logical-immediate-ins.patch

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-02-04 12:13:08 UTC
  • mfrom: (10.1.45 sid)
  • Revision ID: package-import@ubuntu.com-20140204121308-1xq92lrfs75agw2g
Tags: 1.7.0+dfsg-3ubuntu1~ppa1
* Merge 1.7.0+dfsg-3 from debian.  Remaining changes:
  - debian/patches/ubuntu:
    * expose-vmx_qemu64cpu.patch
    * linaro (omap3) and arm64 patches
    * ubuntu/target-ppc-add-stubs-for-kvm-breakpoints: fix FTBFS
      on ppc
    * ubuntu/CVE-2013-4377.patch: fix denial of service via virtio
  - debian/qemu-system-x86.modprobe: set kvm_intel nested=1 options
  - debian/control:
    * add arm64 to Architectures
    * add qemu-common and qemu-system-aarch64 packages
  - debian/qemu-system-common.install: add debian/tmp/usr/lib
  - debian/qemu-system-common.preinst: add kvm group
  - debian/qemu-system-common.postinst: remove acl placed by udev,
    and add udevadm trigger.
  - qemu-system-x86.links: add eepro100.rom, remove pxe-virtio,
    pxe-e1000 and pxe-rtl8139.
  - add qemu-system-x86.qemu-kvm.upstart and .default
  - qemu-user-static.postinst-in: remove arm64 binfmt
  - debian/rules:
    * allow parallel build
    * add aarch64 to system_targets and sys_systems
    * add qemu-kvm-spice links
    * install qemu-system-x86.modprobe
  - add debian/qemu-system-common.links for OVMF.fd link
* Remove kvm-img, kvm-nbd, kvm-ifup and kvm-ifdown symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
From 1c081c1df48f340730d28bca245c4f6e25ef8dae Mon Sep 17 00:00:00 2001
 
2
From: Alexander Graf <agraf@suse.de>
 
3
Date: Tue, 17 Dec 2013 19:42:36 +0000
 
4
Subject: [PATCH 48/49] target-arm: A64: add support for logical (immediate)
 
5
 insns
 
6
 
 
7
This patch adds support for C3.4.4 Logical (immediate),
 
8
which include AND, ANDS, ORR, EOR.
 
9
 
 
10
Signed-off-by: Alexander Graf <agraf@suse.de>
 
11
[claudio: adapted to new decoder, function renaming,
 
12
          removed a TCG temp variable]
 
13
Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
 
14
[PMM: cleaned up some unnecessary code in logic_imm_decode_wmask
 
15
and added clarifying commentary on what it's actually doing.
 
16
Dropped an ext32u that's not needed if we've just done an AND.]
 
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
 
18
Reviewed-by: Richard Henderson <rth@twiddle.net>
 
19
---
 
20
 target-arm/translate-a64.c | 175 ++++++++++++++++++++++++++++++++++++++++++++-
 
21
 1 file changed, 173 insertions(+), 2 deletions(-)
 
22
 
 
23
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
 
24
index 2bb1795..0a76130 100644
 
25
--- a/target-arm/translate-a64.c
 
26
+++ b/target-arm/translate-a64.c
 
27
@@ -201,6 +201,21 @@ static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
 
28
     return t;
 
29
 }
 
30
 
 
31
+/*
 
32
+ * Register access functions
 
33
+ *
 
34
+ * These functions are used for directly accessing a register in where
 
35
+ * changes to the final register value are likely to be made. If you
 
36
+ * need to use a register for temporary calculation (e.g. index type
 
37
+ * operations) use the read_* form.
 
38
+ *
 
39
+ * B1.2.1 Register mappings
 
40
+ *
 
41
+ * In instruction register encoding 31 can refer to ZR (zero register) or
 
42
+ * the SP (stack pointer) depending on context. In QEMU's case we map SP
 
43
+ * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
 
44
+ * This is the point of the _sp forms.
 
45
+ */
 
46
 static TCGv_i64 cpu_reg(DisasContext *s, int reg)
 
47
 {
 
48
     if (reg == 31) {
 
49
@@ -210,6 +225,12 @@ static TCGv_i64 cpu_reg(DisasContext *s, int reg)
 
50
     }
 
51
 }
 
52
 
 
53
+/* register access for when 31 == SP */
 
54
+static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
 
55
+{
 
56
+    return cpu_X[reg];
 
57
+}
 
58
+
 
59
 /* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
 
60
  * representing the register contents. This TCGv is an auto-freed
 
61
  * temporary so it need not be explicitly freed, and may be modified.
 
62
@@ -686,10 +707,160 @@ static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
 
63
     unsupported_encoding(s, insn);
 
64
 }
 
65
 
 
66
-/* Logical (immediate) */
 
67
+/* The input should be a value in the bottom e bits (with higher
 
68
+ * bits zero); returns that value replicated into every element
 
69
+ * of size e in a 64 bit integer.
 
70
+ */
 
71
+static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
 
72
+{
 
73
+    assert(e != 0);
 
74
+    while (e < 64) {
 
75
+        mask |= mask << e;
 
76
+        e *= 2;
 
77
+    }
 
78
+    return mask;
 
79
+}
 
80
+
 
81
+/* Return a value with the bottom len bits set (where 0 < len <= 64) */
 
82
+static inline uint64_t bitmask64(unsigned int length)
 
83
+{
 
84
+    assert(length > 0 && length <= 64);
 
85
+    return ~0ULL >> (64 - length);
 
86
+}
 
87
+
 
88
+/* Simplified variant of pseudocode DecodeBitMasks() for the case where we
 
89
+ * only require the wmask. Returns false if the imms/immr/immn are a reserved
 
90
+ * value (ie should cause a guest UNDEF exception), and true if they are
 
91
+ * valid, in which case the decoded bit pattern is written to result.
 
92
+ */
 
93
+static bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
 
94
+                                   unsigned int imms, unsigned int immr)
 
95
+{
 
96
+    uint64_t mask;
 
97
+    unsigned e, levels, s, r;
 
98
+    int len;
 
99
+
 
100
+    assert(immn < 2 && imms < 64 && immr < 64);
 
101
+
 
102
+    /* The bit patterns we create here are 64 bit patterns which
 
103
+     * are vectors of identical elements of size e = 2, 4, 8, 16, 32 or
 
104
+     * 64 bits each. Each element contains the same value: a run
 
105
+     * of between 1 and e-1 non-zero bits, rotated within the
 
106
+     * element by between 0 and e-1 bits.
 
107
+     *
 
108
+     * The element size and run length are encoded into immn (1 bit)
 
109
+     * and imms (6 bits) as follows:
 
110
+     * 64 bit elements: immn = 1, imms = <length of run - 1>
 
111
+     * 32 bit elements: immn = 0, imms = 0 : <length of run - 1>
 
112
+     * 16 bit elements: immn = 0, imms = 10 : <length of run - 1>
 
113
+     *  8 bit elements: immn = 0, imms = 110 : <length of run - 1>
 
114
+     *  4 bit elements: immn = 0, imms = 1110 : <length of run - 1>
 
115
+     *  2 bit elements: immn = 0, imms = 11110 : <length of run - 1>
 
116
+     * Notice that immn = 0, imms = 11111x is the only combination
 
117
+     * not covered by one of the above options; this is reserved.
 
118
+     * Further, <length of run - 1> all-ones is a reserved pattern.
 
119
+     *
 
120
+     * In all cases the rotation is by immr % e (and immr is 6 bits).
 
121
+     */
 
122
+
 
123
+    /* First determine the element size */
 
124
+    len = 31 - clz32((immn << 6) | (~imms & 0x3f));
 
125
+    if (len < 1) {
 
126
+        /* This is the immn == 0, imms == 0x11111x case */
 
127
+        return false;
 
128
+    }
 
129
+    e = 1 << len;
 
130
+
 
131
+    levels = e - 1;
 
132
+    s = imms & levels;
 
133
+    r = immr & levels;
 
134
+
 
135
+    if (s == levels) {
 
136
+        /* <length of run - 1> mustn't be all-ones. */
 
137
+        return false;
 
138
+    }
 
139
+
 
140
+    /* Create the value of one element: s+1 set bits rotated
 
141
+     * by r within the element (which is e bits wide)...
 
142
+     */
 
143
+    mask = bitmask64(s + 1);
 
144
+    mask = (mask >> r) | (mask << (e - r));
 
145
+    /* ...then replicate the element over the whole 64 bit value */
 
146
+    mask = bitfield_replicate(mask, e);
 
147
+    *result = mask;
 
148
+    return true;
 
149
+}
 
150
+
 
151
+/* C3.4.4 Logical (immediate)
 
152
+ *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
 
153
+ * +----+-----+-------------+---+------+------+------+------+
 
154
+ * | sf | opc | 1 0 0 1 0 0 | N | immr | imms |  Rn  |  Rd  |
 
155
+ * +----+-----+-------------+---+------+------+------+------+
 
156
+ */
 
157
 static void disas_logic_imm(DisasContext *s, uint32_t insn)
 
158
 {
 
159
-    unsupported_encoding(s, insn);
 
160
+    unsigned int sf, opc, is_n, immr, imms, rn, rd;
 
161
+    TCGv_i64 tcg_rd, tcg_rn;
 
162
+    uint64_t wmask;
 
163
+    bool is_and = false;
 
164
+
 
165
+    sf = extract32(insn, 31, 1);
 
166
+    opc = extract32(insn, 29, 2);
 
167
+    is_n = extract32(insn, 22, 1);
 
168
+    immr = extract32(insn, 16, 6);
 
169
+    imms = extract32(insn, 10, 6);
 
170
+    rn = extract32(insn, 5, 5);
 
171
+    rd = extract32(insn, 0, 5);
 
172
+
 
173
+    if (!sf && is_n) {
 
174
+        unallocated_encoding(s);
 
175
+        return;
 
176
+    }
 
177
+
 
178
+    if (opc == 0x3) { /* ANDS */
 
179
+        tcg_rd = cpu_reg(s, rd);
 
180
+    } else {
 
181
+        tcg_rd = cpu_reg_sp(s, rd);
 
182
+    }
 
183
+    tcg_rn = cpu_reg(s, rn);
 
184
+
 
185
+    if (!logic_imm_decode_wmask(&wmask, is_n, imms, immr)) {
 
186
+        /* some immediate field values are reserved */
 
187
+        unallocated_encoding(s);
 
188
+        return;
 
189
+    }
 
190
+
 
191
+    if (!sf) {
 
192
+        wmask &= 0xffffffff;
 
193
+    }
 
194
+
 
195
+    switch (opc) {
 
196
+    case 0x3: /* ANDS */
 
197
+    case 0x0: /* AND */
 
198
+        tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
 
199
+        is_and = true;
 
200
+        break;
 
201
+    case 0x1: /* ORR */
 
202
+        tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
 
203
+        break;
 
204
+    case 0x2: /* EOR */
 
205
+        tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
 
206
+        break;
 
207
+    default:
 
208
+        assert(FALSE); /* must handle all above */
 
209
+        break;
 
210
+    }
 
211
+
 
212
+    if (!sf && !is_and) {
 
213
+        /* zero extend final result; we know we can skip this for AND
 
214
+         * since the immediate had the high 32 bits clear.
 
215
+         */
 
216
+        tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
 
217
+    }
 
218
+
 
219
+    if (opc == 3) { /* ANDS */
 
220
+        gen_logic_CC(sf, tcg_rd);
 
221
+    }
 
222
 }
 
223
 
 
224
 /* Move wide (immediate) */
 
225
-- 
 
226
1.8.5.2
 
227