Statistics
| Branch: | Revision:

root / target-sparc / op.c @ d9bdab86

History | View | Annotate | Download (27.1 kB)

1
/*
2
   SPARC micro operations
3

4
   Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5

6
   This library is free software; you can redistribute it and/or
7
   modify it under the terms of the GNU Lesser General Public
8
   License as published by the Free Software Foundation; either
9
   version 2 of the License, or (at your option) any later version.
10

11
   This library is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
   Lesser General Public License for more details.
15

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
19
*/
20

    
21
#include "exec.h"
22
#include "helper.h"
23

    
24
#define REGNAME f0
25
#define REG (env->fpr[0])
26
#include "fop_template.h"
27
#define REGNAME f1
28
#define REG (env->fpr[1])
29
#include "fop_template.h"
30
#define REGNAME f2
31
#define REG (env->fpr[2])
32
#include "fop_template.h"
33
#define REGNAME f3
34
#define REG (env->fpr[3])
35
#include "fop_template.h"
36
#define REGNAME f4
37
#define REG (env->fpr[4])
38
#include "fop_template.h"
39
#define REGNAME f5
40
#define REG (env->fpr[5])
41
#include "fop_template.h"
42
#define REGNAME f6
43
#define REG (env->fpr[6])
44
#include "fop_template.h"
45
#define REGNAME f7
46
#define REG (env->fpr[7])
47
#include "fop_template.h"
48
#define REGNAME f8
49
#define REG (env->fpr[8])
50
#include "fop_template.h"
51
#define REGNAME f9
52
#define REG (env->fpr[9])
53
#include "fop_template.h"
54
#define REGNAME f10
55
#define REG (env->fpr[10])
56
#include "fop_template.h"
57
#define REGNAME f11
58
#define REG (env->fpr[11])
59
#include "fop_template.h"
60
#define REGNAME f12
61
#define REG (env->fpr[12])
62
#include "fop_template.h"
63
#define REGNAME f13
64
#define REG (env->fpr[13])
65
#include "fop_template.h"
66
#define REGNAME f14
67
#define REG (env->fpr[14])
68
#include "fop_template.h"
69
#define REGNAME f15
70
#define REG (env->fpr[15])
71
#include "fop_template.h"
72
#define REGNAME f16
73
#define REG (env->fpr[16])
74
#include "fop_template.h"
75
#define REGNAME f17
76
#define REG (env->fpr[17])
77
#include "fop_template.h"
78
#define REGNAME f18
79
#define REG (env->fpr[18])
80
#include "fop_template.h"
81
#define REGNAME f19
82
#define REG (env->fpr[19])
83
#include "fop_template.h"
84
#define REGNAME f20
85
#define REG (env->fpr[20])
86
#include "fop_template.h"
87
#define REGNAME f21
88
#define REG (env->fpr[21])
89
#include "fop_template.h"
90
#define REGNAME f22
91
#define REG (env->fpr[22])
92
#include "fop_template.h"
93
#define REGNAME f23
94
#define REG (env->fpr[23])
95
#include "fop_template.h"
96
#define REGNAME f24
97
#define REG (env->fpr[24])
98
#include "fop_template.h"
99
#define REGNAME f25
100
#define REG (env->fpr[25])
101
#include "fop_template.h"
102
#define REGNAME f26
103
#define REG (env->fpr[26])
104
#include "fop_template.h"
105
#define REGNAME f27
106
#define REG (env->fpr[27])
107
#include "fop_template.h"
108
#define REGNAME f28
109
#define REG (env->fpr[28])
110
#include "fop_template.h"
111
#define REGNAME f29
112
#define REG (env->fpr[29])
113
#include "fop_template.h"
114
#define REGNAME f30
115
#define REG (env->fpr[30])
116
#include "fop_template.h"
117
#define REGNAME f31
118
#define REG (env->fpr[31])
119
#include "fop_template.h"
120

    
121
#ifdef TARGET_SPARC64
122
#define REGNAME f32
123
#define REG (env->fpr[32])
124
#include "fop_template.h"
125
#define REGNAME f34
126
#define REG (env->fpr[34])
127
#include "fop_template.h"
128
#define REGNAME f36
129
#define REG (env->fpr[36])
130
#include "fop_template.h"
131
#define REGNAME f38
132
#define REG (env->fpr[38])
133
#include "fop_template.h"
134
#define REGNAME f40
135
#define REG (env->fpr[40])
136
#include "fop_template.h"
137
#define REGNAME f42
138
#define REG (env->fpr[42])
139
#include "fop_template.h"
140
#define REGNAME f44
141
#define REG (env->fpr[44])
142
#include "fop_template.h"
143
#define REGNAME f46
144
#define REG (env->fpr[46])
145
#include "fop_template.h"
146
#define REGNAME f48
147
#define REG (env->fpr[47])
148
#include "fop_template.h"
149
#define REGNAME f50
150
#define REG (env->fpr[50])
151
#include "fop_template.h"
152
#define REGNAME f52
153
#define REG (env->fpr[52])
154
#include "fop_template.h"
155
#define REGNAME f54
156
#define REG (env->fpr[54])
157
#include "fop_template.h"
158
#define REGNAME f56
159
#define REG (env->fpr[56])
160
#include "fop_template.h"
161
#define REGNAME f58
162
#define REG (env->fpr[58])
163
#include "fop_template.h"
164
#define REGNAME f60
165
#define REG (env->fpr[60])
166
#include "fop_template.h"
167
#define REGNAME f62
168
#define REG (env->fpr[62])
169
#include "fop_template.h"
170
#endif
171

    
172
#define FLAG_SET(x) ((env->psr&x)?1:0)
173

    
174
void OPPROTO op_umul_T1_T0(void)
175
{
176
    uint64_t res;
177
    res = (uint64_t) T0 * (uint64_t) T1;
178
#ifdef TARGET_SPARC64
179
    T0 = res;
180
#else
181
    T0 = res & 0xffffffff;
182
#endif
183
    env->y = res >> 32;
184
}
185

    
186
void OPPROTO op_smul_T1_T0(void)
187
{
188
    uint64_t res;
189
    res = (int64_t) ((int32_t) T0) * (int64_t) ((int32_t) T1);
190
#ifdef TARGET_SPARC64
191
    T0 = res;
192
#else
193
    T0 = res & 0xffffffff;
194
#endif
195
    env->y = res >> 32;
196
}
197

    
198
void OPPROTO op_udiv_T1_T0(void)
199
{
200
    uint64_t x0;
201
    uint32_t x1;
202

    
203
    x0 = T0 | ((uint64_t) (env->y) << 32);
204
    x1 = T1;
205

    
206
    if (x1 == 0) {
207
        raise_exception(TT_DIV_ZERO);
208
    }
209

    
210
    x0 = x0 / x1;
211
    if (x0 > 0xffffffff) {
212
        T0 = 0xffffffff;
213
        T1 = 1;
214
    } else {
215
        T0 = x0;
216
        T1 = 0;
217
    }
218
    FORCE_RET();
219
}
220

    
221
void OPPROTO op_sdiv_T1_T0(void)
222
{
223
    int64_t x0;
224
    int32_t x1;
225

    
226
    x0 = T0 | ((int64_t) (env->y) << 32);
227
    x1 = T1;
228

    
229
    if (x1 == 0) {
230
        raise_exception(TT_DIV_ZERO);
231
    }
232

    
233
    x0 = x0 / x1;
234
    if ((int32_t) x0 != x0) {
235
        T0 = x0 < 0? 0x80000000: 0x7fffffff;
236
        T1 = 1;
237
    } else {
238
        T0 = x0;
239
        T1 = 0;
240
    }
241
    FORCE_RET();
242
}
243

    
244
/* Load and store */
245
#define MEMSUFFIX _raw
246
#include "op_mem.h"
247
#if !defined(CONFIG_USER_ONLY)
248
#define MEMSUFFIX _user
249
#include "op_mem.h"
250

    
251
#define MEMSUFFIX _kernel
252
#include "op_mem.h"
253

    
254
#ifdef TARGET_SPARC64
255
#define MEMSUFFIX _hypv
256
#include "op_mem.h"
257
#endif
258
#endif
259

    
260
#ifndef TARGET_SPARC64
261
/* XXX: use another pointer for %iN registers to avoid slow wrapping
262
   handling ? */
