Statistics
| Branch: | Revision:

root / target-sparc / op.c @ 1f5063fb

History | View | Annotate | Download (25 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
void OPPROTO op_faligndata()
572
{
573
    uint64_t tmp;
574

    
575
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
576
    tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
577
    *((uint64_t *)&DT0) = tmp;
578
}
579

    
580
void OPPROTO op_movl_FT0_0(void)
581
{
582
    *((uint32_t *)&FT0) = 0;
583
}
584

    
585
void OPPROTO op_movl_DT0_0(void)
586
{
587
    *((uint64_t *)&DT0) = 0;
588
}
589

    
590
void OPPROTO op_movl_FT0_1(void)
591
{
592
    *((uint32_t *)&FT0) = 0xffffffff;
593
}
594

    
595
void OPPROTO op_movl_DT0_1(void)
596
{
597
    *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
598
}
599

    
600
void OPPROTO op_fnot(void)
601
{
602
    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
603
}
604

    
605
void OPPROTO op_fnots(void)
606
{
607
    *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
608
}
609

    
610
void OPPROTO op_fnor(void)
611
{
612
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
613
}
614

    
615
void OPPROTO op_fnors(void)
616
{
617
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
618
}
619

    
620
void OPPROTO op_for(void)
621
{
622
    *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
623
}
624

    
625
void OPPROTO op_fors(void)
626
{
627
    *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
628
}
629

    
630
void OPPROTO op_fxor(void)
631
{
632
    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
633
}
634

    
635
void OPPROTO op_fxors(void)
636
{
637
    *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
638
}
639

    
640
void OPPROTO op_fand(void)
641
{
642
    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
643
}
644

    
645
void OPPROTO op_fands(void)
646
{
647
    *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
648
}
649

    
650
void OPPROTO op_fornot(void)
651
{
652
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
653
}
654

    
655
void OPPROTO op_fornots(void)
656
{
657
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
658
}
659

    
660
void OPPROTO op_fandnot(void)
661
{
662
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
663
}
664

    
665
void OPPROTO op_fandnots(void)
666
{
667
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
668
}
669

    
670
void OPPROTO op_fnand(void)
671
{
672
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
673
}
674

    
675
void OPPROTO op_fnands(void)
676
{
677
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
678
}
679

    
680
void OPPROTO op_fxnor(void)
681
{
682
    *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
683
}
684

    
685
void OPPROTO op_fxnors(void)
686
{
687
    *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
688
}
689

    
690
#ifdef WORDS_BIGENDIAN
691
#define VIS_B64(n) b[7 - (n)]
692
#define VIS_W64(n) w[3 - (n)]
693
#define VIS_SW64(n) sw[3 - (n)]
694
#define VIS_L64(n) l[1 - (n)]
695
#define VIS_B32(n) b[3 - (n)]
696
#define VIS_W32(n) w[1 - (n)]
697
#else
698
#define VIS_B64(n) b[n]
699
#define VIS_W64(n) w[n]
700
#define VIS_SW64(n) sw[n]
701
#define VIS_L64(n) l[n]
702
#define VIS_B32(n) b[n]
703
#define VIS_W32(n) w[n]
704
#endif
705

    
706
typedef union {
707
    uint8_t b[8];
708
    uint16_t w[4];
709
    int16_t sw[4];
710
    uint32_t l[2];
711
    float64 d;
712
} vis64;
713

    
714
typedef union {
715
    uint8_t b[4];
716
    uint16_t w[2];
717
    uint32_t l;
718
    float32 f;
719
} vis32;
720

    
721
void OPPROTO op_fpmerge(void)
722
{
723
    vis64 s, d;
724

    
725
    s.d = DT0;
726
    d.d = DT1;
727

    
728
    // Reverse calculation order to handle overlap
729
    d.VIS_B64(7) = s.VIS_B64(3);
730
    d.VIS_B64(6) = d.VIS_B64(3);
731
    d.VIS_B64(5) = s.VIS_B64(2);
732
    d.VIS_B64(4) = d.VIS_B64(2);
733
    d.VIS_B64(3) = s.VIS_B64(1);
734
    d.VIS_B64(2) = d.VIS_B64(1);
735
    d.VIS_B64(1) = s.VIS_B64(0);
736
    //d.VIS_B64(0) = d.VIS_B64(0);
737

    
738
    DT0 = d.d;
739
}
740

    
741
void OPPROTO op_fmul8x16(void)
742
{
743
    vis64 s, d;
744
    uint32_t tmp;
745

    
746
    s.d = DT0;
747
    d.d = DT1;
748

    
749
#define PMUL(r)                                                 \
750
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
751
    if ((tmp & 0xff) > 0x7f)                                    \
752
        tmp += 0x100;                                           \
753
    d.VIS_W64(r) = tmp >> 8;
754

    
755
    PMUL(0);
756
    PMUL(1);
757
    PMUL(2);
758
    PMUL(3);
759
#undef PMUL
760

    
761
    DT0 = d.d;
762
}
763

    
764
void OPPROTO op_fmul8x16al(void)
765
{
766
    vis64 s, d;
767
    uint32_t tmp;
768

    
769
    s.d = DT0;
770
    d.d = DT1;
771

    
772
#define PMUL(r)                                                 \
773
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
774
    if ((tmp & 0xff) > 0x7f)                                    \
775
        tmp += 0x100;                                           \
776
    d.VIS_W64(r) = tmp >> 8;
777

    
778
    PMUL(0);
779
    PMUL(1);
780
    PMUL(2);
781
    PMUL(3);
782
#undef PMUL
783

    
784
    DT0 = d.d;
785
}
786

    
787
void OPPROTO op_fmul8x16au(void)
788
{
789
    vis64 s, d;
790
    uint32_t tmp;
791

    
792
    s.d = DT0;
793
    d.d = DT1;
794

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

    
801
    PMUL(0);
802
    PMUL(1);
803
    PMUL(2);
804
    PMUL(3);
805
#undef PMUL
806

    
807
    DT0 = d.d;
808
}
809

    
810
void OPPROTO op_fmul8sux16(void)
811
{
812
    vis64 s, d;
813
    uint32_t tmp;
814

    
815
    s.d = DT0;
816
    d.d = DT1;
817

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

    
824
    PMUL(0);
825
    PMUL(1);
826
    PMUL(2);
827
    PMUL(3);
828
#undef PMUL
829

    
830
    DT0 = d.d;
831
}
832

    
833
void OPPROTO op_fmul8ulx16(void)
834
{
835
    vis64 s, d;
836
    uint32_t tmp;
837

    
838
    s.d = DT0;
839
    d.d = DT1;
840

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

    
847
    PMUL(0);
848
    PMUL(1);
849
    PMUL(2);
850
    PMUL(3);
851
#undef PMUL
852

    
853
    DT0 = d.d;
854
}
855

    
856
void OPPROTO op_fmuld8sux16(void)
857
{
858
    vis64 s, d;
859
    uint32_t tmp;
860

    
861
    s.d = DT0;
862
    d.d = DT1;
863

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

    
870
    // Reverse calculation order to handle overlap
871
    PMUL(1);
872
    PMUL(0);
873
#undef PMUL
874

    
875
    DT0 = d.d;
876
}
877

    
878
void OPPROTO op_fmuld8ulx16(void)
879
{
880
    vis64 s, d;
881
    uint32_t tmp;
882

    
883
    s.d = DT0;
884
    d.d = DT1;
885

    
886
#define PMUL(r)                                                         \
887
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
888
    if ((tmp & 0xff) > 0x7f)                                            \
889
        tmp += 0x100;                                                   \
890
    d.VIS_L64(r) = tmp;
891

    
892
    // Reverse calculation order to handle overlap
893
    PMUL(1);
894
    PMUL(0);
895
#undef PMUL
896

    
897
    DT0 = d.d;
898
}
899

    
900
void OPPROTO op_fexpand(void)
901
{
902
    vis32 s;
903
    vis64 d;
904

    
905
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
906
    d.d = DT1;
907
    d.VIS_L64(0) = s.VIS_W32(0) << 4;
908
    d.VIS_L64(1) = s.VIS_W32(1) << 4;
909
    d.VIS_L64(2) = s.VIS_W32(2) << 4;
910
    d.VIS_L64(3) = s.VIS_W32(3) << 4;
911

    
912
    DT0 = d.d;
913
}
914

    
915
#define VIS_OP(name, F)                                 \
916
    void OPPROTO name##16(void)                         \
917
    {                                                   \
918
        vis64 s, d;                                     \
919
                                                        \
920
        s.d = DT0;                                      \
921
        d.d = DT1;                                      \
922
                                                        \
923
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
924
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
925
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
926
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
927
                                                        \
928
        DT0 = d.d;                                      \
929
    }                                                   \
930
                                                        \
931
    void OPPROTO name##16s(void)                        \
932
    {                                                   \
933
        vis32 s, d;                                     \
934
                                                        \
935
        s.f = FT0;                                      \
936
        d.f = FT1;                                      \
937
                                                        \
938
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
939
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
940
                                                        \
941
        FT0 = d.f;                                      \
942
    }                                                   \
943
                                                        \
944
    void OPPROTO name##32(void)                         \
945
    {                                                   \
946
        vis64 s, d;                                     \
947
                                                        \
948
        s.d = DT0;                                      \
949
        d.d = DT1;                                      \
950
                                                        \
951
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
952
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
953
                                                        \
954
        DT0 = d.d;                                      \
955
    }                                                   \
956
                                                        \
957
    void OPPROTO name##32s(void)                        \
958
    {                                                   \
959
        vis32 s, d;                                     \
960
                                                        \
961
        s.f = FT0;                                      \
962
        d.f = FT1;                                      \
963
                                                        \
964
        d.l = F(d.l, s.l);                              \
965
                                                        \
966
        FT0 = d.f;                                      \
967
    }
968

    
969
#define FADD(a, b) ((a) + (b))
970
#define FSUB(a, b) ((a) - (b))
971
VIS_OP(op_fpadd, FADD)
972
VIS_OP(op_fpsub, FSUB)
973

    
974
#define VIS_CMPOP(name, F)                                        \
975
    void OPPROTO name##16(void)                                   \
976
    {                                                             \
977
        vis64 s, d;                                               \
978
                                                                  \
979
        s.d = DT0;                                                \
980
        d.d = DT1;                                                \
981
                                                                  \
982
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
983
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
984
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
985
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
986
                                                                  \
987
        DT0 = d.d;                                                \
988
    }                                                             \
989
                                                                  \
990
    void OPPROTO name##32(void)                                   \
991
    {                                                             \
992
        vis64 s, d;                                               \
993
                                                                  \
994
        s.d = DT0;                                                \
995
        d.d = DT1;                                                \
996
                                                                  \
997
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
998
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
999
                                                                  \
1000
        DT0 = d.d;                                                \
1001
    }
1002

    
1003
#define FCMPGT(a, b) ((a) > (b))
1004
#define FCMPEQ(a, b) ((a) == (b))
1005
#define FCMPLE(a, b) ((a) <= (b))
1006
#define FCMPNE(a, b) ((a) != (b))
1007

    
1008
VIS_CMPOP(op_fcmpgt, FCMPGT)
1009
VIS_CMPOP(op_fcmpeq, FCMPEQ)
1010
VIS_CMPOP(op_fcmple, FCMPLE)
1011
VIS_CMPOP(op_fcmpne, FCMPNE)
1012

    
1013
#endif
1014

    
1015
#define CHECK_ALIGN_OP(align)                           \
1016
    void OPPROTO op_check_align_T0_ ## align (void)     \
1017
    {                                                   \
1018
        if (T0 & align)                                 \
1019
            raise_exception(TT_UNALIGNED);              \
1020
        FORCE_RET();                                    \
1021
    }
1022

    
1023
CHECK_ALIGN_OP(1)
1024
CHECK_ALIGN_OP(3)
1025
CHECK_ALIGN_OP(7)