Statistics
| Branch: | Revision:

root / target-sparc / op.c @ ff07ec83

History | View | Annotate | Download (20.5 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
/* Load and store */
25
#define MEMSUFFIX _raw
26
#include "op_mem.h"
27
#if !defined(CONFIG_USER_ONLY)
28
#define MEMSUFFIX _user
29
#include "op_mem.h"
30

    
31
#define MEMSUFFIX _kernel
32
#include "op_mem.h"
33

    
34
#ifdef TARGET_SPARC64
35
#define MEMSUFFIX _hypv
36
#include "op_mem.h"
37
#endif
38
#endif
39

    
40
#ifndef TARGET_SPARC64
41
/* XXX: use another pointer for %iN registers to avoid slow wrapping
42
   handling ? */
43
void OPPROTO op_save(void)
44
{
45
    uint32_t cwp;
46
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
47
    if (env->wim & (1 << cwp)) {
48
        raise_exception(TT_WIN_OVF);
49
    }
50
    set_cwp(cwp);
51
    FORCE_RET();
52
}
53

    
54
void OPPROTO op_restore(void)
55
{
56
    uint32_t cwp;
57
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
58
    if (env->wim & (1 << cwp)) {
59
        raise_exception(TT_WIN_UNF);
60
    }
61
    set_cwp(cwp);
62
    FORCE_RET();
63
}
64
#else
65
/* XXX: use another pointer for %iN registers to avoid slow wrapping
66
   handling ? */
67
void OPPROTO op_save(void)
68
{
69
    uint32_t cwp;
70
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
71
    if (env->cansave == 0) {
72
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
73
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
74
                                    ((env->wstate & 0x7) << 2)));
75
    } else {
76
        if (env->cleanwin - env->canrestore == 0) {
77
            // XXX Clean windows without trap
78
            raise_exception(TT_CLRWIN);
79
        } else {
80
            env->cansave--;
81
            env->canrestore++;
82
            set_cwp(cwp);
83
        }
84
    }
85
    FORCE_RET();
86
}
87

    
88
void OPPROTO op_restore(void)
89
{
90
    uint32_t cwp;
91
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
92
    if (env->canrestore == 0) {
93
        raise_exception(TT_FILL | (env->otherwin != 0 ?
94
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
95
                                   ((env->wstate & 0x7) << 2)));
96
    } else {
97
        env->cansave++;
98
        env->canrestore--;
99
        set_cwp(cwp);
100
    }
101
    FORCE_RET();
102
}
103
#endif
104

    
105
void OPPROTO op_jmp_label(void)
106
{
107
    GOTO_LABEL_PARAM(1);
108
}
109

    
110
#define F_OP(name, p) void OPPROTO op_f##name##p(void)
111

    
112
#if defined(CONFIG_USER_ONLY)
113
#define F_BINOP(name)                                           \
114
    F_OP(name, s)                                               \
115
    {                                                           \
116
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
117
    }                                                           \
118
    F_OP(name, d)                                               \
119
    {                                                           \
120
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
121
    }                                                           \
122
    F_OP(name, q)                                               \
123
    {                                                           \
124
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
125
    }
126
#else
127
#define F_BINOP(name)                                           \
128
    F_OP(name, s)                                               \
129
    {                                                           \
130
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
131
    }                                                           \
132
    F_OP(name, d)                                               \
133
    {                                                           \
134
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
135
    }
136
#endif
137

    
138
F_BINOP(add);
139
F_BINOP(sub);
140
F_BINOP(mul);
141
F_BINOP(div);
142
#undef F_BINOP
143

    
144
void OPPROTO op_fsmuld(void)
145
{
146
    DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
147
                      float32_to_float64(FT1, &env->fp_status),
148
                      &env->fp_status);
149
}
150

    
151
#if defined(CONFIG_USER_ONLY)
152
void OPPROTO op_fdmulq(void)
153
{
154
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
155
                       float64_to_float128(DT1, &env->fp_status),
156
                       &env->fp_status);
157
}
158
#endif
159

    
160
#if defined(CONFIG_USER_ONLY)
161
#define F_HELPER(name)    \
162
    F_OP(name, s)         \
163
    {                     \
164
        do_f##name##s();  \
165
    }                     \
166
    F_OP(name, d)         \
167
    {                     \
168
        do_f##name##d();  \
169
    }                     \