263
void OPPROTO op_save(void)
264
{
265
    uint32_t cwp;
266
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
267
    if (env->wim & (1 << cwp)) {
268
        raise_exception(TT_WIN_OVF);
269
    }
270
    set_cwp(cwp);
271
    FORCE_RET();
272
}
273

    
274
void OPPROTO op_restore(void)
275
{
276
    uint32_t cwp;
277
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
278
    if (env->wim & (1 << cwp)) {
279
        raise_exception(TT_WIN_UNF);
280
    }
281
    set_cwp(cwp);
282
    FORCE_RET();
283
}
284
#else
285
void OPPROTO op_rdccr(void)
286
{
287
    T0 = GET_CCR(env);
288
}
289

    
290
void OPPROTO op_wrccr(void)
291
{
292
    PUT_CCR(env, T0);
293
}
294

    
295
// CWP handling is reversed in V9, but we still use the V8 register
296
// order.
297
void OPPROTO op_rdcwp(void)
298
{
299
    T0 = GET_CWP64(env);
300
}
301

    
302
void OPPROTO op_wrcwp(void)
303
{
304
    PUT_CWP64(env, T0);
305
}
306

    
307
/* XXX: use another pointer for %iN registers to avoid slow wrapping
308
   handling ? */
309
void OPPROTO op_save(void)
310
{
311
    uint32_t cwp;
312
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
313
    if (env->cansave == 0) {
314
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
315
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
316
                                    ((env->wstate & 0x7) << 2)));
