Revision 6af0bf9c

b/Makefile.target
72 72
PROGS+=$(QEMU_SYSTEM)
73 73
endif
74 74

  
75
endif # TARGET_ARCH = ppc
76

  
77
ifeq ($(TARGET_ARCH), mips)
78

  
75 79
ifeq ($(ARCH), i386)
76 80
ifdef CONFIG_SOFTMMU
77 81
PROGS+=$(QEMU_SYSTEM)
......
84 88
endif
85 89
endif # ARCH = x86_64
86 90

  
87
endif # TARGET_ARCH = ppc
91
endif # TARGET_ARCH = mips
88 92

  
89 93
ifeq ($(TARGET_ARCH), sparc)
90 94

  
......
263 267
LIBOBJS+= op_helper.o helper.o
264 268
endif
265 269

  
270
ifeq ($(TARGET_ARCH), mips)
271
LIBOBJS+= op_helper.o helper.o
272
endif
273

  
266 274
ifeq ($(TARGET_BASE_ARCH), sparc)
267 275
LIBOBJS+= op_helper.o helper.o
268 276
endif
......
288 296
ifeq ($(findstring ppc, $(TARGET_ARCH) $(ARCH)),ppc)
289 297
LIBOBJS+=ppc-dis.o
290 298
endif
299
ifeq ($(findstring mips, $(TARGET_ARCH) $(ARCH)),mips)
300
LIBOBJS+=mips-dis.o
301
endif
291 302
ifeq ($(findstring sparc, $(TARGET_BASE_ARCH) $(ARCH)),sparc)
292 303
LIBOBJS+=sparc-dis.o
293 304
endif
......
348 359
VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
349 360
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
350 361
endif
362
ifeq ($(TARGET_ARCH), mips)
363
VL_OBJS+= mips.o mips_r4k.o dma.o vga.o serial.o #ide.o ne2000.o pckbd.o
364
VL_OBJS+= #i8259.o i8254.o fdc.o m48t59.o
365
endif
351 366
ifeq ($(TARGET_BASE_ARCH), sparc)
352 367
ifeq ($(TARGET_ARCH), sparc64)
353 368
VL_OBJS+= sun4u.o m48t08.o magic-load.o slavio_serial.o
......
455 470
op_helper.o: op_helper_mem.h
456 471
endif
457 472

  
473
ifeq ($(TARGET_ARCH), mips)
474
op.o: op.c op_template.c op_mem.c
475
op_helper.o: op_helper_mem.c
476
endif
477

  
458 478
mixeng.o: mixeng.c mixeng.h mixeng_template.h
459 479

  
460 480
%.o: %.c
b/cpu-all.h
617 617
#define cpu_gen_code cpu_ppc_gen_code
618 618
#define cpu_signal_handler cpu_ppc_signal_handler
619 619

  
620
#elif defined(TARGET_MIPS)
621
#define CPUState CPUMIPSState
622
#define cpu_init cpu_mips_init
623
#define cpu_exec cpu_mips_exec
624
#define cpu_gen_code cpu_mips_gen_code
625
#define cpu_signal_handler cpu_mips_signal_handler
626

  
620 627
#else
621 628

  
622 629
#error unsupported target CPU
b/cpu-exec.c
182 182
    saved_regwptr = REGWPTR;
183 183
#endif
184 184
#elif defined(TARGET_PPC)
185
#elif defined(TARGET_MIPS)
185 186
#else
186 187
#error unsupported target CPU
187 188
#endif
......
220 221
                                 env->exception_next_eip, 0);
221 222
#elif defined(TARGET_PPC)
222 223
                    do_interrupt(env);
224
#elif defined(TARGET_MIPS)
225
                    do_interrupt(env);
223 226
#elif defined(TARGET_SPARC)
224 227
                    do_interrupt(env->exception_index);
225 228
#endif
......
301 304
                            env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
302 305
			}
303 306
                    }
307
#elif defined(TARGET_MIPS)
308
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
309
                        (env->CP0_Status & (1 << CP0St_IE)) &&
310
                        (env->CP0_Cause & 0x0000FC00) &&
311
                        !(env->hflags & MIPS_HFLAG_EXL) &&
312
                        !(env->hflags & MIPS_HFLAG_ERL) &&
313
                        !(env->hflags & MIPS_HFLAG_DM)) {
314
                        /* Raise it */
315
                        env->exception_index = EXCP_EXT_INTERRUPT;
316
                        env->error_code = 0;
317
                        do_interrupt(env);
318
                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
319
                    }
304 320
#elif defined(TARGET_SPARC)
305 321
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
306 322
			(env->psret != 0)) {
......
376 392
                    cpu_dump_state(env, logfile, fprintf, 0);
377 393
#elif defined(TARGET_PPC)
378 394
                    cpu_dump_state(env, logfile, fprintf, 0);
395
#elif defined(TARGET_MIPS)
396
                    cpu_dump_state(env, logfile, fprintf, 0);
379 397
#else
380 398
#error unsupported target CPU 
381 399
#endif
......
407 425
                    (msr_se << MSR_SE) | (msr_le << MSR_LE);
408 426
                cs_base = 0;
409 427
                pc = env->nip;
428
#elif defined(TARGET_MIPS)
429
                flags = env->hflags & MIPS_HFLAGS_TMASK;
430
                cs_base = NULL;
431
                pc = env->PC;
410 432
#else
411 433
#error unsupported CPU
412 434
#endif
......
684 706
    REGWPTR = saved_regwptr;
685 707
#endif
686 708
#elif defined(TARGET_PPC)
709
#elif defined(TARGET_MIPS)
687 710
#else
688 711
#error unsupported target CPU
689 712
#endif
......
935 958
    /* never comes here */
936 959
    return 1;
937 960
}
961

  
962
#elif defined (TARGET_MIPS)
963
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
964
                                    int is_write, sigset_t *old_set,
965
                                    void *puc)
966
{
967
    TranslationBlock *tb;
968
    int ret;
969
    
970
    if (cpu_single_env)
971
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
972
#if defined(DEBUG_SIGNAL)
973
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
974
           pc, address, is_write, *(unsigned long *)old_set);
975
#endif
976
    /* XXX: locking issue */
977
    if (is_write && page_unprotect(address, pc, puc)) {
978
        return 1;
979
    }
980

  
981
    /* see if it is an MMU fault */
982
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
983
    if (ret < 0)
984
        return 0; /* not an MMU fault */
985
    if (ret == 0)
986
        return 1; /* the MMU fault was handled without causing real CPU fault */
987

  
988
    /* now we have a real cpu fault */
989
    tb = tb_find_pc(pc);
990
    if (tb) {
991
        /* the PC is inside the translated code. It means that we have
992
           a virtual CPU fault */
993
        cpu_restore_state(tb, env, pc, puc);
994
    }
995
    if (ret == 1) {
996
#if 0
997
        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
998
               env->nip, env->error_code, tb);