170
    F_OP(name, q)         \
171
    {                     \
172
        do_f##name##q();  \
173
    }
174
#else
175
#define F_HELPER(name)    \
176
    F_OP(name, s)         \
177
    {                     \
178
        do_f##name##s();  \
179
    }                     \
180
    F_OP(name, d)         \
181
    {                     \
182
        do_f##name##d();  \
183
    }
184
#endif
185

    
186
F_OP(neg, s)
187
{
188
    FT0 = float32_chs(FT1);
189
}
190

    
191
#ifdef TARGET_SPARC64
192
F_OP(neg, d)
193
{
194
    DT0 = float64_chs(DT1);
195
}
196

    
197
#if defined(CONFIG_USER_ONLY)
198
F_OP(neg, q)
199
{
200
    QT0 = float128_chs(QT1);
201
}
202

    
203
#endif
204

    
205
#endif
206

    
207
/* Integer to float conversion.  */
208
#ifdef USE_INT_TO_FLOAT_HELPERS
209
F_HELPER(ito);
210
#ifdef TARGET_SPARC64
211
F_HELPER(xto);
212
#endif
213
#else
214
F_OP(ito, s)
215
{
216
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
217
}
218

    
219
F_OP(ito, d)
220
{
221
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
222
}
223

    
224
#if defined(CONFIG_USER_ONLY)
225
F_OP(ito, q)
226
{
227
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
228
}
229
#endif
230

    
231
#ifdef TARGET_SPARC64
232
F_OP(xto, s)
233
{
234
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
235
}
236

    
237
F_OP(xto, d)
238
{
239
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
240
}
241
#if defined(CONFIG_USER_ONLY)
242
F_OP(xto, q)
243
{
244
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
245
}
246
#endif
247
#endif
248
#endif
249
#undef F_HELPER
250

    
251
/* floating point conversion */
252
void OPPROTO op_fdtos(void)
253
{
254
    FT0 = float64_to_float32(DT1, &env->fp_status);
255
}
256

    
257
void OPPROTO op_fstod(void)
258
{
259
    DT0 = float32_to_float64(FT1, &env->fp_status);
260
}
261

    
262
#if defined(CONFIG_USER_ONLY)
263
void OPPROTO op_fqtos(void)
264
{
265
    FT0 = float128_to_float32(QT1, &env->fp_status);
266
}
267

    
268
void OPPROTO op_fstoq(void)
269
{
270
    QT0 = float32_to_float128(FT1, &env->fp_status);
271
}
272

    
273
void OPPROTO op_fqtod(void)
274
{
275
    DT0 = float128_to_float64(QT1, &env->fp_status);
276
}
277

    
278
void OPPROTO op_fdtoq(void)
279
{
280
    QT0 = float64_to_float128(DT1, &env->fp_status);
281
}
282
#endif
283

    
284
/* Float to integer conversion.  */
285
void OPPROTO op_fstoi(void)
286
{
287
    *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
288
}
289

    
290
void OPPROTO op_fdtoi(void)
291
{
292
    *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
293
}
294

    
295
#if defined(CONFIG_USER_ONLY)
296
void OPPROTO op_fqtoi(void)
297
{
298
    *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
299
}
300
#endif
301

    
302
#ifdef TARGET_SPARC64
303
void OPPROTO op_fstox(void)
304
{
305
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
306
}
307

    
308
void OPPROTO op_fdtox(void)
309
{
310
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
311
}
312

    
313
#if defined(CONFIG_USER_ONLY)
314
void OPPROTO op_fqtox(void)
315
{
316
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
317
}
318
#endif
319

    
320
void OPPROTO op_flushw(void)
321
{
322
    if (env->cansave != NWINDOWS - 2) {
323
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
324
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
325
                                    ((env->wstate & 0x7) << 2)));
326
    }
327
}
328

    
329
void OPPROTO op_saved(void)
330
{
331
    env->cansave++;
332
    if (env->otherwin == 0)
333
        env->canrestore--;
334
    else
335
        env->otherwin--;
336
    FORCE_RET();
337
}
338

    
339
void OPPROTO op_restored(void)
340
{
341
    env->canrestore++;
342
    if (env->cleanwin < NWINDOWS - 1)
343
        env->cleanwin++;
344
    if (env->otherwin == 0)
345
        env->cansave--;
346
    else
347
        env->otherwin--;
348
    FORCE_RET();
349
}
350
#endif
351

    
352
#ifdef TARGET_SPARC64
353
void OPPROTO op_faligndata()
354
{
355
    uint64_t tmp;
356

    
357
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
358
    tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
359
    *((uint64_t *)&DT0) = tmp;
360
}
361

    
362
void OPPROTO op_movl_FT0_0(void)
363
{
364
    *((uint32_t *)&FT0) = 0;
365
}
366

    
367
void OPPROTO op_movl_DT0_0(void)
368
{
369
    *((uint64_t *)&DT0) = 0;
370
}
371

    
372
void OPPROTO op_movl_FT0_1(void)
373
{
374
    *((uint32_t *)&FT0) = 0xffffffff;
375
}
376

    
377
void OPPROTO op_movl_DT0_1(void)
378
{
379
    *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
380
}
381

    
382
void OPPROTO op_fnot(void)
383
{
384
    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
385
}
386

    
387
void OPPROTO op_fnots(void)
388
{
389
    *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
390
}
391

    
392
void OPPROTO op_fnor(void)
393
{
394
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
395
}
396

    
397
void OPPROTO op_fnors(void)
398
{
399
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
400
}
401

    
402
void OPPROTO op_for(void)
403
{
404
    *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
405
}
406

    
407
void OPPROTO op_fors(void)
408
{
409
    *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
410
}
411

    
412
void OPPROTO op_fxor(void)
413
{
414
    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
415
}
416

    
417
void OPPROTO op_fxors(void)
418
{
419
    *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
420
}
421

    
422
void OPPROTO op_fand(void)
423
{
424
    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
425
}
426

    
427
void OPPROTO op_fands(void)
428
{
429
    *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
430
}
431

    
432
void OPPROTO op_fornot(void)
433
{
434
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
435
}
436

    
437
void OPPROTO op_fornots(void)
438
{
439
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
440
}
441

    
442
void OPPROTO op_fandnot(void)
443
{
444
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
445
}
446

    
447
void OPPROTO op_fandnots(void)
448
{
449
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
450
}
451

    
452
void OPPROTO op_fnand(void)
453
{
454
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
455
}
456

    
457
void OPPROTO op_fnands(void)
458
{
459
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
460
}
461

    
462
void OPPROTO op_fxnor(void)
463
{
464
    *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
465
}
466

    
467
void OPPROTO op_fxnors(void)
468
{
469
    *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
470
}
471

    
472
#ifdef WORDS_BIGENDIAN
473
#define VIS_B64(n) b[7 - (n)]
474
#define VIS_W64(n) w[3 - (n)]
475
#define VIS_SW64(n) sw[3 - (n)]
476
#define VIS_L64(n) l[1 - (n)]
477
#define VIS_B32(n) b[3 - (n)]
478
#define VIS_W32(n) w[1 - (n)]
479
#else
480
#define VIS_B64(n) b[n]
481
#define VIS_W64(n) w[n]
482
#define VIS_SW64(n) sw[n]
483
#define VIS_L64(n) l[n]
484
#define VIS_B32(n) b[n]
485
#define VIS_W32(n) w[n]
486
#endif
487

    
488
typedef union {
489
    uint8_t b[8];
490
    uint16_t w[4];
491
    int16_t sw[4];
492
    uint32_t l[2];
493
    float64 d;
494
} vis64;
495

    
496
typedef union {
497
    uint8_t b[4];
498
    uint16_t w[2];
499
    uint32_t l;
500
    float32 f;
501
} vis32;
502

    
503
void OPPROTO op_fpmerge(void)
504
{
505
    vis64 s, d;
506

    
507
    s.d = DT0;
508
    d.d = DT1;
509

    
510
    // Reverse calculation order to handle overlap
511
    d.VIS_B64(7) = s.VIS_B64(3);
512
    d.VIS_B64(6) = d.VIS_B64(3);
513
    d.VIS_B64(5) = s.VIS_B64(2);
514
    d.VIS_B64(4) = d.VIS_B64(2);
515
    d.VIS_B64(3) = s.VIS_B64(1);
516
    d.VIS_B64(2) = d.VIS_B64(1);
517
    d.VIS_B64(1) = s.VIS_B64(0);
518
    //d.VIS_B64(0) = d.VIS_B64(0);
519

    
520
    DT0 = d.d;
521
}
522

    
523
void OPPROTO op_fmul8x16(void)
524
{
525
    vis64 s, d;
526
    uint32_t tmp;
527

    
528
    s.d = DT0;
529
    d.d = DT1;
530

    
531
#define PMUL(r)                                                 \
532
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
533
    if ((tmp & 0xff) > 0x7f)                                    \
534
        tmp += 0x100;                                           \
535
    d.VIS_W64(r) = tmp >> 8;
536

    
537
    PMUL(0);
538
    PMUL(1);
539
    PMUL(2);
540
    PMUL(3);
541
#undef PMUL
542

    
543
    DT0 = d.d;
544
}
545

    
546
void OPPROTO op_fmul8x16al(void)
547
{
548
    vis64 s, d;
549
    uint32_t tmp;
550

    
551
    s.d = DT0;
552
    d.d = DT1;
553

    
554
#define PMUL(r)                                                 \
555
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
556
    if ((tmp & 0xff) > 0x7f)                                    \
557
        tmp += 0x100;                                           \
558
    d.VIS_W64(r) = tmp >> 8;
559

    
560
    PMUL(0);
561
    PMUL(1);
562
    PMUL(2);
563
    PMUL(3);
564
#undef PMUL
565

    
566
    DT0 = d.d;
567
}
568

    
569
void OPPROTO op_fmul8x16au(void)
570
{
571
    vis64 s, d;
572
    uint32_t tmp;
573

    
574
    s.d = DT0;
575
    d.d = DT1;
576

    
577
#define PMUL(r)                                                 \
578
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
579
    if ((tmp & 0xff) > 0x7f)                                    \
580
        tmp += 0x100;                                           \
581
    d.VIS_W64(r) = tmp >> 8;
582

    
583
    PMUL(0);
584
    PMUL(1);
585
    PMUL(2);
586
    PMUL(3);
587
#undef PMUL
588

    
589
    DT0 = d.d;
590
}
591

    
592
void OPPROTO op_fmul8sux16(void)
593
{
594
    vis64 s, d;
595
    uint32_t tmp;
596

    
597
    s.d = DT0;
598
    d.d = DT1;
599

    
600
#define PMUL(r)                                                         \
601
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
602
    if ((tmp & 0xff) > 0x7f)                                            \
603
        tmp += 0x100;                                                   \
604
    d.VIS_W64(r) = tmp >> 8;
605

    
606
    PMUL(0);
607
    PMUL(1);
608
    PMUL(2);
609
    PMUL(3);
610
#undef PMUL
611

    
612
    DT0 = d.d;
613
}
614

    
615
void OPPROTO op_fmul8ulx16(void)
616
{
617
    vis64 s, d;
618
    uint32_t tmp;
619

    
620
    s.d = DT0;
621
    d.d = DT1;
622

    
623
#define PMUL(r)                                                         \
624
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
625
    if ((tmp & 0xff) > 0x7f)                                            \
626
        tmp += 0x100;                                                   \
627
    d.VIS_W64(r) = tmp >> 8;
628

    
629
    PMUL(0);
630
    PMUL(1);
631
    PMUL(2);
632
    PMUL(3);
633
#undef PMUL
634

    
635
    DT0 = d.d;
636
}
637

    
638
void OPPROTO op_fmuld8sux16(void)
639
{
640
    vis64 s, d;
641
    uint32_t tmp;
642

    
643
    s.d = DT0;
644
    d.d = DT1;
645

    
646
#define PMUL(r)                                                         \
647
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
648
    if ((tmp & 0xff) > 0x7f)                                            \
649
        tmp += 0x100;                                                   \
650
    d.VIS_L64(r) = tmp;
651

    
652
    // Reverse calculation order to handle overlap
653
    PMUL(1);
654
    PMUL(0);
655
#undef PMUL
656

    
657
    DT0 = d.d;
658
}
659

    
660
void OPPROTO op_fmuld8ulx16(void)
661
{
662
    vis64 s, d;
663
    uint32_t tmp;
664

    
665
    s.d = DT0;
666
    d.d = DT1;
667

    
668
#define PMUL(r)                                                         \
669
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
670
    if ((tmp & 0xff) > 0x7f)                                            \
671
        tmp += 0x100;                                                   \
672
    d.VIS_L64(r) = tmp;
673

    
674
    // Reverse calculation order to handle overlap
675
    PMUL(1);
676
    PMUL(0);
677
#undef PMUL
678

    
679
    DT0 = d.d;
680
}
681

    
682
void OPPROTO op_fexpand(void)
683
{
684
    vis32 s;
685
    vis64 d;
686

    
687
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
688
    d.d = DT1;
689
    d.VIS_L64(0) = s.VIS_W32(0) << 4;
690
    d.VIS_L64(1) = s.VIS_W32(1) << 4;
691
    d.VIS_L64(2) = s.VIS_W32(2) << 4;
692
    d.VIS_L64(3) = s.VIS_W32(3) << 4;
693

    
694
    DT0 = d.d;
695
}
696

    
697
#define VIS_OP(name, F)                                 \
698
    void OPPROTO name##16(void)                         \
699
    {                                                   \
700
        vis64 s, d;                                     \
701
                                                        \
702
        s.d = DT0;                                      \
703
        d.d = DT1;                                      \
704
                                                        \
705
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
706
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
707
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
708
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
709
                                                        \
710
        DT0 = d.d;                                      \
711
    }                                                   \
712
                                                        \
713
    void OPPROTO name##16s(void)                        \
714
    {                                                   \
715
        vis32 s, d;                                     \
716
                                                        \
717
        s.f = FT0;                                      \
718
        d.f = FT1;                                      \
719
                                                        \
720
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
721
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
722
                                                        \
723
        FT0 = d.f;                                      \
724
    }                                                   \
725
                                                        \
726
    void OPPROTO name##32(void)                         \
727
    {                                                   \
728
        vis64 s, d;                                     \
729
                                                        \
730
        s.d = DT0;                                      \
731
        d.d = DT1;                                      \
732
                                                        \
733
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
734
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
735
                                                        \
736
        DT0 = d.d;                                      \
737
    }                                                   \
738
                                                        \
739
    void OPPROTO name##32s(void)                        \
740
    {                                                   \
741
        vis32 s, d;                                     \
742
                                                        \
743
        s.f = FT0;                                      \
744
        d.f = FT1;                                      \
745
                                                        \
746
        d.l = F(d.l, s.l);                              \
747
                                                        \
748
        FT0 = d.f;                                      \
749
    }
