1 /*
2  * crypto_helper.c - emulate v8 Crypto Extensions instructions
3  *
4  * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  */
11 
12 #include <stdlib.h>
13 
14 #include "cpu.h"
15 #include "exec/exec-all.h"
16 #include "exec/helper-proto.h"
17 #include "qemu/aes.h"
18 
19 union CRYPTO_STATE {
20     uint8_t    bytes[16];
21     uint32_t   words[4];
22     uint64_t   l[2];
23 };
24 
HELPER(crypto_aese)25 void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm,
26                          uint32_t decrypt)
27 {
28     static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox };
29     static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts };
30 
31     union CRYPTO_STATE rk;
32     union CRYPTO_STATE st;
33     int i;
34 
35     rk.l[0] = float64_val(env->vfp.regs[rm]);
36     rk.l[1] = float64_val(env->vfp.regs[rm + 1]);
37     st.l[0] = float64_val(env->vfp.regs[rd]);
38     st.l[1] = float64_val(env->vfp.regs[rd + 1]);
39 
40     assert(decrypt < 2);
41 
42     /* xor state vector with round key */
43     rk.l[0] ^= st.l[0];
44     rk.l[1] ^= st.l[1];
45 
46     /* combine ShiftRows operation and sbox substitution */
47     for (i = 0; i < 16; i++) {
48         st.bytes[i] = sbox[decrypt][rk.bytes[shift[decrypt][i]]];
49     }
50 
51     env->vfp.regs[rd] = make_float64(st.l[0]);
52     env->vfp.regs[rd + 1] = make_float64(st.l[1]);
53 }
54 
HELPER(crypto_aesmc)55 void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
56                           uint32_t decrypt)
57 {
58     static uint32_t const mc[][256] = { {
59         /* MixColumns lookup table */
60         0x00000000, 0x03010102, 0x06020204, 0x05030306,
61         0x0c040408, 0x0f05050a, 0x0a06060c, 0x0907070e,
62         0x18080810, 0x1b090912, 0x1e0a0a14, 0x1d0b0b16,
63         0x140c0c18, 0x170d0d1a, 0x120e0e1c, 0x110f0f1e,
64         0x30101020, 0x33111122, 0x36121224, 0x35131326,
65         0x3c141428, 0x3f15152a, 0x3a16162c, 0x3917172e,
66         0x28181830, 0x2b191932, 0x2e1a1a34, 0x2d1b1b36,
67         0x241c1c38, 0x271d1d3a, 0x221e1e3c, 0x211f1f3e,
68         0x60202040, 0x63212142, 0x66222244, 0x65232346,
69         0x6c242448, 0x6f25254a, 0x6a26264c, 0x6927274e,
70         0x78282850, 0x7b292952, 0x7e2a2a54, 0x7d2b2b56,
71         0x742c2c58, 0x772d2d5a, 0x722e2e5c, 0x712f2f5e,
72         0x50303060, 0x53313162, 0x56323264, 0x55333366,
73         0x5c343468, 0x5f35356a, 0x5a36366c, 0x5937376e,
74         0x48383870, 0x4b393972, 0x4e3a3a74, 0x4d3b3b76,
75         0x443c3c78, 0x473d3d7a, 0x423e3e7c, 0x413f3f7e,
76         0xc0404080, 0xc3414182, 0xc6424284, 0xc5434386,
77         0xcc444488, 0xcf45458a, 0xca46468c, 0xc947478e,
78         0xd8484890, 0xdb494992, 0xde4a4a94, 0xdd4b4b96,
79         0xd44c4c98, 0xd74d4d9a, 0xd24e4e9c, 0xd14f4f9e,
80         0xf05050a0, 0xf35151a2, 0xf65252a4, 0xf55353a6,
81         0xfc5454a8, 0xff5555aa, 0xfa5656ac, 0xf95757ae,
82         0xe85858b0, 0xeb5959b2, 0xee5a5ab4, 0xed5b5bb6,
83         0xe45c5cb8, 0xe75d5dba, 0xe25e5ebc, 0xe15f5fbe,
84         0xa06060c0, 0xa36161c2, 0xa66262c4, 0xa56363c6,
85         0xac6464c8, 0xaf6565ca, 0xaa6666cc, 0xa96767ce,
86         0xb86868d0, 0xbb6969d2, 0xbe6a6ad4, 0xbd6b6bd6,
87         0xb46c6cd8, 0xb76d6dda, 0xb26e6edc, 0xb16f6fde,
88         0x907070e0, 0x937171e2, 0x967272e4, 0x957373e6,
89         0x9c7474e8, 0x9f7575ea, 0x9a7676ec, 0x997777ee,
90         0x887878f0, 0x8b7979f2, 0x8e7a7af4, 0x8d7b7bf6,
91         0x847c7cf8, 0x877d7dfa, 0x827e7efc, 0x817f7ffe,
92         0x9b80801b, 0x98818119, 0x9d82821f, 0x9e83831d,
93         0x97848413, 0x94858511, 0x91868617, 0x92878715,
94         0x8388880b, 0x80898909, 0x858a8a0f, 0x868b8b0d,
95         0x8f8c8c03, 0x8c8d8d01, 0x898e8e07, 0x8a8f8f05,
96         0xab90903b, 0xa8919139, 0xad92923f, 0xae93933d,
97         0xa7949433, 0xa4959531, 0xa1969637, 0xa2979735,
98         0xb398982b, 0xb0999929, 0xb59a9a2f, 0xb69b9b2d,
99         0xbf9c9c23, 0xbc9d9d21, 0xb99e9e27, 0xba9f9f25,
100         0xfba0a05b, 0xf8a1a159, 0xfda2a25f, 0xfea3a35d,
101         0xf7a4a453, 0xf4a5a551, 0xf1a6a657, 0xf2a7a755,
102         0xe3a8a84b, 0xe0a9a949, 0xe5aaaa4f, 0xe6abab4d,
103         0xefacac43, 0xecadad41, 0xe9aeae47, 0xeaafaf45,
104         0xcbb0b07b, 0xc8b1b179, 0xcdb2b27f, 0xceb3b37d,
105         0xc7b4b473, 0xc4b5b571, 0xc1b6b677, 0xc2b7b775,
106         0xd3b8b86b, 0xd0b9b969, 0xd5baba6f, 0xd6bbbb6d,
107         0xdfbcbc63, 0xdcbdbd61, 0xd9bebe67, 0xdabfbf65,
108         0x5bc0c09b, 0x58c1c199, 0x5dc2c29f, 0x5ec3c39d,
109         0x57c4c493, 0x54c5c591, 0x51c6c697, 0x52c7c795,
110         0x43c8c88b, 0x40c9c989, 0x45caca8f, 0x46cbcb8d,
111         0x4fcccc83, 0x4ccdcd81, 0x49cece87, 0x4acfcf85,
112         0x6bd0d0bb, 0x68d1d1b9, 0x6dd2d2bf, 0x6ed3d3bd,
113         0x67d4d4b3, 0x64d5d5b1, 0x61d6d6b7, 0x62d7d7b5,
114         0x73d8d8ab, 0x70d9d9a9, 0x75dadaaf, 0x76dbdbad,
115         0x7fdcdca3, 0x7cdddda1, 0x79dedea7, 0x7adfdfa5,
116         0x3be0e0db, 0x38e1e1d9, 0x3de2e2df, 0x3ee3e3dd,
117         0x37e4e4d3, 0x34e5e5d1, 0x31e6e6d7, 0x32e7e7d5,
118         0x23e8e8cb, 0x20e9e9c9, 0x25eaeacf, 0x26ebebcd,
119         0x2fececc3, 0x2cededc1, 0x29eeeec7, 0x2aefefc5,
120         0x0bf0f0fb, 0x08f1f1f9, 0x0df2f2ff, 0x0ef3f3fd,
121         0x07f4f4f3, 0x04f5f5f1, 0x01f6f6f7, 0x02f7f7f5,
122         0x13f8f8eb, 0x10f9f9e9, 0x15fafaef, 0x16fbfbed,
123         0x1ffcfce3, 0x1cfdfde1, 0x19fefee7, 0x1affffe5,
124     }, {
125         /* Inverse MixColumns lookup table */
126         0x00000000, 0x0b0d090e, 0x161a121c, 0x1d171b12,
127         0x2c342438, 0x27392d36, 0x3a2e3624, 0x31233f2a,
128         0x58684870, 0x5365417e, 0x4e725a6c, 0x457f5362,
129         0x745c6c48, 0x7f516546, 0x62467e54, 0x694b775a,
130         0xb0d090e0, 0xbbdd99ee, 0xa6ca82fc, 0xadc78bf2,
131         0x9ce4b4d8, 0x97e9bdd6, 0x8afea6c4, 0x81f3afca,
132         0xe8b8d890, 0xe3b5d19e, 0xfea2ca8c, 0xf5afc382,
133         0xc48cfca8, 0xcf81f5a6, 0xd296eeb4, 0xd99be7ba,
134         0x7bbb3bdb, 0x70b632d5, 0x6da129c7, 0x66ac20c9,
135         0x578f1fe3, 0x5c8216ed, 0x41950dff, 0x4a9804f1,
136         0x23d373ab, 0x28de7aa5, 0x35c961b7, 0x3ec468b9,
137         0x0fe75793, 0x04ea5e9d, 0x19fd458f, 0x12f04c81,
138         0xcb6bab3b, 0xc066a235, 0xdd71b927, 0xd67cb029,
139         0xe75f8f03, 0xec52860d, 0xf1459d1f, 0xfa489411,
140         0x9303e34b, 0x980eea45, 0x8519f157, 0x8e14f859,
141         0xbf37c773, 0xb43ace7d, 0xa92dd56f, 0xa220dc61,
142         0xf66d76ad, 0xfd607fa3, 0xe07764b1, 0xeb7a6dbf,
143         0xda595295, 0xd1545b9b, 0xcc434089, 0xc74e4987,
144         0xae053edd, 0xa50837d3, 0xb81f2cc1, 0xb31225cf,
145         0x82311ae5, 0x893c13eb, 0x942b08f9, 0x9f2601f7,
146         0x46bde64d, 0x4db0ef43, 0x50a7f451, 0x5baafd5f,
147         0x6a89c275, 0x6184cb7b, 0x7c93d069, 0x779ed967,
148         0x1ed5ae3d, 0x15d8a733, 0x08cfbc21, 0x03c2b52f,
149         0x32e18a05, 0x39ec830b, 0x24fb9819, 0x2ff69117,
150         0x8dd64d76, 0x86db4478, 0x9bcc5f6a, 0x90c15664,
151         0xa1e2694e, 0xaaef6040, 0xb7f87b52, 0xbcf5725c,
152         0xd5be0506, 0xdeb30c08, 0xc3a4171a, 0xc8a91e14,
153         0xf98a213e, 0xf2872830, 0xef903322, 0xe49d3a2c,
154         0x3d06dd96, 0x360bd498, 0x2b1ccf8a, 0x2011c684,
155         0x1132f9ae, 0x1a3ff0a0, 0x0728ebb2, 0x0c25e2bc,
156         0x656e95e6, 0x6e639ce8, 0x737487fa, 0x78798ef4,
157         0x495ab1de, 0x4257b8d0, 0x5f40a3c2, 0x544daacc,
158         0xf7daec41, 0xfcd7e54f, 0xe1c0fe5d, 0xeacdf753,
159         0xdbeec879, 0xd0e3c177, 0xcdf4da65, 0xc6f9d36b,
160         0xafb2a431, 0xa4bfad3f, 0xb9a8b62d, 0xb2a5bf23,
161         0x83868009, 0x888b8907, 0x959c9215, 0x9e919b1b,
162         0x470a7ca1, 0x4c0775af, 0x51106ebd, 0x5a1d67b3,
163         0x6b3e5899, 0x60335197, 0x7d244a85, 0x7629438b,
164         0x1f6234d1, 0x146f3ddf, 0x097826cd, 0x02752fc3,
165         0x335610e9, 0x385b19e7, 0x254c02f5, 0x2e410bfb,
166         0x8c61d79a, 0x876cde94, 0x9a7bc586, 0x9176cc88,
167         0xa055f3a2, 0xab58faac, 0xb64fe1be, 0xbd42e8b0,
168         0xd4099fea, 0xdf0496e4, 0xc2138df6, 0xc91e84f8,
169         0xf83dbbd2, 0xf330b2dc, 0xee27a9ce, 0xe52aa0c0,
170         0x3cb1477a, 0x37bc4e74, 0x2aab5566, 0x21a65c68,
171         0x10856342, 0x1b886a4c, 0x069f715e, 0x0d927850,
172         0x64d90f0a, 0x6fd40604, 0x72c31d16, 0x79ce1418,
173         0x48ed2b32, 0x43e0223c, 0x5ef7392e, 0x55fa3020,
174         0x01b79aec, 0x0aba93e2, 0x17ad88f0, 0x1ca081fe,
175         0x2d83bed4, 0x268eb7da, 0x3b99acc8, 0x3094a5c6,
176         0x59dfd29c, 0x52d2db92, 0x4fc5c080, 0x44c8c98e,
177         0x75ebf6a4, 0x7ee6ffaa, 0x63f1e4b8, 0x68fcedb6,
178         0xb1670a0c, 0xba6a0302, 0xa77d1810, 0xac70111e,
179         0x9d532e34, 0x965e273a, 0x8b493c28, 0x80443526,
180         0xe90f427c, 0xe2024b72, 0xff155060, 0xf418596e,
181         0xc53b6644, 0xce366f4a, 0xd3217458, 0xd82c7d56,
182         0x7a0ca137, 0x7101a839, 0x6c16b32b, 0x671bba25,
183         0x5638850f, 0x5d358c01, 0x40229713, 0x4b2f9e1d,
184         0x2264e947, 0x2969e049, 0x347efb5b, 0x3f73f255,
185         0x0e50cd7f, 0x055dc471, 0x184adf63, 0x1347d66d,
186         0xcadc31d7, 0xc1d138d9, 0xdcc623cb, 0xd7cb2ac5,
187         0xe6e815ef, 0xede51ce1, 0xf0f207f3, 0xfbff0efd,
188         0x92b479a7, 0x99b970a9, 0x84ae6bbb, 0x8fa362b5,
189         0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d,
190     } };
191     union CRYPTO_STATE st;
192     int i;
193     st.l[0] = float64_val(env->vfp.regs[rm]);
194     st.l[1] = float64_val(env->vfp.regs[rm + 1]);
195 
196     assert(decrypt < 2);
197 
198     for (i = 0; i < 16; i += 4) {
199         st.words[i >> 2] = cpu_to_le32(
200             mc[decrypt][st.bytes[i]] ^
201             rol32(mc[decrypt][st.bytes[i + 1]], 8) ^
202             rol32(mc[decrypt][st.bytes[i + 2]], 16) ^
203             rol32(mc[decrypt][st.bytes[i + 3]], 24));
204     }
205 
206     env->vfp.regs[rd] = make_float64(st.l[0]);
207     env->vfp.regs[rd + 1] = make_float64(st.l[1]);
208 }
209 
210 /*
211  * SHA-1 logical functions
212  */
213 
cho(uint32_t x,uint32_t y,uint32_t z)214 static uint32_t cho(uint32_t x, uint32_t y, uint32_t z)
215 {
216     return (x & (y ^ z)) ^ z;
217 }
218 
par(uint32_t x,uint32_t y,uint32_t z)219 static uint32_t par(uint32_t x, uint32_t y, uint32_t z)
220 {
221     return x ^ y ^ z;
222 }
223 
maj(uint32_t x,uint32_t y,uint32_t z)224 static uint32_t maj(uint32_t x, uint32_t y, uint32_t z)
225 {
226     return (x & y) | ((x | y) & z);
227 }
228 
HELPER(crypto_sha1_3reg)229 void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn,
230                               uint32_t rm, uint32_t op)
231 {
232     union CRYPTO_STATE d;
233     union CRYPTO_STATE n;
234     union CRYPTO_STATE m;
235     d.l[0] = float64_val(env->vfp.regs[rd]);
236     d.l[1] = float64_val(env->vfp.regs[rd + 1]);
237     n.l[0] = float64_val(env->vfp.regs[rn]);
238     n.l[1] = float64_val(env->vfp.regs[rn + 1]);
239     m.l[0] = float64_val(env->vfp.regs[rm]);
240     m.l[1] = float64_val(env->vfp.regs[rm + 1]);
241 
242     if (op == 3) { /* sha1su0 */
243         d.l[0] ^= d.l[1] ^ m.l[0];
244         d.l[1] ^= n.l[0] ^ m.l[1];
245     } else {
246         int i;
247 
248         for (i = 0; i < 4; i++) {
249             uint32_t t;
250 
251             switch (op) {
252             case 0: /* sha1c */
253                 t = cho(d.words[1], d.words[2], d.words[3]);
254                 break;
255             case 1: /* sha1p */
256                 t = par(d.words[1], d.words[2], d.words[3]);
257                 break;
258             case 2: /* sha1m */
259                 t = maj(d.words[1], d.words[2], d.words[3]);
260                 break;
261             default:
262                 g_assert_not_reached();
263             }
264             t += rol32(d.words[0], 5) + n.words[0] + m.words[i];
265 
266             n.words[0] = d.words[3];
267             d.words[3] = d.words[2];
268             d.words[2] = ror32(d.words[1], 2);
269             d.words[1] = d.words[0];
270             d.words[0] = t;
271         }
272     }
273     env->vfp.regs[rd] = make_float64(d.l[0]);
274     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
275 }
276 
HELPER(crypto_sha1h)277 void HELPER(crypto_sha1h)(CPUARMState *env, uint32_t rd, uint32_t rm)
278 {
279     union CRYPTO_STATE m;
280     m.l[0] = float64_val(env->vfp.regs[rm]);
281     m.l[1] = float64_val(env->vfp.regs[rm + 1]);
282 
283     m.words[0] = ror32(m.words[0], 2);
284     m.words[1] = m.words[2] = m.words[3] = 0;
285 
286     env->vfp.regs[rd] = make_float64(m.l[0]);
287     env->vfp.regs[rd + 1] = make_float64(m.l[1]);
288 }
289 
HELPER(crypto_sha1su1)290 void HELPER(crypto_sha1su1)(CPUARMState *env, uint32_t rd, uint32_t rm)
291 {
292     union CRYPTO_STATE d;
293     union CRYPTO_STATE m;
294     d.l[0] = float64_val(env->vfp.regs[rd]);
295     d.l[1] = float64_val(env->vfp.regs[rd + 1]);
296     m.l[0] = float64_val(env->vfp.regs[rm]);
297     m.l[1] = float64_val(env->vfp.regs[rm + 1]);
298 
299     d.words[0] = rol32(d.words[0] ^ m.words[1], 1);
300     d.words[1] = rol32(d.words[1] ^ m.words[2], 1);
301     d.words[2] = rol32(d.words[2] ^ m.words[3], 1);
302     d.words[3] = rol32(d.words[3] ^ d.words[0], 1);
303 
304     env->vfp.regs[rd] = make_float64(d.l[0]);
305     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
306 }
307 
308 /*
309  * The SHA-256 logical functions, according to
310  * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
311  */
312 
S0(uint32_t x)313 static uint32_t S0(uint32_t x)
314 {
315     return ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22);
316 }
317 
S1(uint32_t x)318 static uint32_t S1(uint32_t x)
319 {
320     return ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25);
321 }
322 
s0(uint32_t x)323 static uint32_t s0(uint32_t x)
324 {
325     return ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3);
326 }
327 
s1(uint32_t x)328 static uint32_t s1(uint32_t x)
329 {
330     return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10);
331 }
332 
HELPER(crypto_sha256h)333 void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn,
334                             uint32_t rm)
335 {
336     int i;
337     union CRYPTO_STATE d;
338     union CRYPTO_STATE n;
339     union CRYPTO_STATE m;
340     d.l[0] = float64_val(env->vfp.regs[rd]);
341     d.l[1] = float64_val(env->vfp.regs[rd + 1]);
342     n.l[0] = float64_val(env->vfp.regs[rn]);
343     n.l[1] = float64_val(env->vfp.regs[rn + 1]);
344     m.l[0] = float64_val(env->vfp.regs[rm]);
345     m.l[1] = float64_val(env->vfp.regs[rm + 1]);
346 
347     for (i = 0; i < 4; i++) {
348         uint32_t t = cho(n.words[0], n.words[1], n.words[2]) + n.words[3]
349                      + S1(n.words[0]) + m.words[i];
350 
351         n.words[3] = n.words[2];
352         n.words[2] = n.words[1];
353         n.words[1] = n.words[0];
354         n.words[0] = d.words[3] + t;
355 
356         t += maj(d.words[0], d.words[1], d.words[2]) + S0(d.words[0]);
357 
358         d.words[3] = d.words[2];
359         d.words[2] = d.words[1];
360         d.words[1] = d.words[0];
361         d.words[0] = t;
362     }
363 
364     env->vfp.regs[rd] = make_float64(d.l[0]);
365     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
366 }
367 
HELPER(crypto_sha256h2)368 void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn,
369                              uint32_t rm)
370 {
371     union CRYPTO_STATE d;
372     union CRYPTO_STATE n;
373     union CRYPTO_STATE m;
374     int i;
375 
376     d.l[0] = float64_val(env->vfp.regs[rd]);
377     d.l[1] = float64_val(env->vfp.regs[rd + 1]);
378     n.l[0] = float64_val(env->vfp.regs[rn]);
379     n.l[1] = float64_val(env->vfp.regs[rn + 1]);
380     m.l[0] = float64_val(env->vfp.regs[rm]);
381     m.l[1] = float64_val(env->vfp.regs[rm + 1]);
382 
383     for (i = 0; i < 4; i++) {
384         uint32_t t = cho(d.words[0], d.words[1], d.words[2]) + d.words[3]
385                      + S1(d.words[0]) + m.words[i];
386 
387         d.words[3] = d.words[2];
388         d.words[2] = d.words[1];
389         d.words[1] = d.words[0];
390         d.words[0] = n.words[3 - i] + t;
391     }
392 
393     env->vfp.regs[rd] = make_float64(d.l[0]);
394     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
395 }
396 
HELPER(crypto_sha256su0)397 void HELPER(crypto_sha256su0)(CPUARMState *env, uint32_t rd, uint32_t rm)
398 {
399     union CRYPTO_STATE d;
400     union CRYPTO_STATE m;
401     d.l[0] = float64_val(env->vfp.regs[rd]);
402     d.l[1] = float64_val(env->vfp.regs[rd + 1]);
403     m.l[0] = float64_val(env->vfp.regs[rm]);
404     m.l[1] = float64_val(env->vfp.regs[rm + 1]);
405 
406     d.words[0] += s0(d.words[1]);
407     d.words[1] += s0(d.words[2]);
408     d.words[2] += s0(d.words[3]);
409     d.words[3] += s0(m.words[0]);
410 
411     env->vfp.regs[rd] = make_float64(d.l[0]);
412     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
413 }
414 
HELPER(crypto_sha256su1)415 void HELPER(crypto_sha256su1)(CPUARMState *env, uint32_t rd, uint32_t rn,
416                               uint32_t rm)
417 {
418     union CRYPTO_STATE d;
419     union CRYPTO_STATE n;
420     union CRYPTO_STATE m;
421     d.l[0] = float64_val(env->vfp.regs[rd]);
422     d.l[1] = float64_val(env->vfp.regs[rd + 1]);
423     n.l[0] = float64_val(env->vfp.regs[rn]);
424     n.l[1] = float64_val(env->vfp.regs[rn + 1]);
425     m.l[0] = float64_val(env->vfp.regs[rm]);
426     m.l[1] = float64_val(env->vfp.regs[rm + 1]);
427 
428     d.words[0] += s1(m.words[2]) + n.words[1];
429     d.words[1] += s1(m.words[3]) + n.words[2];
430     d.words[2] += s1(d.words[0]) + n.words[3];
431     d.words[3] += s1(d.words[1]) + m.words[0];
432 
433     env->vfp.regs[rd] = make_float64(d.l[0]);
434     env->vfp.regs[rd + 1] = make_float64(d.l[1]);
435 }
436