Statistics
| Branch: | Revision:

root / target-sparc / op.c @ 8879d139

History | View | Annotate | Download (26.7 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_udiv_T1_T0(void)
175
{
176
    uint64_t x0;
177
    uint32_t x1;
178

    
179
    x0 = T0 | ((uint64_t) (env->y) << 32);
180
    x1 = T1;
181

    
182
    if (x1 == 0) {
183
        raise_exception(TT_DIV_ZERO);
184
    }
185

    
186
    x0 = x0 / x1;
187
    if (x0 > 0xffffffff) {
188
        T0 = 0xffffffff;
189
        T1 = 1;
190
    } else {
191
        T0 = x0;
192
        T1 = 0;
193
    }
194
    FORCE_RET();
195
}
196

    
197
void OPPROTO op_sdiv_T1_T0(void)
198
{
199
    int64_t x0;
200
    int32_t x1;
201

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

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

    
209
    x0 = x0 / x1;
210
    if ((int32_t) x0 != x0) {
211
        T0 = x0 < 0? 0x80000000: 0x7fffffff;
212
        T1 = 1;
213
    } else {
214
        T0 = x0;
215
        T1 = 0;
216
    }
217
    FORCE_RET();
218
}
219

    
220
/* Load and store */
221
#define MEMSUFFIX _raw
222
#include "op_mem.h"
223
#if !defined(CONFIG_USER_ONLY)
224
#define MEMSUFFIX _user
225
#include "op_mem.h"
226

    
227
#define MEMSUFFIX _kernel
228
#include "op_mem.h"
229

    
230
#ifdef TARGET_SPARC64
231
#define MEMSUFFIX _hypv
232
#include "op_mem.h"
233
#endif
234
#endif
235

    
236
#ifndef TARGET_SPARC64
237
/* XXX: use another pointer for %iN registers to avoid slow wrapping
238
   handling ? */
239
void OPPROTO op_save(void)
240
{
241
    uint32_t cwp;
242
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
243
    if (env->wim & (1 << cwp)) {
244
        raise_exception(TT_WIN_OVF);
245
    }
246
    set_cwp(cwp);
247
    FORCE_RET();
248
}
249

    
250
void OPPROTO op_restore(void)
251
{
252
    uint32_t cwp;
253
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
254
    if (env->wim & (1 << cwp)) {
255
        raise_exception(TT_WIN_UNF);
256
    }
257
    set_cwp(cwp);
258
    FORCE_RET();
259
}
260
#else
261
void OPPROTO op_rdccr(void)
262
{
263
    T0 = GET_CCR(env);
264
}
265

    
266
void OPPROTO op_wrccr(void)
267
{
268
    PUT_CCR(env, T0);
269
}
270

    
271
// CWP handling is reversed in V9, but we still use the V8 register
272
// order.
273
void OPPROTO op_rdcwp(void)
274
{
275
    T0 = GET_CWP64(env);
276
}
277

    
278
void OPPROTO op_wrcwp(void)
279
{
280
    PUT_CWP64(env, T0);
281
}
282

    
283
/* XXX: use another pointer for %iN registers to avoid slow wrapping
284
   handling ? */
285
void OPPROTO op_save(void)
286
{
287
    uint32_t cwp;
288
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
289
    if (env->cansave == 0) {
290
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
291
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
292
                                    ((env->wstate & 0x7) << 2)));
293
    } else {
294
        if (env->cleanwin - env->canrestore == 0) {
295
            // XXX Clean windows without trap
296
            raise_exception(TT_CLRWIN);
297
        } else {
298
            env->cansave--;
299
            env->canrestore++;
300
            set_cwp(cwp);
301
        }
302
    }
303
    FORCE_RET();
304
}
305

    
306
void OPPROTO op_restore(void)
307
{
308
    uint32_t cwp;
309
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
310
    if (env->canrestore == 0) {
311
        raise_exception(TT_FILL | (env->otherwin != 0 ?
312
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
313
                                   ((env->wstate & 0x7) << 2)));
314
    } else {
315
        env->cansave++;
316
        env->canrestore--;
317
        set_cwp(cwp);
318
    }
319
    FORCE_RET();
320
}
321
#endif
322

    
323
void OPPROTO op_jmp_label(void)
324
{
325
    GOTO_LABEL_PARAM(1);
326
}
327

    
328
#define F_OP(name, p) void OPPROTO op_f##name##p(void)
329

    
330
#if defined(CONFIG_USER_ONLY)
331
#define F_BINOP(name)                                           \
332
    F_OP(name, s)                                               \
