~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to target-ppc/op_helper.c

  • Committer: Blue Swirl
  • Date: 2009-08-31 15:14:40 UTC
  • Revision ID: git-v1:528e93a9787ccfc59582a44035f5f342caf5b84f
Fix breakage due to __thread

Thread-local storage is not supported on all hosts.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 * Lesser General Public License for more details.
15
15
 *
16
16
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19
18
 */
 
19
#include <string.h>
20
20
#include "exec.h"
21
21
#include "host-utils.h"
 
22
#include "helper.h"
22
23
 
23
24
#include "helper_regs.h"
24
 
#include "op_helper.h"
25
 
 
26
 
#define MEMSUFFIX _raw
27
 
#include "op_helper.h"
28
 
#include "op_helper_mem.h"
29
 
#if !defined(CONFIG_USER_ONLY)
30
 
#define MEMSUFFIX _user
31
 
#include "op_helper.h"
32
 
#include "op_helper_mem.h"
33
 
#define MEMSUFFIX _kernel
34
 
#include "op_helper.h"
35
 
#include "op_helper_mem.h"
36
 
#define MEMSUFFIX _hypv
37
 
#include "op_helper.h"
38
 
#include "op_helper_mem.h"
39
 
#endif
40
25
 
41
26
//#define DEBUG_OP
42
27
//#define DEBUG_EXCEPTIONS
43
28
//#define DEBUG_SOFTWARE_TLB
44
29
 
 
30
#ifdef DEBUG_SOFTWARE_TLB
 
31
#  define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
 
32
#else
 
33
#  define LOG_SWTLB(...) do { } while (0)
 
34
#endif
 
35
 
 
36
 
45
37
/*****************************************************************************/
46
38
/* Exceptions processing helpers */
47
39
 
48
 
void do_raise_exception_err (uint32_t exception, int error_code)
 
40
void helper_raise_exception_err (uint32_t exception, uint32_t error_code)
49
41
{
50
42
#if 0
51
43
    printf("Raise exception %3x code : %d\n", exception, error_code);
55
47
    cpu_loop_exit();
56
48
}
57
49
 
58
 
void do_raise_exception (uint32_t exception)
59
 
{
60
 
    do_raise_exception_err(exception, 0);
61
 
}
62
 
 
63
 
void cpu_dump_EA (target_ulong EA);
64
 
void do_print_mem_EA (target_ulong EA)
65
 
{
66
 
    cpu_dump_EA(EA);
67
 
}
68
 
 
69
 
/*****************************************************************************/
70
 
/* Registers load and stores */
71
 
void do_load_cr (void)
72
 
{
73
 
    T0 = (env->crf[0] << 28) |
74
 
        (env->crf[1] << 24) |
75
 
        (env->crf[2] << 20) |
76
 
        (env->crf[3] << 16) |
77
 
        (env->crf[4] << 12) |
78
 
        (env->crf[5] << 8) |
79
 
        (env->crf[6] << 4) |
80
 
        (env->crf[7] << 0);
81
 
}
82
 
 
83
 
void do_store_cr (uint32_t mask)
84
 
{
85
 
    int i, sh;
86
 
 
87
 
    for (i = 0, sh = 7; i < 8; i++, sh--) {
88
 
        if (mask & (1 << sh))
89
 
            env->crf[i] = (T0 >> (sh * 4)) & 0xFUL;
90
 
    }
91
 
}
92
 
 
 
50
void helper_raise_exception (uint32_t exception)
 
51
{
 
52
    helper_raise_exception_err(exception, 0);
 
53
}
 
54
 
 
55
/*****************************************************************************/
 
56
/* SPR accesses */
 
57
void helper_load_dump_spr (uint32_t sprn)
 
58
{
 
59
    qemu_log("Read SPR %d %03x => " TARGET_FMT_lx "\n", sprn, sprn,
 
60
             env->spr[sprn]);
 
61
}
 
62
 
 
63
void helper_store_dump_spr (uint32_t sprn)
 
64
{
 
65
    qemu_log("Write SPR %d %03x <= " TARGET_FMT_lx "\n", sprn, sprn,
 
66
             env->spr[sprn]);
 
67
}
 
68
 
 
69
target_ulong helper_load_tbl (void)
 
70
{
 
71
    return cpu_ppc_load_tbl(env);
 
72
}
 
73
 
 
74
target_ulong helper_load_tbu (void)
 
75
{
 
76
    return cpu_ppc_load_tbu(env);
 
77
}
 
78
 
 
79
target_ulong helper_load_atbl (void)
 
80
{
 
81
    return cpu_ppc_load_atbl(env);
 
82
}
 
83
 
 
84
target_ulong helper_load_atbu (void)
 
85
{
 
86
    return cpu_ppc_load_atbu(env);
 
87
}
 
88
 
 
89
target_ulong helper_load_601_rtcl (void)
 
90
{
 
91
    return cpu_ppc601_load_rtcl(env);
 
92
}
 
93
 
 
94
target_ulong helper_load_601_rtcu (void)
 
95
{
 
96
    return cpu_ppc601_load_rtcu(env);
 
97
}
 
98
 
 
99
#if !defined(CONFIG_USER_ONLY)
 
100
#if defined (TARGET_PPC64)
 
101
void helper_store_asr (target_ulong val)
 
102
{
 
103
    ppc_store_asr(env, val);
 
104
}
 
105
#endif
 
106
 
 
107
void helper_store_sdr1 (target_ulong val)
 
108
{
 
109
    ppc_store_sdr1(env, val);
 
110
}
 
111
 
 
112
void helper_store_tbl (target_ulong val)
 
113
{
 
114
    cpu_ppc_store_tbl(env, val);
 
115
}
 
116
 
 
117
void helper_store_tbu (target_ulong val)
 
118
{
 
119
    cpu_ppc_store_tbu(env, val);
 
120
}
 
121
 
 
122
void helper_store_atbl (target_ulong val)
 
123
{
 
124
    cpu_ppc_store_atbl(env, val);
 
125
}
 
126
 
 
127
void helper_store_atbu (target_ulong val)
 
128
{
 
129
    cpu_ppc_store_atbu(env, val);
 
130
}
 
131
 
 
132
void helper_store_601_rtcl (target_ulong val)
 
133
{
 
134
    cpu_ppc601_store_rtcl(env, val);
 
135
}
 
136
 
 
137
void helper_store_601_rtcu (target_ulong val)
 
138
{
 
139
    cpu_ppc601_store_rtcu(env, val);
 
140
}
 
141
 
 
142
target_ulong helper_load_decr (void)
 
143
{
 
144
    return cpu_ppc_load_decr(env);
 
145
}
 
146
 
 
147
void helper_store_decr (target_ulong val)
 
148
{
 
149
    cpu_ppc_store_decr(env, val);
 
150
}
 
151
 
 
152
void helper_store_hid0_601 (target_ulong val)
 
153
{
 
154
    target_ulong hid0;
 
155
 
 
156
    hid0 = env->spr[SPR_HID0];
 
157
    if ((val ^ hid0) & 0x00000008) {
 
158
        /* Change current endianness */
 
159
        env->hflags &= ~(1 << MSR_LE);
 
160
        env->hflags_nmsr &= ~(1 << MSR_LE);
 
161
        env->hflags_nmsr |= (1 << MSR_LE) & (((val >> 3) & 1) << MSR_LE);
 
162
        env->hflags |= env->hflags_nmsr;
 
163
        qemu_log("%s: set endianness to %c => " TARGET_FMT_lx "\n", __func__,
 
164
                 val & 0x8 ? 'l' : 'b', env->hflags);
 
165
    }
 
166
    env->spr[SPR_HID0] = (uint32_t)val;
 
167
}
 
168
 
 
169
void helper_store_403_pbr (uint32_t num, target_ulong value)
 
170
{
 
171
    if (likely(env->pb[num] != value)) {
 
172
        env->pb[num] = value;
 
173
        /* Should be optimized */
 
174
        tlb_flush(env, 1);
 
175
    }
 
176
}
 
177
 
 
178
target_ulong helper_load_40x_pit (void)
 
179
{
 
180
    return load_40x_pit(env);
 
181
}
 
182
 
 
183
void helper_store_40x_pit (target_ulong val)
 
184
{
 
185
    store_40x_pit(env, val);
 
186
}
 
187
 
 
188
void helper_store_40x_dbcr0 (target_ulong val)
 
189
{
 
190
    store_40x_dbcr0(env, val);
 
191
}
 
192
 
 
193
void helper_store_40x_sler (target_ulong val)
 
194
{
 
195
    store_40x_sler(env, val);
 
196
}
 
197
 
 
198
void helper_store_booke_tcr (target_ulong val)
 
199
{
 
200
    store_booke_tcr(env, val);
 
201
}
 
202
 
 
203
void helper_store_booke_tsr (target_ulong val)
 
204
{
 
205
    store_booke_tsr(env, val);
 
206
}
 
207
 
 
208
void helper_store_ibatu (uint32_t nr, target_ulong val)
 
209
{
 
210
    ppc_store_ibatu(env, nr, val);
 
211
}
 
212
 
 
213
void helper_store_ibatl (uint32_t nr, target_ulong val)
 
214
{
 
215
    ppc_store_ibatl(env, nr, val);
 
216
}
 
217
 
 
218
void helper_store_dbatu (uint32_t nr, target_ulong val)
 
219
{
 
220
    ppc_store_dbatu(env, nr, val);
 
221
}
 
222
 
 
223
void helper_store_dbatl (uint32_t nr, target_ulong val)
 
224
{
 
225
    ppc_store_dbatl(env, nr, val);
 
226
}
 
227
 
 
228
void helper_store_601_batl (uint32_t nr, target_ulong val)
 
229
{
 
230
    ppc_store_ibatl_601(env, nr, val);
 
231
}
 
232
 
 
233
void helper_store_601_batu (uint32_t nr, target_ulong val)
 
234
{
 
235
    ppc_store_ibatu_601(env, nr, val);
 
236
}
 
237
#endif
 
238
 
 
239
/*****************************************************************************/
 
240
/* Memory load and stores */
 
241
 
 
242
static inline target_ulong addr_add(target_ulong addr, target_long arg)
 
243
{
93
244
#if defined(TARGET_PPC64)
94
 
void do_store_pri (int prio)
95
 
{
96
 
    env->spr[SPR_PPR] &= ~0x001C000000000000ULL;
97
 
    env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50;
98
 
}
 
245
        if (!msr_sf)
 
246
            return (uint32_t)(addr + arg);
 
247
        else
99
248
#endif
100
 
 
101
 
target_ulong ppc_load_dump_spr (int sprn)
102
 
{
103
 
    if (loglevel != 0) {
104
 
        fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
105
 
                sprn, sprn, env->spr[sprn]);
106
 
    }
107
 
 
108
 
    return env->spr[sprn];
109
 
}
110
 
 
111
 
void ppc_store_dump_spr (int sprn, target_ulong val)
112
 
{
113
 
    if (loglevel != 0) {
114
 
        fprintf(logfile, "Write SPR %d %03x => " ADDRX " <= " ADDRX "\n",
115
 
                sprn, sprn, env->spr[sprn], val);
116
 
    }
117
 
    env->spr[sprn] = val;
 
249
            return addr + arg;
 
250
}
 
251
 
 
252
void helper_lmw (target_ulong addr, uint32_t reg)
 
253
{
 
254
    for (; reg < 32; reg++) {
 
255
        if (msr_le)
 
256
            env->gpr[reg] = bswap32(ldl(addr));
 
257
        else
 
258
            env->gpr[reg] = ldl(addr);
 
259
        addr = addr_add(addr, 4);
 
260
    }
 
261
}
 
262
 
 
263
void helper_stmw (target_ulong addr, uint32_t reg)
 
264
{
 
265
    for (; reg < 32; reg++) {
 
266
        if (msr_le)
 
267
            stl(addr, bswap32((uint32_t)env->gpr[reg]));
 
268
        else
 
269
            stl(addr, (uint32_t)env->gpr[reg]);
 
270
        addr = addr_add(addr, 4);
 
271
    }
 
272
}
 
273
 
 
274
void helper_lsw(target_ulong addr, uint32_t nb, uint32_t reg)
 
275
{
 
276
    int sh;
 
277
    for (; nb > 3; nb -= 4) {
 
278
        env->gpr[reg] = ldl(addr);
 
279
        reg = (reg + 1) % 32;
 
280
        addr = addr_add(addr, 4);
 
281
    }
 
282
    if (unlikely(nb > 0)) {
 
283
        env->gpr[reg] = 0;
 
284
        for (sh = 24; nb > 0; nb--, sh -= 8) {
 
285
            env->gpr[reg] |= ldub(addr) << sh;
 
286
            addr = addr_add(addr, 1);
 
287
        }
 
288
    }
 
289
}
 
290
/* PPC32 specification says we must generate an exception if
 
291
 * rA is in the range of registers to be loaded.
 
292
 * In an other hand, IBM says this is valid, but rA won't be loaded.
 
293
 * For now, I'll follow the spec...
 
294
 */
 
295
void helper_lswx(target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
 
296
{
 
297
    if (likely(xer_bc != 0)) {
 
298
        if (unlikely((ra != 0 && reg < ra && (reg + xer_bc) > ra) ||
 
299
                     (reg < rb && (reg + xer_bc) > rb))) {
 
300
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
 
301
                                       POWERPC_EXCP_INVAL |
 
302
                                       POWERPC_EXCP_INVAL_LSWX);
 
303
        } else {
 
304
            helper_lsw(addr, xer_bc, reg);
 
305
        }
 
306
    }
 
307
}
 
308
 
 
309
void helper_stsw(target_ulong addr, uint32_t nb, uint32_t reg)
 
310
{
 
311
    int sh;
 
312
    for (; nb > 3; nb -= 4) {
 
313
        stl(addr, env->gpr[reg]);
 
314
        reg = (reg + 1) % 32;
 
315
        addr = addr_add(addr, 4);
 
316
    }
 
317
    if (unlikely(nb > 0)) {
 
318
        for (sh = 24; nb > 0; nb--, sh -= 8) {
 
319
            stb(addr, (env->gpr[reg] >> sh) & 0xFF);
 
320
            addr = addr_add(addr, 1);
 
321
        }
 
322
    }
 
323
}
 
324
 
 
325
static void do_dcbz(target_ulong addr, int dcache_line_size)
 
326
{
 
327
    addr &= ~(dcache_line_size - 1);
 
328
    int i;
 
329
    for (i = 0 ; i < dcache_line_size ; i += 4) {
 
330
        stl(addr + i , 0);
 
331
    }
 
332
    if (env->reserve_addr == addr)
 
333
        env->reserve_addr = (target_ulong)-1ULL;
 
334
}
 
335
 
 
336
void helper_dcbz(target_ulong addr)
 
337
{
 
338
    do_dcbz(addr, env->dcache_line_size);
 
339
}
 
340
 
 
341
void helper_dcbz_970(target_ulong addr)
 
342
{
 
343
    if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1)
 
344
        do_dcbz(addr, 32);
 
345
    else
 
346
        do_dcbz(addr, env->dcache_line_size);
 
347
}
 
348
 
 
349
void helper_icbi(target_ulong addr)
 
350
{
 
351
    uint32_t tmp;
 
352
 
 
353
    addr &= ~(env->dcache_line_size - 1);
 
354
    /* Invalidate one cache line :
 
355
     * PowerPC specification says this is to be treated like a load
 
356
     * (not a fetch) by the MMU. To be sure it will be so,
 
357
     * do the load "by hand".
 
358
     */
 
359
    tmp = ldl(addr);
 
360
    tb_invalidate_page_range(addr, addr + env->icache_line_size);
 
361
}
 
362
 
 
363
// XXX: to be tested
 
364
target_ulong helper_lscbx (target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
 
365
{
 
366
    int i, c, d;
 
367
    d = 24;
 
368
    for (i = 0; i < xer_bc; i++) {
 
369
        c = ldub(addr);
 
370
        addr = addr_add(addr, 1);
 
371
        /* ra (if not 0) and rb are never modified */
 
372
        if (likely(reg != rb && (ra == 0 || reg != ra))) {
 
373
            env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
 
374
        }
 
375
        if (unlikely(c == xer_cmp))
 
376
            break;
 
377
        if (likely(d != 0)) {
 
378
            d -= 8;
 
379
        } else {
 
380
            d = 24;
 
381
            reg++;
 
382
            reg = reg & 0x1F;
 
383
        }
 
384
    }
 
385
    return i;
118
386
}
119
387
 
120
388
/*****************************************************************************/
121
389
/* Fixed point operations helpers */
122
 
void do_adde (void)
123
 
{
124
 
    T2 = T0;
125
 
    T0 += T1 + xer_ca;
126
 
    if (likely(!((uint32_t)T0 < (uint32_t)T2 ||
127
 
                 (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) {
128
 
        xer_ca = 0;
129
 
    } else {
130
 
        xer_ca = 1;
131
 
    }
132
 
}
133
 
 
134
 
#if defined(TARGET_PPC64)
135
 
void do_adde_64 (void)
136
 
{
137
 
    T2 = T0;
138
 
    T0 += T1 + xer_ca;
139
 
    if (likely(!((uint64_t)T0 < (uint64_t)T2 ||
140
 
                 (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) {
141
 
        xer_ca = 0;
142
 
    } else {
143
 
        xer_ca = 1;
144
 
    }
145
 
}
146
 
#endif
147
 
 
148
 
void do_addmeo (void)
149
 
{
150
 
    T1 = T0;
151
 
    T0 += xer_ca + (-1);
152
 
    xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31;
153
 
    xer_so |= xer_ov;
154
 
    if (likely(T1 != 0))
155
 
        xer_ca = 1;
156
 
    else
157
 
        xer_ca = 0;
158
 
}
159
 
 
160
 
#if defined(TARGET_PPC64)
161
 
void do_addmeo_64 (void)
162
 
{
163
 
    T1 = T0;
164
 
    T0 += xer_ca + (-1);
165
 
    xer_ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63;
166
 
    xer_so |= xer_ov;
167
 
    if (likely(T1 != 0))
168
 
        xer_ca = 1;
169
 
    else
170
 
        xer_ca = 0;
171
 
}
172
 
#endif
173
 
 
174
 
void do_divwo (void)
175
 
{
176
 
    if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
177
 
                 (int32_t)T1 == 0))) {
178
 
        xer_ov = 0;
179
 
        T0 = (int32_t)T0 / (int32_t)T1;
180
 
    } else {
181
 
        xer_ov = 1;
182
 
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
183
 
    }
184
 
    xer_so |= xer_ov;
185
 
}
186
 
 
187
 
#if defined(TARGET_PPC64)
188
 
void do_divdo (void)
189
 
{
190
 
    if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == (int64_t)-1LL) ||
191
 
                 (int64_t)T1 == 0))) {
192
 
        xer_ov = 0;
193
 
        T0 = (int64_t)T0 / (int64_t)T1;
194
 
    } else {
195
 
        xer_ov = 1;
196
 
        T0 = UINT64_MAX * ((uint64_t)T0 >> 63);
197
 
    }
198
 
    xer_so |= xer_ov;
199
 
}
200
 
#endif
201
 
 
202
 
void do_divwuo (void)
203
 
{
204
 
    if (likely((uint32_t)T1 != 0)) {
205
 
        xer_ov = 0;
206
 
        T0 = (uint32_t)T0 / (uint32_t)T1;
207
 
    } else {
208
 
        xer_ov = 1;
209
 
        xer_so = 1;
210
 
        T0 = 0;
211
 
    }
212
 
}
213
 
 
214
 
#if defined(TARGET_PPC64)
215
 
void do_divduo (void)
216
 
{
217
 
    if (likely((uint64_t)T1 != 0)) {
218
 
        xer_ov = 0;
219
 
        T0 = (uint64_t)T0 / (uint64_t)T1;
220
 
    } else {
221
 
        xer_ov = 1;
222
 
        xer_so = 1;
223
 
        T0 = 0;
224
 
    }
225
 
}
226
 
#endif
227
 
 
228
 
void do_mullwo (void)
229
 
{
230
 
    int64_t res = (int64_t)T0 * (int64_t)T1;
231
 
 
232
 
    if (likely((int32_t)res == res)) {
233
 
        xer_ov = 0;
234
 
    } else {
235
 
        xer_ov = 1;
236
 
        xer_so = 1;
237
 
    }
238
 
    T0 = (int32_t)res;
239
 
}
240
 
 
241
 
#if defined(TARGET_PPC64)
242
 
void do_mulldo (void)
 
390
#if defined(TARGET_PPC64)
 
391
 
 
392
/* multiply high word */
 
393
uint64_t helper_mulhd (uint64_t arg1, uint64_t arg2)
 
394
{
 
395
    uint64_t tl, th;
 
396
 
 
397
    muls64(&tl, &th, arg1, arg2);
 
398
    return th;
 
399
}
 
400
 
 
401
/* multiply high word unsigned */
 
402
uint64_t helper_mulhdu (uint64_t arg1, uint64_t arg2)
 
403
{
 
404
    uint64_t tl, th;
 
405
 
 
406
    mulu64(&tl, &th, arg1, arg2);
 
407
    return th;
 
408
}
 
409
 
 
410
uint64_t helper_mulldo (uint64_t arg1, uint64_t arg2)
243
411
{
244
412
    int64_t th;
245
413
    uint64_t tl;
246
414
 
247
 
    muls64(&tl, &th, T0, T1);
248
 
    T0 = (int64_t)tl;
 
415
    muls64(&tl, (uint64_t *)&th, arg1, arg2);
249
416
    /* If th != 0 && th != -1, then we had an overflow */
250
417
    if (likely((uint64_t)(th + 1) <= 1)) {
251
 
        xer_ov = 0;
252
 
    } else {
253
 
        xer_ov = 1;
254
 
    }
255
 
    xer_so |= xer_ov;
256
 
}
257
 
#endif
258
 
 
259
 
void do_nego (void)
260
 
{
261
 
    if (likely((int32_t)T0 != INT32_MIN)) {
262
 
        xer_ov = 0;
263
 
        T0 = -(int32_t)T0;
264
 
    } else {
265
 
        xer_ov = 1;
266
 
        xer_so = 1;
267
 
    }
268
 
}
269
 
 
270
 
#if defined(TARGET_PPC64)
271
 
void do_nego_64 (void)
272
 
{
273
 
    if (likely((int64_t)T0 != INT64_MIN)) {
274
 
        xer_ov = 0;
275
 
        T0 = -(int64_t)T0;
276
 
    } else {
277
 
        xer_ov = 1;
278
 
        xer_so = 1;
279
 
    }
280
 
}
281
 
#endif
282
 
 
283
 
void do_subfe (void)
284
 
