Statistics
| Branch: | Revision:

root / target-sparc / op.c @ 19f329ad

History | View | Annotate | Download (38.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_add_T1_T0_cc(void)
175
{
176
    target_ulong src1;
177

    
178
    src1 = T0;
179
    T0 += T1;
180
    env->psr = 0;
181
#ifdef TARGET_SPARC64
182
    if (!(T0 & 0xffffffff))
183
        env->psr |= PSR_ZERO;
184
    if ((int32_t) T0 < 0)
185
        env->psr |= PSR_NEG;
186
    if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
187
        env->psr |= PSR_CARRY;
188
    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
189
         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
190
        env->psr |= PSR_OVF;
191

    
192
    env->xcc = 0;
193
    if (!T0)
194
        env->xcc |= PSR_ZERO;
195
    if ((int64_t) T0 < 0)
196
        env->xcc |= PSR_NEG;
197
    if (T0 < src1)
198
        env->xcc |= PSR_CARRY;
199
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
200
        env->xcc |= PSR_OVF;
201
#else
202
    if (!T0)
203
        env->psr |= PSR_ZERO;
204
    if ((int32_t) T0 < 0)
205
        env->psr |= PSR_NEG;
206
    if (T0 < src1)
207
        env->psr |= PSR_CARRY;
208
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
209
        env->psr |= PSR_OVF;
210
#endif
211
    FORCE_RET();
212
}
213

    
214
void OPPROTO op_addx_T1_T0_cc(void)
215
{
216
    target_ulong src1;
217
    src1 = T0;
218
    if (FLAG_SET(PSR_CARRY))
219
    {
220
      T0 += T1 + 1;
221
      env->psr = 0;
222
#ifdef TARGET_SPARC64
223
      if ((T0 & 0xffffffff) <= (src1 & 0xffffffff))
224
        env->psr |= PSR_CARRY;
225
      env->xcc = 0;
226
      if (T0 <= src1)
227
        env->xcc |= PSR_CARRY;
228
#else
229
      if (T0 <= src1)
230
        env->psr |= PSR_CARRY;
231
#endif
232
    }
233
    else
234
    {
235
      T0 += T1;
236
      env->psr = 0;
237
#ifdef TARGET_SPARC64
238
      if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
239
        env->psr |= PSR_CARRY;
240
      env->xcc = 0;
241
      if (T0 < src1)
242
        env->xcc |= PSR_CARRY;
243
#else
244
      if (T0 < src1)
245
        env->psr |= PSR_CARRY;
246
#endif
247
    }
248
#ifdef TARGET_SPARC64
249
    if (!(T0 & 0xffffffff))
250
        env->psr |= PSR_ZERO;
251
    if ((int32_t) T0 < 0)
252
        env->psr |= PSR_NEG;
253
    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
254
         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
255
        env->psr |= PSR_OVF;
256

    
257
    if (!T0)
258
        env->xcc |= PSR_ZERO;
259
    if ((int64_t) T0 < 0)
260
        env->xcc |= PSR_NEG;
261
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
262
        env->xcc |= PSR_OVF;
263
#else
264
    if (!T0)
265
        env->psr |= PSR_ZERO;
266
    if ((int32_t) T0 < 0)
267
        env->psr |= PSR_NEG;
268
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
269
        env->psr |= PSR_OVF;
270
#endif
271
    FORCE_RET();
272
}
273

    
274
void OPPROTO op_tadd_T1_T0_cc(void)
275
{
276
    target_ulong src1;
277

    
278
    src1 = T0;
279
    T0 += T1;
280
    env->psr = 0;
281
#ifdef TARGET_SPARC64
282
    if (!(T0 & 0xffffffff))
283
        env->psr |= PSR_ZERO;
284
    if ((int32_t) T0 < 0)
285
        env->psr |= PSR_NEG;
286
    if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
287
        env->psr |= PSR_CARRY;
288
    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
289
         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
290
        env->psr |= PSR_OVF;
291
    if ((src1 & 0x03) || (T1 & 0x03))
292
        env->psr |= PSR_OVF;
293

    
294
    env->xcc = 0;
295
    if (!T0)
296
        env->xcc |= PSR_ZERO;
297
    if ((int64_t) T0 < 0)
298
        env->xcc |= PSR_NEG;
299
    if (T0 < src1)
300
        env->xcc |= PSR_CARRY;
301
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
302
        env->xcc |= PSR_OVF;
303
#else
304
    if (!T0)
305
        env->psr |= PSR_ZERO;
306
    if ((int32_t) T0 < 0)
307
        env->psr |= PSR_NEG;
308
    if (T0 < src1)
309
        env->psr |= PSR_CARRY;
310
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
311
        env->psr |= PSR_OVF;
312
    if ((src1 & 0x03) || (T1 & 0x03))
313
        env->psr |= PSR_OVF;
314
#endif
315
    FORCE_RET();
316
}
317

    
318
void OPPROTO op_tadd_T1_T0_ccTV(void)
319
{
320
    target_ulong src1;
321

    
322
    if ((T0 & 0x03) || (T1 & 0x03)) {
323
        raise_exception(TT_TOVF);
324
        FORCE_RET();
325
        return;
326
    }
327

    
328
    src1 = T0;
329
    T0 += T1;
330

    
331
#ifdef TARGET_SPARC64
332
    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
333
         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
334
        raise_exception(TT_TOVF);
335
#else
336
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
337
        raise_exception(TT_TOVF);
338
#endif
339

    
340
    env->psr = 0;
341
#ifdef TARGET_SPARC64
342
    if (!(T0 & 0xffffffff))
343
        env->psr |= PSR_ZERO;
344
    if ((int32_t) T0 < 0)
345
        env->psr |= PSR_NEG;
346
    if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
347
        env->psr |= PSR_CARRY;
348

    
349
    env->xcc = 0;
350
    if (!T0)
351
        env->xcc |= PSR_ZERO;
352
    if ((int64_t) T0 < 0)
353
        env->xcc |= PSR_NEG;
354
    if (T0 < src1)
355
        env->xcc |= PSR_CARRY;
356
#else
357
    if (!T0)
358
        env->psr |= PSR_ZERO;
359
    if ((int32_t) T0 < 0)
360
        env->psr |= PSR_NEG;
361
    if (T0 < src1)
362
        env->psr |= PSR_CARRY;
363
#endif
364
    FORCE_RET();
365
}
366

    
367
void OPPROTO op_sub_T1_T0_cc(void)
368
{
369
    target_ulong src1;
370

    
371
    src1 = T0;
372
    T0 -= T1;
373
    env->psr = 0;
374
#ifdef TARGET_SPARC64
375
    if (!(T0 & 0xffffffff))
376
        env->psr |= PSR_ZERO;
377
    if ((int32_t) T0 < 0)
378
        env->psr |= PSR_NEG;
379
    if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
380
        env->psr |= PSR_CARRY;
381
    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
382
         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
383
        env->psr |= PSR_OVF;
384

    
385
    env->xcc = 0;
386
    if (!T0)
387
        env->xcc |= PSR_ZERO;
388
    if ((int64_t) T0 < 0)
389
        env->xcc |= PSR_NEG;
390
    if (src1 < T1)
391
        env->xcc |= PSR_CARRY;
392
    if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
393
        env->xcc |= PSR_OVF;
394
#else
395
    if (!T0)
396
        env->psr |= PSR_ZERO;
397
    if ((int32_t) T0 < 0)
398
        env->psr |= PSR_NEG;
399
    if (src1 < T1)
400
        env->psr |= PSR_CARRY;
401
    if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
402
        env->psr |= PSR_OVF;
403
#endif
404
    FORCE_RET();
405
}
406

    
407
void OPPROTO op_subx_T1_T0_cc(void)
408
{
409
    target_ulong src1;
410
    src1 = T0;
411
    if (FLAG_SET(PSR_CARRY))
412
    {
413
      T0 -= T1 + 1;
414
      env->psr = 0;
415
#ifdef TARGET_SPARC64
416
      if ((src1 & 0xffffffff) <= (T1 & 0xffffffff))
417
        env->psr |= PSR_CARRY;
418
      env->xcc = 0;
419
      if (src1 <= T1)
420
        env->xcc |= PSR_CARRY;
421
#else
422
      if (src1 <= T1)
423
        env->psr |= PSR_CARRY;
424
#endif
425
    }
426
    else
427
    {
428
      T0 -= T1;
429
      env->psr = 0;
430
#ifdef TARGET_SPARC64
431
      if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
432
        env->psr |= PSR_CARRY;
433
      env->xcc = 0;
434
      if (src1 < T1)
435
        env->xcc |= PSR_CARRY;
436
#else
437
      if (src1 < T1)
438
        env->psr |= PSR_CARRY;
439
#endif
440
    }
441
#ifdef TARGET_SPARC64
442
    if (!(T0 & 0xffffffff))
443
        env->psr |= PSR_ZERO;
444
    if ((int32_t) T0 < 0)
445
        env->psr |= PSR_NEG;
446
    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
447
         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
448
        env->psr |= PSR_OVF;
449

    
450
    if (!T0)
451
        env->xcc |= PSR_ZERO;
452
    if ((int64_t) T0 < 0)
453
        env->xcc |= PSR_NEG;
454
    if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
455
        env->xcc |= PSR_OVF;
456
#else
457
    if (!T0)
458
        env->psr |= PSR_ZERO;
459
    if ((int32_t) T0 < 0)
460
        env->psr |= PSR_NEG;
461
    if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
462
        env->psr |= PSR_OVF;
463
#endif
464
    FORCE_RET();
465
}
466

    
467
void OPPROTO op_tsub_T1_T0_cc(void)
468
{
469
    target_ulong src1;
470

    
471
    src1 = T0;
472
    T0 -= T1;
473
    env->psr = 0;
474
#ifdef TARGET_SPARC64
475
    if (!(T0 & 0xffffffff))
476
        env->psr |= PSR_ZERO;
477
    if ((int32_t) T0 < 0)
478
        env->psr |= PSR_NEG;
479
    if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
480
        env->psr |= PSR_CARRY;
481
    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
482
         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
483
        env->psr |= PSR_OVF;
484
    if ((src1 & 0x03) || (T1 & 0x03))
485
        env->psr |= PSR_OVF;
486

    
487
    env->xcc = 0;
488
    if (!T0)
489
        env->xcc |= PSR_ZERO;
490
    if ((int64_t) T0 < 0)
491
        env->xcc |= PSR_NEG;
492
    if (src1 < T1)
493
        env->xcc |= PSR_CARRY;
494
    if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
495
        env->xcc |= PSR_OVF;
496
#else
497
    if (!T0)
498
        env->psr |= PSR_ZERO;
499
    if ((int32_t) T0 < 0)
500
        env->psr |= PSR_NEG;
501
    if (src1 < T1)
502
        env->psr |= PSR_CARRY;
503
    if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
504
        env->psr |= PSR_OVF;
505
    if ((src1 & 0x03) || (T1 & 0x03))
506
        env->psr |= PSR_OVF;
507
#endif
508
    FORCE_RET();
509
}
510

    
511
void OPPROTO op_tsub_T1_T0_ccTV(void)
512
{
513
    target_ulong src1;
514

    
515
    if ((T0 & 0x03) || (T1 & 0x03))
516
        raise_exception(TT_TOVF);
517

    
518
    src1 = T0;
519
    T0 -= T1;
520

    
521
#ifdef TARGET_SPARC64
522
    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
523
         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
524
        raise_exception(TT_TOVF);
525
#else
526
    if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
527
        raise_exception(TT_TOVF);
528
#endif
529

    
530
    env->psr = 0;
531
#ifdef TARGET_SPARC64
532
    if (!(T0 & 0xffffffff))
533
        env->psr |= PSR_ZERO;
534
    if ((int32_t) T0 < 0)
535
        env->psr |= PSR_NEG;
536
    if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
537
        env->psr |= PSR_CARRY;
538

    
539
    env->xcc = 0;
540
    if (!T0)
541
        env->xcc |= PSR_ZERO;
542
    if ((int64_t) T0 < 0)
543
        env->xcc |= PSR_NEG;
544
    if (src1 < T1)
545
        env->xcc |= PSR_CARRY;
546
#else
547
    if (!T0)
548
        env->psr |= PSR_ZERO;
549
    if ((int32_t) T0 < 0)
550
        env->psr |= PSR_NEG;
551
    if (src1 < T1)
552
        env->psr |= PSR_CARRY;
553
#endif
554
    FORCE_RET();
555
}
556

    
557
void OPPROTO op_andn_T1_T0(void)
558
{
559
    T0 &= ~T1;
560
}
561

    
562
void OPPROTO op_orn_T1_T0(void)
563
{
564
    T0 |= ~T1;
565
}
566

    
567
void OPPROTO op_xnor_T1_T0(void)
568
{
569
    T0 ^= ~T1;
570
}
571

    
572
void OPPROTO op_umul_T1_T0(void)
573
{
574
    uint64_t res;
575
    res = (uint64_t) T0 * (uint64_t) T1;
576
#ifdef TARGET_SPARC64
577
    T0 = res;
578
#else
579
    T0 = res & 0xffffffff;
580
#endif
581
    env->y = res >> 32;
582
}
583

    
584
void OPPROTO op_smul_T1_T0(void)
585
{
586
    uint64_t res;
587
    res = (int64_t) ((int32_t) T0) * (int64_t) ((int32_t) T1);
588
#ifdef TARGET_SPARC64
589
    T0 = res;
590
#else
591
    T0 = res & 0xffffffff;
592
#endif
593
    env->y = res >> 32;
594
}
595

    
596
void OPPROTO op_mulscc_T1_T0(void)
597
{
598
    unsigned int b1, N, V, b2;
599
    target_ulong src1;
600

    
601
    N = FLAG_SET(PSR_NEG);
602
    V = FLAG_SET(PSR_OVF);
603
    b1 = N ^ V;
604
    b2 = T0 & 1;
605
    T0 = (b1 << 31) | (T0 >> 1);
606
    if (!(env->y & 1))
607
        T1 = 0;
608
    /* do addition and update flags */
609
    src1 = T0;
610
    T0 += T1;
611
    env->psr = 0;
612
    if (!T0)
613
        env->psr |= PSR_ZERO;
614
    if ((int32_t) T0 < 0)
615
        env->psr |= PSR_NEG;
616
    if (T0 < src1)
617
        env->psr |= PSR_CARRY;
618
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
619
        env->psr |= PSR_OVF;
620
    env->y = (b2 << 31) | (env->y >> 1);
621
    FORCE_RET();
622
}
623

    
624
void OPPROTO op_udiv_T1_T0(void)
625
{
626
    uint64_t x0;
627
    uint32_t x1;
628

    
629
    x0 = T0 | ((uint64_t) (env->y) << 32);
630
    x1 = T1;
631

    
632
    if (x1 == 0) {
633
        raise_exception(TT_DIV_ZERO);
634
    }
635

    
636
    x0 = x0 / x1;
637
    if (x0 > 0xffffffff) {
638
        T0 = 0xffffffff;
639
        T1 = 1;
640
    } else {
641
        T0 = x0;
642
        T1 = 0;
643
    }
644
    FORCE_RET();
645
}
646

    
647
void OPPROTO op_sdiv_T1_T0(void)
648
{
649
    int64_t x0;
650
    int32_t x1;
651

    
652
    x0 = T0 | ((int64_t) (env->y) << 32);
653
    x1 = T1;
654

    
655
    if (x1 == 0) {
656
        raise_exception(TT_DIV_ZERO);
657
    }
658

    
659
    x0 = x0 / x1;
660
    if ((int32_t) x0 != x0) {
661
        T0 = x0 < 0? 0x80000000: 0x7fffffff;
662
        T1 = 1;
663
    } else {
664
        T0 = x0;
665
        T1 = 0;
666
    }
667
    FORCE_RET();
668
}
669

    
670
void OPPROTO op_div_cc(void)
671
{
672
    env->psr = 0;
673
#ifdef TARGET_SPARC64
674
    if (!T0)
675
        env->psr |= PSR_ZERO;
676
    if ((int32_t) T0 < 0)
677
        env->psr |= PSR_NEG;
678
    if (T1)
679
        env->psr |= PSR_OVF;
680

    
681
    env->xcc = 0;
682
    if (!T0)
683
        env->xcc |= PSR_ZERO;
684
    if ((int64_t) T0 < 0)
685
        env->xcc |= PSR_NEG;
686
#else
687
    if (!T0)
688
        env->psr |= PSR_ZERO;
689
    if ((int32_t) T0 < 0)
690
        env->psr |= PSR_NEG;
691
    if (T1)
692
        env->psr |= PSR_OVF;
693
#endif
694
    FORCE_RET();
695
}
696

    
697
#ifdef TARGET_SPARC64
698
void OPPROTO op_udivx_T1_T0(void)
699
{
700
    if (T1 == 0) {
701
        raise_exception(TT_DIV_ZERO);
702
    }
703
    T0 /= T1;
704
    FORCE_RET();
705
}
706

    
707
void OPPROTO op_sdivx_T1_T0(void)
708
{
709
    if (T1 == 0) {
710
        raise_exception(TT_DIV_ZERO);
711
    }
712
    if (T0 == INT64_MIN && T1 == -1)
713
        T0 = INT64_MIN;
714
    else
715
        T0 /= (target_long) T1;
716
    FORCE_RET();
717
}
718
#endif
719

    
720
void OPPROTO op_logic_T0_cc(void)
721
{
722
    env->psr = 0;
723
#ifdef TARGET_SPARC64
724
    if (!(T0 & 0xffffffff))
725
        env->psr |= PSR_ZERO;
726
    if ((int32_t) T0 < 0)
727
        env->psr |= PSR_NEG;
728

    
729
    env->xcc = 0;
730
    if (!T0)
731
        env->xcc |= PSR_ZERO;
732
    if ((int64_t) T0 < 0)
733
        env->xcc |= PSR_NEG;
734
#else
735
    if (!T0)
736
        env->psr |= PSR_ZERO;
737
    if ((int32_t) T0 < 0)
738
        env->psr |= PSR_NEG;
739
#endif
740
    FORCE_RET();
741
}
742

    
743
/* Load and store */
744
#define MEMSUFFIX _raw
745
#include "op_mem.h"
746
#if !defined(CONFIG_USER_ONLY)
747
#define MEMSUFFIX _user
748
#include "op_mem.h"
749

    
750
#define MEMSUFFIX _kernel
751
#include "op_mem.h"
752

    
753
#ifdef TARGET_SPARC64
754
#define MEMSUFFIX _hypv
755
#include "op_mem.h"
756
#endif
757
#endif
758

    
759
void OPPROTO op_ldfsr(void)
760
{
761
    PUT_FSR32(env, *((uint32_t *) &FT0));
762
}
763

    
764
void OPPROTO op_stfsr(void)
765
{
766
    *((uint32_t *) &FT0) = GET_FSR32(env);
767
}
768

    
769
#ifndef TARGET_SPARC64
770
/* XXX: use another pointer for %iN registers to avoid slow wrapping
771
   handling ? */
772
void OPPROTO op_save(void)
773
{
774
    uint32_t cwp;
775
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
776
    if (env->wim & (1 << cwp)) {
777
        raise_exception(TT_WIN_OVF);
778
    }
779
    set_cwp(cwp);
780
    FORCE_RET();
781
}
782

    
783
void OPPROTO op_restore(void)
784
{
785
    uint32_t cwp;
786
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
787
    if (env->wim & (1 << cwp)) {
788
        raise_exception(TT_WIN_UNF);
789
    }
790
    set_cwp(cwp);
791
    FORCE_RET();
792
}
793
#else
794
void OPPROTO op_rdccr(void)
795
{
796
    T0 = GET_CCR(env);
797
}
798

    
799
void OPPROTO op_wrccr(void)
800
{
801
    PUT_CCR(env, T0);
802
}
803

    
804
// CWP handling is reversed in V9, but we still use the V8 register
805
// order.
806
void OPPROTO op_rdcwp(void)
807
{
808
    T0 = GET_CWP64(env);
809
}
810

    
811
void OPPROTO op_wrcwp(void)
812
{
813
    PUT_CWP64(env, T0);
814
}
815

    
816
/* XXX: use another pointer for %iN registers to avoid slow wrapping
817
   handling ? */
818
void OPPROTO op_save(void)
819
{
820
    uint32_t cwp;
821
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
822
    if (env->cansave == 0) {
823
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
824
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
825
                                    ((env->wstate & 0x7) << 2)));
826
    } else {
827
        if (env->cleanwin - env->canrestore == 0) {
828
            // XXX Clean windows without trap
829
            raise_exception(TT_CLRWIN);
830
        } else {
831
            env->cansave--;
832
            env->canrestore++;
833
            set_cwp(cwp);
834
        }
835
    }
