Statistics
| Branch: | Revision:

root / target-mips / op_helper.c @ 92af06d2

History | View | Annotate | Download (67 kB)

1
/*
2
 *  MIPS emulation helpers for qemu.
3
 *
4
 *  Copyright (c) 2004-2005 Jocelyn Mayer
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
#include <stdlib.h>
21
#include "exec.h"
22

    
23
#include "host-utils.h"
24

    
25
/*****************************************************************************/
26
/* Exceptions processing helpers */
27

    
28
void do_raise_exception_err (uint32_t exception, int error_code)
29
{
30
#if 1
31
    if (logfile && exception < 0x100)
32
        fprintf(logfile, "%s: %d %d\n", __func__, exception, error_code);
33
#endif
34
    env->exception_index = exception;
35
    env->error_code = error_code;
36
    T0 = 0;
37
    cpu_loop_exit();
38
}
39

    
40
void do_raise_exception (uint32_t exception)
41
{
42
    do_raise_exception_err(exception, 0);
43
}
44

    
45
void do_interrupt_restart (void)
46
{
47
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
48
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
49
        !(env->hflags & MIPS_HFLAG_DM) &&
50
        (env->CP0_Status & (1 << CP0St_IE)) &&
51
        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
52
        env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
53
        do_raise_exception(EXCP_EXT_INTERRUPT);
54
    }