{
285
 
    T0 = T1 + ~T0 + xer_ca;
286
 
    if (likely((uint32_t)T0 >= (uint32_t)T1 &&
287
 
               (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) {
288
 
        xer_ca = 0;
289
 
    } else {
290
 
        xer_ca = 1;
291
 
    }
292
 
}
293
 
 
294
 
#if defined(TARGET_PPC64)
295
 
void do_subfe_64 (void)
296
 
{
297
 
    T0 = T1 + ~T0 + xer_ca;
298
 
    if (likely((uint64_t)T0 >= (uint64_t)T1 &&
299
 
               (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) {
300
 
        xer_ca = 0;
301
 
    } else {
302
 
        xer_ca = 1;
303
 
    }
304
 
}
305
 
#endif
306
 
 
307
 
void do_subfmeo (void)
308
 
{
309
 
    T1 = T0;
310
 
    T0 = ~T0 + xer_ca - 1;
311
 
    xer_ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31;
312
 
    xer_so |= xer_ov;
313
 
    if (likely((uint32_t)T1 != UINT32_MAX))
314
 
        xer_ca = 1;
315
 
    else
316
 
        xer_ca = 0;
317
 
}
318
 
 
319
 
#if defined(TARGET_PPC64)
320
 
void do_subfmeo_64 (void)
321
 
{
322
 
    T1 = T0;
323
 
    T0 = ~T0 + xer_ca - 1;
324
 
    xer_ov = ((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0)) >> 63;
325
 
    xer_so |= xer_ov;
326
 
    if (likely((uint64_t)T1 != UINT64_MAX))
327
 
        xer_ca = 1;
328
 
    else
329
 
        xer_ca = 0;
330
 
}
331
 
#endif
332
 
 
333
 
void do_subfzeo (void)
334
 
{
335
 
    T1 = T0;
336
 
    T0 = ~T0 + xer_ca;
337
 
    xer_ov = (((uint32_t)~T1 ^ UINT32_MAX) &
338
 
              ((uint32_t)(~T1) ^ (uint32_t)T0)) >> 31;
339
 
    xer_so |= xer_ov;
340
 
    if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
341
 
        xer_ca = 0;
342
 
    } else {
343
 
        xer_ca = 1;
344
 
    }
345
 
}
346
 
 
347
 
#if defined(TARGET_PPC64)
348
 
void do_subfzeo_64 (void)
349
 
{
350
 
    T1 = T0;
351
 
    T0 = ~T0 + xer_ca;
352
 
    xer_ov = (((uint64_t)~T1 ^  UINT64_MAX) &
353
 
              ((uint64_t)(~T1) ^ (uint64_t)T0)) >> 63;
354
 
    xer_so |= xer_ov;
355
 
    if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
356
 
        xer_ca = 0;
357
 
    } else {
358
 
        xer_ca = 1;
359
 
    }
360
 
}
361
 
#endif
362
 
 
363
 
void do_cntlzw (void)
364
 
{
365
 
    T0 = clz32(T0);
366
 
}
367
 
 
368
 
#if defined(TARGET_PPC64)
369
 
void do_cntlzd (void)
370
 
{
371
 
    T0 = clz64(T0);
 
418
        env->xer &= ~(1 << XER_OV);
 
419
    } else {
 
420
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
 
421
    }
 
422
    return (int64_t)tl;
 
423
}
 
424
#endif
 
425
 
 
426
target_ulong helper_cntlzw (target_ulong t)
 
427
{
 
428
    return clz32(t);
 
429
}
 
430
 
 
431
#if defined(TARGET_PPC64)
 
432
target_ulong helper_cntlzd (target_ulong t)
 
433
{
 
434
    return clz64(t);
372
435
}
373
436
#endif
374
437
 
375
438
/* shift right arithmetic helper */
376
 
void do_sraw (void)
 
439
target_ulong helper_sraw (target_ulong value, target_ulong shift)
377
440
{
378
441
    int32_t ret;
379
442
 
380
 
    if (likely(!(T1 & 0x20UL))) {
381
 
        if (likely((uint32_t)T1 != 0)) {
382
 
            ret = (int32_t)T0 >> (T1 & 0x1fUL);
383
 
            if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
384
 
                xer_ca = 0;
 
443
    if (likely(!(shift & 0x20))) {
 
444
        if (likely((uint32_t)shift != 0)) {
 
445
            shift &= 0x1f;
 
446
            ret = (int32_t)value >> shift;
 
447
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
 
448
                env->xer &= ~(1 << XER_CA);
385
449
            } else {
386
 
                xer_ca = 1;
 
450
                env->xer |= (1 << XER_CA);
387
451
            }
388
452
        } else {
389
 
            ret = T0;
390
 
            xer_ca = 0;
 
453
            ret = (int32_t)value;
 
454
            env->xer &= ~(1 << XER_CA);
391
455
        }
392
456
    } else {
393
 
        ret = UINT32_MAX * ((uint32_t)T0 >> 31);
394
 
        if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
395
 
            xer_ca = 0;
 
457
        ret = (int32_t)value >> 31;
 
458
        if (ret) {
 
459
            env->xer |= (1 << XER_CA);
396
460
        } else {
397
 
            xer_ca = 1;
 
461
            env->xer &= ~(1 << XER_CA);
398
462
        }
399
463
    }
400
 
    T0 = ret;
 
464
    return (target_long)ret;
401
465
}
402
466
 
403
467
#if defined(TARGET_PPC64)
404
 
void do_srad (void)
 
468
target_ulong helper_srad (target_ulong value, target_ulong shift)
405
469
{
406
470
    int64_t ret;
407
471
 
408
 
    if (likely(!(T1 & 0x40UL))) {
409
 
        if (likely((uint64_t)T1 != 0)) {
410
 
            ret = (int64_t)T0 >> (T1 & 0x3FUL);
411
 
            if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) {
412
 
                xer_ca = 0;
 
472
    if (likely(!(shift & 0x40))) {
 
473
        if (likely((uint64_t)shift != 0)) {
 
474
            shift &= 0x3f;
 
475
            ret = (int64_t)value >> shift;
 
476
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
 
477
                env->xer &= ~(1 << XER_CA);
413
478
            } else {
414
 
                xer_ca = 1;
 
479
                env->xer |= (1 << XER_CA);
415
480
            }
416
481
        } else {
417
 
            ret = T0;
418
 
            xer_ca = 0;
 
482
            ret = (int64_t)value;
 
483
            env->xer &= ~(1 << XER_CA);
419
484
        }
420
485
    } else {
421
 
        ret = UINT64_MAX * ((uint64_t)T0 >> 63);
422
 
        if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) {
423
 
            xer_ca = 0;
 
486
        ret = (int64_t)value >> 63;
 
487
        if (ret) {
 
488
            env->xer |= (1 << XER_CA);
424
489
        } else {
425
 
            xer_ca = 1;
 
490
            env->xer &= ~(1 << XER_CA);
426
491
        }
427
492
    }
428
 
    T0 = ret;
 
493
    return ret;
429
494
}
430
495
#endif
431
496
 
432
 
void do_popcntb (void)
 
497
target_ulong helper_popcntb (target_ulong val)
433
498
{
434
 
    uint32_t ret;
435
 
    int i;
436
 
 
437
 
    ret = 0;
438
 
    for (i = 0; i < 32; i += 8)
439
 
        ret |= ctpop8((T0 >> i) & 0xFF) << i;
440
 
    T0 = ret;
 
499
    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
 
500
    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
 
501
    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
 
502
    return val;
441
503
}
442
504
 
443
505
#if defined(TARGET_PPC64)
444
 
void do_popcntb_64 (void)
 
506
target_ulong helper_popcntb_64 (target_ulong val)
445
507
{
446
 
    uint64_t ret;
447
 
    int i;
448
 
 
449
 
    ret = 0;
450
 
    for (i = 0; i < 64; i += 8)
451
 
        ret |= ctpop8((T0 >> i) & 0xFF) << i;
452
 
    T0 = ret;
 
508
    val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
 
509
    val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
 
510
    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
 
511
    return val;
453
512
}
454
513
#endif
455
514
 
456
515
/*****************************************************************************/
457
516
/* Floating point operations helpers */
458
 
static always_inline int fpisneg (float64 d)
459
 
{
460
 
    CPU_DoubleU u;
461
 
 
462
 
    u.d = d;
463
 
 
464
 
    return u.ll >> 63 != 0;
465
 
}
466
 
 
467
 
static always_inline int isden (float64 d)
 
517
uint64_t helper_float32_to_float64(uint32_t arg)
 
518
{
 
519
    CPU_FloatU f;
 
520
    CPU_DoubleU d;
 
521
    f.l = arg;
 
522
    d.d = float32_to_float64(f.f, &env->fp_status);
 
523
    return d.ll;
 
524
}
 
525
 
 
526
uint32_t helper_float64_to_float32(uint64_t arg)
 
527
{
 
528
    CPU_FloatU f;
 
529
    CPU_DoubleU d;
 
530
    d.ll = arg;
 
531
    f.f = float64_to_float32(d.d, &env->fp_status);
 
532
    return f.l;
 
533
}
 
534
 
 
535
static inline int isden(float64 d)
468
536
{
469
537
    CPU_DoubleU u;
470
538
 
473
541
    return ((u.ll >> 52) & 0x7FF) == 0;
474
542
}
475
543
 
476
 
static always_inline int iszero (float64 d)
477
 
{
478
 
    CPU_DoubleU u;
479
 
 
480
 
    u.d = d;
481
 
 
482
 
    return (u.ll & ~0x8000000000000000ULL) == 0;
483
 
}
484
 
 
485
 
static always_inline int isinfinity (float64 d)
486
 
{
487
 
    CPU_DoubleU u;
488
 
 
489
 
    u.d = d;
490
 
 
491
 
    return ((u.ll >> 52) & 0x7FF) == 0x7FF &&
492
 
        (u.ll & 0x000FFFFFFFFFFFFFULL) == 0;
493
 
}
494
 
 
495
 
#ifdef CONFIG_SOFTFLOAT
496
 
static always_inline int isfinite (float64 d)
497
 
{
498
 
    CPU_DoubleU u;
499
 
 
500
 
    u.d = d;
501
 
 
502
 
    return (((u.ll >> 52) & 0x7FF) != 0x7FF);
503
 
}
504
 
 
505
 
static always_inline int isnormal (float64 d)
506
 
{
507
 
    CPU_DoubleU u;
508
 
 
509
 
    u.d = d;
510
 
 
511
 
    uint32_t exp = (u.ll >> 52) & 0x7FF;
512
 
    return ((0 < exp) && (exp < 0x7FF));
513
 
}
514
 
#endif
515
 
 
516
 
void do_compute_fprf (int set_fprf)
517
 
{
 
544
uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf)
 
545
{
 
546
    CPU_DoubleU farg;
518
547
    int isneg;
519
 
 
520
 
    isneg = fpisneg(FT0);
521
 
    if (unlikely(float64_is_nan(FT0))) {
522
 
        if (float64_is_signaling_nan(FT0)) {
 
548
    int ret;
 
549
    farg.ll = arg;
 
550
    isneg = float64_is_neg(farg.d);
 
551
    if (unlikely(float64_is_nan(farg.d))) {
 
552
        if (float64_is_signaling_nan(farg.d)) {
523
553
            /* Signaling NaN: flags are undefined */
524
 
            T0 = 0x00;
 
554
            ret = 0x00;
525
555
        } else {
526
556
            /* Quiet NaN */
527
 
            T0 = 0x11;
 
557
            ret = 0x11;
528
558
        }
529
 
    } else if (unlikely(isinfinity(FT0))) {
 
559
    } else if (unlikely(float64_is_infinity(farg.d))) {
530
560
        /* +/- infinity */
531
561
        if (isneg)
532
 
            T0 = 0x09;
 
562
            ret = 0x09;
533
563
        else
534
 
            T0 = 0x05;
 
564
            ret = 0x05;
535
565
    } else {
536
 
        if (iszero(FT0)) {
 
566
        if (float64_is_zero(farg.d)) {
537
567
            /* +/- zero */
538
568
            if (isneg)
539
 
                T0 = 0x12;
 
569
                ret = 0x12;
540
570
            else
541
 
                T0 = 0x02;
 
571
                ret = 0x02;
542
572
        } else {
543
 
            if (isden(FT0)) {
 
573
            if (isden(farg.d)) {
544
574
                /* Denormalized numbers */
545
 
                T0 = 0x10;
 
575
                ret = 0x10;
546
576
            } else {
547
577
                /* Normalized numbers */
548
 
                T0 = 0x00;
 
578
                ret = 0x00;
549
579
            }
550
580
            if (isneg) {
551
 
                T0 |= 0x08;
 
581
                ret |= 0x08;
552
582
            } else {
553
 
                T0 |= 0x04;
 
583
                ret |= 0x04;
554
584
            }
555
585
        }
556
586
    }
557
587
    if (set_fprf) {
558
588
        /* We update FPSCR_FPRF */
559
589
        env->fpscr &= ~(0x1F << FPSCR_FPRF);
560
 
        env->fpscr |= T0 << FPSCR_FPRF;
 
590
        env->fpscr |= ret << FPSCR_FPRF;
561
591
    }
562
592
    /* We just need fpcc to update Rc1 */
563
 
    T0 &= 0xF;
 
593
    return ret & 0xF;
564
594
}
565
595
 
566
596
/* Floating-point invalid operations exception */
567
 
static always_inline void fload_invalid_op_excp (int op)
 
597
static inline uint64_t fload_invalid_op_excp(int op)
568
598
{
 
599
    uint64_t ret = 0;
569
600
    int ve;
570
601
 
571
602
    ve = fpscr_ve;
572
 
    if (op & POWERPC_EXCP_FP_VXSNAN) {
573
 
        /* Operation on signaling NaN */
 
603
    switch (op) {
 
604
    case POWERPC_EXCP_FP_VXSNAN:
574
605
        env->fpscr |= 1 << FPSCR_VXSNAN;
575
 
    }
576
 
    if (op & POWERPC_EXCP_FP_VXSOFT) {
577
 
        /* Software-defined condition */
 
606
        break;
 
607
    case POWERPC_EXCP_FP_VXSOFT:
578
608
        env->fpscr |= 1 << FPSCR_VXSOFT;
579
 
    }
580
 
    switch (op & ~(POWERPC_EXCP_FP_VXSOFT | POWERPC_EXCP_FP_VXSNAN)) {
 
609
        break;
581
610
    case POWERPC_EXCP_FP_VXISI:
582
611
        /* Magnitude subtraction of infinities */
583
612
        env->fpscr |= 1 << FPSCR_VXISI;
616
645
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
617
646
        if (ve == 0) {
618
647
            /* Set the result to quiet NaN */
619
 
            FT0 = UINT64_MAX;
 
648
            ret = 0xFFF8000000000000ULL;
620
649
            env->fpscr &= ~(0xF << FPSCR_FPCC);
621
650
            env->fpscr |= 0x11 << FPSCR_FPCC;
622
651
        }
627
656
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
628
657
        if (ve == 0) {
629
658
            /* Set the result to quiet NaN */
630
 
            FT0 = UINT64_MAX;
 
659
            ret = 0xFFF8000000000000ULL;
631
660
            env->fpscr &= ~(0xF << FPSCR_FPCC);
632
661
            env->fpscr |= 0x11 << FPSCR_FPCC;
633
662
        }
641
670
        /* Update the floating-point enabled exception summary */
642
671
        env->fpscr |= 1 << FPSCR_FEX;
643
672
        if (msr_fe0 != 0 || msr_fe1 != 0)
644
 
            do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
 
673
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
645
674
    }
 
675
    return ret;
646
676
}
647
677
 
648
 
static always_inline void float_zero_divide_excp (void)
 
678
static inline void float_zero_divide_excp(void)
649
679
{
650
 
    CPU_DoubleU u0, u1;
651
 
 
652
680
    env->fpscr |= 1 << FPSCR_ZX;
653
681
    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
654
682
    /* Update the floating-point exception summary */
657
685
        /* Update the floating-point enabled exception summary */
658
686
        env->fpscr |= 1 << FPSCR_FEX;
659
687
        if (msr_fe0 != 0 || msr_fe1 != 0) {
660
 
            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
661
 
                                   POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
 
688
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
 
689
                                       POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
662
690
        }
663
 
    } else {
664
 
        /* Set the result to infinity */
665
 
        u0.d = FT0;
666
 
        u1.d = FT1;
667
 
        u0.ll = ((u0.ll ^ u1.ll) & 0x8000000000000000ULL);
668
 
        u0.ll |= 0x7FFULL << 52;
669
 
        FT0 = u0.d;
670
691
    }
671
692
}
672
693
 
673
 
static always_inline void float_overflow_excp (void)
 
694
static inline void float_overflow_excp(void)
674
695
{
675
696
    env->fpscr |= 1 << FPSCR_OX;
676
697
    /* Update the floating-point exception summary */
688
709
    }
689
710
}
690
711
 
691
 
static always_inline void float_underflow_excp (void)
 
712
static inline void float_underflow_excp(void)
692
713
{
693
714
    env->fpscr |= 1 << FPSCR_UX;
694
715
    /* Update the floating-point exception summary */
703
724
    }
704
725
}
705
726
 
706
 
static always_inline void float_inexact_excp (void)
 
727
static inline void float_inexact_excp(void)
707
728
{
708
729
    env->fpscr |= 1 << FPSCR_XX;
709
730
    /* Update the floating-point exception summary */
717
738
    }
718
739
}
719
740
 
720
 
static always_inline void fpscr_set_rounding_mode (void)
 
741
static inline void fpscr_set_rounding_mode(void)
721
742
{
722
743
    int rnd_type;
723
744
 
744
765
    set_float_rounding_mode(rnd_type, &env->fp_status);
745
766
}
746
767
 
747
 
void do_fpscr_setbit (int bit)
 
768
void helper_fpscr_clrbit (uint32_t bit)
 
769
{
 
770
    int prev;
 
771
 
 
772
    prev = (env->fpscr >> bit) & 1;
 
773
    env->fpscr &= ~(1 << bit);
 
774
    if (prev == 1) {
 
775
        switch (bit) {
 
776
        case FPSCR_RN1:
 
777
        case FPSCR_RN:
 
778
            fpscr_set_rounding_mode();
 
779
            break;
 
780
        default:
 
781
            break;
 
782
        }
 
783
    }
 
784
}
 
785
 
 
786
void helper_fpscr_setbit (uint32_t bit)
748
787
{
749
788
    int prev;
750
789
 
859
898
    }
860
899
}
861
900
 
862
 
#if defined(WORDS_BIGENDIAN)
863
 
#define WORD0 0
864
 
#define WORD1 1
865
 
#else
866
 
#define WORD0 1
867
 
#define WORD1 0
868
 
#endif
869
 
void do_store_fpscr (uint32_t mask)
 
901
void helper_store_fpscr (uint64_t arg, uint32_t mask)
870
902
{
871
903
    /*
872
904
     * We use only the 32 LSB of the incoming fpr
873
905
     */
874
 
    CPU_DoubleU u;
875
906
    uint32_t prev, new;
876
907
    int i;
877
908
 
878
 
    u.d = FT0;
879
909
    prev = env->fpscr;
880
 
    new = u.l.lower;
881
 
    new &= ~0x90000000;
882
 
    new |= prev & 0x90000000;
883
 
    for (i = 0; i < 7; i++) {
 
910
    new = (uint32_t)arg;
 
911
    new &= ~0x60000000;
 
912
    new |= prev & 0x60000000;
 
913
    for (i = 0; i < 8; i++) {
884
914
        if (mask & (1 << i)) {
885
915
            env->fpscr &= ~(0xF << (4 * i));
886
916
            env->fpscr |= new & (0xF << (4 * i));
901
931
        env->fpscr &= ~(1 << FPSCR_FEX);
902
932
    fpscr_set_rounding_mode();
903
933
}
904
 
#undef WORD0
905
 
#undef WORD1
906
 
 
907
 
#ifdef CONFIG_SOFTFLOAT
908
 
void do_float_check_status (void)
909
 
{
910
 
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
911
 
        (env->error_code & POWERPC_EXCP_FP)) {
912
 
        /* Differred floating-point exception after target FPR update */
913
 
        if (msr_fe0 != 0 || msr_fe1 != 0)
914
 
            do_raise_exception_err(env->exception_index, env->error_code);
915
 
    } else if (env->fp_status.float_exception_flags & float_flag_overflow) {
916
 
        float_overflow_excp();
917
 
    } else if (env->fp_status.float_exception_flags & float_flag_underflow) {
918
 
        float_underflow_excp();
919
 
    } else if (env->fp_status.float_exception_flags & float_flag_inexact) {
920
 
        float_inexact_excp();
921
 
    }
922
 
}
923
 
#endif
924
 
 
 
934
 
 
935
void helper_float_check_status (void)
 
936
{
 
937
#ifdef CONFIG_SOFTFLOAT
 
938
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
 
939
        (env->error_code & POWERPC_EXCP_FP)) {
 
940
        /* Differred floating-point exception after target FPR update */
 
941
        if (msr_fe0 != 0 || msr_fe1 != 0)
 
942
            helper_raise_exception_err(env->exception_index, env->error_code);
 
943
    } else {
 
944
        int status = get_float_exception_flags(&env->fp_status);
 
945
        if (status & float_flag_divbyzero) {
 
946
            float_zero_divide_excp();
 
947
        } else if (status & float_flag_overflow) {
 
948
            float_overflow_excp();
 
949
        } else if (status & float_flag_underflow) {
 
950
            float_underflow_excp();
 
951
        } else if (status & float_flag_inexact) {
 
952
            float_inexact_excp();
 
953
        }
 
954
    }
 
955
#else
 
956
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
 
957
        (env->error_code & POWERPC_EXCP_FP)) {
 
958
        /* Differred floating-point exception after target FPR update */
 
959
        if (msr_fe0 != 0 || msr_fe1 != 0)
 
960
            helper_raise_exception_err(env->exception_index, env->error_code);
 
961
    }
 
962
#endif
 
963
}
 
964
 
 
965
#ifdef CONFIG_SOFTFLOAT
 
966
void helper_reset_fpstatus (void)
 
967
{
 
968
    set_float_exception_flags(0, &env->fp_status);
 
969
}
 
970
#endif
 
971
 
 
972
/* fadd - fadd. */
 
973
uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
 
974
{
 
975
    CPU_DoubleU farg1, farg2;
 
976
 
 
977
    farg1.ll = arg1;
 
978
    farg2.ll = arg2;
925
979
#if USE_PRECISE_EMULATION
926
 
void do_fadd (void)
927
 
{
928
 
    if (unlikely(float64_is_signaling_nan(FT0) ||
929
 
                 float64_is_signaling_nan(FT1))) {
 
980
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
 
981
                 float64_is_signaling_nan(farg2.d))) {
930
982
        /* sNaN addition */
931
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
932
 
    } else if (likely(isfinite(FT0) || isfinite(FT1) ||
933
 
                      fpisneg(FT0) == fpisneg(FT1))) {
934
 
        FT0 = float64_add(FT0, FT1, &env->fp_status);
 
983
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
984
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
 
985
                      float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
 
986
        /* Magnitude subtraction of infinities */
 
987
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
935
988
    } else {
936
 
        /* Magnitude subtraction of infinities */
937
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
 
989
        farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
938
990
    }
 
991
#else
 
992
    farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
 
993
#endif
 
994
    return farg1.ll;
939
995
}
940
996
 
941
 
void do_fsub (void)
942
 
{
943
 
    if (unlikely(float64_is_signaling_nan(FT0) ||
944
 
                 float64_is_signaling_nan(FT1))) {
 
997
/* fsub - fsub. */
 
998
uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
 
999
{
 
1000
    CPU_DoubleU farg1, farg2;
 
1001
 
 
1002
    farg1.ll = arg1;
 
1003
    farg2.ll = arg2;
 
1004
#if USE_PRECISE_EMULATION
 
1005
{
 
1006
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
 
1007
                 float64_is_signaling_nan(farg2.d))) {
945
1008
        /* sNaN subtraction */
946
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
947
 
    } else if (likely(isfinite(FT0) || isfinite(FT1) ||
948
 
                      fpisneg(FT0) != fpisneg(FT1))) {
949
 
        FT0 = float64_sub(FT0, FT1, &env->fp_status);
 
1009
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1010
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
 
1011
                      float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
 
1012
        /* Magnitude subtraction of infinities */
 
1013
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
950
1014
    } else {
951
 
        /* Magnitude subtraction of infinities */
952
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
 
1015
        farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
953
1016
    }
954
1017
}
 
1018
#else
 
1019
    farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
 
1020
#endif
 
1021
    return farg1.ll;
 
1022
}
955
1023
 
956
 
void do_fmul (void)
 
1024
/* fmul - fmul. */
 
1025
uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
957
1026
{
958
 
    if (unlikely(float64_is_signaling_nan(FT0) ||
959
 
                 float64_is_signaling_nan(FT1))) {
 
1027
    CPU_DoubleU farg1, farg2;
 
1028
 
 
1029
    farg1.ll = arg1;
 
1030
    farg2.ll = arg2;
 
1031
#if USE_PRECISE_EMULATION
 
1032
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
 
1033
                 float64_is_signaling_nan(farg2.d))) {
960
1034
        /* sNaN multiplication */
961
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
962
 
    } else if (unlikely((isinfinity(FT0) && iszero(FT1)) ||
963
 
                        (iszero(FT0) && isinfinity(FT1)))) {
 
1035
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1036
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
 
1037
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
964
1038
        /* Multiplication of zero by infinity */
965
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
 
1039
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
966
1040
    } else {
967
 
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
 
1041
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
968
1042
    }
 
1043
#else
 
1044
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
 
1045
#endif
 
1046
    return farg1.ll;
969
1047
}
970
1048
 
971
 
void do_fdiv (void)
 
1049
/* fdiv - fdiv. */
 
1050
uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
972
1051
{
973
 
    if (unlikely(float64_is_signaling_nan(FT0) ||
974
 
                 float64_is_signaling_nan(FT1))) {
 
1052
    CPU_DoubleU farg1, farg2;
 
1053
 
 
1054
    farg1.ll = arg1;
 
1055
    farg2.ll = arg2;
 
1056
#if USE_PRECISE_EMULATION
 
1057
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
 
1058
                 float64_is_signaling_nan(farg2.d))) {
975
1059
        /* sNaN division */
976
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
977
 
    } else if (unlikely(isinfinity(FT0) && isinfinity(FT1))) {
 
1060
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1061
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
978
1062
        /* Division of infinity by infinity */
979
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
980
 
    } else if (unlikely(iszero(FT1))) {
981
 
        if (iszero(FT0)) {
982
 
            /* Division of zero by zero */
983
 
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
984
 
        } else {
985
 
            /* Division by zero */
986
 
            float_zero_divide_excp();
987
 
        }
988
 
    } else {
989
 
        FT0 = float64_div(FT0, FT1, &env->fp_status);
990
 
    }
991
 
}
992
 
#endif /* USE_PRECISE_EMULATION */
993
 
 
994
 
void do_fctiw (void)
995
 
{
996
 
    CPU_DoubleU p;
997
 
 
998
 
    if (unlikely(float64_is_signaling_nan(FT0))) {
999
 
        /* sNaN conversion */
1000
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1001
 
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1002
 
        /* qNan / infinity conversion */
1003
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1004
 
    } else {
1005
 
        p.ll = float64_to_int32(FT0, &env->fp_status);
1006
 
#if USE_PRECISE_EMULATION
1007
 
        /* XXX: higher bits are not supposed to be significant.
1008
 
         *     to make tests easier, return the same as a real PowerPC 750
1009
 
         */
1010
 
        p.ll |= 0xFFF80000ULL << 32;
1011
 
#endif
1012
 
        FT0 = p.d;
1013
 
    }
1014
 
}
1015
 
 
1016
 
void do_fctiwz (void)
1017
 
{
1018
 
    CPU_DoubleU p;
1019
 
 
1020
 
    if (unlikely(float64_is_signaling_nan(FT0))) {
1021
 
        /* sNaN conversion */
1022
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1023
 
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1024
 
        /* qNan / infinity conversion */
1025
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1026
 
    } else {
1027
 
        p.ll = float64_to_int32_round_to_zero(FT0, &env->fp_status);
1028
 
#if USE_PRECISE_EMULATION
1029
 
        /* XXX: higher bits are not supposed to be significant.
1030
 
         *     to make tests easier, return the same as a real PowerPC 750
1031
 
         */
1032
 
        p.ll |= 0xFFF80000ULL << 32;
1033
 
#endif
1034
 
        FT0 = p.d;
1035
 
    }
 
1063
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
 
1064
    } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
 
1065
        /* Division of zero by zero */
 
1066
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
 
1067
    } else {
 
1068
        farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
 
1069
    }
 
1070
#else
 
1071
    farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
 
1072
#endif
 
1073
    return farg1.ll;
 
1074
}
 
1075
 
 
1076
/* fabs */
 
1077
uint64_t helper_fabs (uint64_t arg)
 
1078
{
 
1079
    CPU_DoubleU farg;
 
1080
 
 
1081
    farg.ll = arg;
 
1082
    farg.d = float64_abs(farg.d);
 
1083
    return farg.ll;
 
1084
}
 
1085
 
 
1086
/* fnabs */
 
1087
uint64_t helper_fnabs (uint64_t arg)
 
1088
{
 
1089
    CPU_DoubleU farg;
 
1090
 
 
1091
    farg.ll = arg;
 
1092
    farg.d = float64_abs(farg.d);
 
1093
    farg.d = float64_chs(farg.d);
 
1094
    return farg.ll;
 
1095
}
 
1096
 
 
1097
/* fneg */
 
1098
uint64_t helper_fneg (uint64_t arg)
 
1099
{
 
1100
    CPU_DoubleU farg;
 
1101
 
 
1102
    farg.ll = arg;
 
1103
    farg.d = float64_chs(farg.d);
 
1104
    return farg.ll;
 
1105
}
 
1106
 
 
1107
/* fctiw - fctiw. */
 
1108
uint64_t helper_fctiw (uint64_t arg)
 
1109
{
 
1110
    CPU_DoubleU farg;
 
1111
    farg.ll = arg;
 
1112
 
 
1113
    if (unlikely(float64_is_signaling_nan(farg.d))) {
 
1114
        /* sNaN conversion */
 
1115
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
 
1116
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
 
1117
        /* qNan / infinity conversion */
 
1118
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
 
1119
    } else {
 
1120
        farg.ll = float64_to_int32(farg.d, &env->fp_status);
 
1121
#if USE_PRECISE_EMULATION
 
1122
        /* XXX: higher bits are not supposed to be significant.
 
1123
         *     to make tests easier, return the same as a real PowerPC 750
 
1124
         */
 
1125
        farg.ll |= 0xFFF80000ULL << 32;
 
1126
#endif
 
1127
    }
 
1128
    return farg.ll;
 
1129
}
 
1130
 
 
1131
/* fctiwz - fctiwz. */
 
1132
uint64_t helper_fctiwz (uint64_t arg)
 
1133
{
 
1134
    CPU_DoubleU farg;
 
1135
    farg.ll = arg;
 
1136
 
 
1137
    if (unlikely(float64_is_signaling_nan(farg.d))) {
 
1138
        /* sNaN conversion */
 
1139
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
 
1140
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
 
1141
        /* qNan / infinity conversion */
 
1142
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
 
1143
    } else {
 
1144
        farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
 
1145
#if USE_PRECISE_EMULATION
 
1146
        /* XXX: higher bits are not supposed to be significant.
 
1147
         *     to make tests easier, return the same as a real PowerPC 750
 
1148
         */
 
1149
        farg.ll |= 0xFFF80000ULL << 32;
 
1150
#endif
 
1151
    }
 
1152
    return farg.ll;
1036
1153
}
1037
1154
 
1038
1155
#if defined(TARGET_PPC64)
1039
 
void do_fcfid (void)
1040
 
{
1041
 
    CPU_DoubleU p;
1042
 
 
1043
 
    p.d = FT0;
1044
 
    FT0 = int64_to_float64(p.ll, &env->fp_status);
1045
 
}
1046
 
 
1047
 
void do_fctid (void)
1048
 
{
1049
 
    CPU_DoubleU p;
1050
 
 
1051
 
    if (unlikely(float64_is_signaling_nan(FT0))) {
1052
 
        /* sNaN conversion */
1053
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1054
 
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1055
 
        /* qNan / infinity conversion */
1056
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1057
 
    } else {
1058
 
        p.ll = float64_to_int64(FT0, &env->fp_status);
1059
 
        FT0 = p.d;
1060
 
    }
1061
 
}
1062
 
 
1063
 
void do_fctidz (void)
1064
 