999
#endif
1000
    /* we restore the process signal mask as the sigreturn should
1001
       do it (XXX: use sigsetjmp) */
1002
        sigprocmask(SIG_SETMASK, old_set, NULL);
1003
        do_raise_exception_err(env->exception_index, env->error_code);
1004
    } else {
1005
        /* activate soft MMU for this block */
1006
        cpu_resume_from_signal(env, puc);
1007
    }
1008
    /* never comes here */
1009
    return 1;
1010
}
1011

  
938 1012
#else
939 1013
#error unsupported target CPU
940 1014
#endif
b/dis-asm.h
404 404

  
405 405
bfd_vma bfd_getl32 (const bfd_byte *addr);
406 406
bfd_vma bfd_getb32 (const bfd_byte *addr);
407
bfd_vma bfd_getl16 (const bfd_byte *addr);
408
bfd_vma bfd_getb16 (const bfd_byte *addr);
407 409
typedef enum bfd_boolean {false, true} boolean;
408 410

  
409 411
#endif /* ! defined (DIS_ASM_H) */
b/disas.c
108 108
  return (bfd_vma) v;
109 109
}
110 110

  
111
bfd_vma bfd_getl16 (const bfd_byte *addr)
112
{
113
  unsigned long v;
114

  
115
  v = (unsigned long) addr[0];
116
  v |= (unsigned long) addr[1] << 8;
117
  return (bfd_vma) v;
118
}
119

  
120
bfd_vma bfd_getb16 (const bfd_byte *addr)
121
{
122
  unsigned long v;
123

  
124
  v = (unsigned long) addr[0] << 24;
125
  v |= (unsigned long) addr[1] << 16;
126
  return (bfd_vma) v;
127
}
128

  
111 129
#ifdef TARGET_ARM
112 130
static int
113 131
print_insn_thumb1(bfd_vma pc, disassemble_info *info)
......
162 180
    if (cpu_single_env->msr[MSR_LE])
163 181
        disasm_info.endian = BFD_ENDIAN_LITTLE;
164 182
    print_insn = print_insn_ppc;
183
#elif defined(TARGET_MIPS)
184
    print_insn = print_insn_big_mips;
165 185
#else
166 186
    fprintf(out, "0x" TARGET_FMT_lx
167 187
	    ": Asm output not supported on this arch\n", code);
......
222 242
    print_insn = print_insn_sparc;
223 243
#elif defined(__arm__) 
224 244
    print_insn = print_insn_arm;
245
#elif defined(__MIPSEB__)
246
    print_insn = print_insn_big_mips;
247
#elif defined(__MIPSEL__)
248
    print_insn = print_insn_little_mips;
225 249
#else
226 250
    fprintf(out, "0x%lx: Asm output not supported on this arch\n",
227 251
	    (long) code);
......
332 356
    print_insn = print_insn_sparc;
333 357
#elif defined(TARGET_PPC)
334 358
    print_insn = print_insn_ppc;
359
#elif defined(TARGET_MIPS)
360
    print_insn = print_insn_big_mips;
335 361
#else
336 362
    term_printf("0x" TARGET_FMT_lx
337 363
		": Asm output not supported on this arch\n", pc);
b/elf.h
31 31
#define PT_LOPROC  0x70000000
32 32
#define PT_HIPROC  0x7fffffff
33 33
#define PT_MIPS_REGINFO		0x70000000
34
#define PT_MIPS_OPTIONS		0x70000001
34 35

  
35 36
/* Flags in the e_flags field of the header */
37
/* MIPS architecture level. */
38
#define EF_MIPS_ARCH_1		0x00000000	/* -mips1 code.  */
39
#define EF_MIPS_ARCH_2		0x10000000	/* -mips2 code.  */
40
#define EF_MIPS_ARCH_3		0x20000000	/* -mips3 code.  */
41
#define EF_MIPS_ARCH_4		0x30000000	/* -mips4 code.  */
42
#define EF_MIPS_ARCH_5		0x40000000	/* -mips5 code.  */
43
#define EF_MIPS_ARCH_32		0x50000000	/* MIPS32 code.  */
44
#define EF_MIPS_ARCH_64		0x60000000	/* MIPS64 code.  */
45

  
46
/* The ABI of a file. */
47
#define EF_MIPS_ABI_O32		0x00001000	/* O32 ABI.  */
48
#define EF_MIPS_ABI_O64		0x00002000	/* O32 extended for 64 bit.  */
49

  
36 50
#define EF_MIPS_NOREORDER 0x00000001
37 51
#define EF_MIPS_PIC       0x00000002
38 52
#define EF_MIPS_CPIC      0x00000004
53
#define EF_MIPS_ABI2		0x00000020
54
#define EF_MIPS_OPTIONS_FIRST	0x00000080
55
#define EF_MIPS_32BITMODE	0x00000100
56
#define EF_MIPS_ABI		0x0000f000
39 57
#define EF_MIPS_ARCH      0xf0000000
40 58

  
41 59
/* These constants define the different elf file types */
b/exec-all.h
582 582
    is_user = ((env->hflags & HF_CPL_MASK) == 3);
583 583
#elif defined (TARGET_PPC)
584 584
    is_user = msr_pr;
585
#elif defined (TARGET_MIPS)
586
    is_user = ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
585 587
#elif defined (TARGET_SPARC)
586 588
    is_user = (env->psrs == 0);