55
}
56

    
57
void do_restore_state (void *pc_ptr)
58
{
59
    TranslationBlock *tb;
60
    unsigned long pc = (unsigned long) pc_ptr;
61
    
62
    tb = tb_find_pc (pc);
63
    if (tb) {
64
        cpu_restore_state (tb, env, pc, NULL);
65
    }
66
}
67

    
68
void do_clo (void)
69
{
70
    T0 = clo32(T0);
71
}
72

    
73
void do_clz (void)
74
{
75
    T0 = clz32(T0);
76
}
77

    
78
#if defined(TARGET_MIPS64)
79
#if TARGET_LONG_BITS > HOST_LONG_BITS
80
/* Those might call libgcc functions.  */
81
void do_dsll (void)
82
{
83
    T0 = T0 << T1;
84
}
85

    
86
void do_dsll32 (void)
87
{
88
    T0 = T0 << (T1 + 32);
89
}
90

    
91
void do_dsra (void)
92
{
93
    T0 = (int64_t)T0 >> T1;
94
}
95

    
96
void do_dsra32 (void)
97
{
98
    T0 = (int64_t)T0 >> (T1 + 32);
99
}
100

    
101
void do_dsrl (void)
102
{
103
    T0 = T0 >> T1;
104
}
105

    
106
void do_dsrl32 (void)
107
{
108
    T0 = T0 >> (T1 + 32);
109
}
110

    
111
void do_drotr (void)
112
{
113
    target_ulong tmp;
114

    
115
    if (T1) {
116
        tmp = T0 << (0x40 - T1);
117
        T0 = (T0 >> T1) | tmp;
118
    }
119
}
120

    
121
void do_drotr32 (void)
122
{
123
    target_ulong tmp;
124

    
125
    tmp = T0 << (0x40 - (32 + T1));
126
    T0 = (T0 >> (32 + T1)) | tmp;
127
}
128

    
129
void do_dsllv (void)
130
{
131
    T0 = T1 << (T0 & 0x3F);
132
}
133

    
134
void do_dsrav (void)
135
{
136
    T0 = (int64_t)T1 >> (T0 & 0x3F);
137
}
138

    
139
void do_dsrlv (void)
140
{
141
    T0 = T1 >> (T0 & 0x3F);
142
}
143

    
144
void do_drotrv (void)
145
{
146
    target_ulong tmp;
147

    
148
    T0 &= 0x3F;
149
    if (T0) {
150
        tmp = T1 << (0x40 - T0);
151
        T0 = (T1 >> T0) | tmp;
152
    } else
153
        T0 = T1;
154
}
155

    
156
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
157

    
158
void do_dclo (void)
159
{
160
    T0 = clo64(T0);
161
}
162

    
163
void do_dclz (void)
164
{
165
    T0 = clz64(T0);
166
}
167

    
168
#endif /* TARGET_MIPS64 */
169

    
170
/* 64 bits arithmetic for 32 bits hosts */
171
static always_inline uint64_t get_HILO (void)
172
{
173
    return ((uint64_t)(env->HI[env->current_tc][0]) << 32) | (uint32_t)env->LO[env->current_tc][0];
174
}
175

    
176
static always_inline void set_HILO (uint64_t HILO)
177
{
178
    env->LO[env->current_tc][0] = (int32_t)HILO;
179
    env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
180
}
181

    
182
static always_inline void set_HIT0_LO (uint64_t HILO)
183
{
184
    env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
185
    T0 = env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
186
}
187

    
188
static always_inline void set_HI_LOT0 (uint64_t HILO)
189
{
190
    T0 = env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
191
    env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
192
}
193

    
194
#if TARGET_LONG_BITS > HOST_LONG_BITS
195
void do_madd (void)
196
{
197
    int64_t tmp;
198

    
199
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
200
    set_HILO((int64_t)get_HILO() + tmp);
201
}
202

    
203
void do_maddu (void)
204
{
205
    uint64_t tmp;
206

    
207
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
208
    set_HILO(get_HILO() + tmp);
209
}
210

    
211
void do_msub (void)
212
{
213
    int64_t tmp;
214

    
215
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
216
    set_HILO((int64_t)get_HILO() - tmp);
217
}
218

    
219
void do_msubu (void)
220
{
221
    uint64_t tmp;
222

    
223
    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
224
    set_HILO(get_HILO() - tmp);
225
}
226
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
227

    
228
/* Multiplication variants of the vr54xx. */
229
void do_muls (void)
230
{
231
    set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
232
}
233

    
234
void do_mulsu (void)
235
{
236
    set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
237
}
238

    
239
void do_macc (void)
240
{
241
    set_HI_LOT0(((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
242
}
243

    
244
void do_macchi (void)
245
{
246
    set_HIT0_LO(((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
247
}
248

    
249
void do_maccu (void)
250
{
251
    set_HI_LOT0(((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
252
}
253

    
254
void do_macchiu (void)
255
{
256
    set_HIT0_LO(((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
257
}
258

    
259
void do_msac (void)
260
{
261
    set_HI_LOT0(((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
262
}
263

    
264
void do_msachi (void)
265
{
266
    set_HIT0_LO(((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
267
}
268

    
269
void do_msacu (void)
270
{
271
    set_HI_LOT0(((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
272
}
273

    
274
void do_msachiu (void)
275
{
276
    set_HIT0_LO(((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
277
}
278

    
279
void do_mulhi (void)
280
{
281
    set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
282
}
283

    
284
void do_mulhiu (void)
285
{
286
    set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
287
}
288

    
289
void do_mulshi (void)
290
{
291
    set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
292
}
293

    
294
void do_mulshiu (void)
295
{
296
    set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
297
}
298

    
299
#ifdef TARGET_MIPS64
300
void do_dmult (void)
301
{
302
    muls64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1);
303
}
304

    
305
void do_dmultu (void)
306
{
307
    mulu64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1);
308
}
309
#endif
310

    
311
#ifdef CONFIG_USER_ONLY
312
void do_mfc0_random (void)
313
{
314
    cpu_abort(env, "mfc0 random\n");
315
}
316

    
317
void do_mfc0_count (void)
318
{
319
    cpu_abort(env, "mfc0 count\n");
320
}
321

    
322
void cpu_mips_store_count(CPUState *env, uint32_t value)
323
{
324
    cpu_abort(env, "mtc0 count\n");
325
}
326

    
327
void cpu_mips_store_compare(CPUState *env, uint32_t value)
328
{
329
    cpu_abort(env, "mtc0 compare\n");
330
}
331

    
332
void cpu_mips_start_count(CPUState *env)
333
{
334
    cpu_abort(env, "start count\n");
335
}
336

    
337
void cpu_mips_stop_count(CPUState *env)
338
{
339
    cpu_abort(env, "stop count\n");
340
}
341

    
342
void cpu_mips_update_irq(CPUState *env)
343
{
344
    cpu_abort(env, "mtc0 status / mtc0 cause\n");
345
}
346

    
347
void do_mtc0_status_debug(uint32_t old, uint32_t val)
348
{
349
    cpu_abort(env, "mtc0 status debug\n");
350
}
351

    
352
void do_mtc0_status_irqraise_debug (void)
353
{
354
    cpu_abort(env, "mtc0 status irqraise debug\n");
355
}
356

    
357
void cpu_mips_tlb_flush (CPUState *env, int flush_global)
358
{
359
    cpu_abort(env, "mips_tlb_flush\n");
360
}
361

    
362
#else
363

    
364
/* CP0 helpers */
365
void do_mfc0_mvpcontrol (void)
366
{
367
    T0 = env->mvp->CP0_MVPControl;
368
}
369

    
370
void do_mfc0_mvpconf0 (void)
371
{
372
    T0 = env->mvp->CP0_MVPConf0;
373
}
374

    
375
void do_mfc0_mvpconf1 (void)
376
{
377
    T0 = env->mvp->CP0_MVPConf1;
378
}
379

    
380
void do_mfc0_random (void)
381
{
382
    T0 = (int32_t)cpu_mips_get_random(env);
383
}
384

    
385
void do_mfc0_tcstatus (void)
386
{
387
    T0 = env->CP0_TCStatus[env->current_tc];
388
}
389

    
390
void do_mftc0_tcstatus(void)
391
{
392
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
393

    
394
    T0 = env->CP0_TCStatus[other_tc];
395
}
396

    
397
void do_mfc0_tcbind (void)
398
{
399
    T0 = env->CP0_TCBind[env->current_tc];
400
}
401

    
402
void do_mftc0_tcbind(void)
403
{
404
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
405

    
406
    T0 = env->CP0_TCBind[other_tc];
407
}
408

    
409
void do_mfc0_tcrestart (void)
410
{
411
    T0 = env->PC[env->current_tc];
412
}
413

    
414
void do_mftc0_tcrestart(void)
415
{
416
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
417

    
418
    T0 = env->PC[other_tc];
419
}
420

    
421
void do_mfc0_tchalt (void)
422
{
423
    T0 = env->CP0_TCHalt[env->current_tc];
424
}
425

    
426
void do_mftc0_tchalt(void)
427
{
428
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
429

    
430
    T0 = env->CP0_TCHalt[other_tc];
431
}
432

    
433
void do_mfc0_tccontext (void)
434
{
435
    T0 = env->CP0_TCContext[env->current_tc];
436
}
437

    
438
void do_mftc0_tccontext(void)
439
{
440
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
441

    
442
    T0 = env->CP0_TCContext[other_tc];
443
}
444

    
445
void do_mfc0_tcschedule (void)
446
{
447
    T0 = env->CP0_TCSchedule[env->current_tc];
448
}
449

    
450
void do_mftc0_tcschedule(void)
451
{
452
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
453

    
454
    T0 = env->CP0_TCSchedule[other_tc];
455
}
456

    
457
void do_mfc0_tcschefback (void)
458
{
459
    T0 = env->CP0_TCScheFBack[env->current_tc];
460
}
461

    
462
void do_mftc0_tcschefback(void)
463
{
464
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
465

    
466
    T0 = env->CP0_TCScheFBack[other_tc];
467
}
468

    
469
void do_mfc0_count (void)
470
{
471
    T0 = (int32_t)cpu_mips_get_count(env);
472
}
473

    
474
void do_mftc0_entryhi(void)
475
{
476
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
477

    
478
    T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
479
}
480

    
481
void do_mftc0_status(void)
482
{
483
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
484
    uint32_t tcstatus = env->CP0_TCStatus[other_tc];
485

    
486
    T0 = env->CP0_Status & ~0xf1000018;
487
    T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
488
    T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
489
    T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
490
}
491

    
492
void do_mfc0_lladdr (void)
493
{
494
    T0 = (int32_t)env->CP0_LLAddr >> 4;
495
}
496

    
497
void do_mfc0_watchlo (uint32_t sel)
498
{
499
    T0 = (int32_t)env->CP0_WatchLo[sel];
500
}
501

    
502
void do_mfc0_watchhi (uint32_t sel)
503
{
504
    T0 = env->CP0_WatchHi[sel];
505
}
506

    
507
void do_mfc0_debug (void)
508
{
509
    T0 = env->CP0_Debug;
510
    if (env->hflags & MIPS_HFLAG_DM)
511
        T0 |= 1 << CP0DB_DM;
512
}
513

    
514
void do_mftc0_debug(void)
515
{
516
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
517

    
518
    /* XXX: Might be wrong, check with EJTAG spec. */
519
    T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
520
         (env->CP0_Debug_tcstatus[other_tc] &
521
          ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
522
}
523

    
524
#if defined(TARGET_MIPS64)
525
void do_dmfc0_tcrestart (void)
526
{
527
    T0 = env->PC[env->current_tc];
528
}
529

    
530
void do_dmfc0_tchalt (void)
531
{
532
    T0 = env->CP0_TCHalt[env->current_tc];
533
}
534

    
535
void do_dmfc0_tccontext (void)
536
{
537
    T0 = env->CP0_TCContext[env->current_tc];
538
}
539

    
540
void do_dmfc0_tcschedule (void)
541
{
542
    T0 = env->CP0_TCSchedule[env->current_tc];
543
}
544

    
545
void do_dmfc0_tcschefback (void)
546
{
547
    T0 = env->CP0_TCScheFBack[env->current_tc];
548
}
549

    
550
void do_dmfc0_lladdr (void)
551
{
552
    T0 = env->CP0_LLAddr >> 4;
553
}
554

    
555
void do_dmfc0_watchlo (uint32_t sel)
556
{
557
    T0 = env->CP0_WatchLo[sel];
558
}
559
#endif /* TARGET_MIPS64 */
560

    
561
void do_mtc0_index (void)
562
{
563
    int num = 1;
564
    unsigned int tmp = env->tlb->nb_tlb;
565

    
566
    do {
567
        tmp >>= 1;
568
        num <<= 1;
569
    } while (tmp);
570
    env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (num - 1));
571
}
572

    
573
void do_mtc0_mvpcontrol (void)
574
{
575
    uint32_t mask = 0;
576
    uint32_t newval;
577

    
578
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
579
        mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
580
                (1 << CP0MVPCo_EVP);
581
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
582
        mask |= (1 << CP0MVPCo_STLB);
583
    newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
584

    
585
    // TODO: Enable/disable shared TLB, enable/disable VPEs.
586

    
587
    env->mvp->CP0_MVPControl = newval;
588
}
589

    
590
void do_mtc0_vpecontrol (void)
591
{
592
    uint32_t mask;
593
    uint32_t newval;
594

    
595
    mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
596
           (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
597
    newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
598

    
599
    /* Yield scheduler intercept not implemented. */
600
    /* Gating storage scheduler intercept not implemented. */
601

    
602
    // TODO: Enable/disable TCs.
603

    
604
    env->CP0_VPEControl = newval;
605
}
606

    
607
void do_mtc0_vpeconf0 (void)
608
{
609
    uint32_t mask = 0;
610
    uint32_t newval;
611

    
612
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
613
        if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
614
            mask |= (0xff << CP0VPEC0_XTC);
615
        mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
616
    }
617
    newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
618

    
619
    // TODO: TC exclusive handling due to ERL/EXL.
620

    
621
    env->CP0_VPEConf0 = newval;
622
}
623

    
624
void do_mtc0_vpeconf1 (void)
625
{
626
    uint32_t mask = 0;
627
    uint32_t newval;
628

    
629
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
630
        mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
631
                (0xff << CP0VPEC1_NCP1);
632
    newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
633

    
634
    /* UDI not implemented. */
635
    /* CP2 not implemented. */
636

    
637
    // TODO: Handle FPU (CP1) binding.
638

    
639
    env->CP0_VPEConf1 = newval;
640
}
641

    
642
void do_mtc0_yqmask (void)
643
{
644
    /* Yield qualifier inputs not implemented. */
645
    env->CP0_YQMask = 0x00000000;
646
}
647

    
648
void do_mtc0_vpeopt (void)
649
{
650
    env->CP0_VPEOpt = T0 & 0x0000ffff;
651
}
652

    
653
void do_mtc0_entrylo0 (void)
654
{
655
    /* Large physaddr (PABITS) not implemented */
656
    /* 1k pages not implemented */
657
    env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
658
}
659

    
660
void do_mtc0_tcstatus (void)
661
{
662
    uint32_t mask = env->CP0_TCStatus_rw_bitmask;
663
    uint32_t newval;
664

    
665
    newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
666

    
667
    // TODO: Sync with CP0_Status.
668

    
669
    env->CP0_TCStatus[env->current_tc] = newval;
670
}
671

    
672
void do_mttc0_tcstatus (void)
673
{
674
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
675

    
676
    // TODO: Sync with CP0_Status.
677

    
678
    env->CP0_TCStatus[other_tc] = T0;
679
}
680

    
681
void do_mtc0_tcbind (void)
682
{
683
    uint32_t mask = (1 << CP0TCBd_TBE);
684
    uint32_t newval;
685

    
686
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
687
        mask |= (1 << CP0TCBd_CurVPE);
688
    newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask);
689
    env->CP0_TCBind[env->current_tc] = newval;
690
}
691

    
692
void do_mttc0_tcbind (void)
693
{
694
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
695
    uint32_t mask = (1 << CP0TCBd_TBE);
696
    uint32_t newval;
697

    
698
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
699
        mask |= (1 << CP0TCBd_CurVPE);
700
    newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask);
701
    env->CP0_TCBind[other_tc] = newval;
702
}
703

    
704
void do_mtc0_tcrestart (void)
705
{
706
    env->PC[env->current_tc] = T0;
707
    env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
708
    env->CP0_LLAddr = 0ULL;
709
    /* MIPS16 not implemented. */
710
}
711

    
712
void do_mttc0_tcrestart (void)
713
{
714
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
715

    
716
    env->PC[other_tc] = T0;
717
    env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
718
    env->CP0_LLAddr = 0ULL;
719
    /* MIPS16 not implemented. */
720
}
721

    
722
void do_mtc0_tchalt (void)
723
{
724
    env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
725

    
726
    // TODO: Halt TC / Restart (if allocated+active) TC.
727
}
728

    
729
void do_mttc0_tchalt (void)
730
{
731
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
732

    
733
    // TODO: Halt TC / Restart (if allocated+active) TC.
734

    
735
    env->CP0_TCHalt[other_tc] = T0;
736
}
737

    
738
void do_mtc0_tccontext (void)
739
{
740
    env->CP0_TCContext[env->current_tc] = T0;
741
}
742

    
743
void do_mttc0_tccontext (void)
744
{
745
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
746

    
747
    env->CP0_TCContext[other_tc] = T0;
748
}
749

    
750
void do_mtc0_tcschedule (void)
751
{
752
    env->CP0_TCSchedule[env->current_tc] = T0;
753
}
754

    
755
void do_mttc0_tcschedule (void)
756
{
757
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
758

    
759
    env->CP0_TCSchedule[other_tc] = T0;
760
}
761

    
762
void do_mtc0_tcschefback (void)
763
{
764
    env->CP0_TCScheFBack[env->current_tc] = T0;
765
}
766

    
767
void do_mttc0_tcschefback (void)
768
{
769
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
770

    
771
    env->CP0_TCScheFBack[other_tc] = T0;
772
}
773

    
774
void do_mtc0_entrylo1 (void)
775
{
776
    /* Large physaddr (PABITS) not implemented */
777
    /* 1k pages not implemented */
778
    env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
779
}
780

    
781
void do_mtc0_context (void)
782
{
783
    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
784
}
785

    
786
void do_mtc0_pagemask (void)
787
{
788
    /* 1k pages not implemented */
789
    env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
790
}
791

    
792
void do_mtc0_pagegrain (void)
793
{
794
    /* SmartMIPS not implemented */
795
    /* Large physaddr (PABITS) not implemented */
796
    /* 1k pages not implemented */
797
    env->CP0_PageGrain = 0;
798
}
799

    
800
void do_mtc0_wired (void)
801
{
802
    env->CP0_Wired = T0 % env->tlb->nb_tlb;
803
}
804

    
805
void do_mtc0_srsconf0 (void)
806
{
807
    env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
808
}
809

    
810
void do_mtc0_srsconf1 (void)
811
{
812
    env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
813
}
814

    
815
void do_mtc0_srsconf2 (void)
816
{
817
    env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
818
}
819

    
820
void do_mtc0_srsconf3 (void)
821
{
822
    env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
823
}
824

    
825
void do_mtc0_srsconf4 (void)
826
{
827
    env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
828
}
829

    
830
void do_mtc0_hwrena (void)
831
{
832
    env->CP0_HWREna = T0 & 0x0000000F;
833
}
834

    
835
void do_mtc0_count (void)
836
{
837
    cpu_mips_store_count(env, T0);
838
}
839

    
840
void do_mtc0_entryhi (void)
841
{
842
    target_ulong old, val;
843

    
844
    /* 1k pages not implemented */
845
    val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
846
#if defined(TARGET_MIPS64)
847
    val &= env->SEGMask;
848
#endif
849
    old = env->CP0_EntryHi;
850
    env->CP0_EntryHi = val;
851
    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
852
        uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
853
        env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
854
    }
855
    /* If the ASID changes, flush qemu's TLB.  */
856
    if ((old & 0xFF) != (val & 0xFF))
857
        cpu_mips_tlb_flush(env, 1);
858
}
859

    
860
void do_mttc0_entryhi(void)
861
{
862
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
863

    
864
    env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
865
    env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
866
}
867

    
868
void do_mtc0_compare (void)
869
{
870
    cpu_mips_store_compare(env, T0);
871
}
872

    
873
void do_mtc0_status (void)
874
{
875
    uint32_t val, old;
876
    uint32_t mask = env->CP0_Status_rw_bitmask;
877

    
878
    val = T0 & mask;
879
    old = env->CP0_Status;
880
    env->CP0_Status = (env->CP0_Status & ~mask) | val;
881
    compute_hflags(env);
882
    if (loglevel & CPU_LOG_EXEC)
883
        do_mtc0_status_debug(old, val);
884
    cpu_mips_update_irq(env);
885
}
886

    
887
void do_mttc0_status(void)
888
{
889
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
890
    uint32_t tcstatus = env->CP0_TCStatus[other_tc];
891

    
892
    env->CP0_Status = T0 & ~0xf1000018;
893
    tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
894
    tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
895
    tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
896
    env->CP0_TCStatus[other_tc] = tcstatus;
897
}
898

    
899
void do_mtc0_intctl (void)
900
{
901
    /* vectored interrupts not implemented, no performance counters. */
902
    env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
903
}
904

    
905
void do_mtc0_srsctl (void)
906
{
907
    uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
908
    env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
909
}
910

    
911
void do_mtc0_cause (void)
912
{
913
    uint32_t mask = 0x00C00300;
914
    uint32_t old = env->CP0_Cause;
915

    
916
    if (env->insn_flags & ISA_MIPS32R2)
917
        mask |= 1 << CP0Ca_DC;
918

    
919
    env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
920

    
921
    if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
922
        if (env->CP0_Cause & (1 << CP0Ca_DC))
923
            cpu_mips_stop_count(env);
924
        else
925
            cpu_mips_start_count(env);
926
    }
927

    
928
    /* Handle the software interrupt as an hardware one, as they
929
       are very similar */
930
    if (T0 & CP0Ca_IP_mask) {
931
        cpu_mips_update_irq(env);
932
    }
933
}
934

    
935
void do_mtc0_ebase (void)
936
{
937
    /* vectored interrupts not implemented */
938
    /* Multi-CPU not implemented */
939
    env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
940
}
941

    
942
void do_mtc0_config0 (void)
943
{
944
    env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
945
}
946

    
947
void do_mtc0_config2 (void)
948
{
949
    /* tertiary/secondary caches not implemented */
950
    env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
951
}
952

    
953
void do_mtc0_watchlo (uint32_t sel)
954
{
955
    /* Watch exceptions for instructions, data loads, data stores
956
       not implemented. */
957
    env->CP0_WatchLo[sel] = (T0 & ~0x7);
958
}
959

    
960
void do_mtc0_watchhi (uint32_t sel)
961
{
962
    env->CP0_WatchHi[sel] = (T0 & 0x40FF0FF8);
963
    env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & T0 & 0x7);
964
}
965

    
966
void do_mtc0_xcontext (void)
967
{
968
    target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
969
    env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
970
}
971

    
972
void do_mtc0_framemask (void)
973
{
974
    env->CP0_Framemask = T0; /* XXX */
975
}
976

    
977
void do_mtc0_debug (void)
978
{
979
    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
980
    if (T0 & (1 << CP0DB_DM))
981
        env->hflags |= MIPS_HFLAG_DM;
982
    else
983
        env->hflags &= ~MIPS_HFLAG_DM;
984
}
985

    
986
void do_mttc0_debug(void)
987
{
988
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
989

    
990
    /* XXX: Might be wrong, check with EJTAG spec. */
991
    env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
992
    env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
993
                     (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
994
}
995

    
996
void do_mtc0_performance0 (void)
997
{
998
    env->CP0_Performance0 = T0 & 0x000007ff;
999
}
1000

    
1001
void do_mtc0_taglo (void)
1002
{
1003
    env->CP0_TagLo = T0 & 0xFFFFFCF6;
1004
}
1005

    
1006
void do_mtc0_datalo (void)
1007
{
1008
    env->CP0_DataLo = T0; /* XXX */
1009
}
1010

    
1011
void do_mtc0_taghi (void)
1012
{
1013
    env->CP0_TagHi = T0; /* XXX */
1014
}
1015

    
1016
void do_mtc0_datahi (void)
1017
{
1018
    env->CP0_DataHi = T0; /* XXX */
1019
}
1020

    
1021
void do_mtc0_status_debug(uint32_t old, uint32_t val)
1022
{
1023
    fprintf(logfile, "Status %08x (%08x) => %08x (%08x) Cause %08x",
1024
            old, old & env->CP0_Cause & CP0Ca_IP_mask,
1025
            val, val & env->CP0_Cause & CP0Ca_IP_mask,
1026
            env->CP0_Cause);
1027
    switch (env->hflags & MIPS_HFLAG_KSU) {
1028
    case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
1029
    case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
1030
    case MIPS_HFLAG_KM: fputs("\n", logfile); break;
1031
    default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1032
    }
1033
}
1034

    
1035
void do_mtc0_status_irqraise_debug(void)
1036
{
1037
    fprintf(logfile, "Raise pending IRQs\n");
1038
}
1039
#endif /* !CONFIG_USER_ONLY */
1040

    
1041
/* MIPS MT functions */
1042
void do_mftgpr(uint32_t sel)
1043
{
1044
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1045

    
1046
    T0 = env->gpr[other_tc][sel];
1047
}
1048

    
1049
void do_mftlo(uint32_t sel)
1050
{
1051
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1052

    
1053
    T0 = env->LO[other_tc][sel];
1054
}
1055

    
1056
void do_mfthi(uint32_t sel)
1057
{
1058
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1059

    
1060
    T0 = env->HI[other_tc][sel];
1061
}
1062

    
1063
void do_mftacx(uint32_t sel)
1064
{
1065
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1066

    
1067
    T0 = env->ACX[other_tc][sel];
1068
}
1069

    
1070
void do_mftdsp(void)
1071
{
1072
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1073

    
1074
    T0 = env->DSPControl[other_tc];
1075
}
1076

    
1077
void do_mttgpr(uint32_t sel)
1078
{
1079
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1080

    
1081
    T0 = env->gpr[other_tc][sel];
1082
}
1083

    
1084
void do_mttlo(uint32_t sel)
1085
{
1086
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1087

    
1088
    T0 = env->LO[other_tc][sel];
1089
}
1090

    
1091
void do_mtthi(uint32_t sel)
1092
{
1093
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1094

    
1095
    T0 = env->HI[other_tc][sel];
1096
}
1097

    
1098
void do_mttacx(uint32_t sel)
1099
{
1100
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1101

    
1102
    T0 = env->ACX[other_tc][sel];
1103
}
1104

    
1105
void do_mttdsp(void)
1106
{
1107
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1108

    
1109
    T0 = env->DSPControl[other_tc];
1110
}
1111

    
1112
/* MIPS MT functions */
1113
void do_dmt(void)
1114
{
1115
    // TODO
1116
    T0 = 0;
1117
    // rt = T0
1118
}
1119

    
1120
void do_emt(void)
1121
{
1122
    // TODO
1123
    T0 = 0;
1124
    // rt = T0
1125
}
1126

    
1127
void do_dvpe(void)
1128
{
1129
    // TODO
1130
    T0 = 0;
1131
    // rt = T0
1132
}
1133

    
1134
void do_evpe(void)
1135
{
1136
    // TODO
1137
    T0 = 0;
1138
    // rt = T0
1139
}
1140

    
1141
void do_fork(void)
1142
{
1143
    // T0 = rt, T1 = rs
1144
    T0 = 0;
1145
    // TODO: store to TC register
1146
}
1147

    
1148
void do_yield(void)
1149
{
1150
    if (T0 < 0) {
1151
        /* No scheduling policy implemented. */
1152
        if (T0 != -2) {
1153
            if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
1154
                env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
1155
                env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1156
                env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
1157
                do_raise_exception(EXCP_THREAD);
1158
            }
1159
        }
1160
    } else if (T0 == 0) {
1161
        if (0 /* TODO: TC underflow */) {
1162
            env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1163
            do_raise_exception(EXCP_THREAD);
1164
        } else {
1165
            // TODO: Deallocate TC
1166
        }
1167
    } else if (T0 > 0) {
1168
        /* Yield qualifier inputs not implemented. */
1169
        env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1170
        env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
1171
        do_raise_exception(EXCP_THREAD);
1172
    }
1173
    T0 = env->CP0_YQMask;
1174
}
1175

    
1176
/* CP1 functions */
1177
void fpu_handle_exception(void)
1178
{
1179
#ifdef CONFIG_SOFTFLOAT
1180
    int flags = get_float_exception_flags(&env->fpu->fp_status);
1181
    unsigned int cpuflags = 0, enable, cause = 0;
1182

    
1183
    enable = GET_FP_ENABLE(env->fpu->fcr31);
1184

    
1185
    /* determine current flags */
1186
    if (flags & float_flag_invalid) {
1187
        cpuflags |= FP_INVALID;
1188
        cause |= FP_INVALID & enable;
1189
    }
1190
    if (flags & float_flag_divbyzero) {
1191
        cpuflags |= FP_DIV0;
1192
        cause |= FP_DIV0 & enable;
1193
    }
1194
    if (flags & float_flag_overflow) {
1195
        cpuflags |= FP_OVERFLOW;
1196
        cause |= FP_OVERFLOW & enable;
1197
    }
1198
    if (flags & float_flag_underflow) {
1199
        cpuflags |= FP_UNDERFLOW;
1200
        cause |= FP_UNDERFLOW & enable;
1201
    }
1202
    if (flags & float_flag_inexact) {
1203
        cpuflags |= FP_INEXACT;
1204
        cause |= FP_INEXACT & enable;
1205
    }
1206
    SET_FP_FLAGS(env->fpu->fcr31, cpuflags);
1207
    SET_FP_CAUSE(env->fpu->fcr31, cause);
1208
#else
1209
    SET_FP_FLAGS(env->fpu->fcr31, 0);
1210
    SET_FP_CAUSE(env->fpu->fcr31, 0);
1211
#endif
1212
}
1213

    
1214
#ifndef CONFIG_USER_ONLY
1215
/* TLB management */
1216
void cpu_mips_tlb_flush (CPUState *env, int flush_global)
1217
{
1218
    /* Flush qemu's TLB and discard all shadowed entries.  */
1219
    tlb_flush (env, flush_global);
1220
    env->tlb->tlb_in_use = env->tlb->nb_tlb;
1221
}
1222

    
1223
static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
1224
{
1225
    /* Discard entries from env->tlb[first] onwards.  */
1226
    while (env->tlb->tlb_in_use > first) {
1227
        r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
1228
    }
1229
}
1230

    
1231
static void r4k_fill_tlb (int idx)
1232
{
1233
    r4k_tlb_t *tlb;
1234

    
1235
    /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
1236
    tlb = &env->tlb->mmu.r4k.tlb[idx];
1237
    tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
1238
#if defined(TARGET_MIPS64)
1239
    tlb->VPN &= env->SEGMask;
1240
#endif
1241
    tlb->ASID = env->CP0_EntryHi & 0xFF;
1242
    tlb->PageMask = env->CP0_PageMask;
1243
    tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
1244
    tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
1245
    tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
1246
    tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
1247
    tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
1248
    tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
1249
    tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
1250
    tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
1251
    tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
1252
}
1253

    
1254
void r4k_do_tlbwi (void)
1255
{
1256
    /* Discard cached TLB entries.  We could avoid doing this if the
1257
       tlbwi is just upgrading access permissions on the current entry;
1258
       that might be a further win.  */
1259
    r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb);
1260

    
1261
    r4k_invalidate_tlb(env, env->CP0_Index % env->tlb->nb_tlb, 0);
1262
    r4k_fill_tlb(env->CP0_Index % env->tlb->nb_tlb);
1263
}
1264

    
1265
void r4k_do_tlbwr (void)
1266
{
1267
    int r = cpu_mips_get_random(env);
1268

    
1269
    r4k_invalidate_tlb(env, r, 1);
1270
    r4k_fill_tlb(r);
1271
}
1272

    
1273
void r4k_do_tlbp (void)
1274
{
1275
    r4k_tlb_t *tlb;
1276
    target_ulong mask;
1277
    target_ulong tag;
1278
    target_ulong VPN;
1279
    uint8_t ASID;
1280
    int i;
1281

    
1282
    ASID = env->CP0_EntryHi & 0xFF;
1283
    for (i = 0; i < env->tlb->nb_tlb; i++) {
1284
        tlb = &env->tlb->mmu.r4k.tlb[i];
1285
        /* 1k pages are not supported. */
1286
        mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1287
        tag = env->CP0_EntryHi & ~mask;
1288
        VPN = tlb->VPN & ~mask;
1289
        /* Check ASID, virtual page number & size */
1290
        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1291
            /* TLB match */
1292
            env->CP0_Index = i;
1293
            break;
1294
        }
1295
    }
1296
    if (i == env->tlb->nb_tlb) {
1297
        /* No match.  Discard any shadow entries, if any of them match.  */
1298
        for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
1299
            tlb = &env->tlb->mmu.r4k.tlb[i];
1300
            /* 1k pages are not supported. */
1301
            mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1302
            tag = env->CP0_EntryHi & ~mask;
1303
            VPN = tlb->VPN & ~mask;
1304
            /* Check ASID, virtual page number & size */
1305
            if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1306
                r4k_mips_tlb_flush_extra (env, i);
1307
                break;
1308
            }
1309
        }
1310

    
1311
        env->CP0_Index |= 0x80000000;
1312
    }
1313
}
1314

    
1315
void r4k_do_tlbr (void)
1316
{
1317
    r4k_tlb_t *tlb;
1318
    uint8_t ASID;
1319

    
1320
    ASID = env->CP0_EntryHi & 0xFF;
1321
    tlb = &env->tlb->mmu.r4k.tlb[env->CP0_Index % env->tlb->nb_tlb];
1322

    
1323
    /* If this will change the current ASID, flush qemu's TLB.  */
1324
    if (ASID != tlb->ASID)
1325
        cpu_mips_tlb_flush (env, 1);
1326

    
1327
    r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
1328

    
1329
    env->CP0_EntryHi = tlb->VPN | tlb->ASID;
1330
    env->CP0_PageMask = tlb->PageMask;
1331
    env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
1332
                        (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
1333
    env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
1334
                        (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
1335
}
1336

    
1337
#endif /* !CONFIG_USER_ONLY */
1338

    
1339
void dump_ldst (const unsigned char *func)
1340
{
1341
    if (loglevel)
1342
        fprintf(logfile, "%s => " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__, T0, T1);
1343
}
1344

    
1345
void dump_sc (void)
1346
{
1347
    if (loglevel) {
1348
        fprintf(logfile, "%s " TARGET_FMT_lx " at " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", __func__,
1349
                T1, T0, env->CP0_LLAddr);
1350
    }
1351
}
1352

    
1353
/* Specials */
1354
void do_di (void)
1355
{
1356
    T0 = env->CP0_Status;
1357
    env->CP0_Status = T0 & ~(1 << CP0St_IE);
1358
    cpu_mips_update_irq(env);
1359
}
1360

    
1361
void do_ei (void)
1362
{
1363
    T0 = env->CP0_Status;
1364
    env->CP0_Status = T0 | (1 << CP0St_IE);
1365
    cpu_mips_update_irq(env);
1366
}
1367

    
1368
void debug_pre_eret (void)
1369
{
1370
    fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1371
            env->PC[env->current_tc], env->CP0_EPC);
1372
    if (env->CP0_Status & (1 << CP0St_ERL))
1373
        fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1374
    if (env->hflags & MIPS_HFLAG_DM)
1375
        fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1376
    fputs("\n", logfile);
1377
}
1378

    
1379
void debug_post_eret (void)
1380
{
1381
    fprintf(logfile, "  =>  PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1382
            env->PC[env->current_tc], env->CP0_EPC);
1383
    if (env->CP0_Status & (1 << CP0St_ERL))
1384
        fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1385
    if (env->hflags & MIPS_HFLAG_DM)
1386
        fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1387
    switch (env->hflags & MIPS_HFLAG_KSU) {
1388
    case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
1389
    case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
1390
    case MIPS_HFLAG_KM: fputs("\n", logfile); break;
1391
    default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1392
    }
1393
}
1394

    
1395
void do_eret (void)
1396
{
1397
    if (loglevel & CPU_LOG_EXEC)
1398
        debug_pre_eret();
1399
    if (env->CP0_Status & (1 << CP0St_ERL)) {
1400
        env->PC[env->current_tc] = env->CP0_ErrorEPC;
1401
        env->CP0_Status &= ~(1 << CP0St_ERL);
1402
    } else {
1403
        env->PC[env->current_tc] = env->CP0_EPC;
1404
        env->CP0_Status &= ~(1 << CP0St_EXL);
1405
    }
1406
    compute_hflags(env);
1407
    if (loglevel & CPU_LOG_EXEC)
1408
        debug_post_eret();
1409
    env->CP0_LLAddr = 1;
1410
}
1411

    
1412
void do_deret (void)
1413
{
1414
    if (loglevel & CPU_LOG_EXEC)
1415
        debug_pre_eret();
1416
    env->PC[env->current_tc] = env->CP0_DEPC;
1417
    env->hflags &= MIPS_HFLAG_DM;
1418
    compute_hflags(env);
1419
    if (loglevel & CPU_LOG_EXEC)
1420
        debug_post_eret();
1421
    env->CP0_LLAddr = 1;
1422
}
1423

    
1424
void do_rdhwr_cpunum(void)
1425
{
1426
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1427
        (env->CP0_HWREna & (1 << 0)))
1428
        T0 = env->CP0_EBase & 0x3ff;
1429
    else
1430
        do_raise_exception(EXCP_RI);
1431
}
1432

    
1433
void do_rdhwr_synci_step(void)
1434
{
1435
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1436
        (env->CP0_HWREna & (1 << 1)))
1437
        T0 = env->SYNCI_Step;
1438
    else
1439
        do_raise_exception(EXCP_RI);
1440
}
1441

    
1442
void do_rdhwr_cc(void)
1443
{
1444
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1445
        (env->CP0_HWREna & (1 << 2)))
1446
        T0 = env->CP0_Count;
1447
    else
1448
        do_raise_exception(EXCP_RI);
1449
}
1450

    
1451
void do_rdhwr_ccres(void)
1452
{
1453
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1454
        (env->CP0_HWREna & (1 << 3)))
1455
        T0 = env->CCRes;
1456
    else
1457
        do_raise_exception(EXCP_RI);
1458
}
1459

    
1460
/* Bitfield operations. */
1461
void do_ext(uint32_t pos, uint32_t size)
1462
{
1463
    T0 = (int32_t)((T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
1464
}
1465

    
1466
void do_ins(uint32_t pos, uint32_t size)
1467
{
1468
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
1469

    
1470
    T0 = (int32_t)((T0 & ~mask) | ((T1 << pos) & mask));
1471
}
1472

    
1473
void do_wsbh(void)
1474
{
1475
    T0 = (int32_t)(((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF));
1476
}
1477

    
1478
#if defined(TARGET_MIPS64)
1479
void do_dext(uint32_t pos, uint32_t size)
1480
{
1481
    T0 = (T1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
1482
}
1483

    
1484
void do_dins(uint32_t pos, uint32_t size)
1485
{
1486
    target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
1487

    
1488
    T0 = (T0 & ~mask) | ((T1 << pos) & mask);
1489
}
1490

    
1491
void do_dsbh(void)
1492
{
1493
    T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
1494
}
1495

    
1496
void do_dshd(void)
1497
{
1498
    T1 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
1499
    T0 = (T1 << 32) | (T1 >> 32);
1500
}
1501
#endif
1502

    
1503
void do_pmon (int function)
1504
{
1505
    function /= 2;
1506
    switch (function) {
1507
    case 2: /* TODO: char inbyte(int waitflag); */
1508
        if (env->gpr[env->current_tc][4] == 0)
1509
            env->gpr[env->current_tc][2] = -1;
1510
        /* Fall through */
1511
    case 11: /* TODO: char inbyte (void); */
1512
        env->gpr[env->current_tc][2] = -1;
1513
        break;
1514
    case 3:
1515
    case 12:
1516
        printf("%c", (char)(env->gpr[env->current_tc][4] & 0xFF));
1517
        break;
1518
    case 17:
1519
        break;
1520
    case 158:
1521
        {
1522
            unsigned char *fmt = (void *)(unsigned long)env->gpr[env->current_tc][4];
1523
            printf("%s", fmt);
1524
        }
1525
        break;
1526
    }
1527
}
1528

    
1529
void do_wait (void)
1530
{
1531
    env->halted = 1;
1532
    do_raise_exception(EXCP_HLT);
1533
}
1534

    
1535
#if !defined(CONFIG_USER_ONLY)
1536

    
1537
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
1538

    
1539
#define MMUSUFFIX _mmu
1540
#define ALIGNED_ONLY
1541

    
1542
#define SHIFT 0
1543
#include "softmmu_template.h"
1544

    
1545
#define SHIFT 1
1546
#include "softmmu_template.h"
1547

    
1548
#define SHIFT 2
1549
#include "softmmu_template.h"
1550

    
1551
#define SHIFT 3
1552
#include "softmmu_template.h"
1553

    
1554
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
1555
{
1556
    env->CP0_BadVAddr = addr;
1557
    do_restore_state (retaddr);
1558
    do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
1559
}
1560

    
1561
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1562
{
1563
    TranslationBlock *tb;
1564
    CPUState *saved_env;
1565
    unsigned long pc;
1566
    int ret;
1567

    
1568
    /* XXX: hack to restore env in all cases, even if not called from
1569
       generated code */
1570
    saved_env = env;
1571
    env = cpu_single_env;
1572
    ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1573
    if (ret) {
1574
        if (retaddr) {
1575
            /* now we have a real cpu fault */
1576
            pc = (unsigned long)retaddr;
1577
            tb = tb_find_pc(pc);
1578
            if (tb) {
1579
                /* the PC is inside the translated code. It means that we have
1580
                   a virtual CPU fault */
1581
                cpu_restore_state(tb, env, pc, NULL);
1582
            }
1583
        }
1584
        do_raise_exception_err(env->exception_index, env->error_code);
1585
    }
1586
    env = saved_env;
1587
}
1588

    
1589
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1590
                          int unused)
1591
{
1592
    if (is_exec)
1593
        do_raise_exception(EXCP_IBE);
1594
    else
1595
        do_raise_exception(EXCP_DBE);
1596
}
1597
#endif /* !CONFIG_USER_ONLY */
1598

    
1599
/* Complex FPU operations which may need stack space. */
1600

    
1601
#define FLOAT_ONE32 make_float32(0x3f8 << 20)
1602
#define FLOAT_ONE64 make_float64(0x3ffULL << 52)
1603
#define FLOAT_TWO32 make_float32(1 << 30)
1604
#define FLOAT_TWO64 make_float64(1ULL << 62)
1605
#define FLOAT_QNAN32 0x7fbfffff
1606
#define FLOAT_QNAN64 0x7ff7ffffffffffffULL
1607
#define FLOAT_SNAN32 0x7fffffff
1608
#define FLOAT_SNAN64 0x7fffffffffffffffULL
1609

    
1610
/* convert MIPS rounding mode in FCR31 to IEEE library */
1611
unsigned int ieee_rm[] = {
1612
    float_round_nearest_even,
1613
    float_round_to_zero,
1614
    float_round_up,
1615
    float_round_down
1616
};
1617

    
1618
#define RESTORE_ROUNDING_MODE \
1619
    set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status)
1620

    
1621
void do_cfc1 (uint32_t reg)
1622
{
1623
    switch (reg) {
1624
    case 0:
1625
        T0 = (int32_t)env->fpu->fcr0;
1626
        break;
1627
    case 25:
1628
        T0 = ((env->fpu->fcr31 >> 24) & 0xfe) | ((env->fpu->fcr31 >> 23) & 0x1);
1629
        break;
1630
    case 26:
1631
        T0 = env->fpu->fcr31 & 0x0003f07c;
1632
        break;
1633
    case 28:
1634
        T0 = (env->fpu->fcr31 & 0x00000f83) | ((env->fpu->fcr31 >> 22) & 0x4);
1635
        break;
1636
    default:
1637
        T0 = (int32_t)env->fpu->fcr31;
1638
        break;
1639
    }
1640
}
1641

    
1642
void do_ctc1 (uint32_t reg)
1643
{
1644
    switch(reg) {
1645
    case 25:
1646
        if (T0 & 0xffffff00)
1647
            return;
1648
        env->fpu->fcr31 = (env->fpu->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) |
1649
                     ((T0 & 0x1) << 23);
1650
        break;
1651
    case 26:
1652
        if (T0 & 0x007c0000)
1653
            return;
1654
        env->fpu->fcr31 = (env->fpu->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c);
1655
        break;
1656
    case 28:
1657
        if (T0 & 0x007c0000)
1658
            return;
1659
        env->fpu->fcr31 = (env->fpu->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) |
1660
                     ((T0 & 0x4) << 22);
1661
        break;
1662
    case 31:
1663
        if (T0 & 0x007c0000)
1664
            return;
1665
        env->fpu->fcr31 = T0;
1666
        break;
1667
    default:
1668
        return;
1669
    }
1670
    /* set rounding mode */
1671
    RESTORE_ROUNDING_MODE;
1672
    set_float_exception_flags(0, &env->fpu->fp_status);
1673
    if ((GET_FP_ENABLE(env->fpu->fcr31) | 0x20) & GET_FP_CAUSE(env->fpu->fcr31))
1674
        do_raise_exception(EXCP_FPE);
1675
}
1676

    
1677
static always_inline char ieee_ex_to_mips(char xcpt)
1678
{
1679
    return (xcpt & float_flag_inexact) >> 5 |
1680
           (xcpt & float_flag_underflow) >> 3 |
1681
           (xcpt & float_flag_overflow) >> 1 |
1682
           (xcpt & float_flag_divbyzero) << 1 |
1683
           (xcpt & float_flag_invalid) << 4;
1684
}
1685

    
1686
static always_inline char mips_ex_to_ieee(char xcpt)
1687
{
1688
    return (xcpt & FP_INEXACT) << 5 |
1689
           (xcpt & FP_UNDERFLOW) << 3 |
1690
           (xcpt & FP_OVERFLOW) << 1 |
1691
           (xcpt & FP_DIV0) >> 1 |
1692
           (xcpt & FP_INVALID) >> 4;
1693
}
1694

    
1695
static always_inline void update_fcr31(void)
1696
{
1697
    int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fpu->fp_status));
1698

    
1699
    SET_FP_CAUSE(env->fpu->fcr31, tmp);
1700
    if (GET_FP_ENABLE(env->fpu->fcr31) & tmp)
1701
        do_raise_exception(EXCP_FPE);
1702
    else
1703
        UPDATE_FP_FLAGS(env->fpu->fcr31, tmp);
1704
}
1705

    
1706
/* Float support.
1707
   Single precition routines have a "s" suffix, double precision a
1708
   "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
1709
   paired single lower "pl", paired single upper "pu".  */
1710

    
1711
#define FLOAT_OP(name, p) void do_float_##name##_##p(void)
1712

    
1713
/* unary operations, modifying fp status  */
1714
#define FLOAT_UNOP(name)  \
1715
FLOAT_OP(name, d)         \
1716
{                         \
1717
    FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
1718
}                         \
1719
FLOAT_OP(name, s)         \
1720
{                         \
1721
    FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
1722
}
1723
FLOAT_UNOP(sqrt)
1724
#undef FLOAT_UNOP
1725

    
1726
FLOAT_OP(cvtd, s)
1727
{
1728
    set_float_exception_flags(0, &env->fpu->fp_status);
1729
    FDT2 = float32_to_float64(FST0, &env->fpu->fp_status);
1730
    update_fcr31();
1731
}
1732
FLOAT_OP(cvtd, w)
1733
{
1734
    set_float_exception_flags(0, &env->fpu->fp_status);
1735
    FDT2 = int32_to_float64(WT0, &env->fpu->fp_status);
1736
    update_fcr31();
1737
}
1738
FLOAT_OP(cvtd, l)
1739
{
1740
    set_float_exception_flags(0, &env->fpu->fp_status);
1741
    FDT2 = int64_to_float64(DT0, &env->fpu->fp_status);
1742
    update_fcr31();
1743
}
1744
FLOAT_OP(cvtl, d)
1745
{
1746
    set_float_exception_flags(0, &env->fpu->fp_status);
1747
    DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
1748
    update_fcr31();
1749
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1750
        DT2 = FLOAT_SNAN64;
1751
}
1752
FLOAT_OP(cvtl, s)
1753
{
1754
    set_float_exception_flags(0, &env->fpu->fp_status);
1755
    DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
1756
    update_fcr31();
1757
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1758
        DT2 = FLOAT_SNAN64;
1759
}
1760

    
1761
FLOAT_OP(cvtps, pw)
1762
{
1763
    set_float_exception_flags(0, &env->fpu->fp_status);
1764
    FST2 = int32_to_float32(WT0, &env->fpu->fp_status);
1765
    FSTH2 = int32_to_float32(WTH0, &env->fpu->fp_status);
1766
    update_fcr31();
1767
}
1768
FLOAT_OP(cvtpw, ps)
1769
{
1770
    set_float_exception_flags(0, &env->fpu->fp_status);
1771
    WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
1772
    WTH2 = float32_to_int32(FSTH0, &env->fpu->fp_status);
1773
    update_fcr31();
1774
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1775
        WT2 = FLOAT_SNAN32;
1776
}
1777
FLOAT_OP(cvts, d)
1778
{
1779
    set_float_exception_flags(0, &env->fpu->fp_status);
1780
    FST2 = float64_to_float32(FDT0, &env->fpu->fp_status);
1781
    update_fcr31();
1782
}
1783
FLOAT_OP(cvts, w)
1784
{
1785
    set_float_exception_flags(0, &env->fpu->fp_status);
1786
    FST2 = int32_to_float32(WT0, &env->fpu->fp_status);
1787
    update_fcr31();
1788
}
1789
FLOAT_OP(cvts, l)
1790
{
1791
    set_float_exception_flags(0, &env->fpu->fp_status);
1792
    FST2 = int64_to_float32(DT0, &env->fpu->fp_status);
1793
    update_fcr31();
1794
}
1795
FLOAT_OP(cvts, pl)
1796
{
1797
    set_float_exception_flags(0, &env->fpu->fp_status);
1798
    WT2 = WT0;
1799
    update_fcr31();
1800
}
1801
FLOAT_OP(cvts, pu)
1802
{
1803
    set_float_exception_flags(0, &env->fpu->fp_status);
1804
    WT2 = WTH0;
1805
    update_fcr31();
1806
}
1807
FLOAT_OP(cvtw, s)
1808
{
1809
    set_float_exception_flags(0, &env->fpu->fp_status);
1810
    WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
1811
    update_fcr31();
1812
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1813
        WT2 = FLOAT_SNAN32;
1814
}
1815
FLOAT_OP(cvtw, d)
1816
{
1817
    set_float_exception_flags(0, &env->fpu->fp_status);
1818
    WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
1819
    update_fcr31();
1820
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1821
        WT2 = FLOAT_SNAN32;
1822
}
1823

    
1824
FLOAT_OP(roundl, d)
1825
{
1826
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
1827
    DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
1828
    RESTORE_ROUNDING_MODE;
1829
    update_fcr31();
1830
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1831
        DT2 = FLOAT_SNAN64;
1832
}
1833
FLOAT_OP(roundl, s)
1834
{
1835
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
1836
    DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
1837
    RESTORE_ROUNDING_MODE;
1838
    update_fcr31();
1839
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1840
        DT2 = FLOAT_SNAN64;
1841
}
1842
FLOAT_OP(roundw, d)
1843
{
1844
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
1845
    WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
1846
    RESTORE_ROUNDING_MODE;
1847
    update_fcr31();
1848
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1849
        WT2 = FLOAT_SNAN32;
1850
}
1851
FLOAT_OP(roundw, s)
1852
{
1853
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
1854
    WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
1855
    RESTORE_ROUNDING_MODE;
1856
    update_fcr31();
1857
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1858
        WT2 = FLOAT_SNAN32;
1859
}
1860

    
1861
FLOAT_OP(truncl, d)
1862
{
1863
    DT2 = float64_to_int64_round_to_zero(FDT0, &env->fpu->fp_status);
1864
    update_fcr31();
1865
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1866
        DT2 = FLOAT_SNAN64;
1867
}
1868
FLOAT_OP(truncl, s)
1869
{
1870
    DT2 = float32_to_int64_round_to_zero(FST0, &env->fpu->fp_status);
1871
    update_fcr31();
1872
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1873
        DT2 = FLOAT_SNAN64;
1874
}
1875
FLOAT_OP(truncw, d)
1876
{
1877
    WT2 = float64_to_int32_round_to_zero(FDT0, &env->fpu->fp_status);
1878
    update_fcr31();
1879
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1880
        WT2 = FLOAT_SNAN32;
1881
}
1882
FLOAT_OP(truncw, s)
1883
{
1884
    WT2 = float32_to_int32_round_to_zero(FST0, &env->fpu->fp_status);
1885
    update_fcr31();
1886
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1887
        WT2 = FLOAT_SNAN32;
1888
}
1889

    
1890
FLOAT_OP(ceill, d)
1891
{
1892
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
1893
    DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
1894
    RESTORE_ROUNDING_MODE;
1895
    update_fcr31();
1896
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1897
        DT2 = FLOAT_SNAN64;
1898
}
1899
FLOAT_OP(ceill, s)
1900
{
1901
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
1902
    DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
1903
    RESTORE_ROUNDING_MODE;
1904
    update_fcr31();
1905
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1906
        DT2 = FLOAT_SNAN64;
1907
}
1908
FLOAT_OP(ceilw, d)
1909
{
1910
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
1911
    WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
1912
    RESTORE_ROUNDING_MODE;
1913
    update_fcr31();
1914
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1915
        WT2 = FLOAT_SNAN32;
1916
}
1917
FLOAT_OP(ceilw, s)
1918
{
1919
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
1920
    WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
1921
    RESTORE_ROUNDING_MODE;
1922
    update_fcr31();
1923
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1924
        WT2 = FLOAT_SNAN32;
1925
}
1926

    
1927
FLOAT_OP(floorl, d)
1928
{
1929
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
1930
    DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
1931
    RESTORE_ROUNDING_MODE;
1932
    update_fcr31();
1933
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1934
        DT2 = FLOAT_SNAN64;
1935
}
1936
FLOAT_OP(floorl, s)
1937
{
1938
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
1939
    DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
1940
    RESTORE_ROUNDING_MODE;
1941
    update_fcr31();
1942
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1943
        DT2 = FLOAT_SNAN64;
1944
}
1945
FLOAT_OP(floorw, d)
1946
{
1947
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
1948
    WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
1949
    RESTORE_ROUNDING_MODE;
1950
    update_fcr31();
1951
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1952
        WT2 = FLOAT_SNAN32;
1953
}
1954
FLOAT_OP(floorw, s)
1955
{
1956
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
1957
    WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
1958
    RESTORE_ROUNDING_MODE;
1959
    update_fcr31();
1960
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
1961
        WT2 = FLOAT_SNAN32;
1962
}
1963

    
1964
/* unary operations, not modifying fp status  */
1965
#define FLOAT_UNOP(name)  \
1966
FLOAT_OP(name, d)         \
1967
{                         \
1968
    FDT2 = float64_ ## name(FDT0);   \
1969
}                         \
1970
FLOAT_OP(name, s)         \
1971
{                         \
1972
    FST2 = float32_ ## name(FST0);   \
1973
}                         \
1974
FLOAT_OP(name, ps)        \
1975
{                         \
1976
    FST2 = float32_ ## name(FST0);   \
1977
    FSTH2 = float32_ ## name(FSTH0); \
1978
}
1979
FLOAT_UNOP(abs)
1980
FLOAT_UNOP(chs)
1981
#undef FLOAT_UNOP
1982

    
1983
/* MIPS specific unary operations */
1984
FLOAT_OP(recip, d)
1985
{
1986
    set_float_exception_flags(0, &env->fpu->fp_status);
1987
    FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status);
1988
    update_fcr31();
1989
}
1990
FLOAT_OP(recip, s)
1991
{
1992
    set_float_exception_flags(0, &env->fpu->fp_status);
1993
    FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status);
1994
    update_fcr31();
1995
}
1996

    
1997
FLOAT_OP(rsqrt, d)
1998
{
1999
    set_float_exception_flags(0, &env->fpu->fp_status);
2000
    FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status);
2001
    FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status);
2002
    update_fcr31();
2003
}
2004
FLOAT_OP(rsqrt, s)
2005
{
2006
    set_float_exception_flags(0, &env->fpu->fp_status);
2007
    FST2 = float32_sqrt(FST0, &env->fpu->fp_status);
2008
    FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status);
2009
    update_fcr31();
2010
}
2011

    
2012
FLOAT_OP(recip1, d)
2013
{
2014
    set_float_exception_flags(0, &env->fpu->fp_status);
2015
    FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status);
2016
    update_fcr31();
2017
}
2018
FLOAT_OP(recip1, s)
2019
{
2020
    set_float_exception_flags(0, &env->fpu->fp_status);
2021
    FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status);
2022
    update_fcr31();
2023
}
2024
FLOAT_OP(recip1, ps)
2025
{
2026
    set_float_exception_flags(0, &env->fpu->fp_status);
2027
    FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status);
2028
    FSTH2 = float32_div(FLOAT_ONE32, FSTH0, &env->fpu->fp_status);
2029
    update_fcr31();
2030
}
2031

    
2032
FLOAT_OP(rsqrt1, d)
2033
{
2034
    set_float_exception_flags(0, &env->fpu->fp_status);
2035
    FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status);
2036
    FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status);
2037
    update_fcr31();
2038
}
2039
FLOAT_OP(rsqrt1, s)
2040
{
2041
    set_float_exception_flags(0, &env->fpu->fp_status);
2042
    FST2 = float32_sqrt(FST0, &env->fpu->fp_status);
2043
    FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status);