750

    
751
#define FADD(a, b) ((a) + (b))
752
#define FSUB(a, b) ((a) - (b))
753
VIS_OP(op_fpadd, FADD)
754
VIS_OP(op_fpsub, FSUB)
755

    
756
#define VIS_CMPOP(name, F)                                        \
757
    void OPPROTO name##16(void)                                   \
758
    {                                                             \
759
        vis64 s, d;                                               \
760
                                                                  \
761
        s.d = DT0;                                                \
762
        d.d = DT1;                                                \
763
                                                                  \
764
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
765
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
766
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
767
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
768
                                                                  \
769
        DT0 = d.d;                                                \
770
    }                                                             \
771
                                                                  \
772
    void OPPROTO name##32(void)                                   \
773
    {                                                             \
774
        vis64 s, d;                                               \
775
                                                                  \
776
        s.d = DT0;                                                \
777
        d.d = DT1;                                                \
778
                                                                  \
779
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
780
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
781
                                                                  \
782
        DT0 = d.d;                                                \
783
    }
784

    
785
#define FCMPGT(a, b) ((a) > (b))
786
#define FCMPEQ(a, b) ((a) == (b))
787
#define FCMPLE(a, b) ((a) <= (b))
788
#define FCMPNE(a, b) ((a) != (b))
789

    
790
VIS_CMPOP(op_fcmpgt, FCMPGT)
791
VIS_CMPOP(op_fcmpeq, FCMPEQ)
792
VIS_CMPOP(op_fcmple, FCMPLE)
793
VIS_CMPOP(op_fcmpne, FCMPNE)
794

    
795
#endif
796

    
797
#define CHECK_ALIGN_OP(align)                           \
798
    void OPPROTO op_check_align_T0_ ## align (void)     \
799
    {                                                   \
800
        if (T0 & align)                                 \
801
            raise_exception(TT_UNALIGNED);              \
802
        FORCE_RET();                                    \
803
    }
804

    
805
CHECK_ALIGN_OP(1)
806
CHECK_ALIGN_OP(3)
807
CHECK_ALIGN_OP(7)