836
    FORCE_RET();
837
}
838

    
839
void OPPROTO op_restore(void)
840
{
841
    uint32_t cwp;
842
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
843
    if (env->canrestore == 0) {
844
        raise_exception(TT_FILL | (env->otherwin != 0 ?
845
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
846
                                   ((env->wstate & 0x7) << 2)));
847
    } else {
848
        env->cansave++;
849
        env->canrestore--;
850
        set_cwp(cwp);
851
    }
852
    FORCE_RET();
853
}
854
#endif
855

    
856
void OPPROTO op_jmp_label(void)
857
{
858
    GOTO_LABEL_PARAM(1);
859
}
860

    
861
#define F_OP(name, p) void OPPROTO op_f##name##p(void)
862

    
863
#if defined(CONFIG_USER_ONLY)
864
#define F_BINOP(name)                                           \
865
    F_OP(name, s)                                               \
866
    {                                                           \
867
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
868
    }                                                           \
869
    F_OP(name, d)                                               \
870
    {                                                           \
871
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
872
    }                                                           \
873
    F_OP(name, q)                                               \
874
    {                                                           \
875
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
876
    }
877
#else
878
#define F_BINOP(name)                                           \
879
    F_OP(name, s)                                               \
880
    {                                                           \
881
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
882
    }                                                           \