2044
    update_fcr31();
2045
}
2046
FLOAT_OP(rsqrt1, ps)
2047
{
2048
    set_float_exception_flags(0, &env->fpu->fp_status);
2049
    FST2 = float32_sqrt(FST0, &env->fpu->fp_status);
2050
    FSTH2 = float32_sqrt(FSTH0, &env->fpu->fp_status);
2051
    FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status);
2052
    FSTH2 = float32_div(FLOAT_ONE32, FSTH2, &env->fpu->fp_status);
2053
    update_fcr31();
2054
}
2055

    
2056
/* binary operations */
2057
#define FLOAT_BINOP(name) \
2058
FLOAT_OP(name, d)         \
2059
{                         \
2060
    set_float_exception_flags(0, &env->fpu->fp_status);            \
2061
    FDT2 = float64_ ## name (FDT0, FDT1, &env->fpu->fp_status);    \
2062
    update_fcr31();                                                \
2063
    if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID)                \
2064
        DT2 = FLOAT_QNAN64;                                        \
2065
}                         \
2066
FLOAT_OP(name, s)         \
2067
{                         \
2068
    set_float_exception_flags(0, &env->fpu->fp_status);            \
2069
    FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status);    \
2070
    update_fcr31();                                                \
2071
    if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID)                \