587 589
#else
b/hw/mips_r4k.c
1
#include "vl.h"
2

  
3
#define DEBUG_IRQ_COUNT
4

  
5
#define BIOS_FILENAME "mips_bios.bin"
6
//#define BIOS_FILENAME "system.bin"
7
#define KERNEL_LOAD_ADDR 0x80010000
8
#define INITRD_LOAD_ADDR 0x80800000
9

  
10
/* MIPS R4K IRQ controler */
11
#if defined(DEBUG_IRQ_COUNT)
12
static uint64_t irq_count[16];
13
#endif
14

  
15
extern FILE *logfile;
16

  
17
void mips_set_irq (int n_IRQ, int level)
18
{
19
    uint32_t mask;
20

  
21
    if (n_IRQ < 0 || n_IRQ >= 8)
22
        return;
23
    mask = 0x100 << n_IRQ;
24
    if (level != 0) {
25
#if 1
26
        if (logfile) {
27
            fprintf(logfile, "%s n %d l %d mask %08x %08x\n",
28
                    __func__, n_IRQ, level, mask, cpu_single_env->CP0_Status);
29
        }
30
#endif
31
        cpu_single_env->CP0_Cause |= mask;
32
        if ((cpu_single_env->CP0_Status & 0x00000001) &&
33
            (cpu_single_env->CP0_Status & mask)) {
34
#if defined(DEBUG_IRQ_COUNT)
35
            irq_count[n_IRQ]++;
36
#endif
37
#if 1
38
            if (logfile)
39
                fprintf(logfile, "%s raise IRQ\n", __func__);
40
#endif
41
            cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
42
        }
43
    } else {
44
        cpu_single_env->CP0_Cause &= ~mask;
45
    }
46
}
47

  
48
void pic_set_irq (int n_IRQ, int level)
49
{
50
    mips_set_irq(n_IRQ + 2, level);
51
}
52

  
53
void pic_info (void)
54
{
55
    term_printf("IRQ asserted: %02x mask: %02x\n",
56
                (cpu_single_env->CP0_Cause >> 8) & 0xFF,
57
                (cpu_single_env->CP0_Status >> 8) & 0xFF);
58
}
59

  
60
void irq_info (void)
61
{
62
#if !defined(DEBUG_IRQ_COUNT)
63
    term_printf("irq statistic code not compiled.\n");
64
#else
65
    int i;
66
    int64_t count;
67

  
68
    term_printf("IRQ statistics:\n");
69
    for (i = 0; i < 8; i++) {
70
        count = irq_count[i];
71
        if (count > 0)
72
            term_printf("%2d: %lld\n", i, count);
73
    }
74
#endif
75
}
76

  
77
void cpu_mips_irqctrl_init (void)
78
{
79
}
80

  
81
/* MIPS R4K timer */
82
uint32_t cpu_mips_get_random (CPUState *env)
83
{
84
    uint64_t now = qemu_get_clock(vm_clock);
85

  
86
    return (uint32_t)now & 0x0000000F;
87
}
88

  
89
uint32_t cpu_mips_get_count (CPUState *env)
90
{
91
    return env->CP0_Count +
92
        (uint32_t)muldiv64(qemu_get_clock(vm_clock),
93
                           100 * 1000 * 1000, ticks_per_sec);
94
}
95

  
96
static void cpu_mips_update_count (CPUState *env, uint32_t count,
97
                                   uint32_t compare)
98
{
99
    uint64_t now, next;
100
    uint32_t tmp;
101
    
102
    tmp = count;
103
    if (count == compare)
104
        tmp++;
105
    now = qemu_get_clock(vm_clock);
106
    next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000);
107
    if (next == now)
108
	next++;
109
#if 1
110
    if (logfile) {
111
        fprintf(logfile, "%s: 0x%08llx %08x %08x => 0x%08llx\n",
112
                __func__, now, count, compare, next - now);
113
    }
114
#endif
115
    /* Store new count and compare registers */
116
    env->CP0_Compare = compare;
117
    env->CP0_Count =
118
        count - (uint32_t)muldiv64(now, 100 * 1000 * 1000, ticks_per_sec);
119
    /* Adjust timer */
120
    qemu_mod_timer(env->timer, next);
121
}
122

  
123
void cpu_mips_store_count (CPUState *env, uint32_t value)
124
{
125
    cpu_mips_update_count(env, value, env->CP0_Compare);
126
}
127

  
128
void cpu_mips_store_compare (CPUState *env, uint32_t value)
129
{
130
    cpu_mips_update_count(env, cpu_mips_get_count(env), value);
131
    pic_set_irq(5, 0);
132
}
133

  
134
static void mips_timer_cb (void *opaque)
135
{
136
    CPUState *env;
137

  
138
    env = opaque;
139
#if 1
140
    if (logfile) {
141
        fprintf(logfile, "%s\n", __func__);
142
    }
143
#endif
144
    cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
145
    pic_set_irq(5, 1);
146
}
147

  
148
void cpu_mips_clock_init (CPUState *env)
149
{
150
    env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
151
    env->CP0_Compare = 0;
152
    cpu_mips_update_count(env, 1, 0);
153
}
154

  
155
static void io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
156
{
157
    if (logfile)
158
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
159
    cpu_outb(NULL, addr & 0xffff, value);
160
}
161

  
162
static uint32_t io_readb (void *opaque, target_phys_addr_t addr)
163
{
164
    uint32_t ret = cpu_inb(NULL, addr & 0xffff);
165
    if (logfile)
166
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
167
    return ret;
168
}
169

  
170
static void io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
171
{
172
    if (logfile)
173
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
174
#ifdef TARGET_WORDS_BIGENDIAN
175
    value = bswap16(value);
176
#endif
177
    cpu_outw(NULL, addr & 0xffff, value);
178
}
179

  
180
static uint32_t io_readw (void *opaque, target_phys_addr_t addr)
181
{
182
    uint32_t ret = cpu_inw(NULL, addr & 0xffff);
183
#ifdef TARGET_WORDS_BIGENDIAN
184
    ret = bswap16(ret);
185
#endif
186
    if (logfile)
187
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
188
    return ret;
189
}
190

  
191
static void io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
192
{
193
    if (logfile)
194
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
195
#ifdef TARGET_WORDS_BIGENDIAN
196
    value = bswap32(value);
197
#endif
198
    cpu_outl(NULL, addr & 0xffff, value);
199
}
200

  
201
static uint32_t io_readl (void *opaque, target_phys_addr_t addr)
202
{
203
    uint32_t ret = cpu_inl(NULL, addr & 0xffff);
204

  
205
#ifdef TARGET_WORDS_BIGENDIAN
206
    ret = bswap32(ret);
207
#endif
208
    if (logfile)
209
        fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
210
    return ret;
211
}
212

  
213
CPUWriteMemoryFunc *io_write[] = {
214
    &io_writeb,
215
    &io_writew,
216
    &io_writel,
217
};
218

  
219
CPUReadMemoryFunc *io_read[] = {
220
    &io_readb,
221
    &io_readw,
222
    &io_readl,
223
};
224

  
225
void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
226
                    DisplayState *ds, const char **fd_filename, int snapshot,
227
                    const char *kernel_filename, const char *kernel_cmdline,
228
                    const char *initrd_filename)
229
{
230
    char buf[1024];
231
    target_ulong kernel_base, kernel_size, initrd_base, initrd_size;
232
    unsigned long bios_offset;
233
    int io_memory;
234
    int linux_boot;
235
    int ret;
236

  
237
    printf("%s: start\n", __func__);
238
    linux_boot = (kernel_filename != NULL);
239
    /* allocate RAM */
240
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
241
    bios_offset = ram_size + vga_ram_size;
242
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
243
    printf("%s: load BIOS '%s' size %d\n", __func__, buf, BIOS_SIZE);
244
    ret = load_image(buf, phys_ram_base + bios_offset);
245
    if (ret != BIOS_SIZE) {
246
        fprintf(stderr, "qemu: could not load MIPS bios '%s'\n", buf);
247
        exit(1);
248
    }
249
    cpu_register_physical_memory((uint32_t)(0x1fc00000),
250
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
251
#if 0
252
    memcpy(phys_ram_base + 0x10000, phys_ram_base + bios_offset, BIOS_SIZE);
253
    cpu_single_env->PC = 0x80010004;
254
#else
255
    cpu_single_env->PC = 0xBFC00004;
256
#endif
257
    if (linux_boot) {
258
        kernel_base = KERNEL_LOAD_ADDR;
259
        /* now we can load the kernel */
260
        kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
261
        if (kernel_size < 0) {
262
            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
263
                    kernel_filename);
264
            exit(1);
265
        }
266
        /* load initrd */
267
        if (initrd_filename) {
268
            initrd_base = INITRD_LOAD_ADDR;
269
            initrd_size = load_image(initrd_filename,
270
                                     phys_ram_base + initrd_base);
271
            if (initrd_size < 0) {
272
                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
273
                        initrd_filename);
274
                exit(1);
275
            }
276
        } else {
277
            initrd_base = 0;
278
            initrd_size = 0;
279
        }
280
        cpu_single_env->PC = KERNEL_LOAD_ADDR;
281
    } else {
282
        kernel_base = 0;
283
        kernel_size = 0;
284
        initrd_base = 0;
285
        initrd_size = 0;
286
    }