883
    F_OP(name, d)                                               \
884
    {                                                           \
885
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
886
    }
887
#endif
888

    
889
F_BINOP(add);
890
F_BINOP(sub);
891
F_BINOP(mul);
892
F_BINOP(div);
893
#undef F_BINOP
894

    
895
void OPPROTO op_fsmuld(void)
896
{
897
    DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
898
                      float32_to_float64(FT1, &env->fp_status),
899
                      &env->fp_status);
900
}
901

    
902
#if defined(CONFIG_USER_ONLY)
903
void OPPROTO op_fdmulq(void)
904
{
905
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
906
                       float64_to_float128(DT1, &env->fp_status),
907
                       &env->fp_status);
908
}
909
#endif
910

    
911
#if defined(CONFIG_USER_ONLY)
912
#define F_HELPER(name)    \
913
    F_OP(name, s)         \
914
    {                     \
915
        do_f##name##s();  \
916
    }                     \
917
    F_OP(name, d)         \
918
    {                     \
919
        do_f##name##d();  \
920
    }                     \
921
    F_OP(name, q)         \
922
    {                     \
923
        do_f##name##q();  \
924
    }
925
#else
926
#define F_HELPER(name)    \
927
    F_OP(name, s)         \
928
    {                     \
929
        do_f##name##s();  \
930
    }                     \