333
    {                                                           \
334
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
335
    }                                                           \
336
    F_OP(name, d)                                               \
337
    {                                                           \
338
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
339
    }                                                           \
340
    F_OP(name, q)                                               \
341
    {                                                           \
342
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
343
    }
344
#else
345
#define F_BINOP(name)                                           \
346
    F_OP(name, s)                                               \
347
    {                                                           \
348
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
349
    }                                                           \
350
    F_OP(name, d)                                               \
351
    {                                                           \
352
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
353
    }
354
#endif
355

    
356
F_BINOP(add);
357
F_BINOP(sub);
358
F_BINOP(mul);
359
F_BINOP(div);
360
#undef F_BINOP
361

    
362
void OPPROTO op_fsmuld(void)
363
{
364
    DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
365
                      float32_to_float64(FT1, &env->fp_status),
366
                      &env->fp_status);
367
}
368

    
369
#if defined(CONFIG_USER_ONLY)
370
void OPPROTO op_fdmulq(void)
371
{
372
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
373
                       float64_to_float128(DT1, &env->fp_status),
374
                       &env->fp_status);
375
}
376
#endif
377

    
378
#if defined(CONFIG_USER_ONLY)
379
#define F_HELPER(name)    \
380
    F_OP(name, s)         \
381
    {                     \
382
        do_f##name##s();  \
383
    }                     \
384
    F_OP(name, d)         \
385
    {                     \
386
        do_f##name##d();  \
387
    }                     \
388
    F_OP(name, q)         \
389
    {                     \
390
        do_f##name##q();  \
391
    }
392
#else
393
#define F_HELPER(name)    \
394
    F_OP(name, s)         \
395
    {                     \
396
        do_f##name##s();  \
397
    }                     \
398
    F_OP(name, d)         \
399
    {                     \
400
        do_f##name##d();  \
401
    }
402
#endif
403

    
404
F_OP(neg, s)
405
{
406
    FT0 = float32_chs(FT1);
407
}
408

    
409
#ifdef TARGET_SPARC64
410
F_OP(neg, d)
411
{
412
    DT0 = float64_chs(DT1);
413
}
414

    
415
#if defined(CONFIG_USER_ONLY)
416
F_OP(neg, q)
417
{
418
    QT0 = float128_chs(QT1);
419
}
420

    
421
#endif
422

    
423
#endif
424

    
425
/* Integer to float conversion.  */
426
#ifdef USE_INT_TO_FLOAT_HELPERS
427
F_HELPER(ito);
428
#ifdef TARGET_SPARC64
429
F_HELPER(xto);
430
#endif
431
#else
432
F_OP(ito, s)
433
{
434
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
435
}
436

    
437
F_OP(ito, d)
438
{
439
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
440
}
441

    
442
#if defined(CONFIG_USER_ONLY)
443
F_OP(ito, q)
444
{
445
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
446
}
447
#endif
448

    
449
#ifdef TARGET_SPARC64
450
F_OP(xto, s)
451
{
452
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
453
}
454

    
455
F_OP(xto, d)
456
{
457
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
458
}
459
#if defined(CONFIG_USER_ONLY)
460
F_OP(xto, q)
461
{
462
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
463
}
464
#endif
465
#endif
466
#endif
467
#undef F_HELPER
468

    
469
/* floating point conversion */
470
void OPPROTO op_fdtos(void)
471
{
472
    FT0 = float64_to_float32(DT1, &env->fp_status);
473
}
474

    
475
void OPPROTO op_fstod(void)
476
{
477
    DT0 = float32_to_float64(FT1, &env->fp_status);
478
}
479

    
480
#if defined(CONFIG_USER_ONLY)
481
void OPPROTO op_fqtos(void)
482
{
483
    FT0 = float128_to_float32(QT1, &env->fp_status);
484
}
485

    
486
void OPPROTO op_fstoq(void)
487
{
488
    QT0 = float32_to_float128(FT1, &env->fp_status);
489
}
490

    
491
void OPPROTO op_fqtod(void)
492
{
493
    DT0 = float128_to_float64(QT1, &env->fp_status);
494
}
495

    
496
void OPPROTO op_fdtoq(void)
497
{
498
    QT0 = float64_to_float128(DT1, &env->fp_status);
499
}
500
#endif
501

    
502
/* Float to integer conversion.  */
503
void OPPROTO op_fstoi(void)
504
{
505
    *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
506
}
507

    
508
void OPPROTO op_fdtoi(void)
509
{
510
    *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
511
}
512

    
513
#if defined(CONFIG_USER_ONLY)
514
void OPPROTO op_fqtoi(void)
515
{
516
    *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
517
}
518
#endif
519

    
520
#ifdef TARGET_SPARC64
521
void OPPROTO op_fstox(void)
522
{
523
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
524
}
525

    
526
void OPPROTO op_fdtox(void)
527
{
528
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
529
}
530

    
531
#if defined(CONFIG_USER_ONLY)
532
void OPPROTO op_fqtox(void)
533
{
534
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
535
}
536
#endif
537

    
538
void OPPROTO op_flushw(void)
539
{
540
    if (env->cansave != NWINDOWS - 2) {
541
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
542
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
543
                                    ((env->wstate & 0x7) << 2)));