{
1065
 
    CPU_DoubleU p;
1066
 
 
1067
 
    if (unlikely(float64_is_signaling_nan(FT0))) {
1068
 
        /* sNaN conversion */
1069
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1070
 
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1071
 
        /* qNan / infinity conversion */
1072
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1073
 
    } else {
1074
 
        p.ll = float64_to_int64_round_to_zero(FT0, &env->fp_status);
1075
 
        FT0 = p.d;
1076
 
    }
 
1156
/* fcfid - fcfid. */
 
1157
uint64_t helper_fcfid (uint64_t arg)
 
1158
{
 
1159
    CPU_DoubleU farg;
 
1160
    farg.d = int64_to_float64(arg, &env->fp_status);
 
1161
    return farg.ll;
 
1162
}
 
1163
 
 
1164
/* fctid - fctid. */
 
1165
uint64_t helper_fctid (uint64_t arg)
 
1166
{
 
1167
    CPU_DoubleU farg;
 
1168
    farg.ll = arg;
 
1169
 
 
1170
    if (unlikely(float64_is_signaling_nan(farg.d))) {
 
1171
        /* sNaN conversion */
 
1172
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
 
1173
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
 
1174
        /* qNan / infinity conversion */
 
1175
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
 
1176
    } else {
 
1177
        farg.ll = float64_to_int64(farg.d, &env->fp_status);
 
1178
    }
 
1179
    return farg.ll;
 
1180
}
 
1181
 
 
1182
/* fctidz - fctidz. */
 
1183
uint64_t helper_fctidz (uint64_t arg)
 
1184
{
 
1185
    CPU_DoubleU farg;
 
1186
    farg.ll = arg;
 
1187
 
 
1188
    if (unlikely(float64_is_signaling_nan(farg.d))) {
 
1189
        /* sNaN conversion */
 
1190
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
 
1191
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
 
1192
        /* qNan / infinity conversion */
 
1193
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
 
1194
    } else {
 
1195
        farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
 
1196
    }
 
1197
    return farg.ll;
1077
1198
}
1078
1199
 
1079
1200
#endif
1080
1201
 
1081
 
static always_inline void do_fri (int rounding_mode)
 
1202
static inline uint64_t do_fri(uint64_t arg, int rounding_mode)
1082
1203
{
1083
 
    if (unlikely(float64_is_signaling_nan(FT0))) {
 
1204
    CPU_DoubleU farg;
 
1205
    farg.ll = arg;
 
1206
 
 
1207
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1084
1208
        /* sNaN round */
1085
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1086
 
    } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
 
1209
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
 
1210
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1087
1211
        /* qNan / infinity round */
1088
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
 
1212
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1089
1213
    } else {
1090
1214
        set_float_rounding_mode(rounding_mode, &env->fp_status);
1091
 
        FT0 = float64_round_to_int(FT0, &env->fp_status);
 
1215
        farg.ll = float64_round_to_int(farg.d, &env->fp_status);
1092
1216
        /* Restore rounding mode from FPSCR */
1093
1217
        fpscr_set_rounding_mode();
1094
1218
    }
1095
 
}
1096
 
 
1097
 
void do_frin (void)
1098
 
{
1099
 
    do_fri(float_round_nearest_even);
1100
 
}
1101
 
 
1102
 
void do_friz (void)
1103
 
{
1104
 
    do_fri(float_round_to_zero);
1105
 
}
1106
 
 
1107
 
void do_frip (void)
1108
 
{
1109
 
    do_fri(float_round_up);
1110
 
}
1111
 
 
1112
 
void do_frim (void)
1113
 
{
1114
 
    do_fri(float_round_down);
1115
 
}
1116
 
 
1117
 
#if USE_PRECISE_EMULATION
1118
 
void do_fmadd (void)
1119
 
{
1120
 
    if (unlikely(float64_is_signaling_nan(FT0) ||
1121
 
                 float64_is_signaling_nan(FT1) ||
1122
 
                 float64_is_signaling_nan(FT2))) {
1123
 
        /* sNaN operation */
1124
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1125
 
    } else {
1126
 
#ifdef FLOAT128
1127
 
        /* This is the way the PowerPC specification defines it */
1128
 
        float128 ft0_128, ft1_128;
1129
 
 
1130
 
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1131
 
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1132
 
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1133
 
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1134
 
        ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1135
 
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1136
 
#else
1137
 
        /* This is OK on x86 hosts */
1138
 
        FT0 = (FT0 * FT1) + FT2;
1139
 
#endif
1140
 
    }
1141
 
}
1142
 
 
1143
 
void do_fmsub (void)
1144
 
{
1145
 
    if (unlikely(float64_is_signaling_nan(FT0) ||
1146
 
                 float64_is_signaling_nan(FT1) ||
1147
 
                 float64_is_signaling_nan(FT2))) {
1148
 
        /* sNaN operation */
1149
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1150
 
    } else {
1151
 
#ifdef FLOAT128
1152
 
        /* This is the way the PowerPC specification defines it */
1153
 
        float128 ft0_128, ft1_128;
1154
 
 
1155
 
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1156
 
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1157
 
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1158
 
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1159
 
        ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1160
 
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1161
 
#else
1162
 
        /* This is OK on x86 hosts */
1163
 
        FT0 = (FT0 * FT1) - FT2;
1164
 
#endif
1165
 
    }
1166
 
}
1167
 
#endif /* USE_PRECISE_EMULATION */
1168
 
 
1169
 
void do_fnmadd (void)
1170
 
{
1171
 
    if (unlikely(float64_is_signaling_nan(FT0) ||
1172
 
                 float64_is_signaling_nan(FT1) ||
1173
 
                 float64_is_signaling_nan(FT2))) {
1174
 
        /* sNaN operation */
1175
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1176
 
    } else {
1177
 
#if USE_PRECISE_EMULATION
1178
 
#ifdef FLOAT128
1179
 
        /* This is the way the PowerPC specification defines it */
1180
 
        float128 ft0_128, ft1_128;
1181
 
 
1182
 
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1183
 
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1184
 
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1185
 
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1186
 
        ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1187
 
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1188
 
#else
1189
 
        /* This is OK on x86 hosts */
1190
 
        FT0 = (FT0 * FT1) + FT2;
1191
 
#endif
1192
 
#else
1193
 
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
1194
 
        FT0 = float64_add(FT0, FT2, &env->fp_status);
1195
 
#endif
1196
 
        if (likely(!isnan(FT0)))
1197
 
            FT0 = float64_chs(FT0);
1198
 
    }
1199
 
}
1200
 
 
1201
 
void do_fnmsub (void)
1202
 
{
1203
 
    if (unlikely(float64_is_signaling_nan(FT0) ||
1204
 
                 float64_is_signaling_nan(FT1) ||
1205
 
                 float64_is_signaling_nan(FT2))) {
1206
 
        /* sNaN operation */
1207
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1208
 
    } else {
1209
 
#if USE_PRECISE_EMULATION
1210
 
#ifdef FLOAT128
1211
 
        /* This is the way the PowerPC specification defines it */
1212
 
        float128 ft0_128, ft1_128;
1213
 
 
1214
 
        ft0_128 = float64_to_float128(FT0, &env->fp_status);
1215
 
        ft1_128 = float64_to_float128(FT1, &env->fp_status);
1216
 
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1217
 
        ft1_128 = float64_to_float128(FT2, &env->fp_status);
1218
 
        ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1219
 
        FT0 = float128_to_float64(ft0_128, &env->fp_status);
1220
 
#else
1221
 
        /* This is OK on x86 hosts */
1222
 
        FT0 = (FT0 * FT1) - FT2;
1223
 
#endif
1224
 
#else
1225
 
        FT0 = float64_mul(FT0, FT1, &env->fp_status);
1226
 
        FT0 = float64_sub(FT0, FT2, &env->fp_status);
1227
 
#endif
1228
 
        if (likely(!isnan(FT0)))
1229
 
            FT0 = float64_chs(FT0);
1230
 
    }
1231
 
}
1232
 
 
1233
 
#if USE_PRECISE_EMULATION
1234
 
void do_frsp (void)
1235
 
{
1236
 
    if (unlikely(float64_is_signaling_nan(FT0))) {
1237
 
        /* sNaN square root */
1238
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1239
 
    } else {
1240
 
        FT0 = float64_to_float32(FT0, &env->fp_status);
1241
 
    }
1242
 
}
1243
 
#endif /* USE_PRECISE_EMULATION */
1244
 
 
1245
 
void do_fsqrt (void)
1246
 
{
1247
 
    if (unlikely(float64_is_signaling_nan(FT0))) {
1248
 
        /* sNaN square root */
1249
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1250
 
    } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
 
1219
    return farg.ll;
 
1220
}
 
1221
 
 
1222
uint64_t helper_frin (uint64_t arg)
 
1223
{
 
1224
    return do_fri(arg, float_round_nearest_even);
 
1225
}
 
1226
 
 
1227
uint64_t helper_friz (uint64_t arg)
 
1228
{
 
1229
    return do_fri(arg, float_round_to_zero);
 
1230
}
 
1231
 
 
1232
uint64_t helper_frip (uint64_t arg)
 
1233
{
 
1234
    return do_fri(arg, float_round_up);
 
1235
}
 
1236
 
 
1237
uint64_t helper_frim (uint64_t arg)
 
1238
{
 
1239
    return do_fri(arg, float_round_down);
 
1240
}
 
1241
 
 
1242
/* fmadd - fmadd. */
 
1243
uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
 
1244
{
 
1245
    CPU_DoubleU farg1, farg2, farg3;
 
1246
 
 
1247
    farg1.ll = arg1;
 
1248
    farg2.ll = arg2;
 
1249
    farg3.ll = arg3;
 
1250
#if USE_PRECISE_EMULATION
 
1251
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
 
1252
                 float64_is_signaling_nan(farg2.d) ||
 
1253
                 float64_is_signaling_nan(farg3.d))) {
 
1254
        /* sNaN operation */
 
1255
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1256
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
 
1257
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
 
1258
        /* Multiplication of zero by infinity */
 
1259
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
 
1260
    } else {
 
1261
#ifdef FLOAT128
 
1262
        /* This is the way the PowerPC specification defines it */
 
1263
        float128 ft0_128, ft1_128;
 
1264
 
 
1265
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
 
1266
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
 
1267
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
 
1268
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
 
1269
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
 
1270
            /* Magnitude subtraction of infinities */
 
1271
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
 
1272
        } else {
 
1273
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
 
1274
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
 
1275
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
 
1276
        }
 
1277
#else
 
1278
        /* This is OK on x86 hosts */
 
1279
        farg1.d = (farg1.d * farg2.d) + farg3.d;
 
1280
#endif
 
1281
    }
 
1282
#else
 
1283
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
 
1284
    farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
 
1285
#endif
 
1286
    return farg1.ll;
 
1287
}
 
1288
 
 
1289
/* fmsub - fmsub. */
 
1290
uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
 
1291
{
 
1292
    CPU_DoubleU farg1, farg2, farg3;
 
1293
 
 
1294
    farg1.ll = arg1;
 
1295
    farg2.ll = arg2;
 
1296
    farg3.ll = arg3;
 
1297
#if USE_PRECISE_EMULATION
 
1298
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
 
1299
                 float64_is_signaling_nan(farg2.d) ||
 
1300
                 float64_is_signaling_nan(farg3.d))) {
 
1301
        /* sNaN operation */
 
1302
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1303
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
 
1304
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
 
1305
        /* Multiplication of zero by infinity */
 
1306
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
 
1307
    } else {
 
1308
#ifdef FLOAT128
 
1309
        /* This is the way the PowerPC specification defines it */
 
1310
        float128 ft0_128, ft1_128;
 
1311
 
 
1312
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
 
1313
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
 
1314
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
 
1315
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
 
1316
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
 
1317
            /* Magnitude subtraction of infinities */
 
1318
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
 
1319
        } else {
 
1320
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
 
1321
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
 
1322
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
 
1323
        }
 
1324
#else
 
1325
        /* This is OK on x86 hosts */
 
1326
        farg1.d = (farg1.d * farg2.d) - farg3.d;
 
1327
#endif
 
1328
    }
 
1329
#else
 
1330
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
 
1331
    farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
 
1332
#endif
 
1333
    return farg1.ll;
 
1334
}
 
1335
 
 
1336
/* fnmadd - fnmadd. */
 
1337
uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
 
1338
{
 
1339
    CPU_DoubleU farg1, farg2, farg3;
 
1340
 
 
1341
    farg1.ll = arg1;
 
1342
    farg2.ll = arg2;
 
1343
    farg3.ll = arg3;
 
1344
 
 
1345
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
 
1346
                 float64_is_signaling_nan(farg2.d) ||
 
1347
                 float64_is_signaling_nan(farg3.d))) {
 
1348
        /* sNaN operation */
 
1349
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1350
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
 
1351
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
 
1352
        /* Multiplication of zero by infinity */
 
1353
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
 
1354
    } else {
 
1355
#if USE_PRECISE_EMULATION
 
1356
#ifdef FLOAT128
 
1357
        /* This is the way the PowerPC specification defines it */
 
1358
        float128 ft0_128, ft1_128;
 
1359
 
 
1360
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
 
1361
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
 
1362
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
 
1363
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
 
1364
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
 
1365
            /* Magnitude subtraction of infinities */
 
1366
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
 
1367
        } else {
 
1368
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
 
1369
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
 
1370
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
 
1371
        }
 
1372
#else
 
1373
        /* This is OK on x86 hosts */
 
1374
        farg1.d = (farg1.d * farg2.d) + farg3.d;
 
1375
#endif
 
1376
#else
 
1377
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
 
1378
        farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
 
1379
#endif
 
1380
        if (likely(!float64_is_nan(farg1.d)))
 
1381
            farg1.d = float64_chs(farg1.d);
 
1382
    }
 
1383
    return farg1.ll;
 
1384
}
 
1385
 
 
1386
/* fnmsub - fnmsub. */
 
1387
uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
 
1388
{
 
1389
    CPU_DoubleU farg1, farg2, farg3;
 
1390
 
 
1391
    farg1.ll = arg1;
 
1392
    farg2.ll = arg2;
 
1393
    farg3.ll = arg3;
 
1394
 
 
1395
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
 
1396
                 float64_is_signaling_nan(farg2.d) ||
 
1397
                 float64_is_signaling_nan(farg3.d))) {
 
1398
        /* sNaN operation */
 
1399
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1400
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
 
1401
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
 
1402
        /* Multiplication of zero by infinity */
 
1403
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
 
1404
    } else {
 
1405
#if USE_PRECISE_EMULATION
 
1406
#ifdef FLOAT128
 
1407
        /* This is the way the PowerPC specification defines it */
 
1408
        float128 ft0_128, ft1_128;
 
1409
 
 
1410
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
 
1411
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
 
1412
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
 
1413
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
 
1414
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
 
1415
            /* Magnitude subtraction of infinities */
 
1416
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
 
1417
        } else {
 
1418
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
 
1419
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
 
1420
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
 
1421
        }
 
1422
#else
 
1423
        /* This is OK on x86 hosts */
 
1424
        farg1.d = (farg1.d * farg2.d) - farg3.d;
 
1425
#endif
 
1426
#else
 
1427
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
 
1428
        farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
 
1429
#endif
 
1430
        if (likely(!float64_is_nan(farg1.d)))
 
1431
            farg1.d = float64_chs(farg1.d);
 
1432
    }
 
1433
    return farg1.ll;
 
1434
}
 
1435
 
 
1436
/* frsp - frsp. */
 
1437
uint64_t helper_frsp (uint64_t arg)
 
1438
{
 
1439
    CPU_DoubleU farg;
 
1440
    float32 f32;
 
1441
    farg.ll = arg;
 
1442
 
 
1443
#if USE_PRECISE_EMULATION
 
1444
    if (unlikely(float64_is_signaling_nan(farg.d))) {
 
1445
        /* sNaN square root */
 
1446
       farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1447
    } else {
 
1448
       f32 = float64_to_float32(farg.d, &env->fp_status);
 
1449
       farg.d = float32_to_float64(f32, &env->fp_status);
 
1450
    }
 
1451
#else
 
1452
    f32 = float64_to_float32(farg.d, &env->fp_status);
 
1453
    farg.d = float32_to_float64(f32, &env->fp_status);
 
1454
#endif
 
1455
    return farg.ll;
 
1456
}
 
1457
 
 
1458
/* fsqrt - fsqrt. */
 
1459
uint64_t helper_fsqrt (uint64_t arg)
 
1460
{
 
1461
    CPU_DoubleU farg;
 
1462
    farg.ll = arg;
 
1463
 
 
1464
    if (unlikely(float64_is_signaling_nan(farg.d))) {
 
1465
        /* sNaN square root */
 
1466
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1467
    } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1251
1468
        /* Square root of a negative nonzero number */
1252
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1253
 
    } else {
1254
 
        FT0 = float64_sqrt(FT0, &env->fp_status);
1255
 
    }
1256
 
}
1257
 
 
1258
 
void do_fre (void)
1259
 
{
1260
 
    CPU_DoubleU p;
1261
 
 
1262
 
    if (unlikely(float64_is_signaling_nan(FT0))) {
1263
 
        /* sNaN reciprocal */
1264
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1265
 
    } else if (unlikely(iszero(FT0))) {
1266
 
        /* Zero reciprocal */
1267
 
        float_zero_divide_excp();
1268
 
    } else if (likely(isnormal(FT0))) {
1269
 
        FT0 = float64_div(1.0, FT0, &env->fp_status);
1270
 
    } else {
1271
 
        p.d = FT0;
1272
 
        if (p.ll == 0x8000000000000000ULL) {
1273
 
            p.ll = 0xFFF0000000000000ULL;
1274
 
        } else if (p.ll == 0x0000000000000000ULL) {
1275
 
            p.ll = 0x7FF0000000000000ULL;
1276
 
        } else if (isnan(FT0)) {
1277
 
            p.ll = 0x7FF8000000000000ULL;
1278
 
        } else if (fpisneg(FT0)) {
1279
 
            p.ll = 0x8000000000000000ULL;
1280
 
        } else {
1281
 
            p.ll = 0x0000000000000000ULL;
1282
 
        }
1283
 
        FT0 = p.d;
1284
 
    }
1285
 
}
1286
 
 
1287
 
void do_fres (void)
1288
 
{
1289
 
    CPU_DoubleU p;
1290
 
 
1291
 
    if (unlikely(float64_is_signaling_nan(FT0))) {
1292
 
        /* sNaN reciprocal */
1293
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1294
 
    } else if (unlikely(iszero(FT0))) {
1295
 
        /* Zero reciprocal */
1296
 
        float_zero_divide_excp();
1297
 
    } else if (likely(isnormal(FT0))) {
1298
 
#if USE_PRECISE_EMULATION
1299
 
        FT0 = float64_div(1.0, FT0, &env->fp_status);
1300
 
        FT0 = float64_to_float32(FT0, &env->fp_status);
1301
 
#else
1302
 
        FT0 = float32_div(1.0, FT0, &env->fp_status);
1303
 
#endif
1304
 
    } else {
1305
 
        p.d = FT0;
1306
 
        if (p.ll == 0x8000000000000000ULL) {
1307
 
            p.ll = 0xFFF0000000000000ULL;
1308
 
        } else if (p.ll == 0x0000000000000000ULL) {
1309
 
            p.ll = 0x7FF0000000000000ULL;
1310
 
        } else if (isnan(FT0)) {
1311
 
            p.ll = 0x7FF8000000000000ULL;
1312
 
        } else if (fpisneg(FT0)) {
1313
 
            p.ll = 0x8000000000000000ULL;
1314
 
        } else {
1315
 
            p.ll = 0x0000000000000000ULL;
1316
 
        }
1317
 
        FT0 = p.d;
1318
 
    }
1319
 
}
1320
 
 
1321
 
void do_frsqrte (void)
1322
 
{
1323
 
    CPU_DoubleU p;
1324
 
 
1325
 
    if (unlikely(float64_is_signaling_nan(FT0))) {
 
1469
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
 
1470
    } else {
 
1471
        farg.d = float64_sqrt(farg.d, &env->fp_status);
 
1472
    }
 
1473
    return farg.ll;
 
1474
}
 
1475
 
 
1476
/* fre - fre. */
 
1477
uint64_t helper_fre (uint64_t arg)
 
1478
{
 
1479
    CPU_DoubleU farg;
 
1480
    farg.ll = arg;
 
1481
 
 
1482
    if (unlikely(float64_is_signaling_nan(farg.d))) {
 
1483
        /* sNaN reciprocal */
 
1484
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1485
    } else {
 
1486
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
 
1487
    }
 
1488
    return farg.d;
 
1489
}
 
1490
 
 
1491
/* fres - fres. */
 
1492
uint64_t helper_fres (uint64_t arg)
 
1493
{
 
1494
    CPU_DoubleU farg;
 
1495
    float32 f32;
 
1496
    farg.ll = arg;
 
1497
 
 
1498
    if (unlikely(float64_is_signaling_nan(farg.d))) {
 
1499
        /* sNaN reciprocal */
 
1500
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1501
    } else {
 
1502
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
 
1503
        f32 = float64_to_float32(farg.d, &env->fp_status);
 
1504
        farg.d = float32_to_float64(f32, &env->fp_status);
 
1505
    }
 
1506
    return farg.ll;
 
1507
}
 
1508
 
 
1509
/* frsqrte  - frsqrte. */
 
1510
uint64_t helper_frsqrte (uint64_t arg)
 
1511
{
 
1512
    CPU_DoubleU farg;
 
1513
    float32 f32;
 
1514
    farg.ll = arg;
 
1515
 
 
1516
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1326
1517
        /* sNaN reciprocal square root */
1327
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1328
 
    } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
 
1518
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1519
    } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1329
1520
        /* Reciprocal square root of a negative nonzero number */
1330
 
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1331
 
    } else if (likely(isnormal(FT0))) {
1332
 
        FT0 = float64_sqrt(FT0, &env->fp_status);
1333
 
        FT0 = float32_div(1.0, FT0, &env->fp_status);
 
1521
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1334
1522
    } else {
1335
 
        p.d = FT0;
1336
 
        if (p.ll == 0x8000000000000000ULL) {
1337
 
            p.ll = 0xFFF0000000000000ULL;
1338
 
        } else if (p.ll == 0x0000000000000000ULL) {
1339
 
            p.ll = 0x7FF0000000000000ULL;
1340
 
        } else if (isnan(FT0)) {
1341
 
            p.ll |= 0x000FFFFFFFFFFFFFULL;
1342
 
        } else if (fpisneg(FT0)) {
1343
 
            p.ll = 0x7FF8000000000000ULL;
1344
 
        } else {
1345
 
            p.ll = 0x0000000000000000ULL;
1346
 
        }
1347
 
        FT0 = p.d;
 
1523
        farg.d = float64_sqrt(farg.d, &env->fp_status);
 
1524
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
 
1525
        f32 = float64_to_float32(farg.d, &env->fp_status);
 
1526
        farg.d = float32_to_float64(f32, &env->fp_status);
1348
1527
    }
 
1528
    return farg.ll;
1349
1529
}
1350
1530
 
1351
 
void do_fsel (void)
 
1531
/* fsel - fsel. */
 
1532
uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1352
1533
{
1353
 
    if (!fpisneg(FT0) || iszero(FT0))
1354
 
        FT0 = FT1;
 
1534
    CPU_DoubleU farg1;
 
1535
 
 
1536
    farg1.ll = arg1;
 
1537
 
 
1538
    if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_nan(farg1.d))
 
1539
        return arg2;
1355
1540
    else
1356
 
        FT0 = FT2;
 
1541
        return arg3;
1357
1542
}
1358
1543
 
1359
 
void do_fcmpu (void)
 
1544
void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
1360
1545
{
1361
 
    if (unlikely(float64_is_signaling_nan(FT0) ||
1362
 
                 float64_is_signaling_nan(FT1))) {
 
1546
    CPU_DoubleU farg1, farg2;
 
1547
    uint32_t ret = 0;
 
1548
    farg1.ll = arg1;
 
1549
    farg2.ll = arg2;
 
1550
 
 
1551
    if (unlikely(float64_is_nan(farg1.d) ||
 
1552
                 float64_is_nan(farg2.d))) {
 
1553
        ret = 0x01UL;
 
1554
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
 
1555
        ret = 0x08UL;
 
1556
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
 
1557
        ret = 0x04UL;
 
1558
    } else {
 
1559
        ret = 0x02UL;
 
1560
    }
 
1561
 
 
1562
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
 
1563
    env->fpscr |= ret << FPSCR_FPRF;
 
1564
    env->crf[crfD] = ret;
 
1565
    if (unlikely(ret == 0x01UL
 
1566
                 && (float64_is_signaling_nan(farg1.d) ||
 
1567
                     float64_is_signaling_nan(farg2.d)))) {
1363
1568
        /* sNaN comparison */
1364
1569
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
 
1570
    }
 
1571
}
 
1572
 
 
1573
void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD)
 
1574
{
 
1575
    CPU_DoubleU farg1, farg2;
 
1576
    uint32_t ret = 0;
 
1577
    farg1.ll = arg1;
 
1578
    farg2.ll = arg2;
 
1579
 
 
1580
    if (unlikely(float64_is_nan(farg1.d) ||
 
1581
                 float64_is_nan(farg2.d))) {
 
1582
        ret = 0x01UL;
 
1583
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
 
1584
        ret = 0x08UL;
 
1585
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
 
1586
        ret = 0x04UL;
1365
1587
    } else {
1366
 
        if (float64_lt(FT0, FT1, &env->fp_status)) {
1367
 
            T0 = 0x08UL;
1368
 
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
1369
 
            T0 = 0x04UL;
1370
 
        } else {
1371
 
            T0 = 0x02UL;
1372
 
        }
 
1588
        ret = 0x02UL;
1373
1589
    }
 
1590
 
1374
1591
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1375
 
    env->fpscr |= T0 << FPSCR_FPRF;
1376
 
}
1377
 
 
1378
 
void do_fcmpo (void)
1379
 
{
1380
 
    if (unlikely(float64_is_nan(FT0) ||
1381
 
                 float64_is_nan(FT1))) {
1382
 
        if (float64_is_signaling_nan(FT0) ||
1383
 
            float64_is_signaling_nan(FT1)) {
 
1592
    env->fpscr |= ret << FPSCR_FPRF;
 
1593
    env->crf[crfD] = ret;
 
1594
    if (unlikely (ret == 0x01UL)) {
 
1595
        if (float64_is_signaling_nan(farg1.d) ||
 
1596
            float64_is_signaling_nan(farg2.d)) {
1384
1597
            /* sNaN comparison */
1385
1598
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1386
1599
                                  POWERPC_EXCP_FP_VXVC);
1388
1601
            /* qNaN comparison */
1389
1602
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
1390
1603
        }
1391
 
    } else {
1392
 
        if (float64_lt(FT0, FT1, &env->fp_status)) {
1393
 
            T0 = 0x08UL;
1394
 
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
1395
 
            T0 = 0x04UL;
1396
 
        } else {
1397
 
            T0 = 0x02UL;
1398
 
        }
1399
1604
    }
1400
 
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1401
 
    env->fpscr |= T0 << FPSCR_FPRF;
1402
1605
}
1403
1606
 
1404
1607
#if !defined (CONFIG_USER_ONLY)
1405
 
void cpu_dump_rfi (target_ulong RA, target_ulong msr);
1406
 
 
1407
 
void do_store_msr (void)
 
1608
void helper_store_msr (target_ulong val)
1408
1609
{
1409
 
    T0 = hreg_store_msr(env, T0, 0);
1410
 
    if (T0 != 0) {
 
1610
    val = hreg_store_msr(env, val, 0);
 
1611
    if (val != 0) {
1411
1612
        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1412
 
        do_raise_exception(T0);
 
1613
        helper_raise_exception(val);
1413
1614
    }
1414
1615
}
1415
1616
 
1416
 
static always_inline void __do_rfi (target_ulong nip, target_ulong msr,
1417
 
                                    target_ulong msrm, int keep_msrh)
 
1617
static inline void do_rfi(target_ulong nip, target_ulong msr,
 
1618
                          target_ulong msrm, int keep_msrh)
1418
1619
{
1419
1620
#if defined(TARGET_PPC64)
1420
1621
    if (msr & (1ULL << MSR_SF)) {
1442
1643
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1443
1644
}
1444
1645
 
1445
 
void do_rfi (void)
 
1646
void helper_rfi (void)
1446
1647
{
1447
 
    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1448
 
             ~((target_ulong)0xFFFF0000), 1);
 
1648
    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
 
1649
           ~((target_ulong)0x0), 1);
1449
1650
}
1450
1651
 
1451
1652
#if defined(TARGET_PPC64)
1452
 
void do_rfid (void)
1453
 
{
1454
 
    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1455
 
             ~((target_ulong)0xFFFF0000), 0);
1456
 
}
1457
 
 
1458
 