931
    F_OP(name, d)         \
932
    {                     \
933
        do_f##name##d();  \
934
    }
935
#endif
936

    
937
F_OP(neg, s)
938
{
939
    FT0 = float32_chs(FT1);
940
}
941

    
942
#ifdef TARGET_SPARC64
943
F_OP(neg, d)
944
{
945
    DT0 = float64_chs(DT1);
946
}
947

    
948
#if defined(CONFIG_USER_ONLY)
949
F_OP(neg, q)
950
{
951
    QT0 = float128_chs(QT1);
952
}
953

    
954
#endif
955

    
956
#endif
957

    
958
/* Integer to float conversion.  */
959
#ifdef USE_INT_TO_FLOAT_HELPERS
960
F_HELPER(ito);
961
#ifdef TARGET_SPARC64
962
F_HELPER(xto);
963
#endif
964
#else
965
F_OP(ito, s)
966
{
967
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
968
}
969

    
970
F_OP(ito, d)
971
{
972
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
973
}
974

    
975
#if defined(CONFIG_USER_ONLY)
976
F_OP(ito, q)
977
{
978
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
979
}
980
#endif
981

    
982
#ifdef TARGET_SPARC64
983
F_OP(xto, s)
984
{
985
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
986
}
987

    
988
F_OP(xto, d)
989
{
990
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
991
}
992
#if defined(CONFIG_USER_ONLY)
993
F_OP(xto, q)
994
{
995
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
996
}
997
#endif
998
#endif
999
#endif
1000
#undef F_HELPER
1001

    
1002
/* floating point conversion */
1003
void OPPROTO op_fdtos(void)
1004
{
1005
    FT0 = float64_to_float32(DT1, &env->fp_status);
1006
}
1007

    
1008
void OPPROTO op_fstod(void)
1009
{
1010
    DT0 = float32_to_float64(FT1, &env->fp_status);
1011
}
1012

    
1013
#if defined(CONFIG_USER_ONLY)
1014
void OPPROTO op_fqtos(void)
1015
{
1016
    FT0 = float128_to_float32(QT1, &env->fp_status);
1017
}
1018

    
1019
void OPPROTO op_fstoq(void)
1020
{
1021
    QT0 = float32_to_float128(FT1, &env->fp_status);
1022
}
1023

    
1024
void OPPROTO op_fqtod(void)
1025
{
1026
    DT0 = float128_to_float64(QT1, &env->fp_status);
1027
}
1028

    
1029
void OPPROTO op_fdtoq(void)
1030
{
1031
    QT0 = float64_to_float128(DT1, &env->fp_status);
1032
}
1033
#endif
1034

    
1035
/* Float to integer conversion.  */
1036
void OPPROTO op_fstoi(void)
1037
{
1038
    *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
1039
}
1040

    
1041
void OPPROTO op_fdtoi(void)
1042
{
1043
    *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
1044
}
1045

    
1046
#if defined(CONFIG_USER_ONLY)
1047
void OPPROTO op_fqtoi(void)
1048
{
1049
    *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
1050
}
1051
#endif
1052

    
1053
#ifdef TARGET_SPARC64
1054
void OPPROTO op_fstox(void)
1055
{
1056
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
1057
}
1058

    
1059
void OPPROTO op_fdtox(void)
1060
{
1061
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
1062
}
1063

    
1064
#if defined(CONFIG_USER_ONLY)
1065
void OPPROTO op_fqtox(void)
1066
{
1067
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
1068
}
1069
#endif
1070

    
1071
void OPPROTO op_flushw(void)
1072
{
1073
    if (env->cansave != NWINDOWS - 2) {
1074
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
1075
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
1076
                                    ((env->wstate & 0x7) << 2)));