544
    }
545
}
546

    
547
void OPPROTO op_saved(void)
548
{
549
    env->cansave++;
550
    if (env->otherwin == 0)
551
        env->canrestore--;
552
    else
553
        env->otherwin--;
554
    FORCE_RET();
555
}
556

    
557
void OPPROTO op_restored(void)
558
{
559
    env->canrestore++;
560
    if (env->cleanwin < NWINDOWS - 1)
561
        env->cleanwin++;
562
    if (env->otherwin == 0)
563
        env->cansave--;
564
    else
565
        env->otherwin--;
566
    FORCE_RET();
567
}
568
#endif
569

    
570
#ifdef TARGET_SPARC64
571
// This function uses non-native bit order
572
#define GET_FIELD(X, FROM, TO)                                  \
573
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
574

    
575
// This function uses the order in the manuals, i.e. bit 0 is 2^0
576
#define GET_FIELD_SP(X, FROM, TO)               \
577
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
578

    
579
void OPPROTO op_array8()
580
{
581
    T0 = (GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
582
        (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
583
        (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
584
        (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
585
        (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
586
        (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12);
587
}
588

    
589
void OPPROTO op_array16()
590
{
591
    T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
592
          (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
593
          (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
594
          (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
595
          (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
596
          (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 1;
597
}
598

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

    
609
void OPPROTO op_alignaddr()
610
{
611
    uint64_t tmp;
612

    
613
    tmp = T0 + T1;
614
    env->gsr &= ~7ULL;
615
    env->gsr |= tmp & 7ULL;
616
    T0 = tmp & ~7ULL;
617
}
618

    
619
void OPPROTO op_faligndata()
620
{
621
    uint64_t tmp;
622

    
623
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
624
    tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
625
    *((uint64_t *)&DT0) = tmp;
626
}
627

    
628
void OPPROTO op_movl_FT0_0(void)
629
{
630
    *((uint32_t *)&FT0) = 0;
631
}
632

    
633
void OPPROTO op_movl_DT0_0(void)
634
{
635
    *((uint64_t *)&DT0) = 0;
636
}
637

    
638
void OPPROTO op_movl_FT0_1(void)
639
{
640
    *((uint32_t *)&FT0) = 0xffffffff;
641
}
642

    
643
void OPPROTO op_movl_DT0_1(void)
644
{
645
    *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
646
}
647

    
648
void OPPROTO op_fnot(void)
649
{
650
    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
651
}
652

    
653
void OPPROTO op_fnots(void)
654
{
655
    *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
656
}
657

    
658
void OPPROTO op_fnor(void)
659
{
660
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
661
}
662

    
663
void OPPROTO op_fnors(void)
664
{
665
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
666
}
667

    
668
void OPPROTO op_for(void)
669
{
670
    *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
671
}
672

    
673
void OPPROTO op_fors(void)
674
{
675
    *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
676
}
677

    
678
void OPPROTO op_fxor(void)
679
{
680
    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
681
}
682

    
683
void OPPROTO op_fxors(void)
684
{
685
    *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
686
}
687

    
688
void OPPROTO op_fand(void)
689
{
690
    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
691
}
692

    
693
void OPPROTO op_fands(void)
694
{
695
    *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
696
}
697

    
698
void OPPROTO op_fornot(void)
699
{
700
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
701
}
702

    
703
void OPPROTO op_fornots(void)
704
{
705
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
706
}
707

    
708
void OPPROTO op_fandnot(void)
709
{
710
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
711
}
712

    
713
void OPPROTO op_fandnots(void)
714
{
715
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
716
}
717

    
718
void OPPROTO op_fnand(void)
719
{
720
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
721
}
722

    
723
void OPPROTO op_fnands(void)
724
{
725
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
726
}
727

    
728
void OPPROTO op_fxnor(void)
729
{
730
    *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
731
}
732

    
733
void OPPROTO op_fxnors(void)
734
{
735
    *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
736
}
737

    
738
#ifdef WORDS_BIGENDIAN
739
#define VIS_B64(n) b[7 - (n)]
740
#define VIS_W64(n) w[3 - (n)]
741
#define VIS_SW64(n) sw[3 - (n)]
742
#define VIS_L64(n) l[1 - (n)]
743
#define VIS_B32(n) b[3 - (n)]
744
#define VIS_W32(n) w[1 - (n)]
745
#else
746
#define VIS_B64(n) b[n]
747
#define VIS_W64(n) w[n]
748
#define VIS_SW64(n) sw[n]
749
#define VIS_L64(n) l[n]
750
#define VIS_B32(n) b[n]
751
#define VIS_W32(n) w[n]
752
#endif
753

    
754
typedef union {
755
    uint8_t b[8];
756
    uint16_t w[4];
757
    int16_t sw[4];
758
    uint32_t l[2];
759
    float64 d;
760
} vis64;
761

    
762
typedef union {
763
    uint8_t b[4];
764
    uint16_t w[2];
765
    uint32_t l;
766
    float32 f;
767
} vis32;
768

    
769
void OPPROTO op_fpmerge(void)
770
{
771
    vis64 s, d;
772

    
773
    s.d = DT0;
774
    d.d = DT1;
775

    
776
    // Reverse calculation order to handle overlap
777
    d.VIS_B64(7) = s.VIS_B64(3);
778
    d.VIS_B64(6) = d.VIS_B64(3);
779
    d.VIS_B64(5) = s.VIS_B64(2);
780
    d.VIS_B64(4) = d.VIS_B64(2);
781
    d.VIS_B64(3) = s.VIS_B64(1);
782
    d.VIS_B64(2) = d.VIS_B64(1);
783
    d.VIS_B64(1) = s.VIS_B64(0);
784
    //d.VIS_B64(0) = d.VIS_B64(0);
785

    
786
    DT0 = d.d;
787
}
788

    
789
void OPPROTO op_fmul8x16(void)
790
{
791
    vis64 s, d;
792
    uint32_t tmp;
793

    
794
    s.d = DT0;
795
    d.d = DT1;
796

    
797
#define PMUL(r)                                                 \
798
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
799
    if ((tmp & 0xff) > 0x7f)                                    \
800
        tmp += 0x100;                                           \
801
    d.VIS_W64(r) = tmp >> 8;
802

    
803
    PMUL(0);
804
    PMUL(1);
805
    PMUL(2);
806
    PMUL(3);
807
#undef PMUL
808

    
809
    DT0 = d.d;
810
}
811

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

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

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

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

    
832
    DT0 = d.d;
833
}
834

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

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

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

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

    
855
    DT0 = d.d;
856
}
857

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

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

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

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

    
878
    DT0 = d.d;
879
}
880

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

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

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

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

    
901
    DT0 = d.d;
902
}
903

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

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

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

    
918
    // Reverse calculation order to handle overlap
919
    PMUL(1);
920
    PMUL(0);
921
#undef PMUL
922

    
923
    DT0 = d.d;
924
}
925

    
926
void OPPROTO op_fmuld8ulx16(void)
927
{
928
    vis64 s, d;
929
    uint32_t tmp;
930

    
931
    s.d = DT0;
932
    d.d = DT1;
933

    
934
#define PMUL(r)                                                         \
935
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
936
    if ((tmp & 0xff) > 0x7f)                                            \
937
        tmp += 0x100;                                                   \
938
    d.VIS_L64(r) = tmp;
939

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

    
945
    DT0 = d.d;
946
}
947

    
948
void OPPROTO op_fexpand(void)
949
{
950
    vis32 s;
951
    vis64 d;
952

    
953
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
954
    d.d = DT1;
955
    d.VIS_L64(0) = s.VIS_W32(0) << 4;
956
    d.VIS_L64(1) = s.VIS_W32(1) << 4;
957
    d.VIS_L64(2) = s.VIS_W32(2) << 4;
958
    d.VIS_L64(3) = s.VIS_W32(3) << 4;
959

    
960
    DT0 = d.d;
961
}
962

    
963
#define VIS_OP(name, F)                                 \
964
    void OPPROTO name##16(void)                         \
965
    {                                                   \
966
        vis64 s, d;                                     \
967
                                                        \
968
        s.d = DT0;                                      \
969
        d.d = DT1;                                      \
970
                                                        \
971
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
972
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
973
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
974
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
975
                                                        \
976
        DT0 = d.d;                                      \
977
    }                                                   \
978
                                                        \
979
    void OPPROTO name##16s(void)                        \
980
    {                                                   \
981
        vis32 s, d;                                     \
982
                                                        \
983
        s.f = FT0;                                      \
984
        d.f = FT1;                                      \
985
                                                        \
986
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
987
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
988
                                                        \
989
        FT0 = d.f;                                      \
990
    }                                                   \
991
                                                        \
992
    void OPPROTO name##32(void)                         \
993
    {                                                   \
994
        vis64 s, d;                                     \
995
                                                        \
996
        s.d = DT0;                                      \
997
        d.d = DT1;                                      \
998
                                                        \
999
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
1000
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
1001
                                                        \
1002
        DT0 = d.d;                                      \
1003
    }                                                   \
1004
                                                        \
1005
    void OPPROTO name##32s(void)                        \
1006
    {                                                   \
1007
        vis32 s, d;                                     \
1008
                                                        \
1009
        s.f = FT0;                                      \
1010
        d.f = FT1;                                      \
1011
                                                        \
1012
        d.l = F(d.l, s.l);                              \
1013
                                                        \
1014
        FT0 = d.f;                                      \
1015
    }
1016

    
1017
#define FADD(a, b) ((a) + (b))
1018
#define FSUB(a, b) ((a) - (b))
1019
VIS_OP(op_fpadd, FADD)
1020
VIS_OP(op_fpsub, FSUB)
1021

    
1022
#define VIS_CMPOP(name, F)                                        \
1023
    void OPPROTO name##16(void)                                   \
1024
    {                                                             \
1025
        vis64 s, d;                                               \
1026
                                                                  \
1027
        s.d = DT0;                                                \
1028
        d.d = DT1;                                                \
1029
                                                                  \
1030
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
1031
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
1032
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
1033
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
1034
                                                                  \
1035
        DT0 = d.d;                                                \
1036
    }                                                             \
1037
                                                                  \
1038
    void OPPROTO name##32(void)                                   \
1039
    {                                                             \
1040
        vis64 s, d;                                               \
1041
                                                                  \
1042
        s.d = DT0;                                                \
1043
        d.d = DT1;                                                \
1044
                                                                  \
1045
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
1046
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
1047
                                                                  \
1048
        DT0 = d.d;                                                \
1049
    }
1050

    
1051
#define FCMPGT(a, b) ((a) > (b))
1052
#define FCMPEQ(a, b) ((a) == (b))
1053
#define FCMPLE(a, b) ((a) <= (b))
1054
#define FCMPNE(a, b) ((a) != (b))
1055

    
1056
VIS_CMPOP(op_fcmpgt, FCMPGT)
1057
VIS_CMPOP(op_fcmpeq, FCMPEQ)
1058
VIS_CMPOP(op_fcmple, FCMPLE)
1059
VIS_CMPOP(op_fcmpne, FCMPNE)
1060

    
1061
#endif
1062

    
1063
#define CHECK_ALIGN_OP(align)                           \
1064
    void OPPROTO op_check_align_T0_ ## align (void)     \
1065
    {                                                   \
1066
        if (T0 & align)                                 \
1067
            raise_exception(TT_UNALIGNED);              \
1068
        FORCE_RET();                                    \
1069
    }
1070

    
1071
CHECK_ALIGN_OP(1)
1072
CHECK_ALIGN_OP(3)
1073
CHECK_ALIGN_OP(7)