void do_hrfid (void)
1459
 
{
1460
 
    __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
1461
 
             ~((target_ulong)0xFFFF0000), 0);
1462
 
}
1463
 
#endif
1464
 
#endif
1465
 
 
1466
 
void do_tw (int flags)
1467
 
{
1468
 
    if (!likely(!(((int32_t)T0 < (int32_t)T1 && (flags & 0x10)) ||
1469
 
                  ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
1470
 
                  ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
1471
 
                  ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
1472
 
                  ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
1473
 
        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
 
1653
void helper_rfid (void)
 
1654
{
 
1655
    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
 
1656
           ~((target_ulong)0x0), 0);
 
1657
}
 
1658
 
 
1659
void helper_hrfid (void)
 
1660
{
 
1661
    do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
 
1662
           ~((target_ulong)0x0), 0);
 
1663
}
 
1664
#endif
 
1665
#endif
 
1666
 
 
1667
void helper_tw (target_ulong arg1, target_ulong arg2, uint32_t flags)
 
1668
{
 
1669
    if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
 
1670
                  ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
 
1671
                  ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
 
1672
                  ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
 
1673
                  ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
 
1674
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1474
1675
    }
1475
1676
}
1476
1677
 
1477
1678
#if defined(TARGET_PPC64)
1478
 
void do_td (int flags)
 
1679
void helper_td (target_ulong arg1, target_ulong arg2, uint32_t flags)
1479
1680
{
1480
 
    if (!likely(!(((int64_t)T0 < (int64_t)T1 && (flags & 0x10)) ||
1481
 
                  ((int64_t)T0 > (int64_t)T1 && (flags & 0x08)) ||
1482
 
                  ((int64_t)T0 == (int64_t)T1 && (flags & 0x04)) ||
1483
 
                  ((uint64_t)T0 < (uint64_t)T1 && (flags & 0x02)) ||
1484
 
                  ((uint64_t)T0 > (uint64_t)T1 && (flags & 0x01)))))
1485
 
        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
 
1681
    if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
 
1682
                  ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
 
1683
                  ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
 
1684
                  ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
 
1685
                  ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01)))))
 
1686
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1486
1687
}
1487
1688
#endif
1488
1689
 
1489
1690
/*****************************************************************************/
1490
1691
/* PowerPC 601 specific instructions (POWER bridge) */
1491
 
void do_POWER_abso (void)
1492
 
{
1493
 
    if ((int32_t)T0 == INT32_MIN) {
1494
 
        T0 = INT32_MAX;
1495
 
        xer_ov = 1;
1496
 
    } else if ((int32_t)T0 < 0) {
1497
 
        T0 = -T0;
1498
 
        xer_ov = 0;
1499
 
    } else {
1500
 
        xer_ov = 0;
1501
 
    }
1502
 
    xer_so |= xer_ov;
1503
 
}
1504
1692
 
1505
 
void do_POWER_clcs (void)
 
1693
target_ulong helper_clcs (uint32_t arg)
1506
1694
{
1507
 
    switch (T0) {
 
1695
    switch (arg) {
1508
1696
    case 0x0CUL:
1509
1697
        /* Instruction cache line size */
1510
 
        T0 = env->icache_line_size;
 
1698
        return env->icache_line_size;
1511
1699
        break;
1512
1700
    case 0x0DUL:
1513
1701
        /* Data cache line size */
1514
 
        T0 = env->dcache_line_size;
 
1702
        return env->dcache_line_size;
1515
1703
        break;
1516
1704
    case 0x0EUL:
1517
1705
        /* Minimum cache line size */
1518
 
        T0 = env->icache_line_size < env->dcache_line_size ?
1519
 
            env->icache_line_size : env->dcache_line_size;
 
1706
        return (env->icache_line_size < env->dcache_line_size) ?
 
1707
                env->icache_line_size : env->dcache_line_size;
1520
1708
        break;
1521
1709
    case 0x0FUL:
1522
1710
        /* Maximum cache line size */
1523
 
        T0 = env->icache_line_size > env->dcache_line_size ?
1524
 
            env->icache_line_size : env->dcache_line_size;
 
1711
        return (env->icache_line_size > env->dcache_line_size) ?
 
1712
                env->icache_line_size : env->dcache_line_size;
1525
1713
        break;
1526
1714
    default:
1527
1715
        /* Undefined */
 
1716
        return 0;
1528
1717
        break;
1529
1718
    }
1530
1719
}
1531
1720
 
1532
 
void do_POWER_div (void)
1533
 
{
1534
 
    uint64_t tmp;
1535
 
 
1536
 
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1537
 
        (int32_t)T1 == 0) {
1538
 
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1539
 
        env->spr[SPR_MQ] = 0;
1540
 
    } else {
1541
 
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1542
 
        env->spr[SPR_MQ] = tmp % T1;
1543
 
        T0 = tmp / (int32_t)T1;
1544
 
    }
1545
 
}
1546
 
 
1547
 
void do_POWER_divo (void)
1548
 
{
1549
 
    int64_t tmp;
1550
 
 
1551
 
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1552
 
        (int32_t)T1 == 0) {
1553
 
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1554
 
        env->spr[SPR_MQ] = 0;
1555
 
        xer_ov = 1;
1556
 
    } else {
1557
 
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1558
 
        env->spr[SPR_MQ] = tmp % T1;
1559
 
        tmp /= (int32_t)T1;
1560
 
        if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) {
1561
 
            xer_ov = 1;
1562
 
        } else {
1563
 
            xer_ov = 0;
1564
 
        }
1565
 
        T0 = tmp;
1566
 
    }
1567
 
    xer_so |= xer_ov;
1568
 
}
1569
 
 
1570
 
void do_POWER_divs (void)
1571
 
{
1572
 
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1573
 
        (int32_t)T1 == 0) {
1574
 
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1575
 
        env->spr[SPR_MQ] = 0;
1576
 
    } else {
1577
 
        env->spr[SPR_MQ] = T0 % T1;
1578
 
        T0 = (int32_t)T0 / (int32_t)T1;
1579
 
    }
1580
 
}
1581
 
 
1582
 
void do_POWER_divso (void)
1583
 
{
1584
 
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
1585
 
        (int32_t)T1 == 0) {
1586
 
        T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
1587
 
        env->spr[SPR_MQ] = 0;
1588
 
        xer_ov = 1;
1589
 
    } else {
1590
 
        T0 = (int32_t)T0 / (int32_t)T1;
1591
 
        env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1;
1592
 
        xer_ov = 0;
1593
 
    }
1594
 
    xer_so |= xer_ov;
1595
 
}
1596
 
 
1597
 
void do_POWER_dozo (void)
1598
 
{
1599
 
    if ((int32_t)T1 > (int32_t)T0) {
1600
 
        T2 = T0;
1601
 
        T0 = T1 - T0;
1602
 
        if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
1603
 
            ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) {
1604
 
            xer_ov = 1;
1605
 
            xer_so = 1;
1606
 
        } else {
1607
 
            xer_ov = 0;
1608
 
        }
1609
 
    } else {
1610
 
        T0 = 0;
1611
 
        xer_ov = 0;
1612
 
    }
1613
 
}
1614
 
 
1615
 
void do_POWER_maskg (void)
1616
 
{
1617
 
    uint32_t ret;
1618
 
 
1619
 
    if ((uint32_t)T0 == (uint32_t)(T1 + 1)) {
1620
 
        ret = UINT32_MAX;
1621
 
    } else {
1622
 
        ret = (UINT32_MAX >> ((uint32_t)T0)) ^
1623
 
            ((UINT32_MAX >> ((uint32_t)T1)) >> 1);
1624
 
        if ((uint32_t)T0 > (uint32_t)T1)
1625
 
            ret = ~ret;
1626
 
    }
1627
 
    T0 = ret;
1628
 
}
1629
 
 
1630
 
void do_POWER_mulo (void)
1631
 
{
1632
 
    uint64_t tmp;
1633
 
 
1634
 
    tmp = (uint64_t)T0 * (uint64_t)T1;
1635
 
    env->spr[SPR_MQ] = tmp >> 32;
1636
 
    T0 = tmp;
1637
 
    if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) {
1638
 
        xer_ov = 1;
1639
 
        xer_so = 1;
1640
 
    } else {
1641
 
        xer_ov = 0;
 
1721
target_ulong helper_div (target_ulong arg1, target_ulong arg2)
 
1722
{
 
1723
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
 
1724
 
 
1725
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
 
1726
        (int32_t)arg2 == 0) {
 
1727
        env->spr[SPR_MQ] = 0;
 
1728
        return INT32_MIN;
 
1729
    } else {
 
1730
        env->spr[SPR_MQ] = tmp % arg2;
 
1731
        return  tmp / (int32_t)arg2;
 
1732
    }
 
1733
}
 
1734
 
 
1735
target_ulong helper_divo (target_ulong arg1, target_ulong arg2)
 
1736
{
 
1737
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
 
1738
 
 
1739
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
 
1740
        (int32_t)arg2 == 0) {
 
1741
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
 
1742
        env->spr[SPR_MQ] = 0;
 
1743
        return INT32_MIN;
 
1744
    } else {
 
1745
        env->spr[SPR_MQ] = tmp % arg2;
 
1746
        tmp /= (int32_t)arg2;
 
1747
        if ((int32_t)tmp != tmp) {
 
1748
            env->xer |= (1 << XER_OV) | (1 << XER_SO);
 
1749
        } else {
 
1750
            env->xer &= ~(1 << XER_OV);
 
1751
        }
 
1752
        return tmp;
 
1753
    }
 
1754
}
 
1755
 
 
1756
target_ulong helper_divs (target_ulong arg1, target_ulong arg2)
 
1757
{
 
1758
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
 
1759
        (int32_t)arg2 == 0) {
 
1760
        env->spr[SPR_MQ] = 0;
 
1761
        return INT32_MIN;
 
1762
    } else {
 
1763
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
 
1764
        return (int32_t)arg1 / (int32_t)arg2;
 
1765
    }
 
1766
}
 
1767
 
 
1768
target_ulong helper_divso (target_ulong arg1, target_ulong arg2)
 
1769
{
 
1770
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
 
1771
        (int32_t)arg2 == 0) {
 
1772
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
 
1773
        env->spr[SPR_MQ] = 0;
 
1774
        return INT32_MIN;
 
1775
    } else {
 
1776
        env->xer &= ~(1 << XER_OV);
 
1777
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
 
1778
        return (int32_t)arg1 / (int32_t)arg2;
1642
1779
    }
1643
1780
}
1644
1781
 
1645
1782
#if !defined (CONFIG_USER_ONLY)
1646
 
void do_POWER_rac (void)
 
1783
target_ulong helper_rac (target_ulong addr)
1647
1784
{
1648
1785
    mmu_ctx_t ctx;
1649
1786
    int nb_BATs;
 
1787
    target_ulong ret = 0;
1650
1788
 
1651
1789
    /* We don't have to generate many instances of this instruction,
1652
1790
     * as rac is supervisor only.
1654
1792
    /* XXX: FIX THIS: Pretend we have no BAT */
1655
1793
    nb_BATs = env->nb_BATs;
1656
1794
    env->nb_BATs = 0;
1657
 
    if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT) == 0)
1658
 
        T0 = ctx.raddr;
 
1795
    if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0)
 
1796
        ret = ctx.raddr;
1659
1797
    env->nb_BATs = nb_BATs;
1660
 
}
1661
 
 
1662
 
void do_POWER_rfsvc (void)
1663
 
{
1664
 
    __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1665
 
}
1666
 
 
1667
 
void do_store_hid0_601 (void)
1668
 
{
1669
 
    uint32_t hid0;
1670
 
 
1671
 
    hid0 = env->spr[SPR_HID0];
1672
 
    if ((T0 ^ hid0) & 0x00000008) {
1673
 
        /* Change current endianness */
1674
 
        env->hflags &= ~(1 << MSR_LE);
1675
 
        env->hflags_nmsr &= ~(1 << MSR_LE);
1676
 
        env->hflags_nmsr |= (1 << MSR_LE) & (((T0 >> 3) & 1) << MSR_LE);
1677
 
        env->hflags |= env->hflags_nmsr;
1678
 
        if (loglevel != 0) {
1679
 
            fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n",
1680
 
                    __func__, T0 & 0x8 ? 'l' : 'b', env->hflags);
1681
 
        }
1682
 
    }
1683
 
    env->spr[SPR_HID0] = T0;
 
1798
    return ret;
 
1799
}
 
1800
 
 
1801
void helper_rfsvc (void)
 
1802
{
 
1803
    do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1684
1804
}
1685
1805
#endif
1686
1806
 
1688
1808
/* 602 specific instructions */
1689
1809
/* mfrom is the most crazy instruction ever seen, imho ! */
1690
1810
/* Real implementation uses a ROM table. Do the same */
1691
 
#define USE_MFROM_ROM_TABLE
1692
 
void do_op_602_mfrom (void)
 
1811
/* Extremly decomposed:
 
1812
 *                      -arg / 256
 
1813
 * return 256 * log10(10           + 1.0) + 0.5
 
1814
 */
 
1815
#if !defined (CONFIG_USER_ONLY)
 
1816
target_ulong helper_602_mfrom (target_ulong arg)
1693
1817
{
1694
 
    if (likely(T0 < 602)) {
1695
 
#if defined(USE_MFROM_ROM_TABLE)
 
1818
    if (likely(arg < 602)) {
1696
1819
#include "mfrom_table.c"
1697
 
        T0 = mfrom_ROM_table[T0];
1698
 
#else
1699
 
        double d;
1700
 
        /* Extremly decomposed:
1701
 
         *                    -T0 / 256
1702
 
         * T0 = 256 * log10(10          + 1.0) + 0.5
1703
 
         */
1704
 
        d = T0;
1705
 
        d = float64_div(d, 256, &env->fp_status);
1706
 
        d = float64_chs(d);
1707
 
        d = exp10(d); // XXX: use float emulation function
1708
 
        d = float64_add(d, 1.0, &env->fp_status);
1709
 
        d = log10(d); // XXX: use float emulation function
1710
 
        d = float64_mul(d, 256, &env->fp_status);
1711
 
        d = float64_add(d, 0.5, &env->fp_status);
1712
 
        T0 = float64_round_to_int(d, &env->fp_status);
1713
 
#endif
 
1820
        return mfrom_ROM_table[arg];
1714
1821
    } else {
1715
 
        T0 = 0;
 
1822
        return 0;
1716
1823
    }
1717
1824
}
 
1825
#endif
1718
1826
 
1719
1827
/*****************************************************************************/
1720
1828
/* Embedded PowerPC specific helpers */
1721
 
void do_405_check_sat (void)
1722
 
{
1723
 
    if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1724
 
                !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1725
 
        /* Saturate result */
1726
 
        if (T2 >> 31) {
1727
 
            T0 = INT32_MIN;
1728
 
        } else {
1729
 
            T0 = INT32_MAX;
1730
 
        }
1731
 
    }
1732
 
}
1733
1829
 
1734
1830
/* XXX: to be improved to check access rights when in user-mode */
1735
 
void do_load_dcr (void)
 
1831
target_ulong helper_load_dcr (target_ulong dcrn)
1736
1832
{
1737
 
    target_ulong val;
 
1833
    target_ulong val = 0;
1738
1834
 
1739
1835
    if (unlikely(env->dcr_env == NULL)) {
1740
 
        if (loglevel != 0) {
1741
 
            fprintf(logfile, "No DCR environment\n");
1742
 
        }
1743
 
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1744
 
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1745
 
    } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
1746
 
        if (loglevel != 0) {
1747
 
            fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
1748
 
        }
1749
 
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1750
 
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1751
 
    } else {
1752
 
        T0 = val;
 
1836
        qemu_log("No DCR environment\n");
 
1837
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
 
1838
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
 
1839
    } else if (unlikely(ppc_dcr_read(env->dcr_env, dcrn, &val) != 0)) {
 
1840
        qemu_log("DCR read error %d %03x\n", (int)dcrn, (int)dcrn);
 
1841
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
 
1842
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1753
1843
    }
 
1844
    return val;
1754
1845
}
1755
1846
 
1756
 
void do_store_dcr (void)
 
1847
void helper_store_dcr (target_ulong dcrn, target_ulong val)
1757
1848
{
1758
1849
    if (unlikely(env->dcr_env == NULL)) {
1759
 
        if (loglevel != 0) {
1760
 
            fprintf(logfile, "No DCR environment\n");
1761
 
        }
1762
 
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1763
 
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1764
 
    } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
1765
 
        if (loglevel != 0) {
1766
 
            fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
1767
 
        }
1768
 
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1769
 
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
 
1850
        qemu_log("No DCR environment\n");
 
1851
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
 
1852
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
 
1853
    } else if (unlikely(ppc_dcr_write(env->dcr_env, dcrn, val) != 0)) {
 
1854
        qemu_log("DCR write error %d %03x\n", (int)dcrn, (int)dcrn);
 
1855
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
 
1856
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1770
1857
    }
1771
1858
}
1772
1859
 
1773
1860
#if !defined(CONFIG_USER_ONLY)
1774
 
void do_40x_rfci (void)
1775
 
{
1776
 
    __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1777
 
             ~((target_ulong)0xFFFF0000), 0);
1778
 
}
1779
 
 
1780
 
void do_rfci (void)
1781
 
{
1782
 
    __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1783
 
             ~((target_ulong)0x3FFF0000), 0);
1784
 
}
1785
 
 
1786
 
void do_rfdi (void)
1787
 
{
1788
 
    __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1789
 
             ~((target_ulong)0x3FFF0000), 0);
1790
 
}
1791
 
 
1792
 
void do_rfmci (void)
1793
 
{
1794
 
    __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1795
 
             ~((target_ulong)0x3FFF0000), 0);
1796
 
}
1797
 
 
1798
 
void do_load_403_pb (int num)
1799
 
{
1800
 
    T0 = env->pb[num];
1801
 
}
1802
 
 
1803
 
void do_store_403_pb (int num)
1804
 
{
1805
 
    if (likely(env->pb[num] != T0)) {
1806
 
        env->pb[num] = T0;
1807
 
        /* Should be optimized */
1808
 
        tlb_flush(env, 1);
1809
 
    }
 
1861
void helper_40x_rfci (void)
 
1862
{
 
1863
    do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
 
1864
           ~((target_ulong)0xFFFF0000), 0);
 
1865
}
 
1866
 
 
1867
void helper_rfci (void)
 
1868
{
 
1869
    do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
 
1870
           ~((target_ulong)0x3FFF0000), 0);
 
1871
}
 
1872
 
 
1873
void helper_rfdi (void)
 
1874
{
 
1875
    do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
 
1876
           ~((target_ulong)0x3FFF0000), 0);
 
1877
}
 
1878
 
 
1879
void helper_rfmci (void)
 
1880
{
 
1881
    do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
 
1882
           ~((target_ulong)0x3FFF0000), 0);
1810
1883
}
1811
1884
#endif
1812
1885
 
1813
1886
/* 440 specific */
1814
 
void do_440_dlmzb (void)
 
1887
target_ulong helper_dlmzb (target_ulong high, target_ulong low, uint32_t update_Rc)
1815
1888
{
1816
1889
    target_ulong mask;
1817
1890
    int i;
1818
1891
 
1819
1892
    i = 1;
1820
1893
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1821
 
        if ((T0 & mask) == 0)
 
1894
        if ((high & mask) == 0) {
 
1895
            if (update_Rc) {
 
1896
                env->crf[0] = 0x4;
 
1897
            }
1822
1898
            goto done;
 
1899
        }
1823
1900
        i++;
1824
1901
    }
1825
1902
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1826
 
        if ((T1 & mask) == 0)
1827
 
            break;
 
1903
        if ((low & mask) == 0) {
 
1904
            if (update_Rc) {
 
1905
                env->crf[0] = 0x8;
 
1906
            }
 
1907
            goto done;
 
1908
        }
1828
1909
        i++;
1829
1910
    }
 
1911
    if (update_Rc) {
 
1912
        env->crf[0] = 0x2;
 
1913
    }
1830
1914
 done:
1831
 
    T0 = i;
1832
 
}
1833
 
 
 
1915
    env->xer = (env->xer & ~0x7F) | i;
 
1916
    if (update_Rc) {
 
1917
        env->crf[0] |= xer_so;
 
1918
    }
 
1919
    return i;
 
1920
}
 
1921
 
 
1922
/*****************************************************************************/
 
1923
/* Altivec extension helpers */
 
1924
#if defined(HOST_WORDS_BIGENDIAN)
 
1925
#define HI_IDX 0
 
1926
#define LO_IDX 1
 
1927
#else
 
1928
#define HI_IDX 1
 
1929
#define LO_IDX 0
 
1930
#endif
 
1931
 
 
1932
#if defined(HOST_WORDS_BIGENDIAN)
 
1933
#define VECTOR_FOR_INORDER_I(index, element)            \
 
1934
    for (index = 0; index < ARRAY_SIZE(r->element); index++)
 
1935
#else
 
1936
#define VECTOR_FOR_INORDER_I(index, element)            \
 
1937
  for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
 
1938
#endif
 
1939
 
 
1940
/* If X is a NaN, store the corresponding QNaN into RESULT.  Otherwise,
 
1941
 * execute the following block.  */
 
1942
#define DO_HANDLE_NAN(result, x)                \
 
1943
    if (float32_is_nan(x) || float32_is_signaling_nan(x)) {     \
 
1944
        CPU_FloatU __f;                                         \
 
1945
        __f.f = x;                                              \
 
1946
        __f.l = __f.l | (1 << 22);  /* Set QNaN bit. */         \
 
1947
        result = __f.f;                                         \
 
1948
    } else
 
1949
 
 
1950
#define HANDLE_NAN1(result, x)                  \
 
1951
    DO_HANDLE_NAN(result, x)
 
1952
#define HANDLE_NAN2(result, x, y)               \
 
1953
    DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y)
 
1954
#define HANDLE_NAN3(result, x, y, z)            \
 
1955
    DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y) DO_HANDLE_NAN(result, z)
 
1956
 
 
1957
/* Saturating arithmetic helpers.  */
 
1958
#define SATCVT(from, to, from_type, to_type, min, max, use_min, use_max) \
 
1959
    static inline to_type cvt##from##to(from_type x, int *sat)          \
 
1960
    {                                                                   \
 
1961
        to_type r;                                                      \
 
1962
        if (use_min && x < min) {                                       \
 
1963
            r = min;                                                    \
 
1964
            *sat = 1;                                                   \
 
1965
        } else if (use_max && x > max) {                                \
 
1966
            r = max;                                                    \
 
1967
            *sat = 1;                                                   \
 
1968
        } else {                                                        \
 
1969
            r = x;                                                      \
 
1970
        }                                                               \
 
1971
        return r;                                                       \
 
1972
    }
 
1973
SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX, 1, 1)
 
1974
SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX, 1, 1)
 
1975
SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX, 1, 1)
 
1976
 
 
1977
/* Work around gcc problems with the macro version */
 
1978
static inline uint8_t cvtuhub(uint16_t x, int *sat)
 
1979
{
 
1980
    uint8_t r;
 
1981
 
 
1982
    if (x > UINT8_MAX) {
 
1983
        r = UINT8_MAX;
 
1984
        *sat = 1;
 
1985
    } else {
 
1986
        r = x;
 
1987
    }
 
1988
    return r;
 
1989
}
 
1990
//SATCVT(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX, 0, 1)
 
1991
SATCVT(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX, 0, 1)
 
1992
SATCVT(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX, 0, 1)
 
1993
SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX, 1, 1)
 
1994
SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX, 1, 1)
 
1995
SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX, 1, 1)
 
1996
#undef SATCVT
 
1997
 
 
1998
#define LVE(name, access, swap, element)                        \
 
1999
    void helper_##name (ppc_avr_t *r, target_ulong addr)        \
 
2000
    {                                                           \
 
2001
        size_t n_elems = ARRAY_SIZE(r->element);                \
 
2002
        int adjust = HI_IDX*(n_elems-1);                        \
 
2003
        int sh = sizeof(r->element[0]) >> 1;                    \
 
2004
        int index = (addr & 0xf) >> sh;                         \
 
2005
        if(msr_le) {                                            \
 
2006
            r->element[LO_IDX ? index : (adjust - index)] = swap(access(addr)); \
 
2007
        } else {                                                        \
 
2008
            r->element[LO_IDX ? index : (adjust - index)] = access(addr); \
 
2009
        }                                                               \
 
2010
    }
 
2011
#define I(x) (x)
 
2012
LVE(lvebx, ldub, I, u8)
 
2013
LVE(lvehx, lduw, bswap16, u16)
 
2014
LVE(lvewx, ldl, bswap32, u32)
 
2015
#undef I
 
2016
#undef LVE
 
2017
 
 
2018
void helper_lvsl (ppc_avr_t *r, target_ulong sh)
 
2019
{
 
2020
    int i, j = (sh & 0xf);
 
2021
 
 
2022
    VECTOR_FOR_INORDER_I (i, u8) {
 
2023
        r->u8[i] = j++;
 
2024
    }
 
2025
}
 
2026
 
 
2027
void helper_lvsr (ppc_avr_t *r, target_ulong sh)
 
2028
{
 
2029
    int i, j = 0x10 - (sh & 0xf);
 
2030
 
 
2031
    VECTOR_FOR_INORDER_I (i, u8) {
 
2032
        r->u8[i] = j++;
 
2033
    }
 
2034
}
 
2035
 
 
2036
#define STVE(name, access, swap, element)                       \
 
2037
    void helper_##name (ppc_avr_t *r, target_ulong addr)        \
 
2038
    {                                                           \
 
2039
        size_t n_elems = ARRAY_SIZE(r->element);                \
 
2040
        int adjust = HI_IDX*(n_elems-1);                        \
 
2041
        int sh = sizeof(r->element[0]) >> 1;                    \
 
2042
        int index = (addr & 0xf) >> sh;                         \
 
2043
        if(msr_le) {                                            \
 
2044
            access(addr, swap(r->element[LO_IDX ? index : (adjust - index)])); \
 
2045
        } else {                                                        \
 
2046
            access(addr, r->element[LO_IDX ? index : (adjust - index)]); \
 
2047
        }                                                               \
 
2048
    }
 
2049
#define I(x) (x)
 
2050
STVE(stvebx, stb, I, u8)
 
2051
STVE(stvehx, stw, bswap16, u16)
 
2052
STVE(stvewx, stl, bswap32, u32)
 
2053
#undef I
 
2054
#undef LVE
 
2055
 
 
2056
void helper_mtvscr (ppc_avr_t *r)
 
2057
{
 
2058
#if defined(HOST_WORDS_BIGENDIAN)
 
2059
    env->vscr = r->u32[3];
 
2060
#else
 
2061
    env->vscr = r->u32[0];
 
2062
#endif
 
2063
    set_flush_to_zero(vscr_nj, &env->vec_status);
 
2064
}
 
2065
 
 
2066
void helper_vaddcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2067
{
 
2068
    int i;
 
2069
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
 
2070
        r->u32[i] = ~a->u32[i] < b->u32[i];
 
2071
    }
 
2072
}
 
2073
 
 
2074
#define VARITH_DO(name, op, element)        \
 
2075
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)          \
 
2076
{                                                                       \
 
2077
    int i;                                                              \
 
2078
    for (i = 0; i < ARRAY_SIZE(r->element); i++) {                      \
 
2079
        r->element[i] = a->element[i] op b->element[i];                 \
 
2080
    }                                                                   \
 
2081
}
 