2072
        WT2 = FLOAT_QNAN32;                                        \
2073
}                         \
2074
FLOAT_OP(name, ps)        \
2075
{                         \
2076
    set_float_exception_flags(0, &env->fpu->fp_status);            \
2077
    FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status);    \
2078
    FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fpu->fp_status); \
2079
    update_fcr31();       \
2080
    if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) {              \
2081
        WT2 = FLOAT_QNAN32;                                        \
2082
        WTH2 = FLOAT_QNAN32;                                       \
2083
    }                     \
2084
}
2085
FLOAT_BINOP(add)
2086
FLOAT_BINOP(sub)
2087
FLOAT_BINOP(mul)
2088
FLOAT_BINOP(div)
2089
#undef FLOAT_BINOP
2090

    
2091
/* ternary operations */
2092
#define FLOAT_TERNOP(name1, name2) \
2093
FLOAT_OP(name1 ## name2, d)        \
2094
{                                  \
2095
    FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
2096
    FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
2097
}                                  \
2098
FLOAT_OP(name1 ## name2, s)        \
2099
{                                  \
2100
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2101
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2102
}                                  \
2103
FLOAT_OP(name1 ## name2, ps)       \
2104
{                                  \
2105
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2106
    FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2107
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2108
    FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2109
}
2110
FLOAT_TERNOP(mul, add)
2111
FLOAT_TERNOP(mul, sub)
2112
#undef FLOAT_TERNOP
2113

    
2114
/* negated ternary operations */
2115
#define FLOAT_NTERNOP(name1, name2) \
2116
FLOAT_OP(n ## name1 ## name2, d)    \
2117
{                                   \
2118
    FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
2119
    FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
2120
    FDT2 = float64_chs(FDT2);       \
2121
}                                   \
2122
FLOAT_OP(n ## name1 ## name2, s)    \
2123
{                                   \
2124
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2125
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2126
    FST2 = float32_chs(FST2);       \
2127
}                                   \
2128
FLOAT_OP(n ## name1 ## name2, ps)   \
2129
{                                   \
2130
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2131
    FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2132
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2133
    FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2134
    FST2 = float32_chs(FST2);       \
2135
    FSTH2 = float32_chs(FSTH2);     \
2136
}
2137
FLOAT_NTERNOP(mul, add)
2138
FLOAT_NTERNOP(mul, sub)
2139
#undef FLOAT_NTERNOP
2140

    
2141
/* MIPS specific binary operations */
2142
FLOAT_OP(recip2, d)
2143
{
2144
    set_float_exception_flags(0, &env->fpu->fp_status);
2145
    FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status);
2146
    FDT2 = float64_chs(float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status));
2147
    update_fcr31();
2148
}
2149
FLOAT_OP(recip2, s)
2150
{
2151
    set_float_exception_flags(0, &env->fpu->fp_status);
2152
    FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
2153
    FST2 = float32_chs(float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status));
2154
    update_fcr31();
2155
}
2156
FLOAT_OP(recip2, ps)
2157
{
2158
    set_float_exception_flags(0, &env->fpu->fp_status);
2159
    FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
2160
    FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status);
2161
    FST2 = float32_chs(float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status));
2162
    FSTH2 = float32_chs(float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status));
2163
    update_fcr31();
2164
}
2165

    
2166
FLOAT_OP(rsqrt2, d)
2167
{
2168
    set_float_exception_flags(0, &env->fpu->fp_status);
2169
    FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status);
2170
    FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status);
2171
    FDT2 = float64_chs(float64_div(FDT2, FLOAT_TWO64, &env->fpu->fp_status));
2172
    update_fcr31();
2173
}
2174
FLOAT_OP(rsqrt2, s)
2175
{
2176
    set_float_exception_flags(0, &env->fpu->fp_status);
2177
    FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
2178
    FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status);
2179
    FST2 = float32_chs(float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status));
2180
    update_fcr31();
2181
}
2182
FLOAT_OP(rsqrt2, ps)
2183
{
2184
    set_float_exception_flags(0, &env->fpu->fp_status);
2185
    FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
2186
    FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status);
2187
    FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status);
2188
    FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status);
2189
    FST2 = float32_chs(float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status));
2190
    FSTH2 = float32_chs(float32_div(FSTH2, FLOAT_TWO32, &env->fpu->fp_status));
2191
    update_fcr31();
2192
}
2193

    
2194
FLOAT_OP(addr, ps)
2195
{
2196
    set_float_exception_flags(0, &env->fpu->fp_status);
2197
    FST2 = float32_add (FST0, FSTH0, &env->fpu->fp_status);
2198
    FSTH2 = float32_add (FST1, FSTH1, &env->fpu->fp_status);
2199
    update_fcr31();
2200
}
2201

    
2202
FLOAT_OP(mulr, ps)
2203
{
2204
    set_float_exception_flags(0, &env->fpu->fp_status);
2205
    FST2 = float32_mul (FST0, FSTH0, &env->fpu->fp_status);
2206
    FSTH2 = float32_mul (FST1, FSTH1, &env->fpu->fp_status);
2207
    update_fcr31();
2208
}
2209

    
2210
/* compare operations */
2211
#define FOP_COND_D(op, cond)                   \
2212
void do_cmp_d_ ## op (long cc)                 \
2213
{                                              \
2214
    int c = cond;                              \
2215
    update_fcr31();                            \
2216
    if (c)                                     \
2217
        SET_FP_COND(cc, env->fpu);             \
2218
    else                                       \
2219
        CLEAR_FP_COND(cc, env->fpu);           \
2220
}                                              \
2221
void do_cmpabs_d_ ## op (long cc)              \
2222
{                                              \
2223
    int c;                                     \
2224
    FDT0 = float64_abs(FDT0);                  \
2225
    FDT1 = float64_abs(FDT1);                  \
2226
    c = cond;                                  \
2227
    update_fcr31();                            \
2228
    if (c)                                     \
2229
        SET_FP_COND(cc, env->fpu);             \
2230
    else                                       \
2231
        CLEAR_FP_COND(cc, env->fpu);           \
2232
}
2233

    
2234
int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
2235
{
2236
    if (float64_is_signaling_nan(a) ||
2237
        float64_is_signaling_nan(b) ||
2238
        (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
2239
        float_raise(float_flag_invalid, status);
2240
        return 1;
2241
    } else if (float64_is_nan(a) || float64_is_nan(b)) {
2242
        return 1;
2243
    } else {
2244
        return 0;
2245
    }
2246
}
2247

    
2248
/* NOTE: the comma operator will make "cond" to eval to false,
2249
 * but float*_is_unordered() is still called. */
2250
FOP_COND_D(f,   (float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status), 0))
2251
FOP_COND_D(un,  float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status))
2252
FOP_COND_D(eq,  !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status))
2253
FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status)  || float64_eq(FDT0, FDT1, &env->fpu->fp_status))
2254
FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status))
2255
FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status)  || float64_lt(FDT0, FDT1, &env->fpu->fp_status))
2256
FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status))
2257
FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status)  || float64_le(FDT0, FDT1, &env->fpu->fp_status))
2258
/* NOTE: the comma operator will make "cond" to eval to false,
2259
 * but float*_is_unordered() is still called. */
2260
FOP_COND_D(sf,  (float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status), 0))
2261
FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status))
2262
FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status))
2263
FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status)  || float64_eq(FDT0, FDT1, &env->fpu->fp_status))
2264
FOP_COND_D(lt,  !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status))
2265
FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status)  || float64_lt(FDT0, FDT1, &env->fpu->fp_status))
2266
FOP_COND_D(le,  !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status))
2267
FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status)  || float64_le(FDT0, FDT1, &env->fpu->fp_status))
2268

    
2269
#define FOP_COND_S(op, cond)                   \
2270
void do_cmp_s_ ## op (long cc)                 \
2271
{                                              \
2272
    int c = cond;                              \
2273
    update_fcr31();                            \
2274
    if (c)                                     \
2275
        SET_FP_COND(cc, env->fpu);             \
2276
    else                                       \
2277
        CLEAR_FP_COND(cc, env->fpu);           \
2278
}                                              \
2279
void do_cmpabs_s_ ## op (long cc)              \
2280
{                                              \
2281
    int c;                                     \
2282
    FST0 = float32_abs(FST0);                  \
2283
    FST1 = float32_abs(FST1);                  \
2284
    c = cond;                                  \
2285
    update_fcr31();                            \
2286
    if (c)                                     \
2287
        SET_FP_COND(cc, env->fpu);             \
2288
    else                                       \
2289
        CLEAR_FP_COND(cc, env->fpu);           \
2290
}
2291

    
2292
flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
2293
{
2294
    if (float32_is_signaling_nan(a) ||
2295
        float32_is_signaling_nan(b) ||
2296
        (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
2297
        float_raise(float_flag_invalid, status);
2298
        return 1;
2299
    } else if (float32_is_nan(a) || float32_is_nan(b)) {
2300
        return 1;
2301
    } else {
2302
        return 0;
2303
    }
2304
}
2305

    
2306
/* NOTE: the comma operator will make "cond" to eval to false,
2307
 * but float*_is_unordered() is still called. */
2308
FOP_COND_S(f,   (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0))
2309
FOP_COND_S(un,  float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status))
2310
FOP_COND_S(eq,  !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status))
2311
FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)  || float32_eq(FST0, FST1, &env->fpu->fp_status))
2312
FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status))
2313
FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)  || float32_lt(FST0, FST1, &env->fpu->fp_status))
2314
FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status))
2315
FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)  || float32_le(FST0, FST1, &env->fpu->fp_status))
2316
/* NOTE: the comma operator will make "cond" to eval to false,
2317
 * but float*_is_unordered() is still called. */
2318
FOP_COND_S(sf,  (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0))
2319
FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status))
2320
FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status))
2321
FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)  || float32_eq(FST0, FST1, &env->fpu->fp_status))
2322
FOP_COND_S(lt,  !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status))
2323
FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)  || float32_lt(FST0, FST1, &env->fpu->fp_status))
2324
FOP_COND_S(le,  !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status))
2325
FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)  || float32_le(FST0, FST1, &env->fpu->fp_status))
2326

    
2327
#define FOP_COND_PS(op, condl, condh)          \
2328
void do_cmp_ps_ ## op (long cc)                \
2329
{                                              \
2330
    int cl = condl;                            \
2331
    int ch = condh;                            \
2332
    update_fcr31();                            \
2333
    if (cl)                                    \
2334
        SET_FP_COND(cc, env->fpu);             \
2335
    else                                       \
2336
        CLEAR_FP_COND(cc, env->fpu);           \
2337
    if (ch)                                    \
2338
        SET_FP_COND(cc + 1, env->fpu);         \
2339
    else                                       \
2340
        CLEAR_FP_COND(cc + 1, env->fpu);       \
2341
}                                              \
2342
void do_cmpabs_ps_ ## op (long cc)             \
2343
{                                              \
2344
    int cl, ch;                                \
2345
    FST0 = float32_abs(FST0);                  \
2346
    FSTH0 = float32_abs(FSTH0);                \
2347
    FST1 = float32_abs(FST1);                  \
2348
    FSTH1 = float32_abs(FSTH1);                \
2349
    cl = condl;                                \
2350
    ch = condh;                                \
2351
    update_fcr31();                            \
2352
    if (cl)                                    \
2353
        SET_FP_COND(cc, env->fpu);             \
2354
    else                                       \
2355
        CLEAR_FP_COND(cc, env->fpu);           \
2356
    if (ch)                                    \
2357
        SET_FP_COND(cc + 1, env->fpu);         \
2358
    else                                       \
2359
        CLEAR_FP_COND(cc + 1, env->fpu);       \
2360
}
2361

    
2362
/* NOTE: the comma operator will make "cond" to eval to false,
2363
 * but float*_is_unordered() is still called. */
2364
FOP_COND_PS(f,   (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0),
2365
                 (float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status), 0))
2366
FOP_COND_PS(un,  float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status),
2367
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status))
2368
FOP_COND_PS(eq,  !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)   && float32_eq(FST0, FST1, &env->fpu->fp_status),
2369
                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
2370
FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)    || float32_eq(FST0, FST1, &env->fpu->fp_status),
2371
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
2372
FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)   && float32_lt(FST0, FST1, &env->fpu->fp_status),
2373
                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
2374
FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)    || float32_lt(FST0, FST1, &env->fpu->fp_status),
2375
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
2376
FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)   && float32_le(FST0, FST1, &env->fpu->fp_status),
2377
                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status))
2378
FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)    || float32_le(FST0, FST1, &env->fpu->fp_status),
2379
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_le(FSTH0, FSTH1, &env->fpu->fp_status))
2380
/* NOTE: the comma operator will make "cond" to eval to false,
2381
 * but float*_is_unordered() is still called. */
2382
FOP_COND_PS(sf,  (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0),
2383
                 (float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status), 0))
2384
FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status),
2385
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status))
2386
FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)   && float32_eq(FST0, FST1, &env->fpu->fp_status),
2387
                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
2388
FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)    || float32_eq(FST0, FST1, &env->fpu->fp_status),
2389
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
2390
FOP_COND_PS(lt,  !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)   && float32_lt(FST0, FST1, &env->fpu->fp_status),
2391
                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
2392
FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)    || float32_lt(FST0, FST1, &env->fpu->fp_status),
2393
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
2394
FOP_COND_PS(le,  !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)   && float32_le(FST0, FST1, &env->fpu->fp_status),
2395
                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status))
2396
FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)    || float32_le(FST0, FST1, &env->fpu->fp_status),
2397
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_le(FSTH0, FSTH1, &env->fpu->fp_status))