Revision 4ad40f36

b/target-mips/cpu.h
1 1
#if !defined (__MIPS_CPU_H__)
2 2
#define __MIPS_CPU_H__
3 3

  
4
#define TARGET_HAS_ICE 1
5

  
4 6
#include "mips-defs.h"
5 7
#include "cpu-defs.h"
6 8
#include "config.h"
......
18 20
struct tlb_t {
19 21
    target_ulong VPN;
20 22
    target_ulong end;
23
    target_ulong end2;
21 24
    uint8_t ASID;
22 25
    uint8_t G;
23 26
    uint8_t C[2];
......
151 154
#define MIPS_HFLAG_DM     0x0008 /* Debug mode                         */
152 155
#define MIPS_HFLAG_SM     0x0010 /* Supervisor mode                    */
153 156
#define MIPS_HFLAG_RE     0x0040 /* Reversed endianness                */
154
#define MIPS_HFLAG_DS     0x0080 /* In / out of delay slot             */
155
    /* Those flags keep the branch state if the translation is interrupted
156
     * between the branch instruction and the delay slot
157
     */
158
#define MIPS_HFLAG_BMASK  0x0F00
159
#define MIPS_HFLAG_B      0x0100 /* Unconditional branch               */
160
#define MIPS_HFLAG_BC     0x0200 /* Conditional branch                 */
161
#define MIPS_HFLAG_BL     0x0400 /* Likely branch                      */
162
#define MIPS_HFLAG_BR     0x0800 /* branch to register (can't link TB) */
157
    /* If translation is interrupted between the branch instruction and
158
     * the delay slot, record what type of branch it is so that we can
159
     * resume translation properly.  It might be possible to reduce
160
     * this from three bits to two.  */
161
#define MIPS_HFLAG_BMASK  0x0380
162
#define MIPS_HFLAG_B      0x0080 /* Unconditional branch               */
163
#define MIPS_HFLAG_BC     0x0100 /* Conditional branch                 */
164
#define MIPS_HFLAG_BL     0x0180 /* Likely branch                      */
165
#define MIPS_HFLAG_BR     0x0200 /* branch to register (can't link TB) */
163 166
    target_ulong btarget;        /* Jump / branch target               */
164 167
    int bcond;                   /* Branch condition (if needed)       */
165 168

  
169
    int halted; /* TRUE if the CPU is in suspend state */
170

  
166 171
    CPU_COMMON
167 172
};
168 173

  
......
202 207
    EXCP_IBE,
203 208
    EXCP_DBp,
204 209
    EXCP_SYSCALL,
205
    EXCP_BREAK,
206
    EXCP_CpU, /* 16 */
210
    EXCP_BREAK, /* 16 */
211
    EXCP_CpU,
207 212
    EXCP_RI,
208 213
    EXCP_OVERFLOW,
209 214
    EXCP_TRAP,
210 215
    EXCP_DDBS,
211 216
    EXCP_DWATCH,
212
    EXCP_LAE, /* 22 */
213
    EXCP_SAE,
217
    EXCP_LAE,
218
    EXCP_SAE, /* 24 */
214 219
    EXCP_LTLBL,
215 220
    EXCP_TLBL,
216 221
    EXCP_TLBS,
b/target-mips/exec.h
65 65
void do_tlbwr (void);
66 66
void do_tlbp (void);
67 67
void do_tlbr (void);
68
void do_lwl_raw (void);
69
void do_lwr_raw (void);
70
void do_swl_raw (void);
71
void do_swr_raw (void);
68
void do_lwl_raw (uint32_t);
69
void do_lwr_raw (uint32_t);
70
uint32_t do_swl_raw (uint32_t);
71
uint32_t do_swr_raw (uint32_t);
72 72
#if !defined(CONFIG_USER_ONLY)
73
void do_lwl_user (void);
74
void do_lwl_kernel (void);
75
void do_lwr_user (void);
76
void do_lwr_kernel (void);
77
void do_swl_user (void);
78
void do_swl_kernel (void);
79
void do_swr_user (void);
80
void do_swr_kernel (void);
73
void do_lwl_user (uint32_t);
74
void do_lwl_kernel (uint32_t);
75
void do_lwr_user (uint32_t);
76
void do_lwr_kernel (uint32_t);
77
uint32_t do_swl_user (uint32_t);
78
uint32_t do_swl_kernel (uint32_t);
79
uint32_t do_swr_user (uint32_t);
80
uint32_t do_swr_kernel (uint32_t);
81 81
#endif
82 82
void do_pmon (int function);
83 83

  
......
88 88
void cpu_loop_exit(void);
89 89
void do_raise_exception_err (uint32_t exception, int error_code);
90 90
void do_raise_exception (uint32_t exception);
91
void do_raise_exception_direct (uint32_t exception);
91 92

  
92 93
void cpu_dump_state(CPUState *env, FILE *f, 
93 94
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
b/target-mips/helper.c
46 46
        tlb = &env->tlb[i];
47 47
        /* Check ASID, virtual page number & size */
48 48
        if ((tlb->G == 1 || tlb->ASID == ASID) &&
49
            tlb->VPN == tag && address < tlb->end) {
49
            tlb->VPN == tag && address < tlb->end2) {
50 50
            /* TLB match */
51 51
            n = (address >> 12) & 1;
52 52
            /* Check access rights */
......
167 167
    int ret = 0;
168 168

  
169 169
    if (logfile) {
170
#if 0
170 171
        cpu_dump_state(env, logfile, fprintf, 0);
172
#endif
171 173
        fprintf(logfile, "%s pc %08x ad %08x rw %d is_user %d smmu %d\n",
172 174
                __func__, env->PC, address, rw, is_user, is_softmmu);
173 175
    }
176

  
177
    rw &= 1;
178

  
174 179
    /* data access */
175 180
    /* XXX: put correct access by using cpu_restore_state()
176 181
       correctly */
......
226 231
        /* Raise exception */
227 232
        env->CP0_BadVAddr = address;
228 233
        env->CP0_Context = (env->CP0_Context & 0xff800000) |
229
	                   ((address >> 8) &   0x007ffff0);
234
	                   ((address >> 9) &   0x007ffff0);
230 235
        env->CP0_EntryHi =
231 236
            (env->CP0_EntryHi & 0x000000FF) | (address & 0xFFFFF000);
232 237
        env->exception_index = exception;
......
276 281
        env->CP0_Debug |= 1 << CP0DB_DDBL;
277 282
        goto set_DEPC;
278 283
    set_DEPC:
279
        if (env->hflags & MIPS_HFLAG_DS) {
284
        if (env->hflags & MIPS_HFLAG_BMASK) {
280 285
            /* If the exception was raised from a delay slot,
281 286
             * come back to the jump
282 287
             */
283 288
            env->CP0_DEPC = env->PC - 4;
289
            env->hflags &= ~MIPS_HFLAG_BMASK;
284 290
        } else {
285 291
            env->CP0_DEPC = env->PC;
286 292
        }
......
316 322
        env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) |
317 323
            (1 << CP0St_NMI);
318 324
    set_error_EPC:
319
        env->hflags = MIPS_HFLAG_ERL;
320
        if (env->hflags & MIPS_HFLAG_DS) {
325
        if (env->hflags & MIPS_HFLAG_BMASK) {
321 326
            /* If the exception was raised from a delay slot,
322 327
             * come back to the jump
323 328
             */
......
325 330
        } else {
326 331
            env->CP0_ErrorEPC = env->PC;
327 332
        }
333
        env->hflags = MIPS_HFLAG_ERL;
328 334
        pc = 0xBFC00000;
329 335
        break;
330 336
    case EXCP_MCHECK:
......
366 372
        goto set_EPC;
367 373
    case EXCP_CpU:
368 374
        cause = 11;
369
        /* XXX: fill in the faulty unit number */
375
        env->CP0_Cause = (env->CP0_Cause & ~0x03000000) | (env->error_code << 28);
370 376
        goto set_EPC;
371 377
    case EXCP_OVERFLOW:
372 378
        cause = 12;
......
391 397
        env->hflags |= MIPS_HFLAG_EXL;
392 398
        pc += offset;
393 399
        env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2);
394
        if (env->hflags & MIPS_HFLAG_DS) {
400
        if (env->hflags & MIPS_HFLAG_BMASK) {
395 401
            /* If the exception was raised from a delay slot,
396 402
             * come back to the jump
397 403
             */
398 404
            env->CP0_EPC = env->PC - 4;
399 405
            env->CP0_Cause |= 0x80000000;
406
            env->hflags &= ~MIPS_HFLAG_BMASK;
400 407
        } else {
401 408
            env->CP0_EPC = env->PC;
402 409
            env->CP0_Cause &= ~0x80000000;
b/target-mips/op.c
207 207
    tmp = T0;
208 208
    T0 += T1;
209 209
    if ((T0 >> 31) ^ (T1 >> 31) ^ (tmp >> 31)) {
210
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
210
        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
211 211
    }
212 212
    RETURN();
213 213
}
......
225 225
    tmp = T0;
226 226
    T0 = (int32_t)T0 - (int32_t)T1;
227 227
    if (!((T0 >> 31) ^ (T1 >> 31) ^ (tmp >> 31))) {
228
        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
228
        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
229 229
    }
230 230
    RETURN();
231 231
}
......
364 364

  
365 365
void op_mult (void)
366 366
{
367
    set_HILO((int64_t)T0 * (int64_t)T1);
367
    set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
368 368
    RETURN();
369 369
}
370 370

  
......
378 378
{
379 379
    int64_t tmp;
380 380

  
381
    tmp = ((int64_t)T0 * (int64_t)T1);
381
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
382 382
    set_HILO((int64_t)get_HILO() + tmp);
383 383
    RETURN();
384 384
}
......
396 396
{
397 397
    int64_t tmp;
398 398

  
399
    tmp = ((int64_t)T0 * (int64_t)T1);
399
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
400 400
    set_HILO((int64_t)get_HILO() - tmp);
401 401
    RETURN();
402 402
}
......
595 595
void op_trap (void)
596 596
{
597 597
    if (T0) {
598
        CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
598
        CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
599 599
    }
600 600
    RETURN();
601 601
}
602 602

  
603
void op_debug (void)
604
{
605
  CALL_FROM_TB1(do_raise_exception_direct, EXCP_DEBUG);
606
}
607

  
603 608
void op_set_lladdr (void)
604 609
{
605 610
    env->CP0_LLAddr = T2;
......
654 659
    EXIT_TB();
655 660
}
656 661

  
662
void op_wait (void)
663
{
664
    env->halted = 1;
665
    CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
666
}
b/target-mips/op_helper.c
22 22

  
23 23
#define MIPS_DEBUG_DISAS
24 24

  
25
#define GETPC() (__builtin_return_address(0))
26

  
25 27
/*****************************************************************************/
26 28
/* Exceptions processing helpers */
27 29
void cpu_loop_exit(void)
......
46 48
    do_raise_exception_err(exception, 0);
47 49
}
48 50

  
51
void do_restore_state (void *pc_ptr)
52
{
53
  TranslationBlock *tb;
54
  unsigned long pc = (unsigned long) pc_ptr;
55

  
56
  tb = tb_find_pc (pc);
57
  cpu_restore_state (tb, env, pc, NULL);
58
}
59

  
60
void do_raise_exception_direct (uint32_t exception)
61
{
62
    do_restore_state (GETPC ());
63
    do_raise_exception_err (exception, 0);
64
}
65

  
49 66
#define MEMSUFFIX _raw
50 67
#include "op_helper_mem.c"
51 68
#undef MEMSUFFIX
......
73 90

  
74 91
void do_mult (void)
75 92
{
76
    set_HILO((int64_t)T0 * (int64_t)T1);
93
    set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
77 94
}
78 95

  
79 96
void do_multu (void)
......
85 102
{
86 103
    int64_t tmp;
87 104

  
88
    tmp = ((int64_t)T0 * (int64_t)T1);
105
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
89 106
    set_HILO((int64_t)get_HILO() + tmp);
90 107
}
91 108

  
......
101 118
{
102 119
    int64_t tmp;
103 120

  
104
    tmp = ((int64_t)T0 * (int64_t)T1);
121
    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
105 122
    set_HILO((int64_t)get_HILO() - tmp);
106 123
}
107 124

  
......
353 370
        val = T0 & 0xFFFFF0FF;
354 371
        old = env->CP0_EntryHi;
355 372
        env->CP0_EntryHi = val;
373
	/* If the ASID changes, flush qemu's TLB.  */
374
	if ((old & 0xFF) != (val & 0xFF))
375
	  tlb_flush (env, 1);
356 376
        rn = "EntryHi";
357 377
        break;
358 378
    case 11:
......
525 545
        addr = tlb->PFN[0];
526 546
        end = addr + (tlb->end - tlb->VPN);
527 547
        tb_invalidate_page_range(addr, end);
548
        /* FIXME: Might be faster to just invalidate the whole "tlb" here
549
           and refill it on demand from our simulated TLB.  */
550
        addr = tlb->VPN;
551
        while (addr < tlb->end) {
552
            tlb_flush_page (env, addr);
553
            addr += TARGET_PAGE_SIZE;
554
        }
528 555
    }
529 556
    if (tlb->V[1]) {
530 557
        addr = tlb->PFN[1];
531 558
        end = addr + (tlb->end - tlb->VPN);
532 559
        tb_invalidate_page_range(addr, end);
560
        /* FIXME: Might be faster to just invalidate the whole "tlb" here
561
           and refill it on demand from our simulated TLB.  */
562
        addr = tlb->end;
563
        while (addr < tlb->end2) {
564
            tlb_flush_page (env, addr);
565
            addr += TARGET_PAGE_SIZE;
566
        }
533 567
    }
534 568
}
535 569

  
......
545 579
    size = env->CP0_PageMask >> 13;
546 580
    size = 4 * (size + 1);
547 581
    tlb->end = tlb->VPN + (1 << (8 + size));
582
    tlb->end2 = tlb->end + (1 << (8 + size));
548 583
    tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
549 584
    tlb->V[0] = env->CP0_EntryLo0 & 2;
550 585
    tlb->D[0] = env->CP0_EntryLo0 & 4;
......
601 636
    int size;
602 637

  
603 638
    tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)];
639

  
640
    /* If this will change the current ASID, flush qemu's TLB.  */
641
    /* FIXME: Could avoid flushing things which match global entries... */
642
    if ((env->CP0_EntryHi & 0xFF) != tlb->ASID)
643
      tlb_flush (env, 1);
644

  
604 645
    env->CP0_EntryHi = tlb->VPN | tlb->ASID;
605 646
    size = (tlb->end - tlb->VPN) >> 12;
606 647
    env->CP0_PageMask = (size - 1) << 13;
......
664 705

  
665 706
#if !defined(CONFIG_USER_ONLY) 
666 707

  
708
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
709

  
667 710
#define MMUSUFFIX _mmu
668
#define GETPC() (__builtin_return_address(0))
711
#define ALIGNED_ONLY
669 712

  
670 713
#define SHIFT 0
671 714
#include "softmmu_template.h"
......
679 722
#define SHIFT 3
680 723
#include "softmmu_template.h"
681 724

  
725
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
726
{
727
    env->CP0_BadVAddr = addr;
728
    do_restore_state (retaddr);
729
    do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
730
}
731

  
682 732
void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
683 733
{
684 734
    TranslationBlock *tb;
b/target-mips/op_helper_mem.c
1
void glue(do_lwl, MEMSUFFIX) (void)
1
void glue(do_lwl, MEMSUFFIX) (uint32_t tmp)
2 2
{
3 3
#if defined (DEBUG_OP)
4 4
    target_ulong sav = T0;
5 5
#endif
6
    uint32_t tmp;
7 6

  
8
    tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
9 7
    /* XXX: this is valid only in big-endian mode
10 8
     *      should be reverted for little-endian...
11 9
     */
......
32 30
    RETURN();
33 31
}
34 32

  
35
void glue(do_lwr, MEMSUFFIX) (void)
33
void glue(do_lwr, MEMSUFFIX) (uint32_t tmp)
36 34
{
37 35
#if defined (DEBUG_OP)
38 36
    target_ulong sav = T0;
39 37
#endif
40
    uint32_t tmp;
41 38

  
42
    tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
43 39
    /* XXX: this is valid only in big-endian mode
44 40
     *      should be reverted for little-endian...
45 41
     */
......
66 62
    RETURN();
67 63
}
68 64

  
69
void glue(do_swl, MEMSUFFIX) (void)
65
uint32_t glue(do_swl, MEMSUFFIX) (uint32_t tmp)
70 66
{
71 67
#if defined (DEBUG_OP)
72 68
    target_ulong sav;
73 69
#endif
74
    uint32_t tmp;
75 70

  
76
    tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
77 71
#if defined (DEBUG_OP)
78 72
    sav = tmp;
79 73
#endif
......
94 88
        tmp = (tmp & 0xFFFFFF00) | (T1 >> 24);
95 89
        break;
96 90
    }
97
    glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
98 91
#if defined (DEBUG_OP)
99 92
    if (logfile) {
100 93
        fprintf(logfile, "%s: %08x - %08x %08x => %08x\n",
......
102 95
    }
103 96
#endif
104 97
    RETURN();
98
    return tmp;
105 99
}
106 100

  
107
void glue(do_swr, MEMSUFFIX) (void)
101
uint32_t glue(do_swr, MEMSUFFIX) (uint32_t tmp)
108 102
{
109 103
#if defined (DEBUG_OP)
110 104
    target_ulong sav;
111 105
#endif
112
    uint32_t tmp;
113 106

  
114
    tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
115 107
#if defined (DEBUG_OP)
116 108
    sav = tmp;
117 109
#endif
......
132 124
        tmp = T1;
133 125
        break;
134 126
    }
135
    glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
136 127
#if defined (DEBUG_OP)
137 128
    if (logfile) {
138 129
        fprintf(logfile, "%s: %08x - %08x %08x => %08x\n",
......
140 131
    }
141 132
#endif
142 133
    RETURN();
134
    return tmp;
143 135
}
b/target-mips/op_mem.c
67 67
    RETURN();
68 68
}
69 69

  
70
/* "half" load and stores */
70
/* "half" load and stores.  We must do the memory access inline,
71
   or fault handling won't work.  */
71 72
void glue(op_lwl, MEMSUFFIX) (void)
72 73
{
73
    CALL_FROM_TB0(glue(do_lwl, MEMSUFFIX));
74
    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
75
    CALL_FROM_TB1(glue(do_lwl, MEMSUFFIX), tmp);
74 76
    RETURN();
75 77
}
76 78

  
77 79
void glue(op_lwr, MEMSUFFIX) (void)
78 80
{
79
    CALL_FROM_TB0(glue(do_lwr, MEMSUFFIX));
81
    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
82
    CALL_FROM_TB1(glue(do_lwr, MEMSUFFIX), tmp);
80 83
    RETURN();
81 84
}
82 85

  
83 86
void glue(op_swl, MEMSUFFIX) (void)
84 87
{
85
    CALL_FROM_TB0(glue(do_swl, MEMSUFFIX));
88
    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
89
    tmp = CALL_FROM_TB1(glue(do_swl, MEMSUFFIX), tmp);
90
    glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
86 91
    RETURN();
87 92
}
88 93

  
89 94
void glue(op_swr, MEMSUFFIX) (void)
90 95
{
91
    CALL_FROM_TB0(glue(do_swr, MEMSUFFIX));
96
    uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
97
    tmp = CALL_FROM_TB1(glue(do_swr, MEMSUFFIX), tmp);
98
    glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
92 99
    RETURN();
93 100
}
94 101

  
b/target-mips/translate.c
338 338
    }
339 339
}
340 340

  
341
static inline void generate_exception (DisasContext *ctx, int excp)
341
static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
342 342
{
343 343
#if defined MIPS_DEBUG_DISAS
344 344
    if (loglevel & CPU_LOG_TB_IN_ASM)
345 345
            fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
346 346
#endif
347 347
    save_cpu_state(ctx, 1);
348
    gen_op_raise_exception(excp);
348
    if (err == 0)
349
        gen_op_raise_exception(excp);
350
    else
351
        gen_op_raise_exception_err(excp, err);
349 352
    ctx->bstate = BS_EXCP;
350 353
}
351 354

  
355
static inline void generate_exception (DisasContext *ctx, int excp)
356
{
357
    generate_exception_err (ctx, excp, 0);
358
}
359

  
352 360
#if defined(CONFIG_USER_ONLY)
353 361
#define op_ldst(name)        gen_op_##name##_raw()
354 362
#define OP_LD_TABLE(width)
......
1020 1028
        case OPC_BLEZ:    /* 0 <= 0          */
1021 1029
        case OPC_BLEZL:   /* 0 <= 0 likely   */
1022 1030
            /* Always take */
1023
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
1031
            ctx->hflags |= MIPS_HFLAG_B;
1024 1032
            MIPS_DEBUG("balways");
1025 1033
            break;
1026 1034
        case OPC_BGEZAL:  /* 0 >= 0          */
1027 1035
        case OPC_BGEZALL: /* 0 >= 0 likely   */
1028 1036
            /* Always take and link */
1029 1037
            blink = 31;
1030
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
1038
            ctx->hflags |= MIPS_HFLAG_B;
1031 1039
            MIPS_DEBUG("balways and link");
1032 1040
            break;
1033 1041
        case OPC_BNE:     /* rx != rx        */
......
1053 1061
            gen_goto_tb(ctx, 0, ctx->pc + 4);
1054 1062
            return;
1055 1063
        case OPC_J:
1056
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
1064
            ctx->hflags |= MIPS_HFLAG_B;
1057 1065
            MIPS_DEBUG("j %08x", btarget);
1058 1066
            break;
1059 1067
        case OPC_JAL:
1060 1068
            blink = 31;
1061
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
1069
            ctx->hflags |= MIPS_HFLAG_B;
1062 1070
            MIPS_DEBUG("jal %08x", btarget);
1063 1071
            break;
1064 1072
        case OPC_JR:
1065
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
1073
            ctx->hflags |= MIPS_HFLAG_BR;
1066 1074
            MIPS_DEBUG("jr %s", regnames[rs]);
1067 1075
            break;
1068 1076
        case OPC_JALR:
1069 1077
            blink = rt;
1070
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
1078
            ctx->hflags |= MIPS_HFLAG_BR;
1071 1079
            MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1072 1080
            break;
1073 1081
        default:
......
1144 1152
            blink = 31;
1145 1153
            MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1146 1154
        not_likely:
1147
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BC;
1155
            ctx->hflags |= MIPS_HFLAG_BC;
1148 1156
            break;
1149 1157
        case OPC_BLTZALL:
1150 1158
            gen_op_ltz();
1151 1159
            blink = 31;
1152 1160
            MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1153 1161
        likely:
1154
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BL;
1162
            ctx->hflags |= MIPS_HFLAG_BL;
1155 1163
            break;
1156 1164
        }
1157 1165
        gen_op_set_bcond();
......
1178 1186
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1179 1187
            fprintf(logfile, "CP0 is not usable\n");
1180 1188
        }
1181
        gen_op_raise_exception_err(EXCP_CpU, 0);
1189
        generate_exception_err (ctx, EXCP_CpU, 0);
1182 1190
        return;
1183 1191
    }
1184 1192
    switch (opc) {
......
1236 1244
            ctx->bstate = BS_EXCP;
1237 1245
        }
1238 1246
        break;
1239
    /* XXX: TODO: WAIT */
1247
    case OPC_WAIT:
1248
        opn = "wait";
1249
        /* If we get an exception, we want to restart at next instruction */
1250
        ctx->pc += 4;
1251
        save_cpu_state(ctx, 1);
1252
        ctx->pc -= 4;
1253
        gen_op_wait();
1254
        ctx->bstate = BS_EXCP;
1255
        break;
1240 1256
    default:
1241 1257
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1242 1258
            fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
......
1292 1308
    int l1;
1293 1309
    l1 = gen_new_label();
1294 1310
    gen_op_jnz_T2(l1);
1295
    gen_op_save_state(ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS));
1311
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
1296 1312
    gen_goto_tb(ctx, 1, ctx->pc + 4);
1297 1313
    gen_set_label(l1);
1298 1314
}
......
1304 1320
    uint16_t op, op1;
1305 1321
    int16_t imm;
1306 1322

  
1307
    if ((ctx->hflags & MIPS_HFLAG_DS) &&
1308
        (ctx->hflags & MIPS_HFLAG_BL)) {
1323
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
1309 1324
        /* Handle blikely not taken case */
1310 1325
        MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
1311 1326
        gen_blikely(ctx);
......
1361 1376
        case 0x05:          /* Pmon entry point */
1362 1377
            gen_op_pmon((ctx->opcode >> 6) & 0x1F);
1363 1378
            break;
1364
#if defined (MIPS_HAS_MOVCI)
1379

  
1365 1380
        case 0x01:          /* MOVCI */
1381
#if defined (MIPS_HAS_MOVCI)
1382
            /* XXX */
1383
#else
1384
            /* Not implemented */
1385
            generate_exception_err (ctx, EXCP_CpU, 1);
1366 1386
#endif
1387
            break;
1388

  
1367 1389
#if defined (TARGET_MIPS64)
1368 1390
        case 0x14: /* MIPS64 specific opcodes */
1369 1391
        case 0x16:
......
1438 1460
            gen_cp0(ctx, op1 | EXT_CP0, rt, rd);
1439 1461
            break;
1440 1462
        default:
1441
            gen_cp0(ctx, (ctx->opcode & 0x1F) | EXT_CP0, rt, rd);
1463
            gen_cp0(ctx, (ctx->opcode & 0x3F) | EXT_CP0, rt, rd);
1442 1464
            break;
1443 1465
        }
1444 1466
        break;
......
1467 1489
        break;
1468 1490
    case 0x3F: /* HACK */
1469 1491
        break;
1492

  
1493
    /* Floating point.  */
1494
    case 0x31: /* LWC1 */
1495
    case 0x35: /* LDC1 */
1496
    case 0x39: /* SWC1 */
1497
    case 0x3D: /* SDC1 */
1498
    case 0x11:          /* CP1 opcode */
1470 1499
#if defined(MIPS_USES_FPU)
1471
    case 0x31 ... 0x32: /* Floating point load/store */
1472
    case 0x35 ... 0x36:
1473
    case 0x3A ... 0x3B:
1474
    case 0x3D ... 0x3E:
1475
        /* Not implemented */
1476 1500
        /* XXX: not correct */
1501
#else
1502
        generate_exception_err(ctx, EXCP_CpU, 1);
1477 1503
#endif
1478
    case 0x11:          /* CP1 opcode */
1479
        /* Not implemented */
1480
        /* XXX: not correct */
1504
        break;
1505

  
1506
    /* COP2.  */
1507
    case 0x32: /* LWC2 */
1508
    case 0x36: /* LDC2 */
1509
    case 0x3A: /* SWC2 */
1510
    case 0x3E: /* SDC2 */
1481 1511
    case 0x12:          /* CP2 opcode */
1482 1512
        /* Not implemented */
1483
        /* XXX: not correct */
1513
        generate_exception_err(ctx, EXCP_CpU, 2);
1514
        break;
1515

  
1484 1516
    case 0x13:          /* CP3 opcode */
1485 1517
        /* Not implemented */
1486
        /* XXX: not correct */
1518
        generate_exception_err(ctx, EXCP_CpU, 3);
1519
        break;
1520

  
1487 1521
#if defined (TARGET_MIPS64)
1488 1522
    case 0x18 ... 0x1B:
1489 1523
    case 0x27:
......
1497 1531
#endif
1498 1532
    case 0x1E:
1499 1533
        /* ASE specific */
1500
#if defined (MIPS_HAS_LSC)
1501
    case 0x31: /* LWC1 */
1502
    case 0x32: /* LWC2 */
1503
    case 0x35: /* SDC1 */
1504
    case 0x36: /* SDC2 */
1505
#endif
1506 1534
    default:            /* Invalid */
1507 1535
        MIPS_INVAL("");
1508 1536
        generate_exception(ctx, EXCP_RI);
1509 1537
        break;
1510 1538
    }
1511
    if (ctx->hflags & MIPS_HFLAG_DS) {
1539
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
1512 1540
        int hflags = ctx->hflags;
1513 1541
        /* Branches completion */
1514
        ctx->hflags &= ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS);
1542
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
1515 1543
        ctx->bstate = BS_BRANCH;
1516 1544
        save_cpu_state(ctx, 0);
1517 1545
        switch (hflags & MIPS_HFLAG_BMASK) {
......
1557 1585
    uint16_t *gen_opc_end;
1558 1586
    int j, lj = -1;
1559 1587

  
1588
    if (search_pc && loglevel)
1589
	fprintf (logfile, "search pc %d\n", search_pc);
1590

  
1560 1591
    pc_start = tb->pc;
1561 1592
    gen_opc_ptr = gen_opc_buf;
1562 1593
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1563 1594
    gen_opparam_ptr = gen_opparam_buf;
1564 1595
    nb_gen_labels = 0;
1565 1596
    ctx.pc = pc_start;
1597
    ctx.saved_pc = -1;
1566 1598
    ctx.tb = tb;
1567 1599
    ctx.bstate = BS_NONE;
1568
    /* Restore delay slot state */
1569
    ctx.hflags = env->hflags;
1600
    /* Restore delay slot state from the tb context.  */
1601
    ctx.hflags = tb->flags;
1570 1602
    ctx.saved_hflags = ctx.hflags;
1571 1603
    if (ctx.hflags & MIPS_HFLAG_BR) {
1572 1604
        gen_op_restore_breg_target();
......
1588 1620
#ifdef DEBUG_DISAS
1589 1621
    if (loglevel & CPU_LOG_TB_CPU) {
1590 1622
        fprintf(logfile, "------------------------------------------------\n");
1623
        /* FIXME: This may print out stale hflags from env... */
1591 1624
        cpu_dump_state(env, logfile, fprintf, 0);
1592 1625
    }
1593 1626
#endif
1594 1627
#if defined MIPS_DEBUG_DISAS
1595 1628
    if (loglevel & CPU_LOG_TB_IN_ASM)
1596
        fprintf(logfile, "\ntb %p super %d cond %04x %04x\n",
1597
                tb, ctx.mem_idx, ctx.hflags, env->hflags);
1629
        fprintf(logfile, "\ntb %p super %d cond %04x\n",
1630
                tb, ctx.mem_idx, ctx.hflags);
1598 1631
#endif
1599 1632
    while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1633
        if (env->nb_breakpoints > 0) {
1634
            for(j = 0; j < env->nb_breakpoints; j++) {
1635
                if (env->breakpoints[j] == ctx.pc) {
1636
                    save_cpu_state(ctxp, 1);
1637
                    ctx.bstate = BS_BRANCH;
1638
                    gen_op_debug();
1639
                    goto done_generating;
1640
                }
1641
            }
1642
        }
1643

  
1600 1644
        if (search_pc) {
1601 1645
            j = gen_opc_ptr - gen_opc_buf;
1602
            save_cpu_state(ctxp, 1);
1603 1646
            if (lj < j) {
1604 1647
                lj++;
1605 1648
                while (lj < j)
1606 1649
                    gen_opc_instr_start[lj++] = 0;
1607
                gen_opc_pc[lj] = ctx.pc;
1608
                gen_opc_instr_start[lj] = 1;
1609 1650
            }
1651
            gen_opc_pc[lj] = ctx.pc;
1652
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
1653
            gen_opc_instr_start[lj] = 1;
1610 1654
        }
1611 1655
        ctx.opcode = ldl_code(ctx.pc);
1612 1656
        decode_opc(&ctx);
1613 1657
        ctx.pc += 4;
1658

  
1659
        if (env->singlestep_enabled)
1660
            break;
1661

  
1614 1662
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1615 1663
            break;
1664

  
1616 1665
#if defined (MIPS_SINGLE_STEP)
1617 1666
        break;
1618 1667
#endif
1619 1668
    }
1620
    if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
1669
    if (env->singlestep_enabled) {
1670
        save_cpu_state(ctxp, ctx.bstate == BS_NONE);
1671
        gen_op_debug();
1672
        goto done_generating;
1673
    }
1674
    else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
1621 1675
        save_cpu_state(ctxp, 0);
1622 1676
        gen_goto_tb(&ctx, 0, ctx.pc);
1623 1677
    }
1624 1678
    gen_op_reset_T0();
1625 1679
    /* Generate the return instruction */
1626 1680
    gen_op_exit_tb();
1681
done_generating:
1627 1682
    *gen_opc_ptr = INDEX_op_end;
1628 1683
    if (search_pc) {
1629 1684
        j = gen_opc_ptr - gen_opc_buf;

Also available in: Unified diff