Statistics
| Branch: | Revision:

root / target-sparc / op.c @ 134d77a1

History | View | Annotate | Download (42.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
#ifdef TARGET_SPARC64
173
#define XFLAG_SET(x) ((env->xcc&x)?1:0)
174
#endif
175

    
176
#define FLAG_SET(x) ((env->psr&x)?1:0)
177

    
178
void OPPROTO op_add_T1_T0_cc(void)
179
{
180
    target_ulong src1;
181

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

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

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

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

    
278
void OPPROTO op_tadd_T1_T0_cc(void)
279
{
280
    target_ulong src1;
281

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

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

    
322
void OPPROTO op_tadd_T1_T0_ccTV(void)
323
{
324
    target_ulong src1;
325

    
326
    if ((T0 & 0x03) || (T1 & 0x03)) {
327
        raise_exception(TT_TOVF);
328
        FORCE_RET();
329
        return;
330
    }
331

    
332
    src1 = T0;
333
    T0 += T1;
334

    
335
#ifdef TARGET_SPARC64
336
    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
337
         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
338
        raise_exception(TT_TOVF);
339
#else
340
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
341
        raise_exception(TT_TOVF);
342
#endif
343

    
344
    env->psr = 0;
345
#ifdef TARGET_SPARC64
346
    if (!(T0 & 0xffffffff))
347
        env->psr |= PSR_ZERO;
348
    if ((int32_t) T0 < 0)
349
        env->psr |= PSR_NEG;
350
    if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
351
        env->psr |= PSR_CARRY;
352

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

    
371
void OPPROTO op_sub_T1_T0_cc(void)
372
{
373
    target_ulong src1;
374

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

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

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

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

    
471
void OPPROTO op_tsub_T1_T0_cc(void)
472
{
473
    target_ulong src1;
474

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

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

    
515
void OPPROTO op_tsub_T1_T0_ccTV(void)
516
{
517
    target_ulong src1;
518

    
519
    if ((T0 & 0x03) || (T1 & 0x03))
520
        raise_exception(TT_TOVF);
521

    
522
    src1 = T0;
523
    T0 -= T1;
524

    
525
#ifdef TARGET_SPARC64
526
    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
527
         ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
528
        raise_exception(TT_TOVF);
529
#else
530
    if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
531
        raise_exception(TT_TOVF);
532
#endif
533

    
534
    env->psr = 0;
535
#ifdef TARGET_SPARC64
536
    if (!(T0 & 0xffffffff))
537
        env->psr |= PSR_ZERO;
538
    if ((int32_t) T0 < 0)
539
        env->psr |= PSR_NEG;
540
    if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
541
        env->psr |= PSR_CARRY;
542

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

    
561
void OPPROTO op_andn_T1_T0(void)
562
{
563
    T0 &= ~T1;
564
}
565

    
566
void OPPROTO op_orn_T1_T0(void)
567
{
568
    T0 |= ~T1;
569
}
570

    
571
void OPPROTO op_xnor_T1_T0(void)
572
{
573
    T0 ^= ~T1;
574
}
575

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

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

    
600
void OPPROTO op_mulscc_T1_T0(void)
601
{
602
    unsigned int b1, N, V, b2;
603
    target_ulong src1;
604

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

    
628
void OPPROTO op_udiv_T1_T0(void)
629
{
630
    uint64_t x0;
631
    uint32_t x1;
632

    
633
    x0 = T0 | ((uint64_t) (env->y) << 32);
634
    x1 = T1;
635

    
636
    if (x1 == 0) {
637
        raise_exception(TT_DIV_ZERO);
638
    }
639

    
640
    x0 = x0 / x1;
641
    if (x0 > 0xffffffff) {
642
        T0 = 0xffffffff;
643
        T1 = 1;
644
    } else {
645
        T0 = x0;
646
        T1 = 0;
647
    }
648
    FORCE_RET();
649
}
650

    
651
void OPPROTO op_sdiv_T1_T0(void)
652
{
653
    int64_t x0;
654
    int32_t x1;
655

    
656
    x0 = T0 | ((int64_t) (env->y) << 32);
657
    x1 = T1;
658

    
659
    if (x1 == 0) {
660
        raise_exception(TT_DIV_ZERO);
661
    }
662

    
663
    x0 = x0 / x1;
664
    if ((int32_t) x0 != x0) {
665
        T0 = x0 < 0? 0x80000000: 0x7fffffff;
666
        T1 = 1;
667
    } else {
668
        T0 = x0;
669
        T1 = 0;
670
    }
671
    FORCE_RET();
672
}
673

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

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

    
701
#ifdef TARGET_SPARC64
702
void OPPROTO op_udivx_T1_T0(void)
703
{
704
    if (T1 == 0) {
705
        raise_exception(TT_DIV_ZERO);
706
    }
707
    T0 /= T1;
708
    FORCE_RET();
709
}
710

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

    
724
void OPPROTO op_logic_T0_cc(void)
725
{
726
    env->psr = 0;
727
#ifdef TARGET_SPARC64
728
    if (!(T0 & 0xffffffff))
729
        env->psr |= PSR_ZERO;
730
    if ((int32_t) T0 < 0)
731
        env->psr |= PSR_NEG;
732

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

    
747
/* Load and store */
748
#define MEMSUFFIX _raw
749
#include "op_mem.h"
750
#if !defined(CONFIG_USER_ONLY)
751
#define MEMSUFFIX _user
752
#include "op_mem.h"
753

    
754
#define MEMSUFFIX _kernel
755
#include "op_mem.h"
756

    
757
#ifdef TARGET_SPARC64
758
#define MEMSUFFIX _hypv
759
#include "op_mem.h"
760
#endif
761
#endif
762

    
763
void OPPROTO op_ldfsr(void)
764
{
765
    PUT_FSR32(env, *((uint32_t *) &FT0));
766
}
767

    
768
void OPPROTO op_stfsr(void)
769
{
770
    *((uint32_t *) &FT0) = GET_FSR32(env);
771
}
772

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

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

    
803
void OPPROTO op_wrccr(void)
804
{
805
    PUT_CCR(env, T0);
806
}
807

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

    
815
void OPPROTO op_wrcwp(void)
816
{
817
    PUT_CWP64(env, T0);
818
}
819

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

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

    
860
void OPPROTO op_eval_ba(void)
861
{
862
    T2 = 1;
863
}
864

    
865
void OPPROTO op_eval_be(void)
866
{
867
    T2 = FLAG_SET(PSR_ZERO);
868
}
869

    
870
void OPPROTO op_eval_ble(void)
871
{
872
    target_ulong Z = FLAG_SET(PSR_ZERO), N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
873

    
874
    T2 = Z | (N ^ V);
875
}
876

    
877
void OPPROTO op_eval_bl(void)
878
{
879
    target_ulong N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
880

    
881
    T2 = N ^ V;
882
}
883

    
884
void OPPROTO op_eval_bleu(void)
885
{
886
    target_ulong Z = FLAG_SET(PSR_ZERO), C = FLAG_SET(PSR_CARRY);
887

    
888
    T2 = C | Z;
889
}
890

    
891
void OPPROTO op_eval_bcs(void)
892
{
893
    T2 = FLAG_SET(PSR_CARRY);
894
}
895

    
896
void OPPROTO op_eval_bvs(void)
897
{
898
    T2 = FLAG_SET(PSR_OVF);
899
}
900

    
901
void OPPROTO op_eval_bn(void)
902
{
903
    T2 = 0;
904
}
905

    
906
void OPPROTO op_eval_bneg(void)
907
{
908
    T2 = FLAG_SET(PSR_NEG);
909
}
910

    
911
void OPPROTO op_eval_bne(void)
912
{
913
    T2 = !FLAG_SET(PSR_ZERO);
914
}
915

    
916
void OPPROTO op_eval_bg(void)
917
{
918
    target_ulong Z = FLAG_SET(PSR_ZERO), N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
919

    
920
    T2 = !(Z | (N ^ V));
921
}
922

    
923
void OPPROTO op_eval_bge(void)
924
{
925
    target_ulong N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
926

    
927
    T2 = !(N ^ V);
928
}
929

    
930
void OPPROTO op_eval_bgu(void)
931
{
932
    target_ulong Z = FLAG_SET(PSR_ZERO), C = FLAG_SET(PSR_CARRY);
933

    
934
    T2 = !(C | Z);
935
}
936

    
937
void OPPROTO op_eval_bcc(void)
938
{
939
    T2 = !FLAG_SET(PSR_CARRY);
940
}
941

    
942
void OPPROTO op_eval_bpos(void)
943
{
944
    T2 = !FLAG_SET(PSR_NEG);
945
}
946

    
947
void OPPROTO op_eval_bvc(void)
948
{
949
    T2 = !FLAG_SET(PSR_OVF);
950
}
951

    
952
#ifdef TARGET_SPARC64
953
void OPPROTO op_eval_xbe(void)
954
{
955
    T2 = XFLAG_SET(PSR_ZERO);
956
}
957

    
958
void OPPROTO op_eval_xble(void)
959
{
960
    target_ulong Z = XFLAG_SET(PSR_ZERO), N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
961

    
962
    T2 = Z | (N ^ V);
963
}
964

    
965
void OPPROTO op_eval_xbl(void)
966
{
967
    target_ulong N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
968

    
969
    T2 = N ^ V;
970
}
971

    
972
void OPPROTO op_eval_xbleu(void)
973
{
974
    target_ulong Z = XFLAG_SET(PSR_ZERO), C = XFLAG_SET(PSR_CARRY);
975

    
976
    T2 = C | Z;
977
}
978

    
979
void OPPROTO op_eval_xbcs(void)
980
{
981
    T2 = XFLAG_SET(PSR_CARRY);
982
}
983

    
984
void OPPROTO op_eval_xbvs(void)
985
{
986
    T2 = XFLAG_SET(PSR_OVF);
987
}
988

    
989
void OPPROTO op_eval_xbneg(void)
990
{
991
    T2 = XFLAG_SET(PSR_NEG);
992
}
993

    
994
void OPPROTO op_eval_xbne(void)
995
{
996
    T2 = !XFLAG_SET(PSR_ZERO);
997
}
998

    
999
void OPPROTO op_eval_xbg(void)
1000
{
1001
    target_ulong Z = XFLAG_SET(PSR_ZERO), N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
1002

    
1003
    T2 = !(Z | (N ^ V));
1004
}
1005

    
1006
void OPPROTO op_eval_xbge(void)
1007
{
1008
    target_ulong N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
1009

    
1010
    T2 = !(N ^ V);
1011
}
1012

    
1013
void OPPROTO op_eval_xbgu(void)
1014
{
1015
    target_ulong Z = XFLAG_SET(PSR_ZERO), C = XFLAG_SET(PSR_CARRY);
1016

    
1017
    T2 = !(C | Z);
1018
}
1019

    
1020
void OPPROTO op_eval_xbcc(void)
1021
{
1022
    T2 = !XFLAG_SET(PSR_CARRY);
1023
}
1024

    
1025
void OPPROTO op_eval_xbpos(void)
1026
{
1027
    T2 = !XFLAG_SET(PSR_NEG);
1028
}
1029

    
1030
void OPPROTO op_eval_xbvc(void)
1031
{
1032
    T2 = !XFLAG_SET(PSR_OVF);
1033
}
1034
#endif
1035

    
1036
#define FCC
1037
#define FFLAG_SET(x) (env->fsr & x? 1: 0)
1038
#include "fbranch_template.h"
1039

    
1040
#ifdef TARGET_SPARC64
1041
#define FCC _fcc1
1042
#define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 32))? 1: 0)
1043
#include "fbranch_template.h"
1044
#define FCC _fcc2
1045
#define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 34))? 1: 0)
1046
#include "fbranch_template.h"
1047
#define FCC _fcc3
1048
#define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 36))? 1: 0)
1049
#include "fbranch_template.h"
1050
#endif
1051

    
1052
#ifdef TARGET_SPARC64
1053
void OPPROTO op_eval_brz(void)
1054
{
1055
    T2 = (T0 == 0);
1056
}
1057

    
1058
void OPPROTO op_eval_brnz(void)
1059
{
1060
    T2 = (T0 != 0);
1061
}
1062

    
1063
void OPPROTO op_eval_brlz(void)
1064
{
1065
    T2 = ((int64_t)T0 < 0);
1066
}
1067

    
1068
void OPPROTO op_eval_brlez(void)
1069
{
1070
    T2 = ((int64_t)T0 <= 0);
1071
}
1072

    
1073
void OPPROTO op_eval_brgz(void)
1074
{
1075
    T2 = ((int64_t)T0 > 0);
1076
}
1077

    
1078
void OPPROTO op_eval_brgez(void)
1079
{
1080
    T2 = ((int64_t)T0 >= 0);
1081
}
1082
#endif
1083

    
1084
void OPPROTO op_jmp_label(void)
1085
{
1086
    GOTO_LABEL_PARAM(1);
1087
}
1088

    
1089
void OPPROTO op_jnz_T2_label(void)
1090
{
1091
    if (T2)
1092
        GOTO_LABEL_PARAM(1);
1093
    FORCE_RET();
1094
}
1095

    
1096
void OPPROTO op_jz_T2_label(void)
1097
{
1098
    if (!T2)
1099
        GOTO_LABEL_PARAM(1);
1100
    FORCE_RET();
1101
}
1102

    
1103
#define F_OP(name, p) void OPPROTO op_f##name##p(void)
1104

    
1105
#if defined(CONFIG_USER_ONLY)
1106
#define F_BINOP(name)                                           \
1107
    F_OP(name, s)                                               \
1108
    {                                                           \
1109
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
1110
    }                                                           \
1111
    F_OP(name, d)                                               \
1112
    {                                                           \
1113
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
1114
    }                                                           \
1115
    F_OP(name, q)                                               \
1116
    {                                                           \
1117
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
1118
    }
1119
#else
1120
#define F_BINOP(name)                                           \
1121
    F_OP(name, s)                                               \
1122
    {                                                           \
1123
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
1124
    }                                                           \
1125
    F_OP(name, d)                                               \
1126
    {                                                           \
1127
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
1128
    }
1129
#endif
1130

    
1131
F_BINOP(add);
1132
F_BINOP(sub);
1133
F_BINOP(mul);
1134
F_BINOP(div);
1135
#undef F_BINOP
1136

    
1137
void OPPROTO op_fsmuld(void)
1138
{
1139
    DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
1140
                      float32_to_float64(FT1, &env->fp_status),
1141
                      &env->fp_status);
1142
}
1143

    
1144
#if defined(CONFIG_USER_ONLY)
1145
void OPPROTO op_fdmulq(void)
1146
{
1147
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
1148
                       float64_to_float128(DT1, &env->fp_status),
1149
                       &env->fp_status);
1150
}
1151
#endif
1152

    
1153
#if defined(CONFIG_USER_ONLY)
1154
#define F_HELPER(name)    \
1155
    F_OP(name, s)         \
1156
    {                     \
1157
        do_f##name##s();  \
1158
    }                     \
1159
    F_OP(name, d)         \
1160
    {                     \
1161
        do_f##name##d();  \
1162
    }                     \
1163
    F_OP(name, q)         \
1164
    {                     \
1165
        do_f##name##q();  \
1166
    }
1167
#else
1168
#define F_HELPER(name)    \
1169
    F_OP(name, s)         \
1170
    {                     \
1171
        do_f##name##s();  \
1172
    }                     \
1173
    F_OP(name, d)         \
1174
    {                     \
1175
        do_f##name##d();  \
1176
    }
1177
#endif
1178

    
1179
F_OP(neg, s)
1180
{
1181
    FT0 = float32_chs(FT1);
1182
}
1183

    
1184
#ifdef TARGET_SPARC64
1185
F_OP(neg, d)
1186
{
1187
    DT0 = float64_chs(DT1);
1188
}
1189

    
1190
#if defined(CONFIG_USER_ONLY)
1191
F_OP(neg, q)
1192
{
1193
    QT0 = float128_chs(QT1);
1194
}
1195

    
1196
#endif
1197

    
1198
#endif
1199

    
1200
/* Integer to float conversion.  */
1201
#ifdef USE_INT_TO_FLOAT_HELPERS
1202
F_HELPER(ito);
1203
#ifdef TARGET_SPARC64
1204
F_HELPER(xto);
1205
#endif
1206
#else
1207
F_OP(ito, s)
1208
{
1209
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
1210
}
1211

    
1212
F_OP(ito, d)
1213
{
1214
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
1215
}
1216

    
1217
#if defined(CONFIG_USER_ONLY)
1218
F_OP(ito, q)
1219
{
1220
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
1221
}
1222
#endif
1223

    
1224
#ifdef TARGET_SPARC64
1225
F_OP(xto, s)
1226
{
1227
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
1228
}
1229

    
1230
F_OP(xto, d)
1231
{
1232
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
1233
}
1234
#if defined(CONFIG_USER_ONLY)
1235
F_OP(xto, q)
1236
{
1237
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
1238
}
1239
#endif
1240
#endif
1241
#endif
1242
#undef F_HELPER
1243

    
1244
/* floating point conversion */
1245
void OPPROTO op_fdtos(void)
1246
{
1247
    FT0 = float64_to_float32(DT1, &env->fp_status);
1248
}
1249

    
1250
void OPPROTO op_fstod(void)
1251
{
1252
    DT0 = float32_to_float64(FT1, &env->fp_status);
1253
}
1254

    
1255
#if defined(CONFIG_USER_ONLY)
1256
void OPPROTO op_fqtos(void)
1257
{
1258
    FT0 = float128_to_float32(QT1, &env->fp_status);
1259
}
1260

    
1261
void OPPROTO op_fstoq(void)
1262
{
1263
    QT0 = float32_to_float128(FT1, &env->fp_status);
1264
}
1265

    
1266
void OPPROTO op_fqtod(void)
1267
{
1268
    DT0 = float128_to_float64(QT1, &env->fp_status);
1269
}
1270

    
1271
void OPPROTO op_fdtoq(void)
1272
{
1273
    QT0 = float64_to_float128(DT1, &env->fp_status);
1274
}
1275
#endif
1276

    
1277
/* Float to integer conversion.  */
1278
void OPPROTO op_fstoi(void)
1279
{
1280
    *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
1281
}
1282

    
1283
void OPPROTO op_fdtoi(void)
1284
{
1285
    *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
1286
}
1287

    
1288
#if defined(CONFIG_USER_ONLY)
1289
void OPPROTO op_fqtoi(void)
1290
{
1291
    *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
1292
}
1293
#endif
1294

    
1295
#ifdef TARGET_SPARC64
1296
void OPPROTO op_fstox(void)
1297
{
1298
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
1299
}
1300

    
1301
void OPPROTO op_fdtox(void)
1302
{
1303
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
1304
}
1305

    
1306
#if defined(CONFIG_USER_ONLY)
1307
void OPPROTO op_fqtox(void)
1308
{
1309
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
1310
}
1311
#endif
1312

    
1313
void OPPROTO op_fmovs_cc(void)
1314
{
1315
    if (T2)
1316
        FT0 = FT1;
1317
}
1318

    
1319
void OPPROTO op_fmovd_cc(void)
1320
{
1321
    if (T2)
1322
        DT0 = DT1;
1323
}
1324

    
1325
#if defined(CONFIG_USER_ONLY)
1326
void OPPROTO op_fmovq_cc(void)
1327
{
1328
    if (T2)
1329
        QT0 = QT1;
1330
}
1331
#endif
1332

    
1333
void OPPROTO op_flushw(void)
1334
{
1335
    if (env->cansave != NWINDOWS - 2) {
1336
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
1337
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
1338
                                    ((env->wstate & 0x7) << 2)));
1339
    }
1340
}
1341

    
1342
void OPPROTO op_saved(void)
1343
{
1344
    env->cansave++;
1345
    if (env->otherwin == 0)
1346
        env->canrestore--;
1347
    else
1348
        env->otherwin--;
1349
    FORCE_RET();
1350
}
1351

    
1352
void OPPROTO op_restored(void)
1353
{
1354
    env->canrestore++;
1355
    if (env->cleanwin < NWINDOWS - 1)
1356
        env->cleanwin++;
1357
    if (env->otherwin == 0)
1358
        env->cansave--;
1359
    else
1360
        env->otherwin--;
1361
    FORCE_RET();
1362
}
1363
#endif
1364

    
1365
#ifdef TARGET_SPARC64
1366
// This function uses non-native bit order
1367
#define GET_FIELD(X, FROM, TO)                                  \
1368
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
1369

    
1370
// This function uses the order in the manuals, i.e. bit 0 is 2^0
1371
#define GET_FIELD_SP(X, FROM, TO)               \
1372
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
1373

    
1374
void OPPROTO op_array8()
1375
{
1376
    T0 = (GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
1377
        (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
1378
        (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
1379
        (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
1380
        (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
1381
        (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12);
1382
}
1383

    
1384
void OPPROTO op_array16()
1385
{
1386
    T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
1387
          (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
1388
          (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
1389
          (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
1390
          (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
1391
          (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 1;
1392
}
1393

    
1394
void OPPROTO op_array32()
1395
{
1396
    T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
1397
          (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
1398
          (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
1399
          (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
1400
          (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
1401
          (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 2;
1402
}
1403

    
1404
void OPPROTO op_alignaddr()
1405
{
1406
    uint64_t tmp;
1407

    
1408
    tmp = T0 + T1;
1409
    env->gsr &= ~7ULL;
1410
    env->gsr |= tmp & 7ULL;
1411
    T0 = tmp & ~7ULL;
1412
}
1413

    
1414
void OPPROTO op_faligndata()
1415
{
1416
    uint64_t tmp;
1417

    
1418
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
1419
    tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
1420
    *((uint64_t *)&DT0) = tmp;
1421
}
1422

    
1423
void OPPROTO op_movl_FT0_0(void)
1424
{
1425
    *((uint32_t *)&FT0) = 0;
1426
}
1427

    
1428
void OPPROTO op_movl_DT0_0(void)
1429
{
1430
    *((uint64_t *)&DT0) = 0;
1431
}
1432

    
1433
void OPPROTO op_movl_FT0_1(void)
1434
{
1435
    *((uint32_t *)&FT0) = 0xffffffff;
1436
}
1437

    
1438
void OPPROTO op_movl_DT0_1(void)
1439
{
1440
    *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
1441
}
1442

    
1443
void OPPROTO op_fnot(void)
1444
{
1445
    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
1446
}
1447

    
1448
void OPPROTO op_fnots(void)
1449
{
1450
    *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
1451
}
1452

    
1453
void OPPROTO op_fnor(void)
1454
{
1455
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
1456
}
1457

    
1458
void OPPROTO op_fnors(void)
1459
{
1460
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
1461
}
1462

    
1463
void OPPROTO op_for(void)
1464
{
1465
    *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
1466
}
1467

    
1468
void OPPROTO op_fors(void)
1469
{
1470
    *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
1471
}
1472

    
1473
void OPPROTO op_fxor(void)
1474
{
1475
    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
1476
}
1477

    
1478
void OPPROTO op_fxors(void)
1479
{
1480
    *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
1481
}
1482

    
1483
void OPPROTO op_fand(void)
1484
{
1485
    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
1486
}
1487

    
1488
void OPPROTO op_fands(void)
1489
{
1490
    *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
1491
}
1492

    
1493
void OPPROTO op_fornot(void)
1494
{
1495
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
1496
}
1497

    
1498
void OPPROTO op_fornots(void)
1499
{
1500
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
1501
}
1502

    
1503
void OPPROTO op_fandnot(void)
1504
{
1505
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
1506
}
1507

    
1508
void OPPROTO op_fandnots(void)
1509
{
1510
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
1511
}
1512

    
1513
void OPPROTO op_fnand(void)
1514
{
1515
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
1516
}
1517

    
1518
void OPPROTO op_fnands(void)
1519
{
1520
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
1521
}
1522

    
1523
void OPPROTO op_fxnor(void)
1524
{
1525
    *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
1526
}
1527

    
1528
void OPPROTO op_fxnors(void)
1529
{
1530
    *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
1531
}
1532

    
1533
#ifdef WORDS_BIGENDIAN
1534
#define VIS_B64(n) b[7 - (n)]
1535
#define VIS_W64(n) w[3 - (n)]
1536
#define VIS_SW64(n) sw[3 - (n)]
1537
#define VIS_L64(n) l[1 - (n)]
1538
#define VIS_B32(n) b[3 - (n)]
1539
#define VIS_W32(n) w[1 - (n)]
1540
#else
1541
#define VIS_B64(n) b[n]
1542
#define VIS_W64(n) w[n]
1543
#define VIS_SW64(n) sw[n]
1544
#define VIS_L64(n) l[n]
1545
#define VIS_B32(n) b[n]
1546
#define VIS_W32(n) w[n]
1547
#endif
1548

    
1549
typedef union {
1550
    uint8_t b[8];
1551
    uint16_t w[4];
1552
    int16_t sw[4];
1553
    uint32_t l[2];
1554
    float64 d;
1555
} vis64;
1556

    
1557
typedef union {
1558
    uint8_t b[4];
1559
    uint16_t w[2];
1560
    uint32_t l;
1561
    float32 f;
1562
} vis32;
1563

    
1564
void OPPROTO op_fpmerge(void)
1565
{
1566
    vis64 s, d;
1567

    
1568
    s.d = DT0;
1569
    d.d = DT1;
1570

    
1571
    // Reverse calculation order to handle overlap
1572
    d.VIS_B64(7) = s.VIS_B64(3);
1573
    d.VIS_B64(6) = d.VIS_B64(3);
1574
    d.VIS_B64(5) = s.VIS_B64(2);
1575
    d.VIS_B64(4) = d.VIS_B64(2);
1576
    d.VIS_B64(3) = s.VIS_B64(1);
1577
    d.VIS_B64(2) = d.VIS_B64(1);
1578
    d.VIS_B64(1) = s.VIS_B64(0);
1579
    //d.VIS_B64(0) = d.VIS_B64(0);
1580

    
1581
    DT0 = d.d;
1582
}
1583

    
1584
void OPPROTO op_fmul8x16(void)
1585
{
1586
    vis64 s, d;
1587
    uint32_t tmp;
1588

    
1589
    s.d = DT0;
1590
    d.d = DT1;
1591

    
1592
#define PMUL(r)                                                 \
1593
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
1594
    if ((tmp & 0xff) > 0x7f)                                    \
1595
        tmp += 0x100;                                           \
1596
    d.VIS_W64(r) = tmp >> 8;
1597

    
1598
    PMUL(0);
1599
    PMUL(1);
1600
    PMUL(2);
1601
    PMUL(3);
1602
#undef PMUL
1603

    
1604
    DT0 = d.d;
1605
}
1606

    
1607
void OPPROTO op_fmul8x16al(void)
1608
{
1609
    vis64 s, d;
1610
    uint32_t tmp;
1611

    
1612
    s.d = DT0;
1613
    d.d = DT1;
1614

    
1615
#define PMUL(r)                                                 \
1616
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
1617
    if ((tmp & 0xff) > 0x7f)                                    \
1618
        tmp += 0x100;                                           \
1619
    d.VIS_W64(r) = tmp >> 8;
1620

    
1621
    PMUL(0);
1622
    PMUL(1);
1623
    PMUL(2);
1624
    PMUL(3);
1625
#undef PMUL
1626

    
1627
    DT0 = d.d;
1628
}
1629

    
1630
void OPPROTO op_fmul8x16au(void)
1631
{
1632
    vis64 s, d;
1633
    uint32_t tmp;
1634

    
1635
    s.d = DT0;
1636
    d.d = DT1;
1637

    
1638
#define PMUL(r)                                                 \
1639
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
1640
    if ((tmp & 0xff) > 0x7f)                                    \
1641
        tmp += 0x100;                                           \
1642
    d.VIS_W64(r) = tmp >> 8;
1643

    
1644
    PMUL(0);
1645
    PMUL(1);
1646
    PMUL(2);
1647
    PMUL(3);
1648
#undef PMUL
1649

    
1650
    DT0 = d.d;
1651
}
1652

    
1653
void OPPROTO op_fmul8sux16(void)
1654
{
1655
    vis64 s, d;
1656
    uint32_t tmp;
1657

    
1658
    s.d = DT0;
1659
    d.d = DT1;
1660

    
1661
#define PMUL(r)                                                         \
1662
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
1663
    if ((tmp & 0xff) > 0x7f)                                            \
1664
        tmp += 0x100;                                                   \
1665
    d.VIS_W64(r) = tmp >> 8;
1666

    
1667
    PMUL(0);
1668
    PMUL(1);
1669
    PMUL(2);
1670
    PMUL(3);
1671
#undef PMUL
1672

    
1673
    DT0 = d.d;
1674
}
1675

    
1676
void OPPROTO op_fmul8ulx16(void)
1677
{
1678
    vis64 s, d;
1679
    uint32_t tmp;
1680

    
1681
    s.d = DT0;
1682
    d.d = DT1;
1683

    
1684
#define PMUL(r)                                                         \
1685
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
1686
    if ((tmp & 0xff) > 0x7f)                                            \
1687
        tmp += 0x100;                                                   \
1688
    d.VIS_W64(r) = tmp >> 8;
1689

    
1690
    PMUL(0);
1691
    PMUL(1);
1692
    PMUL(2);
1693
    PMUL(3);
1694
#undef PMUL
1695

    
1696
    DT0 = d.d;
1697
}
1698

    
1699
void OPPROTO op_fmuld8sux16(void)
1700
{
1701
    vis64 s, d;
1702
    uint32_t tmp;
1703

    
1704
    s.d = DT0;
1705
    d.d = DT1;
1706

    
1707
#define PMUL(r)                                                         \
1708
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
1709
    if ((tmp & 0xff) > 0x7f)                                            \
1710
        tmp += 0x100;                                                   \
1711
    d.VIS_L64(r) = tmp;
1712

    
1713
    // Reverse calculation order to handle overlap
1714
    PMUL(1);
1715
    PMUL(0);
1716
#undef PMUL
1717

    
1718
    DT0 = d.d;
1719
}
1720

    
1721
void OPPROTO op_fmuld8ulx16(void)
1722
{
1723
    vis64 s, d;
1724
    uint32_t tmp;
1725

    
1726
    s.d = DT0;
1727
    d.d = DT1;
1728

    
1729
#define PMUL(r)                                                         \
1730
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
1731
    if ((tmp & 0xff) > 0x7f)                                            \
1732
        tmp += 0x100;                                                   \
1733
    d.VIS_L64(r) = tmp;
1734

    
1735
    // Reverse calculation order to handle overlap
1736
    PMUL(1);
1737
    PMUL(0);
1738
#undef PMUL
1739

    
1740
    DT0 = d.d;
1741
}
1742

    
1743
void OPPROTO op_fexpand(void)
1744
{
1745
    vis32 s;
1746
    vis64 d;
1747

    
1748
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
1749
    d.d = DT1;
1750
    d.VIS_L64(0) = s.VIS_W32(0) << 4;
1751
    d.VIS_L64(1) = s.VIS_W32(1) << 4;
1752
    d.VIS_L64(2) = s.VIS_W32(2) << 4;
1753
    d.VIS_L64(3) = s.VIS_W32(3) << 4;
1754

    
1755
    DT0 = d.d;
1756
}
1757

    
1758
#define VIS_OP(name, F)                                 \
1759
    void OPPROTO name##16(void)                         \
1760
    {                                                   \
1761
        vis64 s, d;                                     \
1762
                                                        \
1763
        s.d = DT0;                                      \
1764
        d.d = DT1;                                      \
1765
                                                        \
1766
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
1767
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
1768
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
1769
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
1770
                                                        \
1771
        DT0 = d.d;                                      \
1772
    }                                                   \
1773
                                                        \
1774
    void OPPROTO name##16s(void)                        \
1775
    {                                                   \
1776
        vis32 s, d;                                     \
1777
                                                        \
1778
        s.f = FT0;                                      \
1779
        d.f = FT1;                                      \
1780
                                                        \
1781
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
1782
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
1783
                                                        \
1784
        FT0 = d.f;                                      \
1785
    }                                                   \
1786
                                                        \
1787
    void OPPROTO name##32(void)                         \
1788
    {                                                   \
1789
        vis64 s, d;                                     \
1790
                                                        \
1791
        s.d = DT0;                                      \
1792
        d.d = DT1;                                      \
1793
                                                        \
1794
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
1795
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
1796
                                                        \
1797
        DT0 = d.d;                                      \
1798
    }                                                   \
1799
                                                        \
1800
    void OPPROTO name##32s(void)                        \
1801
    {                                                   \
1802
        vis32 s, d;                                     \
1803
                                                        \
1804
        s.f = FT0;                                      \
1805
        d.f = FT1;                                      \
1806
                                                        \
1807
        d.l = F(d.l, s.l);                              \
1808
                                                        \
1809
        FT0 = d.f;                                      \
1810
    }
1811

    
1812
#define FADD(a, b) ((a) + (b))
1813
#define FSUB(a, b) ((a) - (b))
1814
VIS_OP(op_fpadd, FADD)
1815
VIS_OP(op_fpsub, FSUB)
1816

    
1817
#define VIS_CMPOP(name, F)                                        \
1818
    void OPPROTO name##16(void)                                   \
1819
    {                                                             \
1820
        vis64 s, d;                                               \
1821
                                                                  \
1822
        s.d = DT0;                                                \
1823
        d.d = DT1;                                                \
1824
                                                                  \
1825
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
1826
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
1827
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
1828
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
1829
                                                                  \
1830
        DT0 = d.d;                                                \
1831
    }                                                             \
1832
                                                                  \
1833
    void OPPROTO name##32(void)                                   \
1834
    {                                                             \
1835
        vis64 s, d;                                               \
1836
                                                                  \
1837
        s.d = DT0;                                                \
1838
        d.d = DT1;                                                \
1839
                                                                  \
1840
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
1841
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
1842
                                                                  \
1843
        DT0 = d.d;                                                \
1844
    }
1845

    
1846
#define FCMPGT(a, b) ((a) > (b))
1847
#define FCMPEQ(a, b) ((a) == (b))
1848
#define FCMPLE(a, b) ((a) <= (b))
1849
#define FCMPNE(a, b) ((a) != (b))
1850

    
1851
VIS_CMPOP(op_fcmpgt, FCMPGT)
1852
VIS_CMPOP(op_fcmpeq, FCMPEQ)
1853
VIS_CMPOP(op_fcmple, FCMPLE)
1854
VIS_CMPOP(op_fcmpne, FCMPNE)
1855

    
1856
#endif
1857

    
1858
#define CHECK_ALIGN_OP(align)                           \
1859
    void OPPROTO op_check_align_T0_ ## align (void)     \
1860
    {                                                   \
1861
        if (T0 & align)                                 \
1862
            raise_exception(TT_UNALIGNED);              \
1863
        FORCE_RET();                                    \
1864
    }
1865

    
1866
CHECK_ALIGN_OP(1)
1867
CHECK_ALIGN_OP(3)
1868
CHECK_ALIGN_OP(7)