317
    } else {
318
        if (env->cleanwin - env->canrestore == 0) {
319
            // XXX Clean windows without trap
320
            raise_exception(TT_CLRWIN);
321
        } else {
322
            env->cansave--;
323
            env->canrestore++;
324
            set_cwp(cwp);
325
        }
326
    }
327
    FORCE_RET();
328
}
329

    
330
void OPPROTO op_restore(void)
331
{
332
    uint32_t cwp;
333
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
334
    if (env->canrestore == 0) {
335
        raise_exception(TT_FILL | (env->otherwin != 0 ?
336
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
337
                                   ((env->wstate & 0x7) << 2)));
338
    } else {
339
        env->cansave++;
340
        env->canrestore--;
341
        set_cwp(cwp);
342
    }
343
    FORCE_RET();
344
}
345
#endif
346

    
347
void OPPROTO op_jmp_label(void)
348
{
349
    GOTO_LABEL_PARAM(1);
350
}
351

    
352
#define F_OP(name, p) void OPPROTO op_f##name##p(void)
353

    
354
#if defined(CONFIG_USER_ONLY)
355
#define F_BINOP(name)                                           \
356
    F_OP(name, s)                                               \
357
    {                                                           \
358
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
359
    }                                                           \
360
    F_OP(name, d)                                               \
361
    {                                                           \
362
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
363
    }                                                           \
364
    F_OP(name, q)                                               \
365
    {                                                           \
366
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
367
    }
368
#else
369
#define F_BINOP(name)                                           \
370
    F_OP(name, s)                                               \
371
    {                                                           \
372
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
373
    }                                                           \
374
    F_OP(name, d)                                               \
375
    {                                                           \
376
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
377
    }