2082
#define VARITH(suffix, element)                  \
 
2083
  VARITH_DO(add##suffix, +, element)             \
 
2084
  VARITH_DO(sub##suffix, -, element)
 
2085
VARITH(ubm, u8)
 
2086
VARITH(uhm, u16)
 
2087
VARITH(uwm, u32)
 
2088
#undef VARITH_DO
 
2089
#undef VARITH
 
2090
 
 
2091
#define VARITHFP(suffix, func)                                          \
 
2092
    void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
 
2093
    {                                                                   \
 
2094
        int i;                                                          \
 
2095
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
 
2096
            HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) {                    \
 
2097
                r->f[i] = func(a->f[i], b->f[i], &env->vec_status);     \
 
2098
            }                                                           \
 
2099
        }                                                               \
 
2100
    }
 
2101
VARITHFP(addfp, float32_add)
 
2102
VARITHFP(subfp, float32_sub)
 
2103
#undef VARITHFP
 
2104
 
 
2105
#define VARITHSAT_CASE(type, op, cvt, element)                          \
 
2106
    {                                                                   \
 
2107
        type result = (type)a->element[i] op (type)b->element[i];       \
 
2108
        r->element[i] = cvt(result, &sat);                              \
 
2109
    }
 
2110
 
 
2111
#define VARITHSAT_DO(name, op, optype, cvt, element)                    \
 
2112
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
 
2113
    {                                                                   \
 
2114
        int sat = 0;                                                    \
 
2115
        int i;                                                          \
 
2116
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
 
2117
            switch (sizeof(r->element[0])) {                            \
 
2118
            case 1: VARITHSAT_CASE(optype, op, cvt, element); break;    \
 
2119
            case 2: VARITHSAT_CASE(optype, op, cvt, element); break;    \
 
2120
            case 4: VARITHSAT_CASE(optype, op, cvt, element); break;    \
 
2121
            }                                                           \
 
2122
        }                                                               \
 
2123
        if (sat) {                                                      \
 
2124
            env->vscr |= (1 << VSCR_SAT);                               \
 
2125
        }                                                               \
 
2126
    }
 
2127
#define VARITHSAT_SIGNED(suffix, element, optype, cvt)        \
 
2128
    VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element)    \
 
2129
    VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
 
2130
#define VARITHSAT_UNSIGNED(suffix, element, optype, cvt)       \
 
2131
    VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element)     \
 
2132
    VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
 
2133
VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
 
2134
VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
 
2135
VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
 
2136
VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
 
2137
VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
 
2138
VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
 
2139
#undef VARITHSAT_CASE
 
2140
#undef VARITHSAT_DO
 
2141
#undef VARITHSAT_SIGNED
 
2142
#undef VARITHSAT_UNSIGNED
 
2143
 
 
2144
#define VAVG_DO(name, element, etype)                                   \
 
2145
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
 
2146
    {                                                                   \
 
2147
        int i;                                                          \
 
2148
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
 
2149
            etype x = (etype)a->element[i] + (etype)b->element[i] + 1;  \
 
2150
            r->element[i] = x >> 1;                                     \
 
2151
        }                                                               \
 
2152
    }
 
2153
 
 
2154
#define VAVG(type, signed_element, signed_type, unsigned_element, unsigned_type) \
 
2155
    VAVG_DO(avgs##type, signed_element, signed_type)                    \
 
2156
    VAVG_DO(avgu##type, unsigned_element, unsigned_type)
 
2157
VAVG(b, s8, int16_t, u8, uint16_t)
 
2158
VAVG(h, s16, int32_t, u16, uint32_t)
 
2159
VAVG(w, s32, int64_t, u32, uint64_t)
 
2160
#undef VAVG_DO
 
2161
#undef VAVG
 
2162
 
 
2163
#define VCF(suffix, cvt, element)                                       \
 
2164
    void helper_vcf##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t uim)  \
 
2165
    {                                                                   \
 
2166
        int i;                                                          \
 
2167
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
 
2168
            float32 t = cvt(b->element[i], &env->vec_status);           \
 
2169
            r->f[i] = float32_scalbn (t, -uim, &env->vec_status);       \
 
2170
        }                                                               \
 
2171
    }
 
2172
VCF(ux, uint32_to_float32, u32)
 
2173
VCF(sx, int32_to_float32, s32)
 
2174
#undef VCF
 
2175
 
 
2176
#define VCMP_DO(suffix, compare, element, record)                       \
 
2177
    void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
 
2178
    {                                                                   \
 
2179
        uint32_t ones = (uint32_t)-1;                                   \
 
2180
        uint32_t all = ones;                                            \
 
2181
        uint32_t none = 0;                                              \
 
2182
        int i;                                                          \
 
2183
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
 
2184
            uint32_t result = (a->element[i] compare b->element[i] ? ones : 0x0); \
 
2185
            switch (sizeof (a->element[0])) {                           \
 
2186
            case 4: r->u32[i] = result; break;                          \
 
2187
            case 2: r->u16[i] = result; break;                          \
 
2188
            case 1: r->u8[i] = result; break;                           \
 
2189
            }                                                           \
 
2190
            all &= result;                                              \
 
2191
            none |= result;                                             \
 
2192
        }                                                               \
 
2193
        if (record) {                                                   \
 
2194
            env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
 
2195
        }                                                               \
 
2196
    }
 
2197
#define VCMP(suffix, compare, element)          \
 
2198
    VCMP_DO(suffix, compare, element, 0)        \
 
2199
    VCMP_DO(suffix##_dot, compare, element, 1)
 
2200
VCMP(equb, ==, u8)
 
2201
VCMP(equh, ==, u16)
 
2202
VCMP(equw, ==, u32)
 
2203
VCMP(gtub, >, u8)
 
2204
VCMP(gtuh, >, u16)
 
2205
VCMP(gtuw, >, u32)
 
2206
VCMP(gtsb, >, s8)
 
2207
VCMP(gtsh, >, s16)
 
2208
VCMP(gtsw, >, s32)
 
2209
#undef VCMP_DO
 
2210
#undef VCMP
 
2211
 
 
2212
#define VCMPFP_DO(suffix, compare, order, record)                       \
 
2213
    void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
 
2214
    {                                                                   \
 
2215
        uint32_t ones = (uint32_t)-1;                                   \
 
2216
        uint32_t all = ones;                                            \
 
2217
        uint32_t none = 0;                                              \
 
2218
        int i;                                                          \
 
2219
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
 
2220
            uint32_t result;                                            \
 
2221
            int rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status); \
 
2222
            if (rel == float_relation_unordered) {                      \
 
2223
                result = 0;                                             \
 
2224
            } else if (rel compare order) {                             \
 
2225
                result = ones;                                          \
 
2226
            } else {                                                    \
 
2227
                result = 0;                                             \
 
2228
            }                                                           \
 
2229
            r->u32[i] = result;                                         \
 
2230
            all &= result;                                              \
 
2231
            none |= result;                                             \
 
2232
        }                                                               \
 
2233
        if (record) {                                                   \
 
2234
            env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
 
2235
        }                                                               \
 
2236
    }
 
2237
#define VCMPFP(suffix, compare, order)           \
 
2238
    VCMPFP_DO(suffix, compare, order, 0)         \
 
2239
    VCMPFP_DO(suffix##_dot, compare, order, 1)
 
2240
VCMPFP(eqfp, ==, float_relation_equal)
 
2241
VCMPFP(gefp, !=, float_relation_less)
 
2242
VCMPFP(gtfp, ==, float_relation_greater)
 
2243
#undef VCMPFP_DO
 
2244
#undef VCMPFP
 
2245
 
 
2246
static inline void vcmpbfp_internal(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
 
2247
                                    int record)
 
2248
{
 
2249
    int i;
 
2250
    int all_in = 0;
 
2251
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
 
2252
        int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
 
2253
        if (le_rel == float_relation_unordered) {
 
2254
            r->u32[i] = 0xc0000000;
 
2255
            /* ALL_IN does not need to be updated here.  */
 
2256
        } else {
 
2257
            float32 bneg = float32_chs(b->f[i]);
 
2258
            int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
 
2259
            int le = le_rel != float_relation_greater;
 
2260
            int ge = ge_rel != float_relation_less;
 
2261
            r->u32[i] = ((!le) << 31) | ((!ge) << 30);
 
2262
            all_in |= (!le | !ge);
 
2263
        }
 
2264
    }
 
2265
    if (record) {
 
2266
        env->crf[6] = (all_in == 0) << 1;
 
2267
    }
 
2268
}
 
2269
 
 
2270
void helper_vcmpbfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2271
{
 
2272
    vcmpbfp_internal(r, a, b, 0);
 
2273
}
 
2274
 
 
2275
void helper_vcmpbfp_dot (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2276
{
 
2277
    vcmpbfp_internal(r, a, b, 1);
 
2278
}
 
2279
 
 
2280
#define VCT(suffix, satcvt, element)                                    \
 
2281
    void helper_vct##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t uim)  \
 
2282
    {                                                                   \
 
2283
        int i;                                                          \
 
2284
        int sat = 0;                                                    \
 
2285
        float_status s = env->vec_status;                               \
 
2286
        set_float_rounding_mode(float_round_to_zero, &s);               \
 
2287
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
 
2288
            if (float32_is_nan(b->f[i]) ||                              \
 
2289
                float32_is_signaling_nan(b->f[i])) {                    \
 
2290
                r->element[i] = 0;                                      \
 
2291
            } else {                                                    \
 
2292
                float64 t = float32_to_float64(b->f[i], &s);            \
 
2293
                int64_t j;                                              \
 
2294
                t = float64_scalbn(t, uim, &s);                         \
 
2295
                j = float64_to_int64(t, &s);                            \
 
2296
                r->element[i] = satcvt(j, &sat);                        \
 
2297
            }                                                           \
 
2298
        }                                                               \
 
2299
        if (sat) {                                                      \
 
2300
            env->vscr |= (1 << VSCR_SAT);                               \
 
2301
        }                                                               \
 
2302
    }
 
2303
VCT(uxs, cvtsduw, u32)
 
2304
VCT(sxs, cvtsdsw, s32)
 
2305
#undef VCT
 
2306
 
 
2307
void helper_vmaddfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2308
{
 
2309
    int i;
 
2310
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
 
2311
        HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
 
2312
            /* Need to do the computation in higher precision and round
 
2313
             * once at the end.  */
 
2314
            float64 af, bf, cf, t;
 
2315
            af = float32_to_float64(a->f[i], &env->vec_status);
 
2316
            bf = float32_to_float64(b->f[i], &env->vec_status);
 
2317
            cf = float32_to_float64(c->f[i], &env->vec_status);
 
2318
            t = float64_mul(af, cf, &env->vec_status);
 
2319
            t = float64_add(t, bf, &env->vec_status);
 
2320
            r->f[i] = float64_to_float32(t, &env->vec_status);
 
2321
        }
 
2322
    }
 
2323
}
 
2324
 
 
2325
void helper_vmhaddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2326
{
 
2327
    int sat = 0;
 
2328
    int i;
 
2329
 
 
2330
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
 
2331
        int32_t prod = a->s16[i] * b->s16[i];
 
2332
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
 
2333
        r->s16[i] = cvtswsh (t, &sat);
 
2334
    }
 
2335
 
 
2336
    if (sat) {
 
2337
        env->vscr |= (1 << VSCR_SAT);
 
2338
    }
 
2339
}
 
2340
 
 
2341
void helper_vmhraddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2342
{
 
2343
    int sat = 0;
 
2344
    int i;
 
2345
 
 
2346
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
 
2347
        int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
 
2348
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
 
2349
        r->s16[i] = cvtswsh (t, &sat);
 
2350
    }
 
2351
 
 
2352
    if (sat) {
 
2353
        env->vscr |= (1 << VSCR_SAT);
 
2354
    }
 
2355
}
 
2356
 
 
2357
#define VMINMAX_DO(name, compare, element)                              \
 
2358
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
 
2359
    {                                                                   \
 
2360
        int i;                                                          \
 
2361
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
 
2362
            if (a->element[i] compare b->element[i]) {                  \
 
2363
                r->element[i] = b->element[i];                          \
 
2364
            } else {                                                    \
 
2365
                r->element[i] = a->element[i];                          \
 
2366
            }                                                           \
 
2367
        }                                                               \
 
2368
    }
 
2369
#define VMINMAX(suffix, element)                \
 
2370
  VMINMAX_DO(min##suffix, >, element)           \
 
2371
  VMINMAX_DO(max##suffix, <, element)
 
2372
VMINMAX(sb, s8)
 
2373
VMINMAX(sh, s16)
 
2374
VMINMAX(sw, s32)
 
2375
VMINMAX(ub, u8)
 
2376
VMINMAX(uh, u16)
 
2377
VMINMAX(uw, u32)
 
2378
#undef VMINMAX_DO
 
2379
#undef VMINMAX
 
2380
 
 
2381
#define VMINMAXFP(suffix, rT, rF)                                       \
 
2382
    void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
 
2383
    {                                                                   \
 
2384
        int i;                                                          \
 
2385
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
 
2386
            HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) {                    \
 
2387
                if (float32_lt_quiet(a->f[i], b->f[i], &env->vec_status)) { \
 
2388
                    r->f[i] = rT->f[i];                                 \
 
2389
                } else {                                                \
 
2390
                    r->f[i] = rF->f[i];                                 \
 
2391
                }                                                       \
 
2392
            }                                                           \
 
2393
        }                                                               \
 
2394
    }
 
2395
VMINMAXFP(minfp, a, b)
 
2396
VMINMAXFP(maxfp, b, a)
 
2397
#undef VMINMAXFP
 
2398
 
 
2399
void helper_vmladduhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2400
{
 
2401
    int i;
 
2402
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
 
2403
        int32_t prod = a->s16[i] * b->s16[i];
 
2404
        r->s16[i] = (int16_t) (prod + c->s16[i]);
 
2405
    }
 
2406
}
 
2407
 
 
2408
#define VMRG_DO(name, element, highp)                                   \
 
2409
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
 
2410
    {                                                                   \
 
2411
        ppc_avr_t result;                                               \
 
2412
        int i;                                                          \
 
2413
        size_t n_elems = ARRAY_SIZE(r->element);                        \
 
2414
        for (i = 0; i < n_elems/2; i++) {                               \
 
2415
            if (highp) {                                                \
 
2416
                result.element[i*2+HI_IDX] = a->element[i];             \
 
2417
                result.element[i*2+LO_IDX] = b->element[i];             \
 
2418
            } else {                                                    \
 
2419
                result.element[n_elems - i*2 - (1+HI_IDX)] = b->element[n_elems - i - 1]; \
 
2420
                result.element[n_elems - i*2 - (1+LO_IDX)] = a->element[n_elems - i - 1]; \
 
2421
            }                                                           \
 
2422
        }                                                               \
 
2423
        *r = result;                                                    \
 
2424
    }
 
2425
#if defined(HOST_WORDS_BIGENDIAN)
 
2426
#define MRGHI 0
 
2427
#define MRGLO 1
 
2428
#else
 
2429
#define MRGHI 1
 
2430
#define MRGLO 0
 
2431
#endif
 
2432
#define VMRG(suffix, element)                   \
 
2433
  VMRG_DO(mrgl##suffix, element, MRGHI)         \
 
2434
  VMRG_DO(mrgh##suffix, element, MRGLO)
 
2435
VMRG(b, u8)
 
2436
VMRG(h, u16)
 
2437
VMRG(w, u32)
 
2438
#undef VMRG_DO
 
2439
#undef VMRG
 
2440
#undef MRGHI
 
2441
#undef MRGLO
 
2442
 
 
2443
void helper_vmsummbm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2444
{
 
2445
    int32_t prod[16];
 
2446
    int i;
 
2447
 
 
2448
    for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
 
2449
        prod[i] = (int32_t)a->s8[i] * b->u8[i];
 
2450
    }
 
2451
 
 
2452
    VECTOR_FOR_INORDER_I(i, s32) {
 
2453
        r->s32[i] = c->s32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
 
2454
    }
 
2455
}
 
2456
 
 
2457
void helper_vmsumshm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2458
{
 
2459
    int32_t prod[8];
 
2460
    int i;
 
2461
 
 
2462
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
 
2463
        prod[i] = a->s16[i] * b->s16[i];
 
2464
    }
 
2465
 
 
2466
    VECTOR_FOR_INORDER_I(i, s32) {
 
2467
        r->s32[i] = c->s32[i] + prod[2*i] + prod[2*i+1];
 
2468
    }
 
2469
}
 
2470
 
 
2471
void helper_vmsumshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2472
{
 
2473
    int32_t prod[8];
 
2474
    int i;
 
2475
    int sat = 0;
 
2476
 
 
2477
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
 
2478
        prod[i] = (int32_t)a->s16[i] * b->s16[i];
 
2479
    }
 
2480
 
 
2481
    VECTOR_FOR_INORDER_I (i, s32) {
 
2482
        int64_t t = (int64_t)c->s32[i] + prod[2*i] + prod[2*i+1];
 
2483
        r->u32[i] = cvtsdsw(t, &sat);
 
2484
    }
 
2485
 
 
2486
    if (sat) {
 
2487
        env->vscr |= (1 << VSCR_SAT);
 
2488
    }
 
2489
}
 
2490
 
 
2491
void helper_vmsumubm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2492
{
 
2493
    uint16_t prod[16];
 
2494
    int i;
 
2495
 
 
2496
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
 
2497
        prod[i] = a->u8[i] * b->u8[i];
 
2498
    }
 
2499
 
 
2500
    VECTOR_FOR_INORDER_I(i, u32) {
 
2501
        r->u32[i] = c->u32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
 
2502
    }
 
2503
}
 
2504
 
 
2505
void helper_vmsumuhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2506
{
 
2507
    uint32_t prod[8];
 
2508
    int i;
 
2509
 
 
2510
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
 
2511
        prod[i] = a->u16[i] * b->u16[i];
 
2512
    }
 
2513
 
 
2514
    VECTOR_FOR_INORDER_I(i, u32) {
 
2515
        r->u32[i] = c->u32[i] + prod[2*i] + prod[2*i+1];
 
2516
    }
 
2517
}
 
2518
 
 
2519
void helper_vmsumuhs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2520
{
 
2521
    uint32_t prod[8];
 
2522
    int i;
 
2523
    int sat = 0;
 
2524
 
 
2525
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
 
2526
        prod[i] = a->u16[i] * b->u16[i];
 
2527
    }
 
2528
 
 
2529
    VECTOR_FOR_INORDER_I (i, s32) {
 
2530
        uint64_t t = (uint64_t)c->u32[i] + prod[2*i] + prod[2*i+1];
 
2531
        r->u32[i] = cvtuduw(t, &sat);
 
2532
    }
 
2533
 
 
2534
    if (sat) {
 
2535
        env->vscr |= (1 << VSCR_SAT);
 
2536
    }
 
2537
}
 
2538
 
 
2539
#define VMUL_DO(name, mul_element, prod_element, evenp)                 \
 
2540
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
 
2541
    {                                                                   \
 
2542
        int i;                                                          \
 
2543
        VECTOR_FOR_INORDER_I(i, prod_element) {                         \
 
2544
            if (evenp) {                                                \
 
2545
                r->prod_element[i] = a->mul_element[i*2+HI_IDX] * b->mul_element[i*2+HI_IDX]; \
 
2546
            } else {                                                    \
 
2547
                r->prod_element[i] = a->mul_element[i*2+LO_IDX] * b->mul_element[i*2+LO_IDX]; \
 
2548
            }                                                           \
 
2549
        }                                                               \
 
2550
    }
 
2551
#define VMUL(suffix, mul_element, prod_element) \
 
2552
  VMUL_DO(mule##suffix, mul_element, prod_element, 1) \
 
2553
  VMUL_DO(mulo##suffix, mul_element, prod_element, 0)
 
2554
VMUL(sb, s8, s16)
 
2555
VMUL(sh, s16, s32)
 
2556
VMUL(ub, u8, u16)
 
2557
VMUL(uh, u16, u32)
 
2558
#undef VMUL_DO
 
2559
#undef VMUL
 
2560
 
 
2561
void helper_vnmsubfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2562
{
 
2563
    int i;
 
2564
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
 
2565
        HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
 
2566
            /* Need to do the computation is higher precision and round
 
2567
             * once at the end.  */
 
2568
            float64 af, bf, cf, t;
 
2569
            af = float32_to_float64(a->f[i], &env->vec_status);
 
2570
            bf = float32_to_float64(b->f[i], &env->vec_status);
 
2571
            cf = float32_to_float64(c->f[i], &env->vec_status);
 
2572
            t = float64_mul(af, cf, &env->vec_status);
 
2573
            t = float64_sub(t, bf, &env->vec_status);
 
2574
            t = float64_chs(t);
 
2575
            r->f[i] = float64_to_float32(t, &env->vec_status);
 
2576
        }
 
2577
    }
 
2578
}
 
2579
 
 
2580
void helper_vperm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2581
{
 
2582
    ppc_avr_t result;
 
2583
    int i;
 
2584
    VECTOR_FOR_INORDER_I (i, u8) {
 
2585
        int s = c->u8[i] & 0x1f;
 
2586
#if defined(HOST_WORDS_BIGENDIAN)
 
2587
        int index = s & 0xf;
 
2588
#else
 
2589
        int index = 15 - (s & 0xf);
 
2590
#endif
 
2591
        if (s & 0x10) {
 
2592
            result.u8[i] = b->u8[index];
 
2593
        } else {
 
2594
            result.u8[i] = a->u8[index];
 
2595
        }
 
2596
    }
 
2597
    *r = result;
 
2598
}
 
2599
 
 
2600
#if defined(HOST_WORDS_BIGENDIAN)
 
2601
#define PKBIG 1
 
2602
#else
 
2603
#define PKBIG 0
 
2604
#endif
 
2605
void helper_vpkpx (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2606
{
 
2607
    int i, j;
 
2608
    ppc_avr_t result;
 
2609
#if defined(HOST_WORDS_BIGENDIAN)
 
2610
    const ppc_avr_t *x[2] = { a, b };
 
2611
#else
 
2612
    const ppc_avr_t *x[2] = { b, a };
 
2613
#endif
 
2614
 
 
2615
    VECTOR_FOR_INORDER_I (i, u64) {
 
2616
        VECTOR_FOR_INORDER_I (j, u32){
 
2617
            uint32_t e = x[i]->u32[j];
 
2618
            result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
 
2619
                                 ((e >> 6) & 0x3e0) |
 
2620
                                 ((e >> 3) & 0x1f));
 
2621
        }
 
2622
    }
 
2623
    *r = result;
 
2624
}
 
2625
 
 
2626
#define VPK(suffix, from, to, cvt, dosat)       \
 
2627
    void helper_vpk##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
 
2628
    {                                                                   \
 
2629
        int i;                                                          \
 
2630
        int sat = 0;                                                    \
 
2631
        ppc_avr_t result;                                               \
 
2632
        ppc_avr_t *a0 = PKBIG ? a : b;                                  \
 
2633
        ppc_avr_t *a1 = PKBIG ? b : a;                                  \
 
2634
        VECTOR_FOR_INORDER_I (i, from) {                                \
 
2635
            result.to[i] = cvt(a0->from[i], &sat);                      \
 
2636
            result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);  \
 
2637
        }                                                               \
 
2638
        *r = result;                                                    \
 
2639
        if (dosat && sat) {                                             \
 
2640
            env->vscr |= (1 << VSCR_SAT);                               \
 
2641
        }                                                               \
 
2642
    }
 
2643
#define I(x, y) (x)
 
2644
VPK(shss, s16, s8, cvtshsb, 1)
 
2645
VPK(shus, s16, u8, cvtshub, 1)
 
2646
VPK(swss, s32, s16, cvtswsh, 1)
 
2647
VPK(swus, s32, u16, cvtswuh, 1)
 
2648
VPK(uhus, u16, u8, cvtuhub, 1)
 
2649
VPK(uwus, u32, u16, cvtuwuh, 1)
 
2650
VPK(uhum, u16, u8, I, 0)
 
2651
VPK(uwum, u32, u16, I, 0)
 
2652
#undef I
 
2653
#undef VPK
 
2654
#undef PKBIG
 
2655
 
 
2656
void helper_vrefp (ppc_avr_t *r, ppc_avr_t *b)
 
2657
{
 
2658
    int i;
 
2659
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
 
2660
        HANDLE_NAN1(r->f[i], b->f[i]) {
 
2661
            r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
 
2662
        }
 
2663
    }
 
2664
}
 
2665
 
 
2666
#define VRFI(suffix, rounding)                                          \
 
2667
    void helper_vrfi##suffix (ppc_avr_t *r, ppc_avr_t *b)               \
 
2668
    {                                                                   \
 
2669
        int i;                                                          \
 
2670
        float_status s = env->vec_status;                               \
 
2671
        set_float_rounding_mode(rounding, &s);                          \
 
2672
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
 
2673
            HANDLE_NAN1(r->f[i], b->f[i]) {                             \
 
2674
                r->f[i] = float32_round_to_int (b->f[i], &s);           \
 
2675
            }                                                           \
 
2676
        }                                                               \
 
2677
    }
 
2678
VRFI(n, float_round_nearest_even)
 
2679
VRFI(m, float_round_down)
 
2680
VRFI(p, float_round_up)
 
2681
VRFI(z, float_round_to_zero)
 
2682
#undef VRFI
 
2683
 
 
2684
#define VROTATE(suffix, element)                                        \
 
2685
    void helper_vrl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
 
2686
    {                                                                   \
 
2687
        int i;                                                          \
 
2688
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
 
2689
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
 
2690
            unsigned int shift = b->element[i] & mask;                  \
 
2691
            r->element[i] = (a->element[i] << shift) | (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
 
2692
        }                                                               \
 
2693
    }
 
2694
VROTATE(b, u8)
 
2695
VROTATE(h, u16)
 
2696
VROTATE(w, u32)
 
2697
#undef VROTATE
 
2698
 
 
2699
void helper_vrsqrtefp (ppc_avr_t *r, ppc_avr_t *b)
 
2700
{
 
2701
    int i;
 
2702
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
 
2703
        HANDLE_NAN1(r->f[i], b->f[i]) {
 
2704
            float32 t = float32_sqrt(b->f[i], &env->vec_status);
 
2705
            r->f[i] = float32_div(float32_one, t, &env->vec_status);
 
2706
        }
 
2707
    }
 
2708
}
 
2709
 
 
2710
void helper_vsel (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
 
2711
{
 
2712
    r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
 
2713
    r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
 
2714
}
 
2715
 
 
2716
void helper_vlogefp (ppc_avr_t *r, ppc_avr_t *b)
 
2717
{
 
2718
    int i;
 
2719
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
 
2720
        HANDLE_NAN1(r->f[i], b->f[i]) {
 
2721
            r->f[i] = float32_log2(b->f[i], &env->vec_status);
 
2722
        }
 
2723
    }
 
2724
}
 
2725
 
 
2726
#if defined(HOST_WORDS_BIGENDIAN)
 
2727
#define LEFT 0
 
2728
#define RIGHT 1
 
2729
#else
 
2730
#define LEFT 1
 
2731
#define RIGHT 0
 
2732
#endif
 
2733
/* The specification says that the results are undefined if all of the
 
2734
 * shift counts are not identical.  We check to make sure that they are
 
2735
 * to conform to what real hardware appears to do.  */
 
2736
#define VSHIFT(suffix, leftp)                                           \
 
2737
    void helper_vs##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
 
2738
    {                                                                   \
 
2739
        int shift = b->u8[LO_IDX*15] & 0x7;                             \
 
2740
        int doit = 1;                                                   \
 
2741
        int i;                                                          \
 
2742
        for (i = 0; i < ARRAY_SIZE(r->u8); i++) {                       \
 
2743
            doit = doit && ((b->u8[i] & 0x7) == shift);                 \
 
2744
        }                                                               \
 
2745
        if (doit) {                                                     \
 
2746
            if (shift == 0) {                                           \
 
2747
                *r = *a;                                                \
 
2748
            } else if (leftp) {                                         \
 
2749
                uint64_t carry = a->u64[LO_IDX] >> (64 - shift);        \
 
2750
                r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry;     \
 
2751
                r->u64[LO_IDX] = a->u64[LO_IDX] << shift;               \
 
2752
            } else {                                                    \
 
2753
                uint64_t carry = a->u64[HI_IDX] << (64 - shift);        \
 
2754
                r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry;     \
 
2755
                r->u64[HI_IDX] = a->u64[HI_IDX] >> shift;               \
 
2756
            }                                                           \
 
2757
        }                                                               \
 
2758
    }
 
2759
VSHIFT(l, LEFT)
 
2760
VSHIFT(r, RIGHT)
 
2761
#undef VSHIFT
 
2762
#undef LEFT
 
2763
#undef RIGHT
 
2764
 
 
2765
#define VSL(suffix, element)                                            \
 
2766
    void helper_vsl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
 
2767
    {                                                                   \
 
2768
        int i;                                                          \
 
2769
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
 
2770
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
 
2771
            unsigned int shift = b->element[i] & mask;                  \
 
2772
            r->element[i] = a->element[i] << shift;                     \
 
2773
        }                                                               \
 
2774
    }
 
2775
VSL(b, u8)
 
2776
VSL(h, u16)
 
2777
VSL(w, u32)
 
2778
#undef VSL
 
2779
 
 
2780
void helper_vsldoi (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
 
2781
{
 
2782
    int sh = shift & 0xf;
 
2783
    int i;
 
2784
    ppc_avr_t result;
 
2785
 
 
2786
#if defined(HOST_WORDS_BIGENDIAN)
 
2787
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
 
2788
        int index = sh + i;
 
2789
        if (index > 0xf) {
 
2790
            result.u8[i] = b->u8[index-0x10];
 
2791
        } else {
 
2792
            result.u8[i] = a->u8[index];
 
2793
        }
 
2794
    }
 
2795
#else
 
2796
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
 
2797
        int index = (16 - sh) + i;
 
2798
        if (index > 0xf) {
 
2799
            result.u8[i] = a->u8[index-0x10];
 
2800
        } else {
 
2801
            result.u8[i] = b->u8[index];
 
2802
        }
 
2803
    }
 
2804
#endif
 
2805
    *r = result;
 
2806
}
 
2807
 
 
2808
void helper_vslo (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2809
{
 
2810
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
 
2811
 
 
2812
#if defined (HOST_WORDS_BIGENDIAN)
 
2813
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
 
2814
  memset (&r->u8[16-sh], 0, sh);
 
2815
#else
 
2816
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
 
2817
  memset (&r->u8[0], 0, sh);
 
2818
#endif
 
2819
}
 
2820
 
 
2821
/* Experimental testing shows that hardware masks the immediate.  */
 
2822
#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
 
2823
#if defined(HOST_WORDS_BIGENDIAN)
 
2824
#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
 
2825
#else
 
2826
#define SPLAT_ELEMENT(element) (ARRAY_SIZE(r->element)-1 - _SPLAT_MASKED(element))
 
2827
#endif
 
2828
#define VSPLT(suffix, element)                                          \
 
2829
    void helper_vsplt##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
 
2830
    {                                                                   \
 
2831
        uint32_t s = b->element[SPLAT_ELEMENT(element)];                \
 
2832
        int i;                                                          \
 
2833
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
 
2834
            r->element[i] = s;                                          \
 
2835
        }                                                               \
 
2836
    }
 
2837
VSPLT(b, u8)
 
2838
VSPLT(h, u16)
 
2839
VSPLT(w, u32)
 
2840
#undef VSPLT
 
2841
#undef SPLAT_ELEMENT
 
2842
#undef _SPLAT_MASKED
 
2843
 
 
2844
#define VSPLTI(suffix, element, splat_type)                     \
 
2845
    void helper_vspltis##suffix (ppc_avr_t *r, uint32_t splat)  \
 
2846
    {                                                           \
 
2847
        splat_type x = (int8_t)(splat << 3) >> 3;               \
 
2848
        int i;                                                  \
 
2849
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {          \
 
2850
            r->element[i] = x;                                  \
 
2851
        }                                                       \
 
2852
    }
 
2853
VSPLTI(b, s8, int8_t)
 
2854
VSPLTI(h, s16, int16_t)
 
2855
VSPLTI(w, s32, int32_t)
 
2856
#undef VSPLTI
 
2857
 
 
2858
#define VSR(suffix, element)                                            \
 
2859
    void helper_vsr##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
 
2860
    {                                                                   \
 
2861
        int i;                                                          \
 
2862
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
 
2863
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
 
2864
            unsigned int shift = b->element[i] & mask;                  \
 
2865
            r->element[i] = a->element[i] >> shift;                     \
 
2866
        }                                                               \
 
2867
    }
 
2868
VSR(ab, s8)
 
2869
VSR(ah, s16)
 
2870
VSR(aw, s32)
 
2871
VSR(b, u8)
 
2872
VSR(h, u16)
 
2873
VSR(w, u32)
 
2874
#undef VSR
 
2875
 
 
2876
void helper_vsro (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2877
{
 
2878
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
 
2879
 
 
2880
#if defined (HOST_WORDS_BIGENDIAN)
 
2881
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
 
2882
  memset (&r->u8[0], 0, sh);
 
2883
#else
 
2884
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
 
2885
  memset (&r->u8[16-sh], 0, sh);
 
2886
#endif
 
2887
}
 
2888
 
 
2889
void helper_vsubcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2890
{
 
2891
    int i;
 
2892
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
 
2893
        r->u32[i] = a->u32[i] >= b->u32[i];
 
2894
    }
 
2895
}
 
2896
 
 
2897
void helper_vsumsws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2898
{
 
2899
    int64_t t;
 
2900
    int i, upper;
 
2901
    ppc_avr_t result;
 
2902
    int sat = 0;
 
2903
 
 
2904
#if defined(HOST_WORDS_BIGENDIAN)
 
2905
    upper = ARRAY_SIZE(r->s32)-1;
 
2906
#else
 
2907
    upper = 0;
 
2908
#endif
 
2909
    t = (int64_t)b->s32[upper];
 
2910
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
 
2911
        t += a->s32[i];
 
2912
        result.s32[i] = 0;
 
2913
    }
 
2914
    result.s32[upper] = cvtsdsw(t, &sat);
 
2915
    *r = result;
 
2916
 
 
2917
    if (sat) {
 
2918
        env->vscr |= (1 << VSCR_SAT);
 
2919
    }
 
2920
}
 
2921
 
 
2922
void helper_vsum2sws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2923
{
 
2924
    int i, j, upper;
 
2925
    ppc_avr_t result;
 
2926
    int sat = 0;
 
2927
 
 
2928
#if defined(HOST_WORDS_BIGENDIAN)
 
2929
    upper = 1;
 
2930
#else
 
2931
    upper = 0;
 
2932
#endif
 
2933
    for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
 
2934
        int64_t t = (int64_t)b->s32[upper+i*2];
 
2935
        result.u64[i] = 0;
 
2936
        for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
 
2937
            t += a->s32[2*i+j];
 
2938
        }
 
2939
        result.s32[upper+i*2] = cvtsdsw(t, &sat);
 
2940
    }
 
2941
 
 
2942
    *r = result;
 
2943
    if (sat) {
 
2944
        env->vscr |= (1 << VSCR_SAT);
 
2945
    }
 
2946
}
 
2947
 
 
2948
void helper_vsum4sbs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2949
{
 
2950
    int i, j;
 
2951
    int sat = 0;
 
2952
 
 
2953
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
 
2954
        int64_t t = (int64_t)b->s32[i];
 
2955
        for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
 
2956
            t += a->s8[4*i+j];
 
2957
        }
 
2958
        r->s32[i] = cvtsdsw(t, &sat);
 
2959
    }
 
2960
 
 
2961
    if (sat) {
 
2962
        env->vscr |= (1 << VSCR_SAT);
 
2963
    }
 
2964
}
 
2965
 
 
2966
void helper_vsum4shs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2967
{
 
2968
    int sat = 0;
 
2969
    int i;
 
2970
 
 
2971
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
 
2972
        int64_t t = (int64_t)b->s32[i];
 
2973
        t += a->s16[2*i] + a->s16[2*i+1];
 
2974
        r->s32[i] = cvtsdsw(t, &sat);
 
2975
    }
 
2976
 
 
2977
    if (sat) {
 
2978
        env->vscr |= (1 << VSCR_SAT);
 
2979
    }
 
2980
}
 
2981
 
 
2982
void helper_vsum4ubs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 
2983
{
 
2984
    int i, j;
 
2985
    int sat = 0;
 
2986
 
 
2987
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
 
2988
        uint64_t t = (uint64_t)b->u32[i];
 
2989
        for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
 
2990
            t += a->u8[4*i+j];
 
2991
        }
 
2992
        r->u32[i] = cvtuduw(t, &sat);
 
2993
    }
 
2994
 
 
2995
    if (sat) {
 
2996
        env->vscr |= (1 << VSCR_SAT);
 
2997
    }
 
2998
}
 
2999
 
 
3000
#if defined(HOST_WORDS_BIGENDIAN)
 
3001
#define UPKHI 1
 
3002
#define UPKLO 0
 
3003
#else
 
3004
#define UPKHI 0
 
3005
#define UPKLO 1
 
3006
#endif
 
3007
#define VUPKPX(suffix, hi)                                      \
 
3008
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)       \
 
3009
    {                                                           \
 
3010
        int i;                                                  \
 
3011
        ppc_avr_t result;                                       \
 
3012
        for (i = 0; i < ARRAY_SIZE(r->u32); i++) {              \
 
3013
            uint16_t e = b->u16[hi ? i : i+4];                  \
 
3014
            uint8_t a = (e >> 15) ? 0xff : 0;                   \
 
3015
            uint8_t r = (e >> 10) & 0x1f;                       \
 
3016
            uint8_t g = (e >> 5) & 0x1f;                        \
 
3017
            uint8_t b = e & 0x1f;                               \
 
3018
            result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b;       \
 
3019
        }                                                               \
 
3020
        *r = result;                                                    \
 
3021
    }
 
3022
VUPKPX(lpx, UPKLO)
 
3023
VUPKPX(hpx, UPKHI)
 
3024
#undef VUPKPX
 
3025
 
 
3026
#define VUPK(suffix, unpacked, packee, hi)                              \
 
3027
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)               \
 
3028
    {                                                                   \
 
3029
        int i;                                                          \
 
3030
        ppc_avr_t result;                                               \
 
3031
        if (hi) {                                                       \
 
3032
            for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) {             \
 
3033
                result.unpacked[i] = b->packee[i];                      \
 
3034
            }                                                           \
 
3035
        } else {                                                        \
 
3036
            for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); i++) { \
 
3037
                result.unpacked[i-ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
 
3038
            }                                                           \
 
3039
        }                                                               \
 
3040
        *r = result;                                                    \
 
3041
    }
 
3042
VUPK(hsb, s16, s8, UPKHI)
 
3043
VUPK(hsh, s32, s16, UPKHI)
 
3044
VUPK(lsb, s16, s8, UPKLO)
 
3045
VUPK(lsh, s32, s16, UPKLO)
 
3046
#undef VUPK
 
3047
#undef UPKHI
 
3048
#undef UPKLO
 
3049
 
 
3050
#undef DO_HANDLE_NAN
 
3051
#undef HANDLE_NAN1
 
3052
#undef HANDLE_NAN2
 
3053
#undef HANDLE_NAN3
 
3054
#undef VECTOR_FOR_INORDER_I
 
3055
#undef HI_IDX
 
3056
#undef LO_IDX
 
3057
 
 
3058
/*****************************************************************************/
1834
3059
/* SPE extension helpers */
1835
3060
/* Use a table to make this quicker */
1836
3061
static uint8_t hbrev[16] = {
1838
3063
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1839
3064
};
1840
3065
 
1841
 
static always_inline uint8_t byte_reverse (uint8_t val)
 
3066
static inline uint8_t byte_reverse(uint8_t val)
1842
3067
{
1843
3068
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1844
3069
}
1845
3070
 
1846
 
static always_inline uint32_t word_reverse (uint32_t val)
 
3071
static inline uint32_t word_reverse(uint32_t val)
1847
3072
{
1848
3073
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1849
3074
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1850
3075
}
1851
3076
 
1852
3077
#define MASKBITS 16 // Random value - to be fixed (implementation dependant)
1853
 
void do_brinc (void)
 
3078
target_ulong helper_brinc (target_ulong arg1, target_ulong arg2)
1854
3079
{
1855
3080
    uint32_t a, b, d, mask;
1856
3081
 
1857
3082
    mask = UINT32_MAX >> (32 - MASKBITS);
1858
 
    a = T0 & mask;
1859
 
    b = T1 & mask;
 
3083
    a = arg1 & mask;
 
3084
    b = arg2 & mask;
1860
3085
    d = word_reverse(1 + word_reverse(a | ~b));
1861
 
    T0 = (T0 & ~mask) | (d & b);
1862
 
}
1863
 
 
1864
 
#define DO_SPE_OP2(name)                                                      \
1865
 
void do_ev##name (void)                                                       \
1866
 
{                                                                             \
1867
 
    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32, T1_64 >> 32) << 32) |         \
1868
 
        (uint64_t)_do_e##name(T0_64, T1_64);                                  \
1869
 
}
1870
 
 
1871
 
#define DO_SPE_OP1(name)                                                      \
1872
 
void do_ev##name (void)                                                       \
1873
 
{                                                                             \
1874
 
    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) |                      \
1875
 
        (uint64_t)_do_e##name(T0_64);                                         \
1876
 
}
1877
 
 
1878
 
/* Fixed-point vector arithmetic */
1879
 
static always_inline uint32_t _do_eabs (uint32_t val)
1880
 
{
1881
 
    if ((val & 0x80000000) && val != 0x80000000)
1882
 
        val -= val;
1883
 
 
1884
 
    return val;
1885
 
}
1886
 
 
1887
 
static always_inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
1888
 
{
1889
 
    return op1 + op2;
1890
 
}
1891
 
 
1892
 
static always_inline int _do_ecntlsw (uint32_t val)
 
3086
    return (arg1 & ~mask) | (d & b);
 
3087
}
 
3088
 
 
3089
uint32_t helper_cntlsw32 (uint32_t val)
1893
3090
{
1894
3091
    if (val & 0x80000000)
1895
3092
        return clz32(~val);
1897
3094
        return clz32(val);
1898
3095
}
1899
3096
 
1900
 
static always_inline int _do_ecntlzw (uint32_t val)
 
3097
uint32_t helper_cntlzw32 (uint32_t val)
1901
3098
{
1902
3099
    return clz32(val);
1903
3100
}
1904
3101
 
1905
 
static always_inline uint32_t _do_eneg (uint32_t val)
1906
 
{
1907
 
    if (val != 0x80000000)
1908
 
        val -= val;
1909
 
 
1910
 
    return val;
1911
 
}
1912
 
 
1913
 
static always_inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
1914
 
{
1915
 
    return rotl32(op1, op2);
1916
 
}
1917
 
 
1918
 
static always_inline uint32_t _do_erndw (uint32_t val)
1919
 
{
1920
 
    return (val + 0x000080000000) & 0xFFFF0000;
1921
 
}
1922
 
 
1923
 
static always_inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
1924
 
{
1925
 
    /* No error here: 6 bits are used */
1926
 
    return op1 << (op2 & 0x3F);
1927
 
}
1928
 
 
1929
 
static always_inline int32_t _do_esrws (int32_t op1, uint32_t op2)
1930
 
{
1931
 
    /* No error here: 6 bits are used */
1932
 
    return op1 >> (op2 & 0x3F);
1933
 
}
1934
 
 
1935
 
static always_inline uint32_t _do_esrwu (uint32_t op1, uint32_t op2)
1936
 
{
1937
 
    /* No error here: 6 bits are used */
1938
 
    return op1 >> (op2 & 0x3F);
1939
 
}
1940
 
 
1941
 
static always_inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
1942
 
{
1943
 
    return op2 - op1;
1944
 
}
1945
 
 
1946
 
/* evabs */
1947
 
DO_SPE_OP1(abs);
1948
 
/* evaddw */
1949
 
DO_SPE_OP2(addw);
1950
 
/* evcntlsw */
1951
 
DO_SPE_OP1(cntlsw);
1952
 
/* evcntlzw */
1953
 
DO_SPE_OP1(cntlzw);
1954
 
/* evneg */
1955
 
DO_SPE_OP1(neg);
1956
 
/* evrlw */
1957
 
DO_SPE_OP2(rlw);
1958
 
/* evrnd */
1959
 
DO_SPE_OP1(rndw);
1960
 
/* evslw */
1961
 
DO_SPE_OP2(slw);
1962
 
/* evsrws */
1963
 
DO_SPE_OP2(srws);
1964
 
/* evsrwu */
1965
 
DO_SPE_OP2(srwu);
1966
 
/* evsubfw */
1967
 
DO_SPE_OP2(subfw);
1968
 
 
1969
 
/* evsel is a little bit more complicated... */
1970
 
static always_inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
1971
 
{
1972
 
    if (n)
1973
 
        return op1;
1974
 
    else
1975
 
        return op2;
1976
 
}
1977
 
 
1978
 
void do_evsel (void)
1979
 
{
1980
 
    T0_64 = ((uint64_t)_do_esel(T0_64 >> 32, T1_64 >> 32, T0 >> 3) << 32) |
1981
 
        (uint64_t)_do_esel(T0_64, T1_64, (T0 >> 2) & 1);
1982
 
}
1983
 
 
1984
 
/* Fixed-point vector comparisons */
1985
 
#define DO_SPE_CMP(name)                                                      \
1986
 
void do_ev##name (void)                                                       \
1987
 
{                                                                             \
1988
 
    T0 = _do_evcmp_merge((uint64_t)_do_e##name(T0_64 >> 32,                   \
1989
 
                                               T1_64 >> 32) << 32,            \
1990
 
                         _do_e##name(T0_64, T1_64));                          \
1991
 
}
1992
 
 
1993
 
static always_inline uint32_t _do_evcmp_merge (int t0, int t1)
1994
 
{
1995
 
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1996
 
}
1997
 
static always_inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
1998
 
{
1999
 
    return op1 == op2 ? 1 : 0;
2000
 
}
2001
 
 
2002
 
static always_inline int _do_ecmpgts (int32_t op1, int32_t op2)
2003
 
{
2004
 
    return op1 > op2 ? 1 : 0;
2005
 
}
2006
 
 
2007
 
static always_inline int _do_ecmpgtu (uint32_t op1, uint32_t op2)
2008
 
{
2009
 
    return op1 > op2 ? 1 : 0;
2010
 
}
2011
 
 
2012
 
static always_inline int _do_ecmplts (int32_t op1, int32_t op2)
2013
 
{
2014
 
    return op1 < op2 ? 1 : 0;
2015
 
}
2016
 
 
2017
 
static always_inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
2018
 
{
2019
 
    return op1 < op2 ? 1 : 0;
2020
 
}
2021
 
 
2022
 
/* evcmpeq */
2023
 
DO_SPE_CMP(cmpeq);
2024
 
/* evcmpgts */
2025
 
DO_SPE_CMP(cmpgts);
2026
 
/* evcmpgtu */
2027
 
DO_SPE_CMP(cmpgtu);
2028
 
/* evcmplts */
2029
 
DO_SPE_CMP(cmplts);
2030
 
/* evcmpltu */
2031
 
DO_SPE_CMP(cmpltu);
2032
 
 
2033
 
/* Single precision floating-point conversions from/to integer */
2034
 
static always_inline uint32_t _do_efscfsi (int32_t val)
2035
 
{
2036
 
    CPU_FloatU u;
2037
 
 
2038
 
    u.f = int32_to_float32(val, &env->spe_status);
2039
 
 
2040
 
    return u.l;
2041
 
}
2042
 
 
2043
 
static always_inline uint32_t _do_efscfui (uint32_t val)
2044
 
{
2045
 
    CPU_FloatU u;
2046
 
 
2047
 
    u.f = uint32_to_float32(val, &env->spe_status);
2048
 
 
2049
 
    return u.l;
2050
 
}
2051
 
 
2052
 
static always_inline int32_t _do_efsctsi (uint32_t val)
2053
 
{
2054
 
    CPU_FloatU u;
2055
 
 
2056
 
    u.l = val;
2057
 
    /* NaN are not treated the same way IEEE 754 does */
2058
 
    if (unlikely(isnan(u.f)))
2059
 
        return 0;
2060
 
 
2061
 
    return float32_to_int32(u.f, &env->spe_status);
2062
 
}
2063
 
 
2064
 
static always_inline uint32_t _do_efsctui (uint32_t val)
2065
 
{
2066
 
    CPU_FloatU u;
2067
 
 
2068
 
    u.l = val;
2069
 
    /* NaN are not treated the same way IEEE 754 does */
2070
 
    if (unlikely(isnan(u.f)))
2071
 
        return 0;
2072
 
 
2073
 
    return float32_to_uint32(u.f, &env->spe_status);
2074
 
}
2075
 
 
2076
 
static always_inline int32_t _do_efsctsiz (uint32_t val)
2077
 
{
2078
 
    CPU_FloatU u;
2079
 
 
2080
 
    u.l = val;
2081
 
    /* NaN are not treated the same way IEEE 754 does */
2082
 
    if (unlikely(isnan(u.f)))
2083
 
        return 0;
2084
 
 
2085
 
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
2086
 
}
2087
 
 
2088
 
static always_inline uint32_t _do_efsctuiz (uint32_t val)
2089
 
{
2090
 
    CPU_FloatU u;
2091
 
 
2092
 
    u.l = val;
2093
 
    /* NaN are not treated the same way IEEE 754 does */
2094
 
    if (unlikely(isnan(u.f)))
2095
 
        return 0;
2096
 
 
2097
 
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
2098
 
}
2099
 
 
2100
 
void do_efscfsi (void)
2101
 
{
2102
 
    T0_64 = _do_efscfsi(T0_64);
2103
 
}
2104
 
 
2105
 
void do_efscfui (void)
2106
 
{
2107
 
    T0_64 = _do_efscfui(T0_64);
2108
 
}
2109
 
 
2110
 
void do_efsctsi (void)
2111
 
{
2112
 
    T0_64 = _do_efsctsi(T0_64);
2113
 
}
2114
 
 
2115
 
void do_efsctui (void)
2116
 
{
2117
 
    T0_64 = _do_efsctui(T0_64);
2118
 
}
2119
 
 
2120
 
void do_efsctsiz (void)
2121
 
{
2122
 
    T0_64 = _do_efsctsiz(T0_64);
2123
 
}
2124
 
 
2125
 
void do_efsctuiz (void)
2126
 
{
2127
 
    T0_64 = _do_efsctuiz(T0_64);
2128
 
}
2129
 
 
2130
 
/* Single precision floating-point conversion to/from fractional */
2131
 
static always_inline uint32_t _do_efscfsf (uint32_t val)
2132
 
{
2133
 
    CPU_FloatU u;
2134
 
    float32 tmp;
2135
 
 
2136
 
    u.f = int32_to_float32(val, &env->spe_status);
2137
 
    tmp = int64_to_float32(1ULL << 32, &env->spe_status);
2138
 
    u.f = float32_div(u.f, tmp, &env->spe_status);
2139
 
 
2140
 
    return u.l;
2141
 
}
2142
 
 
2143
 
static always_inline uint32_t _do_efscfuf (uint32_t val)
2144
 
{
2145
 
    CPU_FloatU u;
2146
 
    float32 tmp;
2147
 
 
2148
 
    u.f = uint32_to_float32(val, &env->spe_status);
2149
 
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2150
 
    u.f = float32_div(u.f, tmp, &env->spe_status);
2151
 
 
2152
 
    return u.l;
2153
 
}
2154
 
 
2155
 
static always_inline int32_t _do_efsctsf (uint32_t val)
2156
 
{
2157
 
    CPU_FloatU u;
2158
 
    float32 tmp;
2159
 
 
2160
 
    u.l = val;
2161
 
    /* NaN are not treated the same way IEEE 754 does */
2162
 
    if (unlikely(isnan(u.f)))
2163
 
        return 0;
2164
 
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2165
 
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2166
 
 
2167
 
    return float32_to_int32(u.f, &env->spe_status);
2168
 
}
2169
 
 
2170
 
static always_inline uint32_t _do_efsctuf (uint32_t val)
2171
 
{
2172
 
    CPU_FloatU u;
2173
 
    float32 tmp;
2174
 
 
2175
 
    u.l = val;
2176
 
    /* NaN are not treated the same way IEEE 754 does */
2177
 
    if (unlikely(isnan(u.f)))
2178
 
        return 0;
2179
 
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2180
 
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2181
 
 
2182
 
    return float32_to_uint32(u.f, &env->spe_status);
2183
 
}
2184
 
 
2185
 
static always_inline int32_t _do_efsctsfz (uint32_t val)
2186
 
{
2187
 
    CPU_FloatU u;
2188
 
    float32 tmp;
2189
 
 
2190
 
    u.l = val;
2191
 
    /* NaN are not treated the same way IEEE 754 does */
2192
 
    if (unlikely(isnan(u.f)))
2193
 
        return 0;
2194
 
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2195
 
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2196
 
 
2197
 
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
2198
 
}
2199
 
 
2200
 
static always_inline uint32_t _do_efsctufz (uint32_t val)
2201
 
{
2202
 
    CPU_FloatU u;
2203
 
    float32 tmp;
2204
 
 
2205
 
    u.l = val;
2206
 
    /* NaN are not treated the same way IEEE 754 does */
2207
 
    if (unlikely(isnan(u.f)))
2208
 
        return 0;
2209
 
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2210
 
    u.f = float32_mul(u.f, tmp, &env->spe_status);
2211
 
 
2212
 
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
2213
 
}
2214
 
 
2215
 
void do_efscfsf (void)
2216
 
{
2217
 
    T0_64 = _do_efscfsf(T0_64);
2218
 
}
2219
 
 
2220
 
void do_efscfuf (void)
2221
 
{
2222
 
    T0_64 = _do_efscfuf(T0_64);
2223
 
}
2224
 
 
2225
 
void do_efsctsf (void)
2226
 
{
2227
 
    T0_64 = _do_efsctsf(T0_64);
2228
 
}
2229
 
 
2230
 
void do_efsctuf (void)
2231
 
{
2232
 
    T0_64 = _do_efsctuf(T0_64);
2233
 
}
2234
 
 
2235
 
void do_efsctsfz (void)
2236
 
{
2237
 
    T0_64 = _do_efsctsfz(T0_64);
2238
 
}
2239
 
 
2240
 
void do_efsctufz (void)
2241
 
{
2242
 
    T0_64 = _do_efsctufz(T0_64);
2243
 
}
2244
 
 
2245
 
/* Double precision floating point helpers */
2246
 
static always_inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
2247
 
{
2248
 
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2249
 
    return _do_efdtstlt(op1, op2);
2250
 
}
2251
 
 
2252
 
static always_inline int _do_efdcmpgt (uint64_t op1, uint64_t op2)
2253
 
{
2254
 
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2255
 
    return _do_efdtstgt(op1, op2);
2256
 
}
2257
 
 
2258
 
static always_inline int _do_efdcmpeq (uint64_t op1, uint64_t op2)
2259
 
{
2260
 
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2261
 
    return _do_efdtsteq(op1, op2);
2262
 
}
2263
 
 
2264
 
void do_efdcmplt (void)
2265
 
{
2266
 
    T0 = _do_efdcmplt(T0_64, T1_64);
2267
 
}
2268
 
 
2269
 
void do_efdcmpgt (void)
2270
 
{
2271
 
    T0 = _do_efdcmpgt(T0_64, T1_64);
2272
 
}
2273
 
 
2274
 
void do_efdcmpeq (void)
2275
 
{
2276
 
    T0 = _do_efdcmpeq(T0_64, T1_64);
2277
 
}
2278
 
 
2279
 
/* Double precision floating-point conversion to/from integer */
2280
 
static always_inline uint64_t _do_efdcfsi (int64_t val)
2281
 
{
2282
 
    CPU_DoubleU u;
2283
 
 
2284
 
    u.d = int64_to_float64(val, &env->spe_status);
2285
 
 
2286
 
    return u.ll;
2287
 
}
2288
 
 
2289
 
static always_inline uint64_t _do_efdcfui (uint64_t val)
2290
 
{
2291
 
    CPU_DoubleU u;
2292
 
 
2293
 
    u.d = uint64_to_float64(val, &env->spe_status);
2294
 
 
2295
 
    return u.ll;
2296
 
}
2297
 
 
2298
 
static always_inline int64_t _do_efdctsi (uint64_t val)
2299
 
{
2300
 
    CPU_DoubleU u;
2301
 
 
2302
 
    u.ll = val;
2303
 
    /* NaN are not treated the same way IEEE 754 does */
2304
 
    if (unlikely(isnan(u.d)))
2305
 
        return 0;
2306
 
 
2307
 
    return float64_to_int64(u.d, &env->spe_status);
2308
 
}
2309
 
 
2310
 
static always_inline uint64_t _do_efdctui (uint64_t val)
2311
 
{
2312
 
    CPU_DoubleU u;
2313
 
 
2314
 
    u.ll = val;
2315
 
    /* NaN are not treated the same way IEEE 754 does */
2316
 
    if (unlikely(isnan(u.d)))
2317
 
        return 0;
2318
 
 
2319
 
    return float64_to_uint64(u.d, &env->spe_status);
2320
 
}
2321
 
 
2322
 
static always_inline int64_t _do_efdctsiz (uint64_t val)
2323
 
{
2324
 
    CPU_DoubleU u;
2325
 
 
2326
 
    u.ll = val;
2327
 
    /* NaN are not treated the same way IEEE 754 does */
2328
 
    if (unlikely(isnan(u.d)))
2329
 
        return 0;
2330
 
 
2331
 
    return float64_to_int64_round_to_zero(u.d, &env->spe_status);
2332
 
}
2333
 
 
2334
 
static always_inline uint64_t _do_efdctuiz (uint64_t val)
2335
 
{
2336
 
    CPU_DoubleU u;
2337
 
 
2338
 
    u.ll = val;
2339
 
    /* NaN are not treated the same way IEEE 754 does */
2340
 
    if (unlikely(isnan(u.d)))
2341
 
        return 0;
2342
 
 
2343
 
    return float64_to_uint64_round_to_zero(u.d, &env->spe_status);
2344
 
}
2345
 
 
2346
 
void do_efdcfsi (void)
2347
 
{
2348
 
    T0_64 = _do_efdcfsi(T0_64);
2349
 
}
2350
 
 
2351
 
void do_efdcfui (void)
2352
 
{
2353
 
    T0_64 = _do_efdcfui(T0_64);
2354
 
}
2355
 
 
2356
 
void do_efdctsi (void)
2357
 
{
2358
 
    T0_64 = _do_efdctsi(T0_64);
2359
 
}
2360
 
 
2361
 
void do_efdctui (void)
2362
 
{
2363
 
    T0_64 = _do_efdctui(T0_64);
2364
 
}
2365
 
 
2366
 
void do_efdctsiz (void)
2367
 
{
2368
 
    T0_64 = _do_efdctsiz(T0_64);
2369
 
}
2370
 
 
2371
 
void do_efdctuiz (void)
2372
 
{
2373
 
    T0_64 = _do_efdctuiz(T0_64);
2374
 
}
2375
 
 
2376
 
/* Double precision floating-point conversion to/from fractional */
2377
 
static always_inline uint64_t _do_efdcfsf (int64_t val)
2378
 
{
2379
 
    CPU_DoubleU u;
2380
 
    float64 tmp;
2381
 
 
2382
 
    u.d = int32_to_float64(val, &env->spe_status);
2383
 
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2384
 
    u.d = float64_div(u.d, tmp, &env->spe_status);
2385
 
 
2386
 
    return u.ll;
2387
 
}
2388
 
 
2389
 
static always_inline uint64_t _do_efdcfuf (uint64_t val)
2390
 
{
2391
 
    CPU_DoubleU u;
2392
 
    float64 tmp;
2393
 
 
2394
 
    u.d = uint32_to_float64(val, &env->spe_status);
2395
 
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2396
 
    u.d = float64_div(u.d, tmp, &env->spe_status);
2397
 
 
2398
 
    return u.ll;
2399
 
}
2400
 
 
2401
 
static always_inline int64_t _do_efdctsf (uint64_t val)
2402
 
{
2403
 
    CPU_DoubleU u;
2404
 
    float64 tmp;
2405
 
 
2406
 
    u.ll = val;
2407
 
    /* NaN are not treated the same way IEEE 754 does */
2408
 
    if (unlikely(isnan(u.d)))
2409
 
        return 0;
2410
 
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2411
 
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2412
 
 
2413
 
    return float64_to_int32(u.d, &env->spe_status);
2414
 
}
2415
 
 
2416
 
static always_inline uint64_t _do_efdctuf (uint64_t val)
2417
 
{
2418
 
    CPU_DoubleU u;
2419
 
    float64 tmp;
2420
 
 
2421
 
    u.ll = val;
2422
 
    /* NaN are not treated the same way IEEE 754 does */
2423
 
    if (unlikely(isnan(u.d)))
2424
 
        return 0;
2425
 
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2426
 
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2427
 
 
2428
 
    return float64_to_uint32(u.d, &env->spe_status);
2429
 
}
2430
 
 
2431
 
static always_inline int64_t _do_efdctsfz (uint64_t val)
2432
 
{
2433
 
    CPU_DoubleU u;
2434
 
    float64 tmp;
2435
 
 
2436
 
    u.ll = val;
2437
 
    /* NaN are not treated the same way IEEE 754 does */
2438
 
    if (unlikely(isnan(u.d)))
2439
 
        return 0;
2440
 
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2441
 
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2442
 
 
2443
 
    return float64_to_int32_round_to_zero(u.d, &env->spe_status);
2444
 
}
2445
 
 
2446
 
static always_inline uint64_t _do_efdctufz (uint64_t val)
2447
 
{
2448
 
    CPU_DoubleU u;
2449
 
    float64 tmp;
2450
 
 
2451
 
    u.ll = val;
2452
 
    /* NaN are not treated the same way IEEE 754 does */
2453
 
    if (unlikely(isnan(u.d)))
2454
 
        return 0;
2455
 
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2456
 
    u.d = float64_mul(u.d, tmp, &env->spe_status);
2457
 
 
2458
 
    return float64_to_uint32_round_to_zero(u.d, &env->spe_status);
2459
 
}
2460
 
 
2461
 
void do_efdcfsf (void)
2462
 
{
2463
 
    T0_64 = _do_efdcfsf(T0_64);
2464
 
}
2465
 
 
2466
 
void do_efdcfuf (void)
2467
 
{
2468
 
    T0_64 = _do_efdcfuf(T0_64);
2469
 
}
2470
 
 
2471
 
void do_efdctsf (void)
2472
 
{
2473
 
    T0_64 = _do_efdctsf(T0_64);
2474
 
}
2475
 
 
2476
 
void do_efdctuf (void)
2477
 
{
2478
 
    T0_64 = _do_efdctuf(T0_64);
2479
 
}
2480
 
 
2481
 
void do_efdctsfz (void)
2482
 
{
2483
 
    T0_64 = _do_efdctsfz(T0_64);
2484
 
}
2485
 
 
2486
 
void do_efdctufz (void)
2487
 
{
2488
 
    T0_64 = _do_efdctufz(T0_64);
2489
 
}
2490
 
 
2491
 
/* Floating point conversion between single and double precision */
2492
 
static always_inline uint32_t _do_efscfd (uint64_t val)
2493
 
{
2494
 
    CPU_DoubleU u1;
2495
 
    CPU_FloatU u2;
2496
 
 
2497
 
    u1.ll = val;
2498
 
    u2.f = float64_to_float32(u1.d, &env->spe_status);
2499
 
 
2500
 
    return u2.l;
2501
 
}
2502
 
 
2503
 
static always_inline uint64_t _do_efdcfs (uint32_t val)
2504
 
{
2505
 
    CPU_DoubleU u2;
2506
 
    CPU_FloatU u1;
2507
 
 
2508
 
    u1.l = val;
2509
 
    u2.d = float32_to_float64(u1.f, &env->spe_status);
2510
 
 
2511
 
    return u2.ll;
2512
 
}
2513
 
 
2514
 
void do_efscfd (void)
2515
 
{
2516
 
    T0_64 = _do_efscfd(T0_64);
2517
 
}
2518
 
 
2519
 
void do_efdcfs (void)
2520
 
{
2521
 
    T0_64 = _do_efdcfs(T0_64);
2522
 
}
2523
 
 
2524
 
/* Single precision fixed-point vector arithmetic */
2525
 
/* evfsabs */
2526
 
DO_SPE_OP1(fsabs);
2527
 
/* evfsnabs */
2528
 
DO_SPE_OP1(fsnabs);
2529
 
/* evfsneg */
2530
 
DO_SPE_OP1(fsneg);
2531
 
/* evfsadd */
2532
 
DO_SPE_OP2(fsadd);
2533
 
/* evfssub */
2534
 
DO_SPE_OP2(fssub);
2535
 
/* evfsmul */
2536
 
DO_SPE_OP2(fsmul);
2537
 
/* evfsdiv */
2538
 
DO_SPE_OP2(fsdiv);
2539
 
 
2540
 
/* Single-precision floating-point comparisons */
2541
 
static always_inline int _do_efscmplt (uint32_t op1, uint32_t op2)
2542
 
{
2543
 
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2544
 
    return _do_efststlt(op1, op2);
2545
 
}
2546
 
 
2547
 
static always_inline int _do_efscmpgt (uint32_t op1, uint32_t op2)
2548
 
{
2549
 
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2550
 
    return _do_efststgt(op1, op2);
2551
 
}
2552
 
 
2553
 
static always_inline int _do_efscmpeq (uint32_t op1, uint32_t op2)
2554
 
{
2555
 
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2556
 
    return _do_efststeq(op1, op2);
2557
 
}
2558
 
 
2559
 
void do_efscmplt (void)
2560
 
{
2561
 
    T0 = _do_efscmplt(T0_64, T1_64);
2562
 
}
2563
 
 
2564
 
void do_efscmpgt (void)
2565
 
{
2566
 
    T0 = _do_efscmpgt(T0_64, T1_64);
2567
 
}
2568
 
 
2569
 
void do_efscmpeq (void)
2570
 
{
2571
 
    T0 = _do_efscmpeq(T0_64, T1_64);
2572
 
}
2573
 
 
2574
 
/* Single-precision floating-point vector comparisons */
2575
 
/* evfscmplt */
2576
 
DO_SPE_CMP(fscmplt);
2577
 
/* evfscmpgt */
2578
 
DO_SPE_CMP(fscmpgt);
2579
 
/* evfscmpeq */
2580
 
DO_SPE_CMP(fscmpeq);
2581
 
/* evfststlt */
2582
 
DO_SPE_CMP(fststlt);
2583
 
/* evfststgt */
2584
 
DO_SPE_CMP(fststgt);
2585
 
/* evfststeq */
2586
 
DO_SPE_CMP(fststeq);
2587
 
 
2588
 
/* Single-precision floating-point vector conversions */
 
3102
/* Single-precision floating-point conversions */
 
3103
static inline uint32_t efscfsi(uint32_t val)
 
3104
{
 
3105
    CPU_FloatU u;
 
3106
 
 
3107
    u.f = int32_to_float32(val, &env->vec_status);
 
3108
 
 
3109
    return u.l;
 
3110
}
 
3111
 
 
3112
static inline uint32_t efscfui(uint32_t val)
 
3113
{
 
3114
    CPU_FloatU u;
 
3115
 
 
3116
    u.f = uint32_to_float32(val, &env->vec_status);
 
3117
 
 
3118
    return u.l;
 
3119
}
 
3120
 
 
3121
static inline int32_t efsctsi(uint32_t val)
 
3122
{
 
3123
    CPU_FloatU u;
 
3124
 
 
3125
    u.l = val;
 
3126
    /* NaN are not treated the same way IEEE 754 does */
 
3127
    if (unlikely(float32_is_nan(u.f)))
 
3128
        return 0;
 
3129
 
 
3130
    return float32_to_int32(u.f, &env->vec_status);
 
3131
}
 
3132
 
 
3133
static inline uint32_t efsctui(uint32_t val)
 
3134
{
 
3135
    CPU_FloatU u;
 
3136
 
 
3137
    u.l = val;
 
3138
    /* NaN are not treated the same way IEEE 754 does */
 
3139
    if (unlikely(float32_is_nan(u.f)))
 
3140
        return 0;
 
3141
 
 
3142
    return float32_to_uint32(u.f, &env->vec_status);
 
3143
}
 
3144
 
 
3145
static inline uint32_t efsctsiz(uint32_t val)
 
3146
{
 
3147
    CPU_FloatU u;
 
3148
 
 
3149
    u.l = val;
 
3150
    /* NaN are not treated the same way IEEE 754 does */
 
3151
    if (unlikely(float32_is_nan(u.f)))
 
3152
        return 0;
 
3153
 
 
3154
    return float32_to_int32_round_to_zero(u.f, &env->vec_status);
 
3155
}
 
3156
 
 
3157
static inline uint32_t efsctuiz(uint32_t val)
 
3158
{
 
3159
    CPU_FloatU u;
 
3160
 
 
3161
    u.l = val;
 
3162
    /* NaN are not treated the same way IEEE 754 does */
 
3163
    if (unlikely(float32_is_nan(u.f)))
 
3164
        return 0;
 
3165
 
 
3166
    return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
 
3167
}
 
3168
 
 
3169
static inline uint32_t efscfsf(uint32_t val)
 
3170
{
 
3171
    CPU_FloatU u;
 
3172
    float32 tmp;
 
3173
 
 
3174
    u.f = int32_to_float32(val, &env->vec_status);
 
3175
    tmp = int64_to_float32(1ULL << 32, &env->vec_status);
 
3176
    u.f = float32_div(u.f, tmp, &env->vec_status);
 
3177
 
 
3178
    return u.l;
 
3179
}
 
3180
 
 
3181
static inline uint32_t efscfuf(uint32_t val)
 
3182
{
 
3183
    CPU_FloatU u;
 
3184
    float32 tmp;
 
3185
 
 
3186
    u.f = uint32_to_float32(val, &env->vec_status);
 
3187
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
 
3188
    u.f = float32_div(u.f, tmp, &env->vec_status);
 
3189
 
 
3190
    return u.l;
 
3191
}
 
3192
 
 
3193
static inline uint32_t efsctsf(uint32_t val)
 
3194
{
 
3195
    CPU_FloatU u;
 
3196
    float32 tmp;
 
3197
 
 
3198
    u.l = val;
 
3199
    /* NaN are not treated the same way IEEE 754 does */
 
3200
    if (unlikely(float32_is_nan(u.f)))
 
3201
        return 0;
 
3202
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
 
3203
    u.f = float32_mul(u.f, tmp, &env->vec_status);
 
3204
 
 
3205
    return float32_to_int32(u.f, &env->vec_status);
 
3206
}
 
3207
 
 
3208
static inline uint32_t efsctuf(uint32_t val)
 
3209
{
 
3210
    CPU_FloatU u;
 
3211
    float32 tmp;
 
3212
 
 
3213
    u.l = val;
 
3214
    /* NaN are not treated the same way IEEE 754 does */
 
3215
    if (unlikely(float32_is_nan(u.f)))
 
3216
        return 0;
 
3217
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
 
3218
    u.f = float32_mul(u.f, tmp, &env->vec_status);
 
3219
 
 
3220
    return float32_to_uint32(u.f, &env->vec_status);
 
3221
}
 
3222
 
 
3223
#define HELPER_SPE_SINGLE_CONV(name)                                          \
 
3224
uint32_t helper_e##name (uint32_t val)                                        \
 
3225
{                                                                             \
 
3226
    return e##name(val);                                                      \
 
3227
}
 
3228
/* efscfsi */
 
3229
HELPER_SPE_SINGLE_CONV(fscfsi);
 
3230
/* efscfui */
 
3231
HELPER_SPE_SINGLE_CONV(fscfui);
 
3232
/* efscfuf */
 
3233
HELPER_SPE_SINGLE_CONV(fscfuf);
 
3234
/* efscfsf */
 
3235
HELPER_SPE_SINGLE_CONV(fscfsf);
 
3236
/* efsctsi */
 
3237
HELPER_SPE_SINGLE_CONV(fsctsi);
 
3238
/* efsctui */
 
3239
HELPER_SPE_SINGLE_CONV(fsctui);
 
3240
/* efsctsiz */
 
3241
HELPER_SPE_SINGLE_CONV(fsctsiz);
 
3242
/* efsctuiz */
 
3243
HELPER_SPE_SINGLE_CONV(fsctuiz);
 
3244
/* efsctsf */
 
3245
HELPER_SPE_SINGLE_CONV(fsctsf);
 
3246
/* efsctuf */
 
3247
HELPER_SPE_SINGLE_CONV(fsctuf);
 
3248
 
 
3249
#define HELPER_SPE_VECTOR_CONV(name)                                          \
 
3250
uint64_t helper_ev##name (uint64_t val)                                       \
 
3251
{                                                                             \
 
3252
    return ((uint64_t)e##name(val >> 32) << 32) |                             \
 
3253
            (uint64_t)e##name(val);                                           \
 
3254
}
2589
3255
/* evfscfsi */
2590
 
DO_SPE_OP1(fscfsi);
 
3256
HELPER_SPE_VECTOR_CONV(fscfsi);
2591
3257
/* evfscfui */
2592
 
DO_SPE_OP1(fscfui);
 
3258
HELPER_SPE_VECTOR_CONV(fscfui);
2593
3259
/* evfscfuf */
2594
 
DO_SPE_OP1(fscfuf);
 
3260
HELPER_SPE_VECTOR_CONV(fscfuf);
2595
3261
/* evfscfsf */
2596
 
DO_SPE_OP1(fscfsf);
 
3262
HELPER_SPE_VECTOR_CONV(fscfsf);
2597
3263
/* evfsctsi */
2598
 
DO_SPE_OP1(fsctsi);
 
3264
HELPER_SPE_VECTOR_CONV(fsctsi);
2599
3265
/* evfsctui */
2600
 
DO_SPE_OP1(fsctui);
 
3266
HELPER_SPE_VECTOR_CONV(fsctui);
2601
3267
/* evfsctsiz */
2602
 
DO_SPE_OP1(fsctsiz);
 
3268
HELPER_SPE_VECTOR_CONV(fsctsiz);
2603
3269
/* evfsctuiz */
2604
 
DO_SPE_OP1(fsctuiz);
 
3270
HELPER_SPE_VECTOR_CONV(fsctuiz);
2605
3271
/* evfsctsf */
2606
 
DO_SPE_OP1(fsctsf);
 
3272
HELPER_SPE_VECTOR_CONV(fsctsf);
2607
3273
/* evfsctuf */
2608
 
DO_SPE_OP1(fsctuf);
 
3274
HELPER_SPE_VECTOR_CONV(fsctuf);
 
3275
 
 
3276
/* Single-precision floating-point arithmetic */
 
3277
static inline uint32_t efsadd(uint32_t op1, uint32_t op2)
 
3278
{
 
3279
    CPU_FloatU u1, u2;
 
3280
    u1.l = op1;
 
3281
    u2.l = op2;
 
3282
    u1.f = float32_add(u1.f, u2.f, &env->vec_status);
 
3283
    return u1.l;
 
3284
}
 
3285
 
 
3286
static inline uint32_t efssub(uint32_t op1, uint32_t op2)
 
3287
{
 
3288
    CPU_FloatU u1, u2;
 
3289
    u1.l = op1;
 
3290
    u2.l = op2;
 
3291
    u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
 
3292
    return u1.l;
 
3293
}
 
3294
 
 
3295
static inline uint32_t efsmul(uint32_t op1, uint32_t op2)
 
3296
{
 
3297
    CPU_FloatU u1, u2;
 
3298
    u1.l = op1;
 
3299
    u2.l = op2;
 
3300
    u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
 
3301
    return u1.l;
 
3302
}
 
3303
 
 
3304
static inline uint32_t efsdiv(uint32_t op1, uint32_t op2)
 
3305
{
 
3306
    CPU_FloatU u1, u2;
 
3307
    u1.l = op1;
 
3308
    u2.l = op2;
 
3309
    u1.f = float32_div(u1.f, u2.f, &env->vec_status);
 
3310
    return u1.l;
 
3311
}
 
3312
 
 
3313
#define HELPER_SPE_SINGLE_ARITH(name)                                         \
 
3314
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
 
3315
{                                                                             \
 
3316
    return e##name(op1, op2);                                                 \
 
3317
}
 
3318
/* efsadd */
 
3319
HELPER_SPE_SINGLE_ARITH(fsadd);
 
3320
/* efssub */
 
3321
HELPER_SPE_SINGLE_ARITH(fssub);
 
3322
/* efsmul */
 
3323
HELPER_SPE_SINGLE_ARITH(fsmul);
 
3324
/* efsdiv */
 
3325
HELPER_SPE_SINGLE_ARITH(fsdiv);
 
3326
 
 
3327
#define HELPER_SPE_VECTOR_ARITH(name)                                         \
 
3328
uint64_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
 
3329
{                                                                             \
 
3330
    return ((uint64_t)e##name(op1 >> 32, op2 >> 32) << 32) |                  \
 
3331
            (uint64_t)e##name(op1, op2);                                      \
 
3332
}
 
3333
/* evfsadd */
 
3334
HELPER_SPE_VECTOR_ARITH(fsadd);
 
3335
/* evfssub */
 
3336
HELPER_SPE_VECTOR_ARITH(fssub);
 
3337
/* evfsmul */
 
3338
HELPER_SPE_VECTOR_ARITH(fsmul);
 
3339
/* evfsdiv */
 
3340
HELPER_SPE_VECTOR_ARITH(fsdiv);
 
3341
 
 
3342
/* Single-precision floating-point comparisons */
 
3343
static inline uint32_t efststlt(uint32_t op1, uint32_t op2)
 
3344
{
 
3345
    CPU_FloatU u1, u2;
 
3346
    u1.l = op1;
 
3347
    u2.l = op2;
 
3348
    return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
 
3349
}
 
3350
 
 
3351
static inline uint32_t efststgt(uint32_t op1, uint32_t op2)
 
3352
{
 
3353
    CPU_FloatU u1, u2;
 
3354
    u1.l = op1;
 
3355
    u2.l = op2;
 
3356
    return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
 
3357
}
 
3358
 
 
3359
static inline uint32_t efststeq(uint32_t op1, uint32_t op2)
 
3360
{
 
3361
    CPU_FloatU u1, u2;
 
3362
    u1.l = op1;
 
3363
    u2.l = op2;
 
3364
    return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
 
3365
}
 
3366
 
 
3367
static inline uint32_t efscmplt(uint32_t op1, uint32_t op2)
 
3368
{
 
3369
    /* XXX: TODO: test special values (NaN, infinites, ...) */
 
3370
    return efststlt(op1, op2);
 
3371
}
 
3372
 
 
3373
static inline uint32_t efscmpgt(uint32_t op1, uint32_t op2)
 
3374
{
 
3375
    /* XXX: TODO: test special values (NaN, infinites, ...) */
 
3376
    return efststgt(op1, op2);
 
3377
}
 
3378
 
 
3379
static inline uint32_t efscmpeq(uint32_t op1, uint32_t op2)
 
3380
{
 
3381
    /* XXX: TODO: test special values (NaN, infinites, ...) */
 
3382
    return efststeq(op1, op2);
 
3383
}
 
3384
 
 
3385
#define HELPER_SINGLE_SPE_CMP(name)                                           \
 
3386
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
 
3387
{                                                                             \
 
3388
    return e##name(op1, op2) << 2;                                            \
 
3389
}
 
3390
/* efststlt */
 
3391
HELPER_SINGLE_SPE_CMP(fststlt);
 
3392
/* efststgt */
 
3393
HELPER_SINGLE_SPE_CMP(fststgt);
 
3394
/* efststeq */
 
3395
HELPER_SINGLE_SPE_CMP(fststeq);
 
3396
/* efscmplt */
 
3397
HELPER_SINGLE_SPE_CMP(fscmplt);
 
3398
/* efscmpgt */
 
3399
HELPER_SINGLE_SPE_CMP(fscmpgt);
 
3400
/* efscmpeq */
 
3401
HELPER_SINGLE_SPE_CMP(fscmpeq);
 
3402
 
 
3403
static inline uint32_t evcmp_merge(int t0, int t1)
 
3404
{
 
3405
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
 
3406
}
 
3407
 
 
3408
#define HELPER_VECTOR_SPE_CMP(name)                                           \
 
3409
uint32_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
 
3410
{                                                                             \
 
3411
    return evcmp_merge(e##name(op1 >> 32, op2 >> 32), e##name(op1, op2));     \
 
3412
}
 
3413
/* evfststlt */
 
3414
HELPER_VECTOR_SPE_CMP(fststlt);
 
3415
/* evfststgt */
 
3416
HELPER_VECTOR_SPE_CMP(fststgt);
 
3417
/* evfststeq */
 
3418
HELPER_VECTOR_SPE_CMP(fststeq);
 
3419
/* evfscmplt */
 
3420
HELPER_VECTOR_SPE_CMP(fscmplt);
 
3421
/* evfscmpgt */
 
3422
HELPER_VECTOR_SPE_CMP(fscmpgt);
 
3423
/* evfscmpeq */
 
3424
HELPER_VECTOR_SPE_CMP(fscmpeq);
 
3425
 
 
3426
/* Double-precision floating-point conversion */
 
3427
uint64_t helper_efdcfsi (uint32_t val)
 
3428
{
 
3429
    CPU_DoubleU u;
 
3430
 
 
3431
    u.d = int32_to_float64(val, &env->vec_status);
 
3432
 
 
3433
    return u.ll;
 
3434
}
 
3435
 
 
3436
uint64_t helper_efdcfsid (uint64_t val)
 
3437
{
 
3438
    CPU_DoubleU u;
 
3439
 
 
3440
    u.d = int64_to_float64(val, &env->vec_status);
 
3441
 
 
3442
    return u.ll;
 
3443
}
 
3444
 
 
3445
uint64_t helper_efdcfui (uint32_t val)
 
3446
{
 
3447
    CPU_DoubleU u;
 
3448
 
 
3449
    u.d = uint32_to_float64(val, &env->vec_status);
 
3450
 
 
3451
    return u.ll;
 
3452
}
 
3453
 
 
3454
uint64_t helper_efdcfuid (uint64_t val)
 
3455
{
 
3456
    CPU_DoubleU u;
 
3457
 
 
3458
    u.d = uint64_to_float64(val, &env->vec_status);
 
3459
 
 
3460
    return u.ll;
 
3461
}
 
3462
 
 
3463
uint32_t helper_efdctsi (uint64_t val)
 
3464
{
 
3465
    CPU_DoubleU u;
 
3466
 
 
3467
    u.ll = val;
 
3468
    /* NaN are not treated the same way IEEE 754 does */
 
3469
    if (unlikely(float64_is_nan(u.d)))
 
3470
        return 0;
 
3471
 
 
3472
    return float64_to_int32(u.d, &env->vec_status);
 
3473
}
 
3474
 
 
3475
uint32_t helper_efdctui (uint64_t val)
 
3476
{
 
3477
    CPU_DoubleU u;
 
3478
 
 
3479
    u.ll = val;
 
3480
    /* NaN are not treated the same way IEEE 754 does */
 
3481
    if (unlikely(float64_is_nan(u.d)))
 
3482
        return 0;
 
3483
 
 
3484
    return float64_to_uint32(u.d, &env->vec_status);
 
3485
}
 
3486
 
 
3487
uint32_t helper_efdctsiz (uint64_t val)
 
3488
{
 
3489
    CPU_DoubleU u;
 
3490
 
 
3491
    u.ll = val;
 
3492
    /* NaN are not treated the same way IEEE 754 does */
 
3493
    if (unlikely(float64_is_nan(u.d)))
 
3494
        return 0;
 
3495
 
 
3496
    return float64_to_int32_round_to_zero(u.d, &env->vec_status);
 
3497
}
 
3498
 
 
3499
uint64_t helper_efdctsidz (uint64_t val)
 
3500
{
 
3501
    CPU_DoubleU u;
 
3502
 
 
3503
    u.ll = val;
 
3504
    /* NaN are not treated the same way IEEE 754 does */
 
3505
    if (unlikely(float64_is_nan(u.d)))
 
3506
        return 0;
 
3507
 
 
3508
    return float64_to_int64_round_to_zero(u.d, &env->vec_status);
 
3509
}
 
3510
 
 
3511
uint32_t helper_efdctuiz (uint64_t val)
 
3512
{
 
3513
    CPU_DoubleU u;
 
3514
 
 
3515
    u.ll = val;
 
3516
    /* NaN are not treated the same way IEEE 754 does */
 
3517
    if (unlikely(float64_is_nan(u.d)))
 
3518
        return 0;
 
3519
 
 
3520
    return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
 
3521
}
 
3522
 
 
3523
uint64_t helper_efdctuidz (uint64_t val)
 
3524
{
 
3525
    CPU_DoubleU u;
 
3526
 
 
3527
    u.ll = val;
 
3528
    /* NaN are not treated the same way IEEE 754 does */
 
3529
    if (unlikely(float64_is_nan(u.d)))
 
3530
        return 0;
 
3531
 
 
3532
    return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
 
3533
}
 
3534
 
 
3535
uint64_t helper_efdcfsf (uint32_t val)
 
3536
{
 
3537
    CPU_DoubleU u;
 
3538
    float64 tmp;
 
3539
 
 
3540
    u.d = int32_to_float64(val, &env->vec_status);
 
3541
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
 
3542
    u.d = float64_div(u.d, tmp, &env->vec_status);
 
3543
 
 
3544
    return u.ll;
 
3545
}
 
3546
 
 
3547
uint64_t helper_efdcfuf (uint32_t val)
 
3548
{
 
3549
    CPU_DoubleU u;
 
3550
    float64 tmp;
 
3551
 
 
3552
    u.d = uint32_to_float64(val, &env->vec_status);
 
3553
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
 
3554
    u.d = float64_div(u.d, tmp, &env->vec_status);
 
3555
 
 
3556
    return u.ll;
 
3557
}
 
3558
 
 
3559
uint32_t helper_efdctsf (uint64_t val)
 
3560
{
 
3561
    CPU_DoubleU u;
 
3562
    float64 tmp;
 
3563
 
 
3564
    u.ll = val;
 
3565
    /* NaN are not treated the same way IEEE 754 does */
 
3566
    if (unlikely(float64_is_nan(u.d)))
 
3567
        return 0;
 
3568
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
 
3569
    u.d = float64_mul(u.d, tmp, &env->vec_status);
 
3570
 
 
3571
    return float64_to_int32(u.d, &env->vec_status);
 
3572
}
 
3573
 
 
3574
uint32_t helper_efdctuf (uint64_t val)
 
3575
{
 
3576
    CPU_DoubleU u;
 
3577
    float64 tmp;
 
3578
 
 
3579
    u.ll = val;
 
3580
    /* NaN are not treated the same way IEEE 754 does */
 
3581
    if (unlikely(float64_is_nan(u.d)))
 
3582
        return 0;
 
3583
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
 
3584
    u.d = float64_mul(u.d, tmp, &env->vec_status);
 
3585
 
 
3586
    return float64_to_uint32(u.d, &env->vec_status);
 
3587
}
 
3588
 
 
3589
uint32_t helper_efscfd (uint64_t val)
 
3590
{
 
3591
    CPU_DoubleU u1;
 
3592
    CPU_FloatU u2;
 
3593
 
 
3594
    u1.ll = val;
 
3595
    u2.f = float64_to_float32(u1.d, &env->vec_status);
 
3596
 
 
3597
    return u2.l;
 
3598
}
 
3599
 
 
3600
uint64_t helper_efdcfs (uint32_t val)
 
3601
{
 
3602
    CPU_DoubleU u2;
 
3603
    CPU_FloatU u1;
 
3604
 
 
3605
    u1.l = val;
 
3606
    u2.d = float32_to_float64(u1.f, &env->vec_status);
 
3607
 
 
3608
    return u2.ll;
 
3609
}
 
3610
 
 
3611
/* Double precision fixed-point arithmetic */
 
3612
uint64_t helper_efdadd (uint64_t op1, uint64_t op2)
 
3613
{
 
3614
    CPU_DoubleU u1, u2;
 
3615
    u1.ll = op1;
 
3616
    u2.ll = op2;
 
3617
    u1.d = float64_add(u1.d, u2.d, &env->vec_status);
 
3618
    return u1.ll;
 
3619
}
 
3620
 
 
3621
uint64_t helper_efdsub (uint64_t op1, uint64_t op2)
 
3622
{
 
3623
    CPU_DoubleU u1, u2;
 
3624
    u1.ll = op1;
 
3625
    u2.ll = op2;
 
3626
    u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
 
3627
    return u1.ll;
 
3628
}
 
3629
 
 
3630
uint64_t helper_efdmul (uint64_t op1, uint64_t op2)
 
3631
{
 
3632
    CPU_DoubleU u1, u2;
 
3633
    u1.ll = op1;
 
3634
    u2.ll = op2;
 
3635
    u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
 
3636
    return u1.ll;
 
3637
}
 
3638
 
 
3639
uint64_t helper_efddiv (uint64_t op1, uint64_t op2)
 
3640
{
 
3641
    CPU_DoubleU u1, u2;
 
3642
    u1.ll = op1;
 
3643
    u2.ll = op2;
 
3644
    u1.d = float64_div(u1.d, u2.d, &env->vec_status);
 
3645
    return u1.ll;
 
3646
}
 
3647
 
 
3648
/* Double precision floating point helpers */
 
3649
uint32_t helper_efdtstlt (uint64_t op1, uint64_t op2)
 
3650
{
 
3651
    CPU_DoubleU u1, u2;
 
3652
    u1.ll = op1;
 
3653
    u2.ll = op2;
 
3654
    return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
 
3655
}
 
3656
 
 
3657
uint32_t helper_efdtstgt (uint64_t op1, uint64_t op2)
 
3658
{
 
3659
    CPU_DoubleU u1, u2;
 
3660
    u1.ll = op1;
 
3661
    u2.ll = op2;
 
3662
    return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
 
3663
}
 
3664
 
 
3665
uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
 
3666
{
 
3667
    CPU_DoubleU u1, u2;
 
3668
    u1.ll = op1;
 
3669
    u2.ll = op2;
 
3670
    return float64_eq(u1.d, u2.d, &env->vec_status) ? 4 : 0;
 
3671
}
 
3672
 
 
3673
uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
 
3674
{
 
3675
    /* XXX: TODO: test special values (NaN, infinites, ...) */
 
3676
    return helper_efdtstlt(op1, op2);
 
3677
}
 
3678
 
 
3679
uint32_t helper_efdcmpgt (uint64_t op1, uint64_t op2)
 
3680
{
 
3681
    /* XXX: TODO: test special values (NaN, infinites, ...) */
 
3682
    return helper_efdtstgt(op1, op2);
 
3683
}
 
3684
 
 
3685
uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
 
3686
{
 
3687
    /* XXX: TODO: test special values (NaN, infinites, ...) */
 
3688
    return helper_efdtsteq(op1, op2);
 
3689
}
2609
3690
 
2610
3691
/*****************************************************************************/
2611
3692
/* Softmmu support */
2652
3733
                cpu_restore_state(tb, env, pc, NULL);
2653
3734
            }
2654
3735
        }
2655
 
        do_raise_exception_err(env->exception_index, env->error_code);
 
3736
        helper_raise_exception_err(env->exception_index, env->error_code);
2656
3737
    }
2657
3738
    env = saved_env;
2658
3739
}
2659
3740
 
 
3741
/* Segment registers load and store */
 
3742
target_ulong helper_load_sr (target_ulong sr_num)
 
3743
{
 
3744
#if defined(TARGET_PPC64)
 
3745
    if (env->mmu_model & POWERPC_MMU_64)
 
3746
        return ppc_load_sr(env, sr_num);
 
3747
#endif
 
3748
    return env->sr[sr_num];
 
3749
}
 
3750
 
 
3751
void helper_store_sr (target_ulong sr_num, target_ulong val)
 
3752
{
 
3753
    ppc_store_sr(env, sr_num, val);
 
3754
}
 
3755
 
 
3756
/* SLB management */
 
3757
#if defined(TARGET_PPC64)
 
3758
target_ulong helper_load_slb (target_ulong slb_nr)
 
3759
{
 
3760
    return ppc_load_slb(env, slb_nr);
 
3761
}
 
3762
 
 
3763
void helper_store_slb (target_ulong rb, target_ulong rs)
 
3764
{
 
3765
    ppc_store_slb(env, rb, rs);
 
3766
}
 
3767
 
 
3768
void helper_slbia (void)
 
3769
{
 
3770
    ppc_slb_invalidate_all(env);
 
3771
}
 
3772
 
 
3773
void helper_slbie (target_ulong addr)
 
3774
{
 
3775
    ppc_slb_invalidate_one(env, addr);
 
3776
}
 
3777
 
 
3778
#endif /* defined(TARGET_PPC64) */
 
3779
 
 
3780
/* TLB management */
 
3781
void helper_tlbia (void)
 
3782
{
 
3783
    ppc_tlb_invalidate_all(env);
 
3784
}
 
3785
 
 
3786
void helper_tlbie (target_ulong addr)
 
3787
{
 
3788
    ppc_tlb_invalidate_one(env, addr);
 
3789
}
 
3790
 
2660
3791
/* Software driven TLBs management */
2661
3792
/* PowerPC 602/603 software TLB load instructions helpers */
2662
 
void do_load_6xx_tlb (int is_code)
 
3793
static void do_6xx_tlb (target_ulong new_EPN, int is_code)
2663
3794
{
2664
3795
    target_ulong RPN, CMP, EPN;
2665
3796
    int way;
2673
3804
        EPN = env->spr[SPR_DMISS];
2674
3805
    }
2675
3806
    way = (env->spr[SPR_SRR1] >> 17) & 1;
2676
 
#if defined (DEBUG_SOFTWARE_TLB)
2677
 
    if (loglevel != 0) {
2678
 
        fprintf(logfile, "%s: EPN " TDX " " ADDRX " PTE0 " ADDRX
2679
 
                " PTE1 " ADDRX " way %d\n",
2680
 
                __func__, T0, EPN, CMP, RPN, way);
2681
 
    }
2682
 
#endif
 
3807
    LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
 
3808
              " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
 
3809
              RPN, way);
2683
3810
    /* Store this TLB */
2684
 
    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
 
3811
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2685
3812
                     way, is_code, CMP, RPN);
2686
3813
}
2687
3814
 
2688
 
void do_load_74xx_tlb (int is_code)
 
3815
void helper_6xx_tlbd (target_ulong EPN)
 
3816
{
 
3817
    do_6xx_tlb(EPN, 0);
 
3818
}
 
3819
 
 
3820
void helper_6xx_tlbi (target_ulong EPN)
 
3821
{
 
3822
    do_6xx_tlb(EPN, 1);
 
3823
}
 
3824
 
 
3825
/* PowerPC 74xx software TLB load instructions helpers */
 
3826
static void do_74xx_tlb (target_ulong new_EPN, int is_code)
2689
3827
{
2690
3828
    target_ulong RPN, CMP, EPN;
2691
3829
    int way;
2694
3832
    CMP = env->spr[SPR_PTEHI];
2695
3833
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
2696
3834
    way = env->spr[SPR_TLBMISS] & 0x3;
2697
 
#if defined (DEBUG_SOFTWARE_TLB)
2698
 
    if (loglevel != 0) {
2699
 
        fprintf(logfile, "%s: EPN " TDX " " ADDRX " PTE0 " ADDRX
2700
 
                " PTE1 " ADDRX " way %d\n",
2701
 
                __func__, T0, EPN, CMP, RPN, way);
2702
 
    }
2703
 
#endif
 
3835
    LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
 
3836
              " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
 
3837
              RPN, way);
2704
3838
    /* Store this TLB */
2705
 
    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
 
3839
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2706
3840
                     way, is_code, CMP, RPN);
2707
3841
}
2708
3842
 
2709
 
static always_inline target_ulong booke_tlb_to_page_size (int size)
 
3843
void helper_74xx_tlbd (target_ulong EPN)
 
3844
{
 
3845
    do_74xx_tlb(EPN, 0);
 
3846
}
 
3847
 
 
3848
void helper_74xx_tlbi (target_ulong EPN)
 
3849
{
 
3850
    do_74xx_tlb(EPN, 1);
 
3851
}
 
3852
 
 
3853
static inline target_ulong booke_tlb_to_page_size(int size)
2710
3854
{
2711
3855
    return 1024 << (2 * size);
2712
3856
}
2713
3857
 
2714
 
static always_inline int booke_page_size_to_tlb (target_ulong page_size)
 
3858
static inline int booke_page_size_to_tlb(target_ulong page_size)
2715
3859
{
2716
3860
    int size;
2717
3861
 
2775
3919
}
2776
3920
 
2777
3921
/* Helpers for 4xx TLB management */
2778
 
void do_4xx_tlbre_lo (void)
 
3922
target_ulong helper_4xx_tlbre_lo (target_ulong entry)
2779
3923
{
2780
3924
    ppcemb_tlb_t *tlb;
 
3925
    target_ulong ret;
2781
3926
    int size;
2782
3927
 
2783
 
    T0 &= 0x3F;
2784
 
    tlb = &env->tlb[T0].tlbe;
2785
 
    T0 = tlb->EPN;
 
3928
    entry &= 0x3F;
 
3929
    tlb = &env->tlb[entry].tlbe;
 
3930
    ret = tlb->EPN;
2786
3931
    if (tlb->prot & PAGE_VALID)
2787
 
        T0 |= 0x400;
 
3932
        ret |= 0x400;
2788
3933
    size = booke_page_size_to_tlb(tlb->size);
2789
3934
    if (size < 0 || size > 0x7)
2790
3935
        size = 1;
2791
 
    T0 |= size << 7;
 
3936
    ret |= size << 7;
2792
3937
    env->spr[SPR_40x_PID] = tlb->PID;
 
3938
    return ret;
2793
3939
}
2794
3940
 
2795
 
void do_4xx_tlbre_hi (void)
 
3941
target_ulong helper_4xx_tlbre_hi (target_ulong entry)
2796
3942
{
2797
3943
    ppcemb_tlb_t *tlb;
 
3944
    target_ulong ret;
2798
3945
 
2799
 
    T0 &= 0x3F;
2800
 
    tlb = &env->tlb[T0].tlbe;
2801
 
    T0 = tlb->RPN;
 
3946
    entry &= 0x3F;
 
3947
    tlb = &env->tlb[entry].tlbe;
 
3948
    ret = tlb->RPN;
2802
3949
    if (tlb->prot & PAGE_EXEC)
2803
 
        T0 |= 0x200;
 
3950
        ret |= 0x200;
2804
3951
    if (tlb->prot & PAGE_WRITE)
2805
 
        T0 |= 0x100;
 
3952
        ret |= 0x100;
 
3953
    return ret;
2806
3954
}
2807
3955
 
2808
 
void do_4xx_tlbwe_hi (void)
 
3956
void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
2809
3957
{
2810
3958
    ppcemb_tlb_t *tlb;
2811
3959
    target_ulong page, end;
2812
3960
 
2813
 
#if defined (DEBUG_SOFTWARE_TLB)
2814
 
    if (loglevel != 0) {
2815
 
        fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
2816
 
    }
2817
 
#endif
2818
 
    T0 &= 0x3F;
2819
 
    tlb = &env->tlb[T0].tlbe;
 
3961
    LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
 
3962
              val);
 
3963
    entry &= 0x3F;
 
3964
    tlb = &env->tlb[entry].tlbe;
2820
3965
    /* Invalidate previous TLB (if it's valid) */
2821
3966
    if (tlb->prot & PAGE_VALID) {
2822
3967
        end = tlb->EPN + tlb->size;
2823
 
#if defined (DEBUG_SOFTWARE_TLB)
2824
 
        if (loglevel != 0) {
2825
 
            fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
2826
 
                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2827
 
        }
2828
 
#endif
 
3968
        LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
 
3969
                  TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2829
3970
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2830
3971
            tlb_flush_page(env, page);
2831
3972
    }
2832
 
    tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
 
3973
    tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7);
2833
3974
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2834
3975
     * If this ever occurs, one should use the ppcemb target instead
2835
3976
     * of the ppc or ppc64 one
2836
3977
     */
2837
 
    if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
 
3978
    if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
2838
3979
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
2839
3980
                  "are not supported (%d)\n",
2840
 
                  tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
 
3981
                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2841
3982
    }
2842
 
    tlb->EPN = T1 & ~(tlb->size - 1);
2843
 
    if (T1 & 0x40)
 
3983
    tlb->EPN = val & ~(tlb->size - 1);
 
3984
    if (val & 0x40)
2844
3985
        tlb->prot |= PAGE_VALID;
2845
3986
    else
2846
3987
        tlb->prot &= ~PAGE_VALID;
2847
 
    if (T1 & 0x20) {
 
3988
    if (val & 0x20) {
2848
3989
        /* XXX: TO BE FIXED */
2849
3990
        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
2850
3991
    }
2851
3992
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2852
 
    tlb->attr = T1 & 0xFF;
2853
 
#if defined (DEBUG_SOFTWARE_TLB)
2854
 
    if (loglevel != 0) {
2855
 
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2856
 
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2857
 
                (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2858
 
                tlb->prot & PAGE_READ ? 'r' : '-',
2859
 
                tlb->prot & PAGE_WRITE ? 'w' : '-',
2860
 
                tlb->prot & PAGE_EXEC ? 'x' : '-',
2861
 
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2862
 
    }
2863
 
#endif
 
3993
    tlb->attr = val & 0xFF;
 
3994
    LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
 
3995
              " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
 
3996
              (int)entry, tlb->RPN, tlb->EPN, tlb->size,
 
3997
              tlb->prot & PAGE_READ ? 'r' : '-',
 
3998
              tlb->prot & PAGE_WRITE ? 'w' : '-',
 
3999
              tlb->prot & PAGE_EXEC ? 'x' : '-',
 
4000
              tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2864
4001
    /* Invalidate new TLB (if valid) */
2865
4002
    if (tlb->prot & PAGE_VALID) {
2866
4003
        end = tlb->EPN + tlb->size;
2867
 
#if defined (DEBUG_SOFTWARE_TLB)
2868
 
        if (loglevel != 0) {
2869
 
            fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
2870
 
                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2871
 
        }
2872
 
#endif
 
4004
        LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
 
4005
                  TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2873
4006
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2874
4007
            tlb_flush_page(env, page);
2875
4008
    }
2876
4009
}
2877
4010
 
2878
 
void do_4xx_tlbwe_lo (void)
 
4011
void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
2879
4012
{
2880
4013
    ppcemb_tlb_t *tlb;
2881
4014
 
2882
 
#if defined (DEBUG_SOFTWARE_TLB)
2883
 
    if (loglevel != 0) {
2884
 
        fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
2885
 
    }
2886
 
#endif
2887
 
    T0 &= 0x3F;
2888
 
    tlb = &env->tlb[T0].tlbe;
2889
 
    tlb->RPN = T1 & 0xFFFFFC00;
 
4015
    LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
 
4016
              val);
 
4017
    entry &= 0x3F;
 
4018
    tlb = &env->tlb[entry].tlbe;
 
4019
    tlb->RPN = val & 0xFFFFFC00;
2890
4020
    tlb->prot = PAGE_READ;
2891
 
    if (T1 & 0x200)
 
4021
    if (val & 0x200)
2892
4022
        tlb->prot |= PAGE_EXEC;
2893
 
    if (T1 & 0x100)
 
4023
    if (val & 0x100)
2894
4024
        tlb->prot |= PAGE_WRITE;
2895
 
#if defined (DEBUG_SOFTWARE_TLB)
2896
 
    if (loglevel != 0) {
2897
 
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2898
 
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2899
 
                (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2900
 
                tlb->prot & PAGE_READ ? 'r' : '-',
2901
 
                tlb->prot & PAGE_WRITE ? 'w' : '-',
2902
 
                tlb->prot & PAGE_EXEC ? 'x' : '-',
2903
 
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2904
 
    }
2905
 
#endif
 
4025
    LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
 
4026
              " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
 
4027
              (int)entry, tlb->RPN, tlb->EPN, tlb->size,
 
4028
              tlb->prot & PAGE_READ ? 'r' : '-',
 
4029
              tlb->prot & PAGE_WRITE ? 'w' : '-',
 
4030
              tlb->prot & PAGE_EXEC ? 'x' : '-',
 
4031
              tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
 
4032
}
 
4033
 
 
4034
target_ulong helper_4xx_tlbsx (target_ulong address)
 
4035
{
 
4036
    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
2906
4037
}
2907
4038
 
2908
4039
/* PowerPC 440 TLB management */
2909
 
void do_440_tlbwe (int word)
 
4040
void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
2910
4041
{
2911
4042
    ppcemb_tlb_t *tlb;
2912
4043
    target_ulong EPN, RPN, size;
2913
4044
    int do_flush_tlbs;
2914
4045
 
2915
 
#if defined (DEBUG_SOFTWARE_TLB)
2916
 
    if (loglevel != 0) {
2917
 
        fprintf(logfile, "%s word %d T0 " TDX " T1 " TDX "\n",
2918
 
                __func__, word, T0, T1);
2919
 
    }
2920
 
#endif
 
4046
    LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
 
4047
              __func__, word, (int)entry, value);
2921
4048
    do_flush_tlbs = 0;
2922
 
    T0 &= 0x3F;
2923
 
    tlb = &env->tlb[T0].tlbe;
 
4049
    entry &= 0x3F;
 
4050
    tlb = &env->tlb[entry].tlbe;
2924
4051
    switch (word) {
2925
4052
    default:
2926
4053
        /* Just here to please gcc */
2927
4054
    case 0:
2928
 
        EPN = T1 & 0xFFFFFC00;
 
4055
        EPN = value & 0xFFFFFC00;
2929
4056
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
2930
4057
            do_flush_tlbs = 1;
2931
4058
        tlb->EPN = EPN;
2932
 
        size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
 
4059
        size = booke_tlb_to_page_size((value >> 4) & 0xF);
2933
4060
        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
2934
4061
            do_flush_tlbs = 1;
2935
4062
        tlb->size = size;
2936
4063
        tlb->attr &= ~0x1;
2937
 
        tlb->attr |= (T1 >> 8) & 1;
2938
 
        if (T1 & 0x200) {
 
4064
        tlb->attr |= (value >> 8) & 1;
 
4065
        if (value & 0x200) {
2939
4066
            tlb->prot |= PAGE_VALID;
2940
4067
        } else {
2941
4068
            if (tlb->prot & PAGE_VALID) {
2948
4075
            tlb_flush(env, 1);
2949
4076
        break;
2950
4077
    case 1:
2951
 
        RPN = T1 & 0xFFFFFC0F;
 
4078
        RPN = value & 0xFFFFFC0F;
2952
4079
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
2953
4080
            tlb_flush(env, 1);
2954
4081
        tlb->RPN = RPN;
2955
4082
        break;
2956
4083
    case 2:
2957
 
        tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
 
4084
        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
2958
4085
        tlb->prot = tlb->prot & PAGE_VALID;
2959
 
        if (T1 & 0x1)
 
4086
        if (value & 0x1)
2960
4087
            tlb->prot |= PAGE_READ << 4;
2961
 
        if (T1 & 0x2)
 
4088
        if (value & 0x2)
2962
4089
            tlb->prot |= PAGE_WRITE << 4;
2963
 
        if (T1 & 0x4)
 
4090
        if (value & 0x4)
2964
4091
            tlb->prot |= PAGE_EXEC << 4;
2965
 
        if (T1 & 0x8)
 
4092
        if (value & 0x8)
2966
4093
            tlb->prot |= PAGE_READ;
2967
 
        if (T1 & 0x10)
 
4094
        if (value & 0x10)
2968
4095
            tlb->prot |= PAGE_WRITE;
2969
 
        if (T1 & 0x20)
 
4096
        if (value & 0x20)
2970
4097
            tlb->prot |= PAGE_EXEC;
2971
4098
        break;
2972
4099
    }
2973
4100
}
2974
4101
 
2975
 
void do_440_tlbre (int word)
 
4102
target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
2976
4103
{
2977
4104
    ppcemb_tlb_t *tlb;
 
4105
    target_ulong ret;
2978
4106
    int size;
2979
4107
 
2980
 
    T0 &= 0x3F;
2981
 
    tlb = &env->tlb[T0].tlbe;
 
4108
    entry &= 0x3F;
 
4109
    tlb = &env->tlb[entry].tlbe;
2982
4110
    switch (word) {
2983
4111
    default:
2984
4112
        /* Just here to please gcc */
2985
4113
    case 0:
2986
 
        T0 = tlb->EPN;
 
4114
        ret = tlb->EPN;
2987
4115
        size = booke_page_size_to_tlb(tlb->size);
2988
4116
        if (size < 0 || size > 0xF)
2989
4117
            size = 1;
2990
 
        T0 |= size << 4;
 
4118
        ret |= size << 4;
2991
4119
        if (tlb->attr & 0x1)
2992
 
            T0 |= 0x100;
 
4120
            ret |= 0x100;
2993
4121
        if (tlb->prot & PAGE_VALID)
2994
 
            T0 |= 0x200;
 
4122
            ret |= 0x200;
2995
4123
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2996
4124
        env->spr[SPR_440_MMUCR] |= tlb->PID;
2997
4125
        break;
2998
4126
    case 1:
2999
 
        T0 = tlb->RPN;
 
4127
        ret = tlb->RPN;
3000
4128
        break;
3001
4129
    case 2:
3002
 
        T0 = tlb->attr & ~0x1;
 
4130
        ret = tlb->attr & ~0x1;
3003
4131
        if (tlb->prot & (PAGE_READ << 4))
3004
 
            T0 |= 0x1;
 
4132
            ret |= 0x1;
3005
4133
        if (tlb->prot & (PAGE_WRITE << 4))
3006
 
            T0 |= 0x2;
 
4134
            ret |= 0x2;
3007
4135
        if (tlb->prot & (PAGE_EXEC << 4))
3008
 
            T0 |= 0x4;
 
4136
            ret |= 0x4;
3009
4137
        if (tlb->prot & PAGE_READ)
3010
 
            T0 |= 0x8;
 
4138
            ret |= 0x8;
3011
4139
        if (tlb->prot & PAGE_WRITE)
3012
 
            T0 |= 0x10;
 
4140
            ret |= 0x10;
3013
4141
        if (tlb->prot & PAGE_EXEC)
3014
 
            T0 |= 0x20;
 
4142
            ret |= 0x20;
3015
4143
        break;
3016
4144
    }
3017
 
}
 
4145
    return ret;
 
4146
}
 
4147
 
 
4148
target_ulong helper_440_tlbsx (target_ulong address)
 
4149
{
 
4150
    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
 
4151
}
 
4152
 
3018
4153
#endif /* !CONFIG_USER_ONLY */