1077
    }
1078
}
1079

    
1080
void OPPROTO op_saved(void)
1081
{
1082
    env->cansave++;
1083
    if (env->otherwin == 0)
1084
        env->canrestore--;
1085
    else
1086
        env->otherwin--;
1087
    FORCE_RET();
1088
}
1089

    
1090
void OPPROTO op_restored(void)
1091
{
1092
    env->canrestore++;
1093
    if (env->cleanwin < NWINDOWS - 1)
1094
        env->cleanwin++;
1095
    if (env->otherwin == 0)
1096
        env->cansave--;
1097
    else
1098
        env->otherwin--;
1099
    FORCE_RET();
1100
}
1101
#endif
1102

    
1103
#ifdef TARGET_SPARC64
1104
// This function uses non-native bit order
1105
#define GET_FIELD(X, FROM, TO)                                  \
1106
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
1107

    
1108
// This function uses the order in the manuals, i.e. bit 0 is 2^0
1109
#define GET_FIELD_SP(X, FROM, TO)               \
1110
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
1111

    
1112
void OPPROTO op_array8()
1113
{
1114
    T0 = (GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
1115
        (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
1116
        (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
1117
        (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
1118
        (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
1119
        (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12);
1120
}
1121

    
1122
void OPPROTO op_array16()
1123
{
1124
    T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
1125
          (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
1126
          (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
1127
          (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
1128
          (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
1129
          (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 1;
1130
}
1131

    
1132
void OPPROTO op_array32()
1133
{
1134
    T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
1135
          (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
1136
          (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
1137
          (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
1138
          (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
1139
          (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 2;
1140
}
1141

    
1142
void OPPROTO op_alignaddr()
1143
{
1144
    uint64_t tmp;
1145

    
1146
    tmp = T0 + T1;
1147
    env->gsr &= ~7ULL;
1148
    env->gsr |= tmp & 7ULL;
1149
    T0 = tmp & ~7ULL;
1150
}
1151

    
1152
void OPPROTO op_faligndata()
1153
{
1154
    uint64_t tmp;
1155

    
1156
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
1157
    tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
1158
    *((uint64_t *)&DT0) = tmp;
1159
}
1160

    
1161
void OPPROTO op_movl_FT0_0(void)
1162
{
1163
    *((uint32_t *)&FT0) = 0;
1164
}
1165

    
1166
void OPPROTO op_movl_DT0_0(void)
1167
{
1168
    *((uint64_t *)&DT0) = 0;
1169
}
1170

    
1171
void OPPROTO op_movl_FT0_1(void)
1172
{
1173
    *((uint32_t *)&FT0) = 0xffffffff;
1174
}
1175

    
1176
void OPPROTO op_movl_DT0_1(void)
1177
{
1178
    *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
1179
}
1180

    
1181
void OPPROTO op_fnot(void)
1182
{
1183
    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
1184
}
1185

    
1186
void OPPROTO op_fnots(void)
1187
{
1188
    *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
1189
}
1190

    
1191
void OPPROTO op_fnor(void)
1192
{
1193
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
1194
}
1195

    
1196
void OPPROTO op_fnors(void)
1197
{
1198
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
1199
}
1200

    
1201
void OPPROTO op_for(void)
1202
{
1203
    *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
1204
}
1205

    
1206
void OPPROTO op_fors(void)
1207
{
1208
    *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
1209
}
1210

    
1211
void OPPROTO op_fxor(void)
1212
{
1213
    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
1214
}
1215

    
1216
void OPPROTO op_fxors(void)
1217
{
1218
    *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
1219
}
1220

    
1221
void OPPROTO op_fand(void)
1222
{
1223
    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
1224
}
1225

    
1226
void OPPROTO op_fands(void)
1227
{
1228
    *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
1229
}
1230

    
1231
void OPPROTO op_fornot(void)
1232
{
1233
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
1234
}
1235

    
1236
void OPPROTO op_fornots(void)
1237
{
1238
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
1239
}
1240

    
1241
void OPPROTO op_fandnot(void)
1242
{
1243
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
1244
}
1245

    
1246
void OPPROTO op_fandnots(void)
1247
{
1248
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
1249
}
1250

    
1251
void OPPROTO op_fnand(void)
1252
{
1253
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
1254
}
1255

    
1256
void OPPROTO op_fnands(void)
1257
{
1258
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
1259
}
1260

    
1261
void OPPROTO op_fxnor(void)
1262
{
1263
    *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
1264
}
1265

    
1266
void OPPROTO op_fxnors(void)
1267
{
1268
    *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
1269
}
1270

    
1271
#ifdef WORDS_BIGENDIAN
1272
#define VIS_B64(n) b[7 - (n)]
1273
#define VIS_W64(n) w[3 - (n)]
1274
#define VIS_SW64(n) sw[3 - (n)]
1275
#define VIS_L64(n) l[1 - (n)]
1276
#define VIS_B32(n) b[3 - (n)]
1277
#define VIS_W32(n) w[1 - (n)]
1278
#else
1279
#define VIS_B64(n) b[n]
1280
#define VIS_W64(n) w[n]
1281
#define VIS_SW64(n) sw[n]
1282
#define VIS_L64(n) l[n]
1283
#define VIS_B32(n) b[n]
1284
#define VIS_W32(n) w[n]
1285
#endif
1286

    
1287
typedef union {
1288
    uint8_t b[8];
1289
    uint16_t w[4];
1290
    int16_t sw[4];
1291
    uint32_t l[2];
1292
    float64 d;
1293
} vis64;
1294

    
1295
typedef union {
1296
    uint8_t b[4];
1297
    uint16_t w[2];
1298
    uint32_t l;
1299
    float32 f;
1300
} vis32;
1301

    
1302
void OPPROTO op_fpmerge(void)
1303
{
1304
    vis64 s, d;
1305

    
1306
    s.d = DT0;
1307
    d.d = DT1;
1308

    
1309
    // Reverse calculation order to handle overlap
1310
    d.VIS_B64(7) = s.VIS_B64(3);
1311
    d.VIS_B64(6) = d.VIS_B64(3);
1312
    d.VIS_B64(5) = s.VIS_B64(2);
1313
    d.VIS_B64(4) = d.VIS_B64(2);
1314
    d.VIS_B64(3) = s.VIS_B64(1);
1315
    d.VIS_B64(2) = d.VIS_B64(1);
1316
    d.VIS_B64(1) = s.VIS_B64(0);
1317
    //d.VIS_B64(0) = d.VIS_B64(0);
1318

    
1319
    DT0 = d.d;
1320
}
1321

    
1322
void OPPROTO op_fmul8x16(void)
1323
{
1324
    vis64 s, d;
1325
    uint32_t tmp;
1326

    
1327
    s.d = DT0;
1328
    d.d = DT1;
1329

    
1330
#define PMUL(r)                                                 \
1331
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
1332
    if ((tmp & 0xff) > 0x7f)                                    \
1333
        tmp += 0x100;                                           \
1334
    d.VIS_W64(r) = tmp >> 8;
1335

    
1336
    PMUL(0);
1337
    PMUL(1);
1338
    PMUL(2);
1339
    PMUL(3);
1340
#undef PMUL
1341

    
1342
    DT0 = d.d;
1343
}
1344

    
1345
void OPPROTO op_fmul8x16al(void)
1346
{
1347
    vis64 s, d;
1348
    uint32_t tmp;
1349

    
1350
    s.d = DT0;
1351
    d.d = DT1;
1352

    
1353
#define PMUL(r)                                                 \
1354
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
1355
    if ((tmp & 0xff) > 0x7f)                                    \
1356
        tmp += 0x100;                                           \
1357
    d.VIS_W64(r) = tmp >> 8;
1358

    
1359
    PMUL(0);
1360
    PMUL(1);
1361
    PMUL(2);
1362
    PMUL(3);
1363
#undef PMUL
1364

    
1365
    DT0 = d.d;
1366
}
1367

    
1368
void OPPROTO op_fmul8x16au(void)
1369
{
1370
    vis64 s, d;
1371
    uint32_t tmp;
1372

    
1373
    s.d = DT0;
1374
    d.d = DT1;
1375

    
1376
#define PMUL(r)                                                 \
1377
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
1378
    if ((tmp & 0xff) > 0x7f)                                    \
1379
        tmp += 0x100;                                           \
1380
    d.VIS_W64(r) = tmp >> 8;
1381

    
1382
    PMUL(0);
1383
    PMUL(1);
1384
    PMUL(2);
1385
    PMUL(3);
1386
#undef PMUL
1387

    
1388
    DT0 = d.d;
1389
}
1390

    
1391
void OPPROTO op_fmul8sux16(void)
1392
{
1393
    vis64 s, d;
1394
    uint32_t tmp;
1395

    
1396
    s.d = DT0;
1397
    d.d = DT1;
1398

    
1399
#define PMUL(r)                                                         \
1400
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
1401
    if ((tmp & 0xff) > 0x7f)                                            \
1402
        tmp += 0x100;                                                   \
1403
    d.VIS_W64(r) = tmp >> 8;
1404

    
1405
    PMUL(0);
1406
    PMUL(1);
1407
    PMUL(2);
1408
    PMUL(3);
1409
#undef PMUL
1410

    
1411
    DT0 = d.d;
1412
}
1413

    
1414
void OPPROTO op_fmul8ulx16(void)
1415
{
1416
    vis64 s, d;
1417
    uint32_t tmp;
1418

    
1419
    s.d = DT0;
1420
    d.d = DT1;
1421

    
1422
#define PMUL(r)                                                         \
1423
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
1424
    if ((tmp & 0xff) > 0x7f)                                            \
1425
        tmp += 0x100;                                                   \
1426
    d.VIS_W64(r) = tmp >> 8;
1427

    
1428
    PMUL(0);
1429
    PMUL(1);
1430
    PMUL(2);
1431
    PMUL(3);
1432
#undef PMUL
1433

    
1434
    DT0 = d.d;
1435
}
1436

    
1437
void OPPROTO op_fmuld8sux16(void)
1438
{
1439
    vis64 s, d;
1440
    uint32_t tmp;
1441

    
1442
    s.d = DT0;
1443
    d.d = DT1;
1444

    
1445
#define PMUL(r)                                                         \
1446
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
1447
    if ((tmp & 0xff) > 0x7f)                                            \
1448
        tmp += 0x100;                                                   \
1449
    d.VIS_L64(r) = tmp;
1450

    
1451
    // Reverse calculation order to handle overlap
1452
    PMUL(1);
1453
    PMUL(0);
1454
#undef PMUL
1455

    
1456
    DT0 = d.d;
1457
}
1458

    
1459
void OPPROTO op_fmuld8ulx16(void)
1460
{
1461
    vis64 s, d;
1462
    uint32_t tmp;
1463

    
1464
    s.d = DT0;
1465
    d.d = DT1;
1466

    
1467
#define PMUL(r)                                                         \
1468
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
1469
    if ((tmp & 0xff) > 0x7f)                                            \
1470
        tmp += 0x100;                                                   \
1471
    d.VIS_L64(r) = tmp;
1472

    
1473
    // Reverse calculation order to handle overlap
1474
    PMUL(1);
1475
    PMUL(0);
1476
#undef PMUL
1477

    
1478
    DT0 = d.d;
1479
}
1480

    
1481
void OPPROTO op_fexpand(void)
1482
{
1483
    vis32 s;
1484
    vis64 d;
1485

    
1486
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
1487
    d.d = DT1;
1488
    d.VIS_L64(0) = s.VIS_W32(0) << 4;
1489
    d.VIS_L64(1) = s.VIS_W32(1) << 4;
1490
    d.VIS_L64(2) = s.VIS_W32(2) << 4;
1491
    d.VIS_L64(3) = s.VIS_W32(3) << 4;
1492

    
1493
    DT0 = d.d;
1494
}
1495

    
1496
#define VIS_OP(name, F)                                 \
1497
    void OPPROTO name##16(void)                         \
1498
    {                                                   \
1499
        vis64 s, d;                                     \
1500
                                                        \
1501
        s.d = DT0;                                      \
1502
        d.d = DT1;                                      \
1503
                                                        \
1504
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
1505
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
1506
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
1507
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
1508
                                                        \
1509
        DT0 = d.d;                                      \
1510
    }                                                   \
1511
                                                        \
1512
    void OPPROTO name##16s(void)                        \
1513
    {                                                   \
1514
        vis32 s, d;                                     \
1515
                                                        \
1516
        s.f = FT0;                                      \
1517
        d.f = FT1;                                      \
1518
                                                        \
1519
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
1520
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
1521
                                                        \
1522
        FT0 = d.f;                                      \
1523
    }                                                   \
1524
                                                        \
1525
    void OPPROTO name##32(void)                         \
1526
    {                                                   \
1527
        vis64 s, d;                                     \
1528
                                                        \
1529
        s.d = DT0;                                      \
1530
        d.d = DT1;                                      \
1531
                                                        \
1532
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
1533
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
1534
                                                        \
1535
        DT0 = d.d;                                      \
1536
    }                                                   \
1537
                                                        \
1538
    void OPPROTO name##32s(void)                        \
1539
    {                                                   \
1540
        vis32 s, d;                                     \
1541
                                                        \
1542
        s.f = FT0;                                      \
1543
        d.f = FT1;                                      \
1544
                                                        \
1545
        d.l = F(d.l, s.l);                              \
1546
                                                        \
1547
        FT0 = d.f;                                      \
1548
    }
1549

    
1550
#define FADD(a, b) ((a) + (b))
1551
#define FSUB(a, b) ((a) - (b))
1552
VIS_OP(op_fpadd, FADD)
1553
VIS_OP(op_fpsub, FSUB)
1554

    
1555
#define VIS_CMPOP(name, F)                                        \
1556
    void OPPROTO name##16(void)                                   \
1557
    {                                                             \
1558
        vis64 s, d;                                               \
1559
                                                                  \
1560
        s.d = DT0;                                                \
1561
        d.d = DT1;                                                \
1562
                                                                  \
1563
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
1564
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
1565
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
1566
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
1567
                                                                  \
1568
        DT0 = d.d;                                                \
1569
    }                                                             \
1570
                                                                  \
1571
    void OPPROTO name##32(void)                                   \
1572
    {                                                             \
1573
        vis64 s, d;                                               \
1574
                                                                  \
1575
        s.d = DT0;                                                \
1576
        d.d = DT1;                                                \
1577
                                                                  \
1578
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
1579
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
1580
                                                                  \
1581
        DT0 = d.d;                                                \
1582
    }
1583

    
1584
#define FCMPGT(a, b) ((a) > (b))
1585
#define FCMPEQ(a, b) ((a) == (b))
1586
#define FCMPLE(a, b) ((a) <= (b))
1587
#define FCMPNE(a, b) ((a) != (b))
1588

    
1589
VIS_CMPOP(op_fcmpgt, FCMPGT)
1590
VIS_CMPOP(op_fcmpeq, FCMPEQ)
1591
VIS_CMPOP(op_fcmple, FCMPLE)
1592
VIS_CMPOP(op_fcmpne, FCMPNE)
1593

    
1594
#endif
1595

    
1596
#define CHECK_ALIGN_OP(align)                           \
1597
    void OPPROTO op_check_align_T0_ ## align (void)     \
1598
    {                                                   \
1599
        if (T0 & align)                                 \
1600
            raise_exception(TT_UNALIGNED);              \
1601
        FORCE_RET();                                    \
1602
    }
1603

    
1604
CHECK_ALIGN_OP(1)
1605
CHECK_ALIGN_OP(3)
1606
CHECK_ALIGN_OP(7)