378
#endif
379

    
380
F_BINOP(add);
381
F_BINOP(sub);
382
F_BINOP(mul);
383
F_BINOP(div);
384
#undef F_BINOP
385

    
386
void OPPROTO op_fsmuld(void)
387
{
388
    DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
389
                      float32_to_float64(FT1, &env->fp_status),
390
                      &env->fp_status);
391
}
392

    
393
#if defined(CONFIG_USER_ONLY)
394
void OPPROTO op_fdmulq(void)
395
{
396
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
397
                       float64_to_float128(DT1, &env->fp_status),
398
                       &env->fp_status);
399
}
400
#endif
401

    
402
#if defined(CONFIG_USER_ONLY)
403
#define F_HELPER(name)    \
404
    F_OP(name, s)         \
405
    {                     \
406
        do_f##name##s();  \
407
    }                     \
408
    F_OP(name, d)         \
409
    {                     \
410
        do_f##name##d();  \
411
    }                     \
412
    F_OP(name, q)         \
413
    {                     \
414
        do_f##name##q();  \
415
    }
416
#else
417
#define F_HELPER(name)    \
418
    F_OP(name, s)         \
419
    {                     \
420
        do_f##name##s();  \
421
    }                     \
422
    F_OP(name, d)         \
423
    {                     \
424
        do_f##name##d();  \
425
    }
426
#endif
427

    
428
F_OP(neg, s)
429
{
430
    FT0 = float32_chs(FT1);
431
}
432

    
433
#ifdef TARGET_SPARC64
434
F_OP(neg, d)
435
{
436
    DT0 = float64_chs(DT1);
437
}
438

    
439
#if defined(CONFIG_USER_ONLY)
440
F_OP(neg, q)
441
{
442
    QT0 = float128_chs(QT1);
443
}
444

    
445
#endif
446

    
447
#endif
448

    
449
/* Integer to float conversion.  */
450
#ifdef USE_INT_TO_FLOAT_HELPERS
451
F_HELPER(ito);
452
#ifdef TARGET_SPARC64
453
F_HELPER(xto);
454
#endif
455
#else
456
F_OP(ito, s)
457
{
458
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
459
}
460

    
461
F_OP(ito, d)
462
{
463
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
464
}
465

    
466
#if defined(CONFIG_USER_ONLY)
467
F_OP(ito, q)
468
{
469
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
470
}
471
#endif
472

    
473
#ifdef TARGET_SPARC64
474
F_OP(xto, s)
475
{
476
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
477
}
478

    
479
F_OP(xto, d)
480
{
481
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
482
}
483
#if defined(CONFIG_USER_ONLY)
484
F_OP(xto, q)
485
{
486
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
487
}
488
#endif
489
#endif
490
#endif
491
#undef F_HELPER
492

    
493
/* floating point conversion */
494
void OPPROTO op_fdtos(void)
495
{
496
    FT0 = float64_to_float32(DT1, &env->fp_status);
497
}
498

    
499
void OPPROTO op_fstod(void)
500
{
501
    DT0 = float32_to_float64(FT1, &env->fp_status);
502
}
503

    
504
#if defined(CONFIG_USER_ONLY)
505
void OPPROTO op_fqtos(void)
506
{
507
    FT0 = float128_to_float32(QT1, &env->fp_status);
508
}
509

    
510
void OPPROTO op_fstoq(void)
511
{
512
    QT0 = float32_to_float128(FT1, &env->fp_status);
513
}
514

    
515
void OPPROTO op_fqtod(void)
516
{
517
    DT0 = float128_to_float64(QT1, &env->fp_status);
518
}
519

    
520
void OPPROTO op_fdtoq(void)
521
{
522
    QT0 = float64_to_float128(DT1, &env->fp_status);
523
}
524
#endif
525

    
526
/* Float to integer conversion.  */
527
void OPPROTO op_fstoi(void)
528
{
529
    *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
530
}
531

    
532
void OPPROTO op_fdtoi(void)
533
{
534
    *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
535
}
536

    
537
#if defined(CONFIG_USER_ONLY)
538
void OPPROTO op_fqtoi(void)
539
{
540
    *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
541
}
542
#endif
543

    
544
#ifdef TARGET_SPARC64
545
void OPPROTO op_fstox(void)
546
{
547
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
548
}
549

    
550
void OPPROTO op_fdtox(void)
551
{
552
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
553
}
554

    
555
#if defined(CONFIG_USER_ONLY)
556
void OPPROTO op_fqtox(void)
557
{
558
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
559
}
560
#endif
561

    
562
void OPPROTO op_flushw(void)
563
{
564
    if (env->cansave != NWINDOWS - 2) {
565
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
566
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
567
                                    ((env->wstate & 0x7) << 2)));
568
    }
569
}
570

    
571
void OPPROTO op_saved(void)
572
{
573
    env->cansave++;
574
    if (env->otherwin == 0)
575
        env->canrestore--;
576
    else
577
        env->otherwin--;
578
    FORCE_RET();
579
}
580

    
581
void OPPROTO op_restored(void)
582
{
583
    env->canrestore++;
584
    if (env->cleanwin < NWINDOWS - 1)
585
        env->cleanwin++;
586
    if (env->otherwin == 0)
587
        env->cansave--;
588
    else
589
        env->otherwin--;
590
    FORCE_RET();
591
}
592
#endif
593

    
594
#ifdef TARGET_SPARC64
595
// This function uses non-native bit order
596
#define GET_FIELD(X, FROM, TO)                                  \
597
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
598

    
599
// This function uses the order in the manuals, i.e. bit 0 is 2^0
600
#define GET_FIELD_SP(X, FROM, TO)               \
601
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
602

    
603
void OPPROTO op_array8()
604
{
605
    T0 = (GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
606
        (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
607
        (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
608
        (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
609
        (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
610
        (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12);
611
}
612

    
613
void OPPROTO op_array16()
614
{
615
    T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
616
          (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
617
          (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
618
          (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
619
          (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
620
          (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 1;
621
}
622

    
623
void OPPROTO op_array32()
624
{
625
    T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
626
          (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
627
          (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
628
          (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
629
          (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
630
          (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 2;
631
}
632

    
633
void OPPROTO op_alignaddr()
634
{
635
    uint64_t tmp;
636

    
637
    tmp = T0 + T1;
638
    env->gsr &= ~7ULL;
639
    env->gsr |= tmp & 7ULL;
640
    T0 = tmp & ~7ULL;
641
}
642

    
643
void OPPROTO op_faligndata()
644
{
645
    uint64_t tmp;
646

    
647
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
648
    tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
649
    *((uint64_t *)&DT0) = tmp;
650
}
651

    
652
void OPPROTO op_movl_FT0_0(void)
653
{
654
    *((uint32_t *)&FT0) = 0;
655
}
656

    
657
void OPPROTO op_movl_DT0_0(void)
658
{
659
    *((uint64_t *)&DT0) = 0;
660
}
661

    
662
void OPPROTO op_movl_FT0_1(void)
663
{
664
    *((uint32_t *)&FT0) = 0xffffffff;
665
}
666

    
667
void OPPROTO op_movl_DT0_1(void)
668
{
669
    *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
670
}
671

    
672
void OPPROTO op_fnot(void)
673
{
674
    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
675
}
676

    
677
void OPPROTO op_fnots(void)
678
{
679
    *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
680
}
681

    
682
void OPPROTO op_fnor(void)
683
{
684
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
685
}
686

    
687
void OPPROTO op_fnors(void)
688
{
689
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
690
}
691

    
692
void OPPROTO op_for(void)
693
{
694
    *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
695
}
696

    
697
void OPPROTO op_fors(void)
698
{
699
    *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
700
}
701

    
702
void OPPROTO op_fxor(void)
703
{
704
    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
705
}
706

    
707
void OPPROTO op_fxors(void)
708
{
709
    *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
710
}
711

    
712
void OPPROTO op_fand(void)
713
{
714
    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
715
}
716

    
717
void OPPROTO op_fands(void)
718
{
719
    *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
720
}
721

    
722
void OPPROTO op_fornot(void)
723
{
724
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
725
}
726

    
727
void OPPROTO op_fornots(void)
728
{
729
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
730
}
731

    
732
void OPPROTO op_fandnot(void)
733
{
734
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
735
}
736

    
737
void OPPROTO op_fandnots(void)
738
{
739
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
740
}
741

    
742
void OPPROTO op_fnand(void)
743
{
744
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
745
}
746

    
747
void OPPROTO op_fnands(void)
748
{
749
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
750
}
751

    
752
void OPPROTO op_fxnor(void)
753
{
754
    *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
755
}
756

    
757
void OPPROTO op_fxnors(void)
758
{
759
    *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
760
}
761

    
762
#ifdef WORDS_BIGENDIAN
763
#define VIS_B64(n) b[7 - (n)]
764
#define VIS_W64(n) w[3 - (n)]
765
#define VIS_SW64(n) sw[3 - (n)]
766
#define VIS_L64(n) l[1 - (n)]
767
#define VIS_B32(n) b[3 - (n)]
768
#define VIS_W32(n) w[1 - (n)]
769
#else
770
#define VIS_B64(n) b[n]
771
#define VIS_W64(n) w[n]
772
#define VIS_SW64(n) sw[n]
773
#define VIS_L64(n) l[n]
774
#define VIS_B32(n) b[n]
775
#define VIS_W32(n) w[n]
776
#endif
777

    
778
typedef union {
779
    uint8_t b[8];
780
    uint16_t w[4];
781
    int16_t sw[4];
782
    uint32_t l[2];
783
    float64 d;
784
} vis64;
785

    
786
typedef union {
787
    uint8_t b[4];
788
    uint16_t w[2];
789
    uint32_t l;
790
    float32 f;
791
} vis32;
792

    
793
void OPPROTO op_fpmerge(void)
794
{
795
    vis64 s, d;
796

    
797
    s.d = DT0;
798
    d.d = DT1;
799

    
800
    // Reverse calculation order to handle overlap
801
    d.VIS_B64(7) = s.VIS_B64(3);
802
    d.VIS_B64(6) = d.VIS_B64(3);
803
    d.VIS_B64(5) = s.VIS_B64(2);
804
    d.VIS_B64(4) = d.VIS_B64(2);
805
    d.VIS_B64(3) = s.VIS_B64(1);
806
    d.VIS_B64(2) = d.VIS_B64(1);
807
    d.VIS_B64(1) = s.VIS_B64(0);
808
    //d.VIS_B64(0) = d.VIS_B64(0);
809

    
810
    DT0 = d.d;
811
}
812

    
813
void OPPROTO op_fmul8x16(void)
814
{
815
    vis64 s, d;
816
    uint32_t tmp;
817

    
818
    s.d = DT0;
819
    d.d = DT1;
820

    
821
#define PMUL(r)                                                 \
822
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
823
    if ((tmp & 0xff) > 0x7f)                                    \
824
        tmp += 0x100;                                           \
825
    d.VIS_W64(r) = tmp >> 8;
826

    
827
    PMUL(0);
828
    PMUL(1);
829
    PMUL(2);
830
    PMUL(3);
831
#undef PMUL
832

    
833
    DT0 = d.d;
834
}
835

    
836
void OPPROTO op_fmul8x16al(void)
837
{
838
    vis64 s, d;
839
    uint32_t tmp;
840

    
841
    s.d = DT0;
842
    d.d = DT1;
843

    
844
#define PMUL(r)                                                 \
845
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
846
    if ((tmp & 0xff) > 0x7f)                                    \
847
        tmp += 0x100;                                           \
848
    d.VIS_W64(r) = tmp >> 8;
849

    
850
    PMUL(0);
851
    PMUL(1);
852
    PMUL(2);
853
    PMUL(3);
854
#undef PMUL
855

    
856
    DT0 = d.d;
857
}
858

    
859
void OPPROTO op_fmul8x16au(void)
860
{
861
    vis64 s, d;
862
    uint32_t tmp;
863

    
864
    s.d = DT0;
865
    d.d = DT1;
866

    
867
#define PMUL(r)                                                 \
868
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
869
    if ((tmp & 0xff) > 0x7f)                                    \
870
        tmp += 0x100;                                           \
871
    d.VIS_W64(r) = tmp >> 8;
872

    
873
    PMUL(0);
874
    PMUL(1);
875
    PMUL(2);
876
    PMUL(3);
877
#undef PMUL
878

    
879
    DT0 = d.d;
880
}
881

    
882
void OPPROTO op_fmul8sux16(void)
883
{
884
    vis64 s, d;
885
    uint32_t tmp;
886

    
887
    s.d = DT0;
888
    d.d = DT1;
889

    
890
#define PMUL(r)                                                         \
891
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
892
    if ((tmp & 0xff) > 0x7f)                                            \
893
        tmp += 0x100;                                                   \
894
    d.VIS_W64(r) = tmp >> 8;
895

    
896
    PMUL(0);
897
    PMUL(1);
898
    PMUL(2);
899
    PMUL(3);
900
#undef PMUL
901

    
902
    DT0 = d.d;
903
}
904

    
905
void OPPROTO op_fmul8ulx16(void)
906
{
907
    vis64 s, d;
908
    uint32_t tmp;
909

    
910
    s.d = DT0;
911
    d.d = DT1;
912

    
913
#define PMUL(r)                                                         \
914
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
915
    if ((tmp & 0xff) > 0x7f)                                            \
916
        tmp += 0x100;                                                   \
917
    d.VIS_W64(r) = tmp >> 8;
918

    
919
    PMUL(0);
920
    PMUL(1);
921
    PMUL(2);
922
    PMUL(3);
923
#undef PMUL
924

    
925
    DT0 = d.d;
926
}
927

    
928
void OPPROTO op_fmuld8sux16(void)
929
{
930
    vis64 s, d;
931
    uint32_t tmp;
932

    
933
    s.d = DT0;
934
    d.d = DT1;
935

    
936
#define PMUL(r)                                                         \
937
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
938
    if ((tmp & 0xff) > 0x7f)                                            \
939
        tmp += 0x100;                                                   \
940
    d.VIS_L64(r) = tmp;
941

    
942
    // Reverse calculation order to handle overlap
943
    PMUL(1);
944
    PMUL(0);
945
#undef PMUL
946

    
947
    DT0 = d.d;
948
}
949

    
950
void OPPROTO op_fmuld8ulx16(void)
951
{
952
    vis64 s, d;
953
    uint32_t tmp;
954

    
955
    s.d = DT0;
956
    d.d = DT1;
957

    
958
#define PMUL(r)                                                         \
959
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
960
    if ((tmp & 0xff) > 0x7f)                                            \
961
        tmp += 0x100;                                                   \
962
    d.VIS_L64(r) = tmp;
963

    
964
    // Reverse calculation order to handle overlap
965
    PMUL(1);
966
    PMUL(0);
967
#undef PMUL
968

    
969
    DT0 = d.d;
970
}
971

    
972
void OPPROTO op_fexpand(void)
973
{
974
    vis32 s;
975
    vis64 d;
976

    
977
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
978
    d.d = DT1;
979
    d.VIS_L64(0) = s.VIS_W32(0) << 4;
980
    d.VIS_L64(1) = s.VIS_W32(1) << 4;
981
    d.VIS_L64(2) = s.VIS_W32(2) << 4;
982
    d.VIS_L64(3) = s.VIS_W32(3) << 4;
983

    
984
    DT0 = d.d;
985
}
986

    
987
#define VIS_OP(name, F)                                 \
988
    void OPPROTO name##16(void)                         \
989
    {                                                   \
990
        vis64 s, d;                                     \
991
                                                        \
992
        s.d = DT0;                                      \
993
        d.d = DT1;                                      \
994
                                                        \
995
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
996
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
997
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
998
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
999
                                                        \
1000
        DT0 = d.d;                                      \
1001
    }                                                   \
1002
                                                        \
1003
    void OPPROTO name##16s(void)                        \
1004
    {                                                   \
1005
        vis32 s, d;                                     \
1006
                                                        \
1007
        s.f = FT0;                                      \
1008
        d.f = FT1;                                      \
1009
                                                        \
1010
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
1011
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
1012
                                                        \
1013
        FT0 = d.f;                                      \
1014
    }                                                   \
1015
                                                        \
1016
    void OPPROTO name##32(void)                         \
1017
    {                                                   \
1018
        vis64 s, d;                                     \
1019
                                                        \
1020
        s.d = DT0;                                      \
1021
        d.d = DT1;                                      \
1022
                                                        \
1023
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
1024
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
1025
                                                        \
1026
        DT0 = d.d;                                      \
1027
    }                                                   \
1028
                                                        \
1029
    void OPPROTO name##32s(void)                        \
1030
    {                                                   \
1031
        vis32 s, d;                                     \
1032
                                                        \
1033
        s.f = FT0;                                      \
1034
        d.f = FT1;                                      \
1035
                                                        \
1036
        d.l = F(d.l, s.l);                              \
1037
                                                        \
1038
        FT0 = d.f;                                      \
1039
    }
1040

    
1041
#define FADD(a, b) ((a) + (b))
1042
#define FSUB(a, b) ((a) - (b))
1043
VIS_OP(op_fpadd, FADD)
1044
VIS_OP(op_fpsub, FSUB)
1045

    
1046
#define VIS_CMPOP(name, F)                                        \
1047
    void OPPROTO name##16(void)                                   \
1048
    {                                                             \
1049
        vis64 s, d;                                               \
1050
                                                                  \
1051
        s.d = DT0;                                                \
1052
        d.d = DT1;                                                \
1053
                                                                  \
1054
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
1055
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
1056
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
1057
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
1058
                                                                  \
1059
        DT0 = d.d;                                                \
1060
    }                                                             \
1061
                                                                  \
1062
    void OPPROTO name##32(void)                                   \
1063
    {                                                             \
1064
        vis64 s, d;                                               \
1065
                                                                  \
1066
        s.d = DT0;                                                \
1067
        d.d = DT1;                                                \
1068
                                                                  \
1069
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
1070
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
1071
                                                                  \
1072
        DT0 = d.d;                                                \
1073
    }
1074

    
1075
#define FCMPGT(a, b) ((a) > (b))
1076
#define FCMPEQ(a, b) ((a) == (b))
1077
#define FCMPLE(a, b) ((a) <= (b))
1078
#define FCMPNE(a, b) ((a) != (b))
1079

    
1080
VIS_CMPOP(op_fcmpgt, FCMPGT)
1081
VIS_CMPOP(op_fcmpeq, FCMPEQ)
1082
VIS_CMPOP(op_fcmple, FCMPLE)
1083
VIS_CMPOP(op_fcmpne, FCMPNE)
1084

    
1085
#endif
1086

    
1087
#define CHECK_ALIGN_OP(align)                           \
1088
    void OPPROTO op_check_align_T0_ ## align (void)     \
1089
    {                                                   \
1090
        if (T0 & align)                                 \
1091
            raise_exception(TT_UNALIGNED);              \
1092
        FORCE_RET();                                    \
1093
    }
1094

    
1095
CHECK_ALIGN_OP(1)
1096
CHECK_ALIGN_OP(3)
1097
CHECK_ALIGN_OP(7)