287
    /* XXX: should not be ! */
288
    printf("%s: init VGA\n", __func__);
289
    vga_initialize(NULL, ds, phys_ram_base + ram_size, ram_size, 
290
                   vga_ram_size);
291

  
292

  
293
    /* Init internal devices */
294
    cpu_mips_clock_init(cpu_single_env);
295
    cpu_mips_irqctrl_init();
296

  
297
    isa_mem_base = 0x78000000;
298
    /* Register 64 KB of ISA IO space at random address */
299
    io_memory = cpu_register_io_memory(0, io_read, io_write, NULL);
300
    cpu_register_physical_memory(0x70000000, 0x00010000, io_memory);
301
    serial_init(0x3f8, 4, serial_hds[0]);
302
    printf("%s: done\n", __func__);
303
}
304

  
305
QEMUMachine mips_machine = {
306
    "mips",
307
    "mips r4k platform",
308
    mips_r4k_init,
309
};
b/softmmu_header.h
55 55
#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
56 56
#elif defined (TARGET_PPC)
57 57
#define CPU_MEM_INDEX (msr_pr)
58
#elif defined (TARGET_MIPS)
59
#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
58 60
#elif defined (TARGET_SPARC)
59 61
#define CPU_MEM_INDEX ((env->psrs) == 0)
60 62
#endif
......
66 68
#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
67 69
#elif defined (TARGET_PPC)
68 70
#define CPU_MEM_INDEX (msr_pr)
71
#elif defined (TARGET_MIPS)
72
#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
69 73
#elif defined (TARGET_SPARC)
70 74
#define CPU_MEM_INDEX ((env->psrs) == 0)
71 75
#endif
b/target-mips/cpu.h
1
#if !defined (__MIPS_CPU_H__)
2
#define __MIPS_CPU_H__
3

  
4
#include "mips-defs.h"
5
#include "cpu-defs.h"
6
#include "config.h"
7
#include "softfloat.h"
8

  
9
typedef union fpr_t fpr_t;
10
union fpr_t {
11
    double d;
12
    float  f;
13
    uint32_t u[2];
14
};
15

  
16
#if defined(MIPS_USES_R4K_TLB)
17
typedef struct tlb_t tlb_t;
18
struct tlb_t {
19
    target_ulong VPN;
20
    target_ulong end;
21
    uint8_t ASID;
22
    uint8_t G;
23
    uint8_t C[2];
24
    uint8_t V[2];
25
    uint8_t D[2];
26
    target_ulong PFN[2];
27
};
28
#endif
29

  
30
typedef struct CPUMIPSState CPUMIPSState;
31
struct CPUMIPSState {
32
    /* General integer registers */
33
    target_ulong gpr[32];
34
    /* Special registers */
35
    target_ulong PC;
36
    uint32_t HI, LO;
37
    uint32_t DCR; /* ? */
38
#if defined(MIPS_USES_FPU)
39
    /* Floating point registers */
40
    fpr_t fpr[16];
41
    /* Floating point special purpose registers */
42
    uint32_t fcr0;
43
    uint32_t fcr25;
44
    uint32_t fcr26;
45
    uint32_t fcr28;
46
    uint32_t fcsr;
47
#endif
48
#if defined(MIPS_USES_R4K_TLB)
49
    tlb_t tlb[16];
50
#endif
51
    uint32_t CP0_index;
52
    uint32_t CP0_random;
53
    uint32_t CP0_EntryLo0;
54
    uint32_t CP0_EntryLo1;
55
    uint32_t CP0_Context;
56
    uint32_t CP0_PageMask;
57
    uint32_t CP0_Wired;
58
    uint32_t CP0_BadVAddr;
59
    uint32_t CP0_Count;
60
    uint32_t CP0_EntryHi;
61
    uint32_t CP0_Compare;
62
    uint32_t CP0_Status;
63
#define CP0St_CU3   31
64
#define CP0St_CU2   30
65
#define CP0St_CU1   29
66
#define CP0St_CU0   28
67
#define CP0St_RP    27
68
#define CP0St_RE    25
69
#define CP0St_BEV   22
70
#define CP0St_TS    21
71
#define CP0St_SR    20
72
#define CP0St_NMI   19
73
#define CP0St_IM    8
74
#define CP0St_UM    4
75
#define CP0St_ERL   2
76
#define CP0St_EXL   1
77
#define CP0St_IE    0
78
    uint32_t CP0_Cause;
79
#define CP0Ca_IV   23
80
    uint32_t CP0_EPC;
81
    uint32_t CP0_PRid;
82
    uint32_t CP0_Config0;
83
#define CP0C0_M    31
84
#define CP0C0_K23  28
85
#define CP0C0_KU   25
86
#define CP0C0_MDU  20
87
#define CP0C0_MM   17
88
#define CP0C0_BM   16
89
#define CP0C0_BE   15
90
#define CP0C0_AT   13
91
#define CP0C0_AR   10
92
#define CP0C0_MT   7
93
#define CP0C0_K0   0
94
    uint32_t CP0_Config1;
95
#define CP0C1_MMU  25
96
#define CP0C1_IS   22
97
#define CP0C1_IL   19
98
#define CP0C1_IA   16
99
#define CP0C1_DS   13
100
#define CP0C1_DL   10
101
#define CP0C1_DA   7
102
#define CP0C1_PC   4
103
#define CP0C1_WR   3
104
#define CP0C1_CA   2
105
#define CP0C1_EP   1
106
#define CP0C1_FP   0
107
    uint32_t CP0_LLAddr;
108
    uint32_t CP0_WatchLo;
109
    uint32_t CP0_WatchHi;
110
    uint32_t CP0_Debug;
111
#define CPDB_DBD   31
112
#define CP0DB_DM   30
113
#define CP0DB_LSNM 28
114
#define CP0DB_Doze 27
115
#define CP0DB_Halt 26
116
#define CP0DB_CNT  25
117
#define CP0DB_IBEP 24
118
#define CP0DB_DBEP 21
119
#define CP0DB_IEXI 20
120
#define CP0DB_VER  15
121
#define CP0DB_DEC  10
122
#define CP0DB_SSt  8
123
#define CP0DB_DINT 5
124
#define CP0DB_DIB  4
125
#define CP0DB_DDBS 3
126
#define CP0DB_DDBL 2
127
#define CP0DB_DBp  1
128
#define CP0DB_DSS  0
129
    uint32_t CP0_DEPC;
130
    uint32_t CP0_TagLo;
131
    uint32_t CP0_DataLo;
132
    uint32_t CP0_ErrorEPC;
133
    uint32_t CP0_DESAVE;
134
    /* Qemu */
135
#if defined (USE_HOST_FLOAT_REGS) && defined(MIPS_USES_FPU)
136
    double ft0, ft1, ft2;
137
#endif
138
    struct QEMUTimer *timer; /* Internal timer */
139
    int interrupt_request;
140
    jmp_buf jmp_env;
141
    int exception_index;
142
    int error_code;
143
    int user_mode_only; /* user mode only simulation */
144
    uint32_t hflags;    /* CPU State */
145
    /* TMASK defines different execution modes */
146
#define MIPS_HFLAGS_TMASK 0x00FF
147
#define MIPS_HFLAG_MODE   0x001F /* execution modes                    */
148
#define MIPS_HFLAG_UM     0x0001 /* user mode                          */
149
#define MIPS_HFLAG_ERL    0x0002 /* Error mode                         */
150
#define MIPS_HFLAG_EXL    0x0004 /* Exception mode                     */
151
#define MIPS_HFLAG_DM     0x0008 /* Debug mode                         */
152
#define MIPS_HFLAG_SM     0x0010 /* Supervisor mode                    */
153
#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) */
163
    target_ulong btarget;        /* Jump / branch target               */
164
    int bcond;                   /* Branch condition (if needed)       */
165
    struct TranslationBlock *current_tb; /* currently executing TB  */
166
    /* soft mmu support */
167
    /* in order to avoid passing too many arguments to the memory
168
       write helpers, we store some rarely used information in the CPU
169
       context) */
170
    target_ulong mem_write_pc; /* host pc at which the memory was
171
                                   written */
172
    unsigned long mem_write_vaddr; /* target virtual addr at which the
173
                                      memory was written */
174
    /* 0 = kernel, 1 = user (may have 2 = kernel code, 3 = user code ?) */
175
    CPUTLBEntry tlb_read[2][CPU_TLB_SIZE];
176
    CPUTLBEntry tlb_write[2][CPU_TLB_SIZE];
177
    /* ice debug support */
178
    target_ulong breakpoints[MAX_BREAKPOINTS];
179
    int nb_breakpoints;
180
    int singlestep_enabled; /* XXX: should use CPU single step mode instead */
181
    /* user data */
182
    void *opaque;
183
};
184

  
185
#include "cpu-all.h"
186

  
187
/* Memory access type :
188
 * may be needed for precise access rights control and precise exceptions.
189
 */
190
enum {
191
    /* 1 bit to define user level / supervisor access */
192
    ACCESS_USER  = 0x00,
193
    ACCESS_SUPER = 0x01,
194
    /* 1 bit to indicate direction */
195
    ACCESS_STORE = 0x02,
196
    /* Type of instruction that generated the access */
197
    ACCESS_CODE  = 0x10, /* Code fetch access                */
198
    ACCESS_INT   = 0x20, /* Integer load/store access        */
199
    ACCESS_FLOAT = 0x30, /* floating point load/store access */
200
};
201

  
202
/* Exceptions */
203
enum {
204
    EXCP_NONE          = -1,
205
    EXCP_RESET         = 0,
206
    EXCP_SRESET,
207
    EXCP_DSS,
208
    EXCP_DINT,
209
    EXCP_NMI,
210
    EXCP_MCHECK,
211
    EXCP_EXT_INTERRUPT,
212
    EXCP_DFWATCH,
213
    EXCP_DIB, /* 8 */
214
    EXCP_IWATCH,
215
    EXCP_AdEL,
216
    EXCP_AdES,
217
    EXCP_TLBF,
218
    EXCP_IBE,
219
    EXCP_DBp,
220
    EXCP_SYSCALL,
221
    EXCP_BREAK,
222
    EXCP_CpU, /* 16 */
223
    EXCP_RI,
224
    EXCP_OVERFLOW,
225
    EXCP_TRAP,
226
    EXCP_DDBS,
227
    EXCP_DWATCH,
228
    EXCP_LAE, /* 22 */
229
    EXCP_SAE,
230
    EXCP_LTLBL,
231
    EXCP_TLBL,
232
    EXCP_TLBS,
233
    EXCP_DBE,
234
    EXCP_DDBL,
235
    EXCP_MTCP0         = 0x104, /* mtmsr instruction:               */
236
                                /* may change privilege level       */
237
    EXCP_BRANCH        = 0x108, /* branch instruction               */
238
    EXCP_ERET          = 0x10C, /* return from interrupt            */
239
    EXCP_SYSCALL_USER  = 0x110, /* System call in user mode only    */
240
    EXCP_FLUSH         = 0x109,
241
};
242

  
243
/* MIPS opcodes */
244
#define EXT_SPECIAL  0x100
245
#define EXT_SPECIAL2 0x200
246
#define EXT_REGIMM   0x300
247
#define EXT_CP0      0x400
248
#define EXT_CP1      0x500
249
#define EXT_CP2      0x600
250
#define EXT_CP3      0x700
251

  
252
enum {
253
    /* indirect opcode tables */
254
    OPC_SPECIAL  = 0x00,
255
    OPC_BREGIMM  = 0x01,
256
    OPC_CP0      = 0x10,
257
    OPC_CP1      = 0x11,
258
    OPC_CP2      = 0x12,
259
    OPC_CP3      = 0x13,
260
    OPC_SPECIAL2 = 0x1C,
261
    /* arithmetic with immediate */
262
    OPC_ADDI     = 0x08,
263
    OPC_ADDIU    = 0x09,
264
    OPC_SLTI     = 0x0A,
265
    OPC_SLTIU    = 0x0B,
266
    OPC_ANDI     = 0x0C,
267
    OPC_ORI      = 0x0D,
268
    OPC_XORI     = 0x0E,
269
    OPC_LUI      = 0x0F,
270
    /* Jump and branches */
271
    OPC_J        = 0x02,
272
    OPC_JAL      = 0x03,
273
    OPC_BEQ      = 0x04,  /* Unconditional if rs = rt = 0 (B) */
274
    OPC_BEQL     = 0x14,
275
    OPC_BNE      = 0x05,
276
    OPC_BNEL     = 0x15,
277
    OPC_BLEZ     = 0x06,
278
    OPC_BLEZL    = 0x16,
279
    OPC_BGTZ     = 0x07,
280
    OPC_BGTZL    = 0x17,
281
    OPC_JALX     = 0x1D,  /* MIPS 16 only */
282
    /* Load and stores */
283
    OPC_LB       = 0x20,
284
    OPC_LH       = 0x21,
285
    OPC_LWL      = 0x22,
286
    OPC_LW       = 0x23,
287
    OPC_LBU      = 0x24,
288
    OPC_LHU      = 0x25,
289
    OPC_LWR      = 0x26,
290
    OPC_SB       = 0x28,
291
    OPC_SH       = 0x29,
292
    OPC_SWL      = 0x2A,
293
    OPC_SW       = 0x2B,
294
    OPC_SWR      = 0x2E,
295
    OPC_LL       = 0x30,
296
    OPC_SC       = 0x38,
297
    /* Floating point load/store */
298
    OPC_LWC1     = 0x31,
299
    OPC_LWC2     = 0x32,
300
    OPC_LDC1     = 0x35,
301
    OPC_LDC2     = 0x36,
302
    OPC_SWC1     = 0x39,
303
    OPC_SWC2     = 0x3A,
304
    OPC_SDC1     = 0x3D,
305
    OPC_SDC2     = 0x3E,
306
    /* Cache and prefetch */
307
    OPC_CACHE    = 0x2F,
308
    OPC_PREF     = 0x33,
309
};
310

  
311
/* MIPS special opcodes */
312
enum {
313
    /* Shifts */
314
    OPC_SLL      = 0x00 | EXT_SPECIAL,
315
    /* NOP is SLL r0, r0, 0   */
316
    /* SSNOP is SLL r0, r0, 1 */
317
    OPC_SRL      = 0x02 | EXT_SPECIAL,
318
    OPC_SRA      = 0x03 | EXT_SPECIAL,
319
    OPC_SLLV     = 0x04 | EXT_SPECIAL,
320
    OPC_SRLV     = 0x06 | EXT_SPECIAL,
321
    OPC_SRAV     = 0x07 | EXT_SPECIAL,
322
    /* Multiplication / division */
323
    OPC_MULT     = 0x18 | EXT_SPECIAL,
324
    OPC_MULTU    = 0x19 | EXT_SPECIAL,
325
    OPC_DIV      = 0x1A | EXT_SPECIAL,
326
    OPC_DIVU     = 0x1B | EXT_SPECIAL,
327
    /* 2 registers arithmetic / logic */
328
    OPC_ADD      = 0x20 | EXT_SPECIAL,
329
    OPC_ADDU     = 0x21 | EXT_SPECIAL,
330
    OPC_SUB      = 0x22 | EXT_SPECIAL,
331
    OPC_SUBU     = 0x23 | EXT_SPECIAL,
332
    OPC_AND      = 0x24 | EXT_SPECIAL,
333
    OPC_OR       = 0x25 | EXT_SPECIAL,
334
    OPC_XOR      = 0x26 | EXT_SPECIAL,
335
    OPC_NOR      = 0x27 | EXT_SPECIAL,
336
    OPC_SLT      = 0x2A | EXT_SPECIAL,
337
    OPC_SLTU     = 0x2B | EXT_SPECIAL,
338
    /* Jumps */
339
    OPC_JR       = 0x08 | EXT_SPECIAL,
340
    OPC_JALR     = 0x09 | EXT_SPECIAL,
341
    /* Traps */
342
    OPC_TGE      = 0x30 | EXT_SPECIAL,
343
    OPC_TGEU     = 0x31 | EXT_SPECIAL,
344
    OPC_TLT      = 0x32 | EXT_SPECIAL,
345
    OPC_TLTU     = 0x33 | EXT_SPECIAL,
346
    OPC_TEQ      = 0x34 | EXT_SPECIAL,
347
    OPC_TNE      = 0x36 | EXT_SPECIAL,
348
    /* HI / LO registers load & stores */
349
    OPC_MFHI     = 0x10 | EXT_SPECIAL,
350
    OPC_MTHI     = 0x11 | EXT_SPECIAL,
351
    OPC_MFLO     = 0x12 | EXT_SPECIAL,
352
    OPC_MTLO     = 0x13 | EXT_SPECIAL,
353
    /* Conditional moves */
354
    OPC_MOVZ     = 0x0A | EXT_SPECIAL,
355
    OPC_MOVN     = 0x0B | EXT_SPECIAL,
356

  
357
    OPC_MOVCI    = 0x01 | EXT_SPECIAL,
358

  
359
    /* Special */
360
    OPC_PMON     = 0x05 | EXT_SPECIAL,
361
    OPC_SYSCALL  = 0x0C | EXT_SPECIAL,
362
    OPC_BREAK    = 0x0D | EXT_SPECIAL,
363
    OPC_SYNC     = 0x0F | EXT_SPECIAL,
364
};
365

  
366
enum {
367
    /* Mutiply & xxx operations */
368
    OPC_MADD     = 0x00 | EXT_SPECIAL2,
369
    OPC_MADDU    = 0x01 | EXT_SPECIAL2,
370
    OPC_MUL      = 0x02 | EXT_SPECIAL2,
371
    OPC_MSUB     = 0x04 | EXT_SPECIAL2,
372
    OPC_MSUBU    = 0x05 | EXT_SPECIAL2,
373
    /* Misc */
374
    OPC_CLZ      = 0x20 | EXT_SPECIAL2,
375
    OPC_CLO      = 0x21 | EXT_SPECIAL2,
376
    /* Special */
377
    OPC_SDBBP    = 0x3F | EXT_SPECIAL2,
378
};
379

  
380
/* Branch REGIMM */
381
enum {
382
    OPC_BLTZ     = 0x00 | EXT_REGIMM,
383
    OPC_BLTZL    = 0x02 | EXT_REGIMM,
384
    OPC_BGEZ     = 0x01 | EXT_REGIMM,
385
    OPC_BGEZL    = 0x03 | EXT_REGIMM,
386
    OPC_BLTZAL   = 0x10 | EXT_REGIMM,
387
    OPC_BLTZALL  = 0x12 | EXT_REGIMM,
388
    OPC_BGEZAL   = 0x11 | EXT_REGIMM,
389
    OPC_BGEZALL  = 0x13 | EXT_REGIMM,
390
    OPC_TGEI     = 0x08 | EXT_REGIMM,
391
    OPC_TGEIU    = 0x09 | EXT_REGIMM,
392
    OPC_TLTI     = 0x0A | EXT_REGIMM,
393
    OPC_TLTIU    = 0x0B | EXT_REGIMM,
394
    OPC_TEQI     = 0x0C | EXT_REGIMM,
395
    OPC_TNEI     = 0x0E | EXT_REGIMM,
396
};
397

  
398
enum {
399
    /* Coprocessor 0 (MMU) */
400
    OPC_MFC0     = 0x00 | EXT_CP0,
401
    OPC_MTC0     = 0x04 | EXT_CP0,
402
    OPC_TLBR     = 0x01 | EXT_CP0,
403
    OPC_TLBWI    = 0x02 | EXT_CP0,
404
    OPC_TLBWR    = 0x06 | EXT_CP0,
405
    OPC_TLBP     = 0x08 | EXT_CP0,
406
    OPC_ERET     = 0x18 | EXT_CP0,
407
    OPC_DERET    = 0x1F | EXT_CP0,
408
    OPC_WAIT     = 0x20 | EXT_CP0,
409
};
410

  
411
int cpu_mips_exec(CPUMIPSState *s);
412
CPUMIPSState *cpu_mips_init(void);
413
uint32_t cpu_mips_get_clock (void);
414

  
415
#endif /* !defined (__MIPS_CPU_H__) */
b/target-mips/exec.h
1
#if !defined(__QEMU_MIPS_EXEC_H__)
2
#define __QEMU_MIPS_EXEC_H__
3

  
4
#define DEBUG_OP
5

  
6
#include "mips-defs.h"
7
#include "dyngen-exec.h"
8

  
9
register struct CPUMIPSState *env asm(AREG0);
10

  
11
#if defined (USE_64BITS_REGS)
12
typedef int64_t host_int_t;
13
typedef uint64_t host_uint_t;
14
#else
15
typedef int32_t host_int_t;
16
typedef uint32_t host_uint_t;
17
#endif
18

  
19
register host_uint_t T0 asm(AREG1);
20
register host_uint_t T1 asm(AREG2);
21
register host_uint_t T2 asm(AREG3);
22
register host_int_t Ts0 asm(AREG1);
23
register host_int_t Ts1 asm(AREG2);
24
register host_int_t Ts2 asm(AREG3);
25

  
26
#define PARAM(n) ((uint32_t)PARAM##n)
27
#define SPARAM(n) ((int32_t)PARAM##n)
28

  
29
#if defined (USE_HOST_FLOAT_REGS)
30
register double FT0 asm(FREG0);
31
register double FT1 asm(FREG1);
32
register double FT2 asm(FREG2);
33
register float FTS0 asm(FREG0);
34
register float FTS1 asm(FREG1);
35
register float FTS2 asm(FREG2);
36
#else
37
#define FT0 (env->ft0.d)
38
#define FT1 (env->ft1.d)
39
#define FT2 (env->ft2.d)
40
#define FTS0 (env->ft0.f)
41
#define FTS1 (env->ft1.f)
42
#define FTS2 (env->ft2.f)
43
#endif
44

  
45
#if defined (DEBUG_OP)
46
#define RETURN() __asm__ __volatile__("nop");
47
#else
48
#define RETURN() __asm__ __volatile__("");
49
#endif
50

  
51
#include "cpu.h"
52
#include "exec-all.h"
53

  
54
#if !defined(CONFIG_USER_ONLY)
55

  
56
#define ldul_user ldl_user
57
#define ldul_kernel ldl_kernel
58

  
59
#define ACCESS_TYPE 0
60
#define MEMSUFFIX _kernel
61
#define DATA_SIZE 1
62
#include "softmmu_header.h"
63

  
64
#define DATA_SIZE 2
65
#include "softmmu_header.h"
66

  
67
#define DATA_SIZE 4
68
#include "softmmu_header.h"
69

  
70
#define DATA_SIZE 8
71
#include "softmmu_header.h"
72
#undef ACCESS_TYPE
73
#undef MEMSUFFIX
74

  
75
#define ACCESS_TYPE 1
76
#define MEMSUFFIX _user
77
#define DATA_SIZE 1
78
#include "softmmu_header.h"
79

  
80
#define DATA_SIZE 2
81
#include "softmmu_header.h"
82

  
83
#define DATA_SIZE 4
84
#include "softmmu_header.h"
85

  
86
#define DATA_SIZE 8
87
#include "softmmu_header.h"
88
#undef ACCESS_TYPE
89
#undef MEMSUFFIX
90

  
91
/* these access are slower, they must be as rare as possible */
92
#define ACCESS_TYPE 2
93
#define MEMSUFFIX _data
94
#define DATA_SIZE 1
95
#include "softmmu_header.h"
96

  
97
#define DATA_SIZE 2
98
#include "softmmu_header.h"
99

  
100
#define DATA_SIZE 4
101
#include "softmmu_header.h"
102

  
103
#define DATA_SIZE 8
104
#include "softmmu_header.h"
105
#undef ACCESS_TYPE
106
#undef MEMSUFFIX
107

  
108
#define ldub(p) ldub_data(p)
109
#define ldsb(p) ldsb_data(p)
110
#define lduw(p) lduw_data(p)
111
#define ldsw(p) ldsw_data(p)
112
#define ldl(p) ldl_data(p)
113
#define ldq(p) ldq_data(p)
114

  
115
#define stb(p, v) stb_data(p, v)
116
#define stw(p, v) stw_data(p, v)
117
#define stl(p, v) stl_data(p, v)
118
#define stq(p, v) stq_data(p, v)
119

  
120
#endif /* !defined(CONFIG_USER_ONLY) */
121

  
122
static inline void env_to_regs(void)
123
{
124
}
125

  
126
static inline void regs_to_env(void)
127
{
128
}
129

  
130
#if (HOST_LONG_BITS == 32)
131
void do_mult (void);
132
void do_multu (void);
133
void do_madd (void);
134
void do_maddu (void);
135
void do_msub (void);
136
void do_msubu (void);
137
#endif
138
__attribute__ (( regparm(2) ))
139
void do_mfc0(int reg, int sel);
140
__attribute__ (( regparm(2) ))
141
void do_mtc0(int reg, int sel);
142
void do_tlbwi (void);
143
void do_tlbwr (void);
144
void do_tlbp (void);
145
void do_tlbr (void);
146
void do_lwl_raw (void);
147
void do_lwr_raw (void);
148
void do_swl_raw (void);
149
void do_swr_raw (void);
150
#if !defined(CONFIG_USER_ONLY)
151
void do_lwl_user (void);
152
void do_lwl_kernel (void);
153
void do_lwr_user (void);
154
void do_lwr_kernel (void);
155
void do_swl_user (void);
156
void do_swl_kernel (void);
157
void do_swr_user (void);
158
void do_swr_kernel (void);
159
#endif
160
__attribute__ (( regparm(1) ))
161
void do_pmon (int function);
162

  
163
int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
164
                               int is_user, int is_softmmu);
165
void do_interrupt (CPUState *env);
166

  
167
void cpu_loop_exit(void);
168
__attribute__ (( regparm(2) ))
169
void do_raise_exception_err (uint32_t exception, int error_code);
170
__attribute__ (( regparm(1) ))
171
void do_raise_exception (uint32_t exception);
172

  
173
void cpu_dump_state(CPUState *env, FILE *f, 
174
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
175
                    int flags);
176
void cpu_mips_irqctrl_init (void);
177
uint32_t cpu_mips_get_random (CPUState *env);
178
uint32_t cpu_mips_get_count (CPUState *env);
179
void cpu_mips_store_count (CPUState *env, uint32_t value);
180
void cpu_mips_store_compare (CPUState *env, uint32_t value);
181
void cpu_mips_clock_init (CPUState *env);
182

  
183
#endif /* !defined(__QEMU_MIPS_EXEC_H__) */
b/target-mips/helper.c
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

  
21
#include "exec.h"
22

  
23
/* MIPS32 4K MMU emulation */
24
#if MIPS_USES_4K_TLB
25
static int map_address (CPUState *env, target_ulong *physical, int *prot,
26
                        target_ulong address, int rw, int access_type)
27
{
28
    tlb_t *tlb;
29
    target_ulong tag;
30
    uint8_t ASID;
31
    int i, n;
32
    int ret;
33

  
34
    ret = -2;
35
    tag = (address & 0xFFFFE000);
36
    ASID = env->CP0_EntryHi & 0x000000FF;
37
    for (i = 0; i < 16; i++) {
38
        tlb = &env->tlb[i];
39
        /* Check ASID, virtual page number & size */
40
        if ((tlb->G == 1 || tlb->ASID == ASID) &&
41
            tlb->VPN == tag && address < tlb->end) {
42
            /* TLB match */
43
            n = (address >> 12) & 1;
44
            /* Check access rights */
45
            if ((tlb->V[n] & 2) && (rw == 0 || (tlb->D[n] & 4))) {
46
                *physical = tlb->PFN[n] | (address & 0xFFF);
47
                *prot = PROT_READ;
48
                if (tlb->D[n])
49
                    *prot |= PROT_WRITE;
50
                return 0;
51
            } else if (!(tlb->V[n] & 2)) {
52
                return -3;
53
            } else {
54
                return -4;
55
            }
56
        }
57
    }
58

  
59
    return ret;
60
}
61
#endif
62

  
63
int get_physical_address (CPUState *env, target_ulong *physical, int *prot,
64
                          target_ulong address, int rw, int access_type)
65
{
66
    int user_mode;
67
    int ret;
68

  
69
    /* User mode can only access useg */
70
    user_mode = ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM) ? 1 : 0;
71
#if 0
72
    if (logfile) {
73
        fprintf(logfile, "user mode %d h %08x\n",
74
                user_mode, env->hflags);
75
    }
76
#endif
77
    if (user_mode && address > 0x7FFFFFFFUL)
78
        return -1;
79
    ret = 0;
80
    if (address < 0x80000000UL) {
81
        if (user_mode || !(env->hflags & MIPS_HFLAG_ERL)) {
82
#if MIPS_USES_4K_TLB
83
            ret = map_address(env, physical, prot, address, rw);
84
#else
85
            *physical = address + 0x40000000UL;
86
            *prot = PAGE_READ | PAGE_WRITE;
87
#endif
88
        } else {
89
            *physical = address;
90
            *prot = PAGE_READ | PAGE_WRITE;
91
        }
92
    } else if (address < 0xA0000000UL) {
93
        /* kseg0 */
94
        /* XXX: check supervisor mode */
95
        *physical = address - 0x80000000UL;
96
        *prot = PAGE_READ | PAGE_WRITE;
97
    } else if (address < 0xC0000000UL) {
98
        /* kseg1 */
99
        /* XXX: check supervisor mode */
100
        *physical = address - 0xA0000000UL;
101
        *prot = PAGE_READ | PAGE_WRITE;
102
    } else if (address < 0xE0000000UL) {
103
        /* kseg2 */
104
#if MIPS_USES_4K_TLB
105
        ret = map_address(env, physical, prot, address, rw);
106
#else
107
        *physical = address;
108
        *prot = PAGE_READ | PAGE_WRITE;
109
#endif
110
    } else {
111
        /* kseg3 */
112
        /* XXX: check supervisor mode */
113
        /* XXX: debug segment is not emulated */
114
#if MIPS_USES_4K_TLB
115
        ret = map_address(env, physical, prot, address, rw);
116
#else
117
        *physical = address;
118
        *prot = PAGE_READ | PAGE_WRITE;
119
#endif
120
    }
121
#if 0
122
    if (logfile) {
123
        fprintf(logfile, "%08x %d %d => %08x %d (%d)\n", address, rw,
124
                access_type, *physical, *prot, ret);
125
    }
126
#endif
127

  
128
    return ret;
129
}
130

  
131
#if defined(CONFIG_USER_ONLY) 
132
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
133
{
134
    return addr;
135
}
136
#else
137
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
138
{
139
    target_ulong phys_addr;
140
    int prot;
141

  
142
    if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT) != 0)
143
        return -1;
144
    return phys_addr;
145
}
146
#endif
147

  
148
#if !defined(CONFIG_USER_ONLY) 
149

  
150
#define MMUSUFFIX _mmu
151
#define GETPC() (__builtin_return_address(0))
152

  
153
#define SHIFT 0
154
#include "softmmu_template.h"
155

  
156
#define SHIFT 1
157
#include "softmmu_template.h"
158

  
159
#define SHIFT 2
160
#include "softmmu_template.h"
161

  
162
#define SHIFT 3
163
#include "softmmu_template.h"
164

  
165
void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
166
{
167
    TranslationBlock *tb;
168
    CPUState *saved_env;
169
    unsigned long pc;
170
    int ret;
171

  
172
    /* XXX: hack to restore env in all cases, even if not called from
173
       generated code */
174
    saved_env = env;
175
    env = cpu_single_env;
176
    ret = cpu_mips_handle_mmu_fault(env, addr, is_write, is_user, 1);
177
    if (ret) {
178
        if (retaddr) {
179
            /* now we have a real cpu fault */
180
            pc = (unsigned long)retaddr;
181
            tb = tb_find_pc(pc);
182
            if (tb) {
183
                /* the PC is inside the translated code. It means that we have
184
                   a virtual CPU fault */
185
                cpu_restore_state(tb, env, pc, NULL);
186
            }
187
        }
188
        do_raise_exception_err(env->exception_index, env->error_code);
189
    }
190
    env = saved_env;
191
}
192

  
193
void cpu_mips_init_mmu (CPUState *env)
194
{
195
}
196

  
197
#endif /* !defined(CONFIG_USER_ONLY) */
198

  
199
int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
200
                               int is_user, int is_softmmu)
201
{
202
    target_ulong physical;
203
    int prot;
204
    int exception = 0, error_code = 0;
205
    int access_type;
206
    int ret = 0;
207

  
208
    if (logfile) {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff