Commit 3475187dd814be9b27c4632b59c1e3c76d966d63

Authored by bellard
1 parent 8979b227

sparc64 marge (Blue Swirl)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1462 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
... ... @@ -4,6 +4,7 @@ version 0.7.1:
4 4 - Windows 2000 install disk full hack (original idea from Vladimir
5 5 N. Oleynik)
6 6 - VMDK disk image creation (Filip Navara)
  7 + - SPARC64 progress (Blue Swirl)
7 8  
8 9 version 0.7.0:
9 10  
... ...
Makefile.target
... ... @@ -349,7 +349,11 @@ VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
349 349 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
350 350 endif
351 351 ifeq ($(TARGET_BASE_ARCH), sparc)
352   -VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t08.o magic-load.o slavio_intctl.o slavio_timer.o slavio_serial.o fdc.o esp.o
  352 +ifeq ($(TARGET_ARCH), sparc64)
  353 +VL_OBJS+= sun4u.o m48t08.o magic-load.o slavio_serial.o
  354 +else
  355 +VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t08.o magic-load.o slavio_intctl.o slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o
  356 +endif
353 357 endif
354 358 ifdef CONFIG_GDBSTUB
355 359 VL_OBJS+=gdbstub.o
... ... @@ -442,7 +446,8 @@ op.o: op.c op_template.h
442 446 endif
443 447  
444 448 ifeq ($(TARGET_BASE_ARCH), sparc)
445   -op.o: op.c op_template.h op_mem.h
  449 +op.o: op.c op_template.h op_mem.h fop_template.h fbranch_template.h
  450 +magic_load.o: elf_op.h
446 451 endif
447 452  
448 453 ifeq ($(TARGET_ARCH), ppc)
... ...
cpu-exec.c
... ... @@ -47,6 +47,9 @@ void cpu_loop_exit(void)
47 47 longjmp(env->jmp_env, 1);
48 48 }
49 49 #endif
  50 +#ifndef TARGET_SPARC
  51 +#define reg_T2
  52 +#endif
50 53  
51 54 /* exit the current TB from a signal handler. The host registers are
52 55 restored in a state compatible with the CPU emulator
... ... @@ -74,8 +77,12 @@ void cpu_resume_from_signal(CPUState *env1, void *puc)
74 77  
75 78 int cpu_exec(CPUState *env1)
76 79 {
77   - int saved_T0, saved_T1, saved_T2;
  80 + int saved_T0, saved_T1;
  81 +#if defined(reg_T2)
  82 + int saved_T2;
  83 +#endif
78 84 CPUState *saved_env;
  85 +#if defined(TARGET_I386)
79 86 #ifdef reg_EAX
80 87 int saved_EAX;
81 88 #endif
... ... @@ -100,6 +107,11 @@ int cpu_exec(CPUState *env1)
100 107 #ifdef reg_EDI
101 108 int saved_EDI;
102 109 #endif
  110 +#elif defined(TARGET_SPARC)
  111 +#if defined(reg_REGWPTR)
  112 + uint32_t *saved_regwptr;
  113 +#endif
  114 +#endif
103 115 #ifdef __sparc__
104 116 int saved_i7, tmp_T0;
105 117 #endif
... ... @@ -115,7 +127,9 @@ int cpu_exec(CPUState *env1)
115 127 env = env1;
116 128 saved_T0 = T0;
117 129 saved_T1 = T1;
  130 +#if defined(reg_T2)
118 131 saved_T2 = T2;
  132 +#endif
119 133 #ifdef __sparc__
120 134 /* we also save i7 because longjmp may not restore it */
121 135 asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
... ... @@ -164,6 +178,9 @@ int cpu_exec(CPUState *env1)
164 178 env->cpsr = psr & ~CACHED_CPSR_BITS;
165 179 }
166 180 #elif defined(TARGET_SPARC)
  181 +#if defined(reg_REGWPTR)
  182 + saved_regwptr = REGWPTR;
  183 +#endif
167 184 #elif defined(TARGET_PPC)
168 185 #else
169 186 #error unsupported target CPU
... ... @@ -354,7 +371,9 @@ int cpu_exec(CPUState *env1)
354 371 cpu_dump_state(env, logfile, fprintf, 0);
355 372 env->cpsr &= ~CACHED_CPSR_BITS;
356 373 #elif defined(TARGET_SPARC)
357   - cpu_dump_state (env, logfile, fprintf, 0);
  374 + REGWPTR = env->regbase + (env->cwp * 16);
  375 + env->regwptr = REGWPTR;
  376 + cpu_dump_state(env, logfile, fprintf, 0);
358 377 #elif defined(TARGET_PPC)
359 378 cpu_dump_state(env, logfile, fprintf, 0);
360 379 #else
... ... @@ -376,7 +395,11 @@ int cpu_exec(CPUState *env1)
376 395 cs_base = 0;
377 396 pc = env->regs[15];
378 397 #elif defined(TARGET_SPARC)
379   - flags = 0;
  398 +#ifdef TARGET_SPARC64
  399 + flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
  400 +#else
  401 + flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1);
  402 +#endif
380 403 cs_base = env->npc;
381 404 pc = env->pc;
382 405 #elif defined(TARGET_PPC)
... ... @@ -657,6 +680,9 @@ int cpu_exec(CPUState *env1)
657 680 env->cpsr = compute_cpsr();
658 681 /* XXX: Save/restore host fpu exception state?. */
659 682 #elif defined(TARGET_SPARC)
  683 +#if defined(reg_REGWPTR)
  684 + REGWPTR = saved_regwptr;
  685 +#endif
660 686 #elif defined(TARGET_PPC)
661 687 #else
662 688 #error unsupported target CPU
... ... @@ -666,7 +692,9 @@ int cpu_exec(CPUState *env1)
666 692 #endif
667 693 T0 = saved_T0;
668 694 T1 = saved_T1;
  695 +#if defined(reg_T2)
669 696 T2 = saved_T2;
  697 +#endif
670 698 env = saved_env;
671 699 return ret;
672 700 }
... ...
... ... @@ -155,6 +155,9 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
155 155 print_insn = print_insn_arm;
156 156 #elif defined(TARGET_SPARC)
157 157 print_insn = print_insn_sparc;
  158 +#ifdef TARGET_SPARC64
  159 + disasm_info.mach = bfd_mach_sparc_v9b;
  160 +#endif
158 161 #elif defined(TARGET_PPC)
159 162 if (cpu_single_env->msr[MSR_LE])
160 163 disasm_info.endian = BFD_ENDIAN_LITTLE;
... ...
gdbstub.c
1 1 /*
2 2 * gdb server stub
3 3 *
4   - * Copyright (c) 2003 Fabrice Bellard
  4 + * Copyright (c) 2003-2005 Fabrice Bellard
5 5 *
6 6 * This library is free software; you can redistribute it and/or
7 7 * modify it under the terms of the GNU Lesser General Public
... ... @@ -293,7 +293,7 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
293 293 #elif defined (TARGET_SPARC)
294 294 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
295 295 {
296   - uint32_t *registers = (uint32_t *)mem_buf, tmp;
  296 + target_ulong *registers = (target_ulong *)mem_buf;
297 297 int i;
298 298  
299 299 /* fill in g0..g7 */
... ... @@ -308,10 +308,15 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
308 308 for (i = 0; i < 32; i++) {
309 309 registers[i + 32] = tswapl(*((uint32_t *)&env->fpr[i]));
310 310 }
  311 +#ifndef TARGET_SPARC64
311 312 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
312 313 registers[64] = tswapl(env->y);
313   - tmp = GET_PSR(env);
314   - registers[65] = tswapl(tmp);
  314 + {
  315 + target_ulong tmp;
  316 +
  317 + tmp = GET_PSR(env);
  318 + registers[65] = tswapl(tmp);
  319 + }
315 320 registers[66] = tswapl(env->wim);
316 321 registers[67] = tswapl(env->tbr);
317 322 registers[68] = tswapl(env->pc);
... ... @@ -319,13 +324,24 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
319 324 registers[70] = tswapl(env->fsr);
320 325 registers[71] = 0; /* csr */
321 326 registers[72] = 0;
322   -
323   - return 73 * 4;
  327 + return 73 * sizeof(target_ulong);
  328 +#else
  329 + for (i = 0; i < 32; i += 2) {
  330 + registers[i/2 + 64] = tswapl(*((uint64_t *)&env->fpr[i]));
  331 + }
  332 + registers[81] = tswapl(env->pc);
  333 + registers[82] = tswapl(env->npc);
  334 + registers[83] = tswapl(env->tstate[env->tl]);
  335 + registers[84] = tswapl(env->fsr);
  336 + registers[85] = tswapl(env->fprs);
  337 + registers[86] = tswapl(env->y);
  338 + return 87 * sizeof(target_ulong);
  339 +#endif
324 340 }
325 341  
326 342 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
327 343 {
328   - uint32_t *registers = (uint32_t *)mem_buf;
  344 + target_ulong *registers = (target_ulong *)mem_buf;
329 345 int i;
330 346  
331 347 /* fill in g0..g7 */
... ... @@ -334,12 +350,13 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
334 350 }
335 351 /* fill in register window */
336 352 for(i = 0; i < 24; i++) {
337   - env->regwptr[i] = tswapl(registers[i]);
  353 + env->regwptr[i] = tswapl(registers[i + 8]);
338 354 }
339 355 /* fill in fprs */
340 356 for (i = 0; i < 32; i++) {
341 357 *((uint32_t *)&env->fpr[i]) = tswapl(registers[i + 32]);
342 358 }
  359 +#ifndef TARGET_SPARC64
343 360 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
344 361 env->y = tswapl(registers[64]);
345 362 PUT_PSR(env, tswapl(registers[65]));
... ... @@ -348,6 +365,20 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
348 365 env->pc = tswapl(registers[68]);
349 366 env->npc = tswapl(registers[69]);
350 367 env->fsr = tswapl(registers[70]);
  368 +#else
  369 + for (i = 0; i < 32; i += 2) {
  370 + uint64_t tmp;
  371 + tmp = tswapl(registers[i/2 + 64]) << 32;
  372 + tmp |= tswapl(registers[i/2 + 64 + 1]);
  373 + *((uint64_t *)&env->fpr[i]) = tmp;
  374 + }
  375 + env->pc = tswapl(registers[81]);
  376 + env->npc = tswapl(registers[82]);
  377 + env->tstate[env->tl] = tswapl(registers[83]);
  378 + env->fsr = tswapl(registers[84]);
  379 + env->fprs = tswapl(registers[85]);
  380 + env->y = tswapl(registers[86]);
  381 +#endif
351 382 }
352 383 #elif defined (TARGET_ARM)
353 384 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
... ...
hw/elf_ops.h 0 โ†’ 100644
  1 +#ifdef BSWAP_NEEDED
  2 +static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr)
  3 +{
  4 + bswap16s(&ehdr->e_type); /* Object file type */
  5 + bswap16s(&ehdr->e_machine); /* Architecture */
  6 + bswap32s(&ehdr->e_version); /* Object file version */
  7 + bswapSZs(&ehdr->e_entry); /* Entry point virtual address */
  8 + bswapSZs(&ehdr->e_phoff); /* Program header table file offset */
  9 + bswapSZs(&ehdr->e_shoff); /* Section header table file offset */
  10 + bswap32s(&ehdr->e_flags); /* Processor-specific flags */
  11 + bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
  12 + bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
  13 + bswap16s(&ehdr->e_phnum); /* Program header table entry count */
  14 + bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
  15 + bswap16s(&ehdr->e_shnum); /* Section header table entry count */
  16 + bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
  17 +}
  18 +
  19 +static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr)
  20 +{
  21 + bswap32s(&phdr->p_type); /* Segment type */
  22 + bswapSZs(&phdr->p_offset); /* Segment file offset */
  23 + bswapSZs(&phdr->p_vaddr); /* Segment virtual address */
  24 + bswapSZs(&phdr->p_paddr); /* Segment physical address */
  25 + bswapSZs(&phdr->p_filesz); /* Segment size in file */
  26 + bswapSZs(&phdr->p_memsz); /* Segment size in memory */
  27 + bswap32s(&phdr->p_flags); /* Segment flags */
  28 + bswapSZs(&phdr->p_align); /* Segment alignment */
  29 +}
  30 +
  31 +static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
  32 +{
  33 + bswap32s(&shdr->sh_name);
  34 + bswap32s(&shdr->sh_type);
  35 + bswapSZs(&shdr->sh_flags);
  36 + bswapSZs(&shdr->sh_addr);
  37 + bswapSZs(&shdr->sh_offset);
  38 + bswapSZs(&shdr->sh_size);
  39 + bswap32s(&shdr->sh_link);
  40 + bswap32s(&shdr->sh_info);
  41 + bswapSZs(&shdr->sh_addralign);
  42 + bswapSZs(&shdr->sh_entsize);
  43 +}
  44 +
  45 +static void glue(bswap_sym, SZ)(struct elf_sym *sym)
  46 +{
  47 + bswap32s(&sym->st_name);
  48 + bswapSZs(&sym->st_value);
  49 + bswapSZs(&sym->st_size);
  50 + bswap16s(&sym->st_shndx);
  51 +}
  52 +#endif
  53 +
  54 +static int glue(find_phdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, elf_word type)
  55 +{
  56 + int i, retval;
  57 +
  58 + retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
  59 + if (retval < 0)
  60 + return -1;
  61 +
  62 + for (i = 0; i < ehdr->e_phnum; i++) {
  63 + retval = read(fd, phdr, sizeof(*phdr));
  64 + if (retval < 0)
  65 + return -1;
  66 + glue(bswap_phdr, SZ)(phdr);
  67 + if (phdr->p_type == type)
  68 + return 0;
  69 + }
  70 + return -1;
  71 +}
  72 +
  73 +static void * glue(find_shdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type)
  74 +{
  75 + int i, retval;
  76 +
  77 + retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
  78 + if (retval < 0)
  79 + return NULL;
  80 +
  81 + for (i = 0; i < ehdr->e_shnum; i++) {
  82 + retval = read(fd, shdr, sizeof(*shdr));
  83 + if (retval < 0)
  84 + return NULL;
  85 + glue(bswap_shdr, SZ)(shdr);
  86 + if (shdr->sh_type == type)
  87 + return qemu_malloc(shdr->sh_size);
  88 + }
  89 + return NULL;
  90 +}
  91 +
  92 +static void * glue(find_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
  93 +{
  94 + int retval;
  95 +
  96 + retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
  97 + if (retval < 0)
  98 + return NULL;
  99 +
  100 + retval = read(fd, shdr, sizeof(*shdr));
  101 + if (retval < 0)
  102 + return NULL;
  103 + glue(bswap_shdr, SZ)(shdr);
  104 + if (shdr->sh_type == SHT_STRTAB)
  105 + return qemu_malloc(shdr->sh_size);;
  106 + return NULL;
  107 +}
  108 +
  109 +static int glue(read_program, SZ)(int fd, struct elf_phdr *phdr, void *dst, elf_word entry)
  110 +{
  111 + int retval;
  112 + retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET);
  113 + if (retval < 0)
  114 + return -1;
  115 + return read(fd, dst, phdr->p_filesz);
  116 +}
  117 +
  118 +static int glue(read_section, SZ)(int fd, struct elf_shdr *s, void *dst)
  119 +{
  120 + int retval;
  121 +
  122 + retval = lseek(fd, s->sh_offset, SEEK_SET);
  123 + if (retval < 0)
  124 + return -1;
  125 + retval = read(fd, dst, s->sh_size);
  126 + if (retval < 0)
  127 + return -1;
  128 + return 0;
  129 +}
  130 +
  131 +static void * glue(process_section, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type)
  132 +{
  133 + void *dst;
  134 +
  135 + dst = glue(find_shdr, SZ)(ehdr, fd, shdr, type);
  136 + if (!dst)
  137 + goto error;
  138 +
  139 + if (glue(read_section, SZ)(fd, shdr, dst))
  140 + goto error;
  141 + return dst;
  142 + error:
  143 + qemu_free(dst);
  144 + return NULL;
  145 +}
  146 +
  147 +static void * glue(process_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
  148 +{
  149 + void *dst;
  150 +
  151 + dst = glue(find_strtab, SZ)(ehdr, fd, shdr, symtab);
  152 + if (!dst)
  153 + goto error;
  154 +
  155 + if (glue(read_section, SZ)(fd, shdr, dst))
  156 + goto error;
  157 + return dst;
  158 + error:
  159 + qemu_free(dst);
  160 + return NULL;
  161 +}
  162 +
  163 +static void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd)
  164 +{
  165 + struct elf_shdr symtab, strtab;
  166 + struct elf_sym *syms;
  167 +#if (SZ == 64)
  168 + struct elf32_sym *syms32;
  169 +#endif
  170 + struct syminfo *s;
  171 + int nsyms, i;
  172 + char *str;
  173 +
  174 + /* Symbol table */
  175 + syms = glue(process_section, SZ)(ehdr, fd, &symtab, SHT_SYMTAB);
  176 + if (!syms)
  177 + return;
  178 +
  179 + nsyms = symtab.sh_size / sizeof(struct elf_sym);
  180 +#if (SZ == 64)
  181 + syms32 = qemu_mallocz(nsyms * sizeof(struct elf32_sym));
  182 +#endif
  183 + for (i = 0; i < nsyms; i++) {
  184 + glue(bswap_sym, SZ)(&syms[i]);
  185 +#if (SZ == 64)
  186 + syms32[i].st_name = syms[i].st_name;
  187 + syms32[i].st_info = syms[i].st_info;
  188 + syms32[i].st_other = syms[i].st_other;
  189 + syms32[i].st_shndx = syms[i].st_shndx;
  190 + syms32[i].st_value = syms[i].st_value & 0xffffffff;
  191 + syms32[i].st_size = syms[i].st_size & 0xffffffff;
  192 +#endif
  193 + }
  194 + /* String table */
  195 + str = glue(process_strtab, SZ)(ehdr, fd, &strtab, &symtab);
  196 + if (!str)
  197 + goto error_freesyms;
  198 +
  199 + /* Commit */
  200 + s = qemu_mallocz(sizeof(*s));
  201 +#if (SZ == 64)
  202 + s->disas_symtab = syms32;
  203 + qemu_free(syms);
  204 +#else
  205 + s->disas_symtab = syms;
  206 +#endif
  207 + s->disas_num_syms = nsyms;
  208 + s->disas_strtab = str;
  209 + s->next = syminfos;
  210 + syminfos = s;
  211 + return;
  212 + error_freesyms:
  213 +#if (SZ == 64)
  214 + qemu_free(syms32);
  215 +#endif
  216 + qemu_free(syms);
  217 + return;
  218 +}
... ...
hw/magic-load.c
... ... @@ -56,213 +56,49 @@ static void bswap_ahdr(struct exec *e)
56 56  
57 57 #include "elf.h"
58 58  
59   -#ifdef BSWAP_NEEDED
60   -static void bswap_ehdr(Elf32_Ehdr *ehdr)
61   -{
62   - bswap16s(&ehdr->e_type); /* Object file type */
63   - bswap16s(&ehdr->e_machine); /* Architecture */
64   - bswap32s(&ehdr->e_version); /* Object file version */
65   - bswap32s(&ehdr->e_entry); /* Entry point virtual address */
66   - bswap32s(&ehdr->e_phoff); /* Program header table file offset */
67   - bswap32s(&ehdr->e_shoff); /* Section header table file offset */
68   - bswap32s(&ehdr->e_flags); /* Processor-specific flags */
69   - bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
70   - bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
71   - bswap16s(&ehdr->e_phnum); /* Program header table entry count */
72   - bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
73   - bswap16s(&ehdr->e_shnum); /* Section header table entry count */
74   - bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
75   -}
76   -
77   -static void bswap_phdr(Elf32_Phdr *phdr)
78   -{
79   - bswap32s(&phdr->p_type); /* Segment type */
80   - bswap32s(&phdr->p_offset); /* Segment file offset */
81   - bswap32s(&phdr->p_vaddr); /* Segment virtual address */
82   - bswap32s(&phdr->p_paddr); /* Segment physical address */
83   - bswap32s(&phdr->p_filesz); /* Segment size in file */
84   - bswap32s(&phdr->p_memsz); /* Segment size in memory */
85   - bswap32s(&phdr->p_flags); /* Segment flags */
86   - bswap32s(&phdr->p_align); /* Segment alignment */
87   -}
88   -
89   -static void bswap_shdr(Elf32_Shdr *shdr)
90   -{
91   - bswap32s(&shdr->sh_name);
92   - bswap32s(&shdr->sh_type);
93   - bswap32s(&shdr->sh_flags);
94   - bswap32s(&shdr->sh_addr);
95   - bswap32s(&shdr->sh_offset);
96   - bswap32s(&shdr->sh_size);
97   - bswap32s(&shdr->sh_link);
98   - bswap32s(&shdr->sh_info);
99   - bswap32s(&shdr->sh_addralign);
100   - bswap32s(&shdr->sh_entsize);
101   -}
102   -
103   -static void bswap_sym(Elf32_Sym *sym)
104   -{
105   - bswap32s(&sym->st_name);
106   - bswap32s(&sym->st_value);
107   - bswap32s(&sym->st_size);
108   - bswap16s(&sym->st_shndx);
109   -}
110   -#else
111   -#define bswap_ehdr(e) do { } while (0)
112   -#define bswap_phdr(e) do { } while (0)
113   -#define bswap_shdr(e) do { } while (0)
114   -#define bswap_sym(e) do { } while (0)
  59 +#ifndef BSWAP_NEEDED
  60 +#define bswap_ehdr32(e) do { } while (0)
  61 +#define bswap_phdr32(e) do { } while (0)
  62 +#define bswap_shdr32(e) do { } while (0)
  63 +#define bswap_sym32(e) do { } while (0)
  64 +#ifdef TARGET_SPARC64
  65 +#define bswap_ehdr64(e) do { } while (0)
  66 +#define bswap_phdr64(e) do { } while (0)
  67 +#define bswap_shdr64(e) do { } while (0)
  68 +#define bswap_sym64(e) do { } while (0)
  69 +#endif
115 70 #endif
116 71  
117   -static int find_phdr(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, uint32_t type)
118   -{
119   - int i, retval;
120   -
121   - retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
122   - if (retval < 0)
123   - return -1;
124   -
125   - for (i = 0; i < ehdr->e_phnum; i++) {
126   - retval = read(fd, phdr, sizeof(*phdr));
127   - if (retval < 0)
128   - return -1;
129   - bswap_phdr(phdr);
130   - if (phdr->p_type == type)
131   - return 0;
132   - }
133   - return -1;
134   -}
135   -
136   -static void *find_shdr(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
137   -{
138   - int i, retval;
139   -
140   - retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
141   - if (retval < 0)
142   - return NULL;
143   -
144   - for (i = 0; i < ehdr->e_shnum; i++) {
145   - retval = read(fd, shdr, sizeof(*shdr));
146   - if (retval < 0)
147   - return NULL;
148   - bswap_shdr(shdr);
149   - if (shdr->sh_type == type)
150   - return qemu_malloc(shdr->sh_size);
151   - }
152   - return NULL;
153   -}
154   -
155   -static void *find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
156   -{
157   - int retval;
158   -
159   - retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
160   - if (retval < 0)
161   - return NULL;
162   -
163   - retval = read(fd, shdr, sizeof(*shdr));
164   - if (retval < 0)
165   - return NULL;
166   - bswap_shdr(shdr);
167   - if (shdr->sh_type == SHT_STRTAB)
168   - return qemu_malloc(shdr->sh_size);;
169   - return NULL;
170   -}
171   -
172   -static int read_program(int fd, struct elf_phdr *phdr, void *dst, uint32_t entry)
173   -{
174   - int retval;
175   - retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET);
176   - if (retval < 0)
177   - return -1;
178   - return read(fd, dst, phdr->p_filesz);
179   -}
180   -
181   -static int read_section(int fd, struct elf_shdr *s, void *dst)
182   -{
183   - int retval;
184   -
185   - retval = lseek(fd, s->sh_offset, SEEK_SET);
186   - if (retval < 0)
187   - return -1;
188   - retval = read(fd, dst, s->sh_size);
189   - if (retval < 0)
190   - return -1;
191   - return 0;
192   -}
193   -
194   -static void *process_section(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
195   -{
196   - void *dst;
197   -
198   - dst = find_shdr(ehdr, fd, shdr, type);
199   - if (!dst)
200   - goto error;
201   -
202   - if (read_section(fd, shdr, dst))
203   - goto error;
204   - return dst;
205   - error:
206   - qemu_free(dst);
207   - return NULL;
208   -}
209   -
210   -static void *process_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
211   -{
212   - void *dst;
213   -
214   - dst = find_strtab(ehdr, fd, shdr, symtab);
215   - if (!dst)
216   - goto error;
217   -
218   - if (read_section(fd, shdr, dst))
219   - goto error;
220   - return dst;
221   - error:
222   - qemu_free(dst);
223   - return NULL;
224   -}
225   -
226   -static void load_symbols(struct elfhdr *ehdr, int fd)
227   -{
228   - struct elf_shdr symtab, strtab;
229   - struct elf_sym *syms;
230   - struct syminfo *s;
231   - int nsyms, i;
232   - char *str;
233   -
234   - /* Symbol table */
235   - syms = process_section(ehdr, fd, &symtab, SHT_SYMTAB);
236   - if (!syms)
237   - return;
238   -
239   - nsyms = symtab.sh_size / sizeof(struct elf_sym);
240   - for (i = 0; i < nsyms; i++)
241   - bswap_sym(&syms[i]);
242   -
243   - /* String table */
244   - str = process_strtab(ehdr, fd, &strtab, &symtab);
245   - if (!str)
246   - goto error_freesyms;
247   -
248   - /* Commit */
249   - s = qemu_mallocz(sizeof(*s));
250   - s->disas_symtab = syms;
251   - s->disas_num_syms = nsyms;
252   - s->disas_strtab = str;
253   - s->next = syminfos;
254   - syminfos = s;
255   - return;
256   - error_freesyms:
257   - qemu_free(syms);
258   - return;
259   -}
  72 +#define SZ 32
  73 +#define elf_word uint32_t
  74 +#define bswapSZs bswap32s
  75 +#include "elf_ops.h"
  76 +
  77 +#ifdef TARGET_SPARC64
  78 +#undef elfhdr
  79 +#undef elf_phdr
  80 +#undef elf_shdr
  81 +#undef elf_sym
  82 +#undef elf_note
  83 +#undef elf_word
  84 +#undef bswapSZs
  85 +#undef SZ
  86 +#define elfhdr elf64_hdr
  87 +#define elf_phdr elf64_phdr
  88 +#define elf_note elf64_note
  89 +#define elf_shdr elf64_shdr
  90 +#define elf_sym elf64_sym
  91 +#define elf_word uint64_t
  92 +#define bswapSZs bswap64s
  93 +#define SZ 64
  94 +#include "elf_ops.h"
  95 +#endif
260 96  
261 97 int load_elf(const char *filename, uint8_t *addr)
262 98 {
263   - struct elfhdr ehdr;
264   - struct elf_phdr phdr;
  99 + struct elf32_hdr ehdr;
265 100 int retval, fd;
  101 + Elf32_Half machine;
266 102  
267 103 fd = open(filename, O_RDONLY | O_BINARY);
268 104 if (fd < 0)
... ... @@ -272,21 +108,43 @@ int load_elf(const char *filename, uint8_t *addr)
272 108 if (retval < 0)
273 109 goto error;
274 110  
275   - bswap_ehdr(&ehdr);
276   -
277 111 if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E'
278   - || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F'
279   - || (ehdr.e_machine != EM_SPARC
280   - && ehdr.e_machine != EM_SPARC32PLUS))
  112 + || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F')
281 113 goto error;
  114 + machine = tswap16(ehdr.e_machine);
  115 + if (machine == EM_SPARC || machine == EM_SPARC32PLUS) {
  116 + struct elf32_phdr phdr;
282 117  
283   - if (find_phdr(&ehdr, fd, &phdr, PT_LOAD))
284   - goto error;
285   - retval = read_program(fd, &phdr, addr, ehdr.e_entry);
286   - if (retval < 0)
287   - goto error;
  118 + bswap_ehdr32(&ehdr);
288 119  
289   - load_symbols(&ehdr, fd);
  120 + if (find_phdr32(&ehdr, fd, &phdr, PT_LOAD))
  121 + goto error;
  122 + retval = read_program32(fd, &phdr, addr, ehdr.e_entry);
  123 + if (retval < 0)
  124 + goto error;
  125 + load_symbols32(&ehdr, fd);
  126 + }
  127 +#ifdef TARGET_SPARC64
  128 + else if (machine == EM_SPARCV9) {
  129 + struct elf64_hdr ehdr64;
  130 + struct elf64_phdr phdr;
  131 +
  132 + lseek(fd, 0, SEEK_SET);
  133 +
  134 + retval = read(fd, &ehdr64, sizeof(ehdr64));
  135 + if (retval < 0)
  136 + goto error;
  137 +
  138 + bswap_ehdr64(&ehdr64);
  139 +
  140 + if (find_phdr64(&ehdr64, fd, &phdr, PT_LOAD))
  141 + goto error;
  142 + retval = read_program64(fd, &phdr, addr, ehdr64.e_entry);
  143 + if (retval < 0)
  144 + goto error;
  145 + load_symbols64(&ehdr64, fd);
  146 + }
  147 +#endif
290 148  
291 149 close(fd);
292 150 return retval;
... ...
hw/slavio_intctl.c
... ... @@ -144,14 +144,14 @@ static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, uin
144 144 switch (saddr) {
145 145 case 2: // clear (enable)
146 146 // Force clear unused bits
147   - val &= ~0x7fb2007f;
  147 + val &= ~0x4fb2007f;
148 148 s->intregm_disabled &= ~val;
149 149 DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
150 150 slavio_check_interrupts(s);
151 151 break;
152 152 case 3: // set (disable, clear pending)
153 153 // Force clear unused bits
154   - val &= ~0x7fb2007f;
  154 + val &= ~0x4fb2007f;
155 155 s->intregm_disabled |= val;
156 156 s->intregm_pending &= ~val;
157 157 DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
... ... @@ -208,7 +208,7 @@ void slavio_irq_info(void *opaque)
208 208  
209 209 static const uint32_t intbit_to_level[32] = {
210 210 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12,
211   - 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0,
  211 + 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0,
212 212 };
213 213  
214 214 static void slavio_check_interrupts(void *opaque)
... ...
hw/slavio_misc.c 0 โ†’ 100644
  1 +/*
  2 + * QEMU Sparc SLAVIO aux io port emulation
  3 + *
  4 + * Copyright (c) 2005 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +/* debug misc */
  26 +//#define DEBUG_MISC
  27 +
  28 +/*
  29 + * This is the auxio port, chip control and system control part of
  30 + * chip STP2001 (Slave I/O), also produced as NCR89C105. See
  31 + * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
  32 + *
  33 + * This also includes the PMC CPU idle controller.
  34 + */
  35 +
  36 +#ifdef DEBUG_MISC
  37 +#define MISC_DPRINTF(fmt, args...) \
  38 +do { printf("MISC: " fmt , ##args); } while (0)
  39 +#else
  40 +#define MISC_DPRINTF(fmt, args...)
  41 +#endif
  42 +
  43 +typedef struct MiscState {
  44 + int irq;
  45 + uint8_t config;
  46 + uint8_t aux1, aux2;
  47 + uint8_t diag, mctrl;
  48 +} MiscState;
  49 +
  50 +#define MISC_MAXADDR 1
  51 +
  52 +static void slavio_misc_update_irq(void *opaque)
  53 +{
  54 + MiscState *s = opaque;
  55 +
  56 + if ((s->aux2 & 0x4) && (s->config & 0x8)) {
  57 + pic_set_irq(s->irq, 1);
  58 + } else {
  59 + pic_set_irq(s->irq, 0);
  60 + }
  61 +}
  62 +
  63 +static void slavio_misc_reset(void *opaque)
  64 +{
  65 + MiscState *s = opaque;
  66 +
  67 + // Diagnostic register not cleared in reset
  68 + s->config = s->aux1 = s->aux2 = s->mctrl = 0;
  69 +}
  70 +
  71 +void slavio_set_power_fail(void *opaque, int power_failing)
  72 +{
  73 + MiscState *s = opaque;
  74 +
  75 + MISC_DPRINTF("Power fail: %d, config: %d\n", power_failing, s->config);
  76 + if (power_failing && (s->config & 0x8)) {
  77 + s->aux2 |= 0x4;
  78 + } else {
  79 + s->aux2 &= ~0x4;
  80 + }
  81 + slavio_misc_update_irq(s);
  82 +}
  83 +
  84 +static void slavio_misc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
  85 +{
  86 + MiscState *s = opaque;
  87 +
  88 + switch (addr & 0xfff0000) {
  89 + case 0x1800000:
  90 + MISC_DPRINTF("Write config %2.2x\n", val & 0xff);
  91 + s->config = val & 0xff;
  92 + slavio_misc_update_irq(s);
  93 + break;
  94 + case 0x1900000:
  95 + MISC_DPRINTF("Write aux1 %2.2x\n", val & 0xff);
  96 + s->aux1 = val & 0xff;
  97 + break;
  98 + case 0x1910000:
  99 + val &= 0x3;
  100 + MISC_DPRINTF("Write aux2 %2.2x\n", val);
  101 + val |= s->aux2 & 0x4;
  102 + if (val & 0x2) // Clear Power Fail int
  103 + val &= 0x1;
  104 + s->aux2 = val;
  105 + if (val & 1)
  106 + qemu_system_shutdown_request();
  107 + slavio_misc_update_irq(s);
  108 + break;
  109 + case 0x1a00000:
  110 + MISC_DPRINTF("Write diag %2.2x\n", val & 0xff);
  111 + s->diag = val & 0xff;
  112 + break;
  113 + case 0x1b00000:
  114 + MISC_DPRINTF("Write modem control %2.2x\n", val & 0xff);
  115 + s->mctrl = val & 0xff;
  116 + break;
  117 + case 0x1f00000:
  118 + MISC_DPRINTF("Write system control %2.2x\n", val & 0xff);
  119 + if (val & 1)
  120 + qemu_system_reset_request();
  121 + break;
  122 + case 0xa000000:
  123 + MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
  124 +#if 0
  125 + // XXX: halting CPU does not work
  126 + raise_exception(EXCP_HLT);
  127 + cpu_loop_exit();
  128 +#endif
  129 + break;
  130 + }
  131 +}
  132 +
  133 +static uint32_t slavio_misc_mem_readb(void *opaque, target_phys_addr_t addr)
  134 +{
  135 + MiscState *s = opaque;
  136 + uint32_t ret = 0;
  137 +
  138 + switch (addr & 0xfff0000) {
  139 + case 0x1800000:
  140 + ret = s->config;
  141 + MISC_DPRINTF("Read config %2.2x\n", ret);
  142 + break;
  143 + case 0x1900000:
  144 + ret = s->aux1;
  145 + MISC_DPRINTF("Read aux1 %2.2x\n", ret);
  146 + break;
  147 + case 0x1910000:
  148 + ret = s->aux2;
  149 + MISC_DPRINTF("Read aux2 %2.2x\n", ret);
  150 + break;
  151 + case 0x1a00000:
  152 + ret = s->diag;
  153 + MISC_DPRINTF("Read diag %2.2x\n", ret);
  154 + break;
  155 + case 0x1b00000:
  156 + ret = s->mctrl;
  157 + MISC_DPRINTF("Read modem control %2.2x\n", ret);
  158 + break;
  159 + case 0x1f00000:
  160 + MISC_DPRINTF("Read system control %2.2x\n", ret);
  161 + break;
  162 + case 0xa000000:
  163 + MISC_DPRINTF("Read power management %2.2x\n", ret);
  164 + break;
  165 + }
  166 + return ret;
  167 +}
  168 +
  169 +static CPUReadMemoryFunc *slavio_misc_mem_read[3] = {
  170 + slavio_misc_mem_readb,
  171 + slavio_misc_mem_readb,
  172 + slavio_misc_mem_readb,
  173 +};
  174 +
  175 +static CPUWriteMemoryFunc *slavio_misc_mem_write[3] = {
  176 + slavio_misc_mem_writeb,
  177 + slavio_misc_mem_writeb,
  178 + slavio_misc_mem_writeb,
  179 +};
  180 +
  181 +static void slavio_misc_save(QEMUFile *f, void *opaque)
  182 +{
  183 + MiscState *s = opaque;
  184 +
  185 + qemu_put_be32s(f, &s->irq);
  186 + qemu_put_8s(f, &s->config);
  187 + qemu_put_8s(f, &s->aux1);
  188 + qemu_put_8s(f, &s->aux2);
  189 + qemu_put_8s(f, &s->diag);
  190 + qemu_put_8s(f, &s->mctrl);
  191 +}
  192 +
  193 +static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id)
  194 +{
  195 + MiscState *s = opaque;
  196 +
  197 + if (version_id != 1)
  198 + return -EINVAL;
  199 +
  200 + qemu_get_be32s(f, &s->irq);
  201 + qemu_get_8s(f, &s->config);
  202 + qemu_get_8s(f, &s->aux1);
  203 + qemu_get_8s(f, &s->aux2);
  204 + qemu_get_8s(f, &s->diag);
  205 + qemu_get_8s(f, &s->mctrl);
  206 + return 0;
  207 +}
  208 +
  209 +void *slavio_misc_init(uint32_t base, int irq)
  210 +{
  211 + int slavio_misc_io_memory;
  212 + MiscState *s;
  213 +
  214 + s = qemu_mallocz(sizeof(MiscState));
  215 + if (!s)
  216 + return NULL;
  217 +
  218 + slavio_misc_io_memory = cpu_register_io_memory(0, slavio_misc_mem_read, slavio_misc_mem_write, s);
  219 + // Slavio control
  220 + cpu_register_physical_memory(base + 0x1800000, MISC_MAXADDR, slavio_misc_io_memory);
  221 + // AUX 1
  222 + cpu_register_physical_memory(base + 0x1900000, MISC_MAXADDR, slavio_misc_io_memory);
  223 + // AUX 2
  224 + cpu_register_physical_memory(base + 0x1910000, MISC_MAXADDR, slavio_misc_io_memory);
  225 + // Diagnostics
  226 + cpu_register_physical_memory(base + 0x1a00000, MISC_MAXADDR, slavio_misc_io_memory);
  227 + // Modem control
  228 + cpu_register_physical_memory(base + 0x1b00000, MISC_MAXADDR, slavio_misc_io_memory);
  229 + // System control
  230 + cpu_register_physical_memory(base + 0x1f00000, MISC_MAXADDR, slavio_misc_io_memory);
  231 + // Power management
  232 + cpu_register_physical_memory(base + 0xa000000, MISC_MAXADDR, slavio_misc_io_memory);
  233 +
  234 + s->irq = irq;
  235 +
  236 + register_savevm("slavio_misc", base, 1, slavio_misc_save, slavio_misc_load, s);
  237 + qemu_register_reset(slavio_misc_reset, s);
  238 + slavio_misc_reset(s);
  239 + return s;
  240 +}
... ...
hw/sun4m.c
... ... @@ -37,6 +37,7 @@
37 37 // bits
38 38 #define PHYS_JJ_IOMMU 0x10000000 /* I/O MMU */
39 39 #define PHYS_JJ_TCX_FB 0x50000000 /* TCX frame buffer */
  40 +#define PHYS_JJ_SLAVIO 0x70000000 /* Slavio base */
40 41 #define PHYS_JJ_ESPDMA 0x78400000 /* ESP DMA controller */
41 42 #define PHYS_JJ_ESP 0x78800000 /* ESP SCSI */
42 43 #define PHYS_JJ_ESP_IRQ 18
... ... @@ -55,6 +56,7 @@
55 56 #define PHYS_JJ_SER_IRQ 15
56 57 #define PHYS_JJ_FDC 0x71400000 /* Floppy */
57 58 #define PHYS_JJ_FLOPPY_IRQ 22
  59 +#define PHYS_JJ_ME_IRQ 30 /* Module error, power fail */
58 60  
59 61 /* TSC handling */
60 62  
... ... @@ -202,6 +204,13 @@ uint32_t iommu_translate(uint32_t addr)
202 204 return iommu_translate_local(iommu, addr);
203 205 }
204 206  
  207 +static void *slavio_misc;
  208 +
  209 +void qemu_system_powerdown(void)
  210 +{
  211 + slavio_set_power_fail(slavio_misc, 1);
  212 +}
  213 +
205 214 /* Sun4m hardware initialisation */
206 215 static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
207 216 DisplayState *ds, const char **fd_filename, int snapshot,
... ... @@ -230,6 +239,7 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
230 239 slavio_serial_init(PHYS_JJ_SER, PHYS_JJ_SER_IRQ, serial_hds[1], serial_hds[0]);
231 240 fdctrl_init(PHYS_JJ_FLOPPY_IRQ, 0, 1, PHYS_JJ_FDC, fd_table);
232 241 esp_init(bs_table, PHYS_JJ_ESP_IRQ, PHYS_JJ_ESP, PHYS_JJ_ESPDMA);
  242 + slavio_misc = slavio_misc_init(PHYS_JJ_SLAVIO, PHYS_JJ_ME_IRQ);
233 243  
234 244 prom_offset = ram_size + vram_size;
235 245  
... ...
hw/sun4u.c 0 โ†’ 100644
  1 +/*
  2 + * QEMU Sun4u System Emulator
  3 + *
  4 + * Copyright (c) 2005 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +#include "m48t08.h"
  26 +
  27 +#define KERNEL_LOAD_ADDR 0x00004000
  28 +#define CMDLINE_ADDR 0x007ff000
  29 +#define INITRD_LOAD_ADDR 0x00800000
  30 +#define PROM_ADDR 0xffd00000
  31 +#define PROM_FILENAMEB "proll-sparc64.bin"
  32 +#define PROM_FILENAMEE "proll-sparc64.elf"
  33 +#define PHYS_JJ_EEPROM 0x71200000 /* m48t08 */
  34 +#define PHYS_JJ_IDPROM_OFF 0x1FD8
  35 +#define PHYS_JJ_EEPROM_SIZE 0x2000
  36 +// IRQs are not PIL ones, but master interrupt controller register
  37 +// bits
  38 +#define PHYS_JJ_MS_KBD 0x71000000 /* Mouse and keyboard */
  39 +#define PHYS_JJ_MS_KBD_IRQ 14
  40 +#define PHYS_JJ_SER 0x71100000 /* Serial */
  41 +#define PHYS_JJ_SER_IRQ 15
  42 +
  43 +/* TSC handling */
  44 +
  45 +uint64_t cpu_get_tsc()
  46 +{
  47 + return qemu_get_clock(vm_clock);
  48 +}
  49 +
  50 +int DMA_get_channel_mode (int nchan)
  51 +{
  52 + return 0;
  53 +}
  54 +int DMA_read_memory (int nchan, void *buf, int pos, int size)
  55 +{
  56 + return 0;
  57 +}
  58 +int DMA_write_memory (int nchan, void *buf, int pos, int size)
  59 +{
  60 + return 0;
  61 +}
  62 +void DMA_hold_DREQ (int nchan) {}
  63 +void DMA_release_DREQ (int nchan) {}
  64 +void DMA_schedule(int nchan) {}
  65 +void DMA_run (void) {}
  66 +void DMA_init (int high_page_enable) {}
  67 +void DMA_register_channel (int nchan,
  68 + DMA_transfer_handler transfer_handler,
  69 + void *opaque)
  70 +{
  71 +}
  72 +
  73 +static void nvram_set_word (m48t08_t *nvram, uint32_t addr, uint16_t value)
  74 +{
  75 + m48t08_write(nvram, addr++, (value >> 8) & 0xff);
  76 + m48t08_write(nvram, addr++, value & 0xff);
  77 +}
  78 +
  79 +static void nvram_set_lword (m48t08_t *nvram, uint32_t addr, uint32_t value)
  80 +{
  81 + m48t08_write(nvram, addr++, value >> 24);
  82 + m48t08_write(nvram, addr++, (value >> 16) & 0xff);
  83 + m48t08_write(nvram, addr++, (value >> 8) & 0xff);
  84 + m48t08_write(nvram, addr++, value & 0xff);
  85 +}
  86 +
  87 +static void nvram_set_string (m48t08_t *nvram, uint32_t addr,
  88 + const unsigned char *str, uint32_t max)
  89 +{
  90 + unsigned int i;
  91 +
  92 + for (i = 0; i < max && str[i] != '\0'; i++) {
  93 + m48t08_write(nvram, addr + i, str[i]);
  94 + }
  95 + m48t08_write(nvram, addr + max - 1, '\0');
  96 +}
  97 +
  98 +static m48t08_t *nvram;
  99 +
  100 +extern int nographic;
  101 +
  102 +static void nvram_init(m48t08_t *nvram, uint8_t *macaddr, const char *cmdline,
  103 + int boot_device, uint32_t RAM_size,
  104 + uint32_t kernel_size,
  105 + int width, int height, int depth)
  106 +{
  107 + unsigned char tmp = 0;
  108 + int i, j;
  109 +
  110 + // Try to match PPC NVRAM
  111 + nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
  112 + nvram_set_lword(nvram, 0x10, 0x00000001); /* structure v1 */
  113 + // NVRAM_size, arch not applicable
  114 + m48t08_write(nvram, 0x2F, nographic & 0xff);
  115 + nvram_set_lword(nvram, 0x30, RAM_size);
  116 + m48t08_write(nvram, 0x34, boot_device & 0xff);
  117 + nvram_set_lword(nvram, 0x38, KERNEL_LOAD_ADDR);
  118 + nvram_set_lword(nvram, 0x3C, kernel_size);
  119 + if (cmdline) {
  120 + strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
  121 + nvram_set_lword(nvram, 0x40, CMDLINE_ADDR);
  122 + nvram_set_lword(nvram, 0x44, strlen(cmdline));
  123 + }
  124 + // initrd_image, initrd_size passed differently
  125 + nvram_set_word(nvram, 0x54, width);
  126 + nvram_set_word(nvram, 0x56, height);
  127 + nvram_set_word(nvram, 0x58, depth);
  128 +
  129 + // Sun4m specific use
  130 + i = 0x1fd8;
  131 + m48t08_write(nvram, i++, 0x01);
  132 + m48t08_write(nvram, i++, 0x80); /* Sun4m OBP */
  133 + j = 0;
  134 + m48t08_write(nvram, i++, macaddr[j++]);
  135 + m48t08_write(nvram, i++, macaddr[j++]);
  136 + m48t08_write(nvram, i++, macaddr[j++]);
  137 + m48t08_write(nvram, i++, macaddr[j++]);
  138 + m48t08_write(nvram, i++, macaddr[j++]);
  139 + m48t08_write(nvram, i, macaddr[j]);
  140 +
  141 + /* Calculate checksum */
  142 + for (i = 0x1fd8; i < 0x1fe7; i++) {
  143 + tmp ^= m48t08_read(nvram, i);
  144 + }
  145 + m48t08_write(nvram, 0x1fe7, tmp);
  146 +}
  147 +
  148 +void pic_info()
  149 +{
  150 +}
  151 +
  152 +void irq_info()
  153 +{
  154 +}
  155 +
  156 +void pic_set_irq(int irq, int level)
  157 +{
  158 +}
  159 +
  160 +void vga_update_display()
  161 +{
  162 +}
  163 +
  164 +void vga_invalidate_display()
  165 +{
  166 +}
  167 +
  168 +void vga_screen_dump(const char *filename)
  169 +{
  170 +}
  171 +
  172 +void qemu_system_powerdown(void)
  173 +{
  174 +}
  175 +
  176 +/* Sun4u hardware initialisation */
  177 +static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
  178 + DisplayState *ds, const char **fd_filename, int snapshot,
  179 + const char *kernel_filename, const char *kernel_cmdline,
  180 + const char *initrd_filename)
  181 +{
  182 + char buf[1024];
  183 + int ret, linux_boot;
  184 + unsigned int i;
  185 + long vram_size = 0x100000, prom_offset, initrd_size, kernel_size;
  186 +
  187 + linux_boot = (kernel_filename != NULL);
  188 +
  189 + /* allocate RAM */
  190 + cpu_register_physical_memory(0, ram_size, 0);
  191 +
  192 + nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE);
  193 + // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
  194 + // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
  195 + slavio_serial_init(PHYS_JJ_SER, PHYS_JJ_SER_IRQ, serial_hds[1], serial_hds[0]);
  196 +
  197 + prom_offset = ram_size + vram_size;
  198 +
  199 + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
  200 + ret = load_elf(buf, phys_ram_base + prom_offset);
  201 + if (ret < 0) {
  202 + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
  203 + ret = load_image(buf, phys_ram_base + prom_offset);
  204 + }
  205 + if (ret < 0) {
  206 + fprintf(stderr, "qemu: could not load prom '%s'\n",
  207 + buf);
  208 + exit(1);
  209 + }
  210 + cpu_register_physical_memory(PROM_ADDR, (ret + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK,
  211 + prom_offset | IO_MEM_ROM);
  212 +
  213 + kernel_size = 0;
  214 + if (linux_boot) {
  215 + kernel_size = load_elf(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
  216 + if (kernel_size < 0)
  217 + kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
  218 + if (kernel_size < 0)
  219 + kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
  220 + if (kernel_size < 0) {
  221 + fprintf(stderr, "qemu: could not load kernel '%s'\n",
  222 + kernel_filename);
  223 + exit(1);
  224 + }
  225 +
  226 + /* load initrd */
  227 + initrd_size = 0;
  228 + if (initrd_filename) {
  229 + initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
  230 + if (initrd_size < 0) {
  231 + fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
  232 + initrd_filename);
  233 + exit(1);
  234 + }
  235 + }
  236 + if (initrd_size > 0) {
  237 + for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
  238 + if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
  239 + == 0x48647253) { // HdrS
  240 + stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
  241 + stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
  242 + break;
  243 + }
  244 + }
  245 + }
  246 + }
  247 + nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline, boot_device, ram_size, kernel_size, graphic_width, graphic_height, graphic_depth);
  248 +}
  249 +
  250 +QEMUMachine sun4u_machine = {
  251 + "sun4u",
  252 + "Sun4u platform",
  253 + sun4u_init,
  254 +};
... ...
linux-user/main.c
... ... @@ -552,6 +552,7 @@ void cpu_loop (CPUSPARCState *env)
552 552 env->pc = env->npc;
553 553 env->npc = env->npc + 4;
554 554 break;
  555 +#ifndef TARGET_SPARC64
555 556 case TT_WIN_OVF: /* window overflow */
556 557 save_window(env);
557 558 break;
... ... @@ -569,6 +570,9 @@ void cpu_loop (CPUSPARCState *env)
569 570 queue_signal(info.si_signo, &info);
570 571 }
571 572 break;
  573 +#else
  574 + // XXX
  575 +#endif
572 576 case 0x100: // XXX, why do we get these?
573 577 break;
574 578 case EXCP_DEBUG:
... ...
monitor.c
... ... @@ -767,6 +767,11 @@ static void do_system_reset(void)
767 767 qemu_system_reset_request();
768 768 }
769 769  
  770 +static void do_system_powerdown(void)
  771 +{
  772 + qemu_system_powerdown_request();
  773 +}
  774 +
770 775 #if defined(TARGET_I386)
771 776 static void print_pte(uint32_t addr, uint32_t pte, uint32_t mask)
772 777 {
... ... @@ -922,6 +927,8 @@ static term_cmd_t term_cmds[] = {
922 927 "keys", "send keys to the VM (e.g. 'sendkey ctrl-alt-f1')" },
923 928 { "system_reset", "", do_system_reset,
924 929 "", "reset the system" },
  930 + { "system_powerdown", "", do_system_powerdown,
  931 + "", "send system power down event" },
925 932 { "sum", "ii", do_sum,
926 933 "addr size", "compute the checksum of a memory region" },
927 934 { NULL, NULL, },
... ...
qemu-doc.texi
... ... @@ -42,10 +42,11 @@ For system emulation, the following hardware targets are supported:
42 42 @item PC (x86 processor)
43 43 @item PREP (PowerPC processor)
44 44 @item PowerMac (PowerPC processor, in progress)
45   -@item Sun4m (Sparc processor, in progress)
  45 +@item Sun4m (32-bit Sparc processor)
  46 +@item Sun4u (64-bit Sparc processor, in progress)
46 47 @end itemize
47 48  
48   -For user emulation, x86, PowerPC, ARM, and SPARC CPUs are supported.
  49 +For user emulation, x86, PowerPC, ARM, and Sparc32/64 CPUs are supported.
49 50  
50 51 @chapter Installation
51 52  
... ... @@ -999,15 +1000,15 @@ Set the initial VGA graphic mode. The default is 800x600x15.
999 1000 More information is available at
1000 1001 @url{http://jocelyn.mayer.free.fr/qemu-ppc/}.
1001 1002  
1002   -@chapter Sparc System emulator invocation
  1003 +@chapter Sparc32 System emulator invocation
1003 1004  
1004 1005 Use the executable @file{qemu-system-sparc} to simulate a JavaStation
1005   -(sun4m architecture). The emulation is far from complete.
  1006 +(sun4m architecture). The emulation is somewhat complete.
1006 1007  
1007 1008 QEMU emulates the following sun4m peripherals:
1008 1009  
1009 1010 @itemize @minus
1010   -@item
  1011 +@item
1011 1012 IOMMU
1012 1013 @item
1013 1014 TCX Frame buffer
... ... @@ -1016,14 +1017,42 @@ Lance (Am7990) Ethernet
1016 1017 @item
1017 1018 Non Volatile RAM M48T08
1018 1019 @item
1019   -Slave I/O: timers, interrupt controllers, Zilog serial ports
  1020 +Slave I/O: timers, interrupt controllers, Zilog serial ports, keyboard
  1021 +and power/reset logic
  1022 +@item
  1023 +ESP SCSI controller with hard disk and CD-ROM support
  1024 +@item
  1025 +Floppy drive
1020 1026 @end itemize
1021 1027  
  1028 +The number of peripherals is fixed in the architecture.
  1029 +
1022 1030 QEMU uses the Proll, a PROM replacement available at
1023   -@url{http://people.redhat.com/zaitcev/linux/}.
  1031 +@url{http://people.redhat.com/zaitcev/linux/}. The required
  1032 +QEMU-specific patches are included with the sources.
  1033 +
  1034 +A sample Linux 2.6 series kernel and ram disk image are available on
  1035 +the QEMU web site. Please note that currently neither Linux 2.4
  1036 +series, NetBSD, nor OpenBSD kernels work.
  1037 +
  1038 +@c man begin OPTIONS
  1039 +
  1040 +The following options are specific to the Sparc emulation:
  1041 +
  1042 +@table @option
  1043 +
  1044 +@item -g WxH
  1045 +
  1046 +Set the initial TCX graphic mode. The default is 1024x768.
  1047 +
  1048 +@end table
  1049 +
  1050 +@c man end
  1051 +
  1052 +@chapter Sparc64 System emulator invocation
1024 1053  
1025   -A sample Linux kernel and ram disk image are available on the QEMU web
1026   -site.
  1054 +Use the executable @file{qemu-system-sparc64} to simulate a Sun4u machine.
  1055 +The emulator is not usable for anything yet.
1027 1056  
1028 1057 @chapter QEMU User space emulator invocation
1029 1058  
... ...
qemu-tech.texi
... ... @@ -138,9 +138,32 @@ FPU and MMU.
138 138 @itemize
139 139  
140 140 @item Somewhat complete SPARC V8 emulation, including privileged
141   -instructions, FPU and MMU.
  141 +instructions, FPU and MMU. SPARC V9 emulation includes most privileged
  142 +instructions, FPU and I/D MMU, but misses VIS instructions.
142 143  
143   -@item Can run some SPARC Linux binaries.
  144 +@item Can run some 32-bit SPARC Linux binaries.
  145 +
  146 +@end itemize
  147 +
  148 +Current QEMU limitations:
  149 +
  150 +@itemize
  151 +
  152 +@item Tagged add/subtract instructions are not supported, but they are
  153 +probably not used.
  154 +
  155 +@item IPC syscalls are missing.
  156 +
  157 +@item 128-bit floating point operations are not supported, though none of the
  158 +real CPUs implement them either. FCMPE[SD] are not correctly
  159 +implemented. Floating point exception support is untested.
  160 +
  161 +@item Alignment is not enforced at all.
  162 +
  163 +@item Atomic instructions are not correctly implemented.
  164 +
  165 +@item Sparc64 emulators are not usable for anything yet.
  166 +Address space is limited to first 4 gigabytes.
144 167  
145 168 @end itemize
146 169  
... ...
target-sparc/cpu.h
... ... @@ -6,12 +6,11 @@
6 6 #if !defined(TARGET_SPARC64)
7 7 #define TARGET_LONG_BITS 32
8 8 #define TARGET_FPREGS 32
9   -#define TARGET_FPREG_T float
10 9 #else
11 10 #define TARGET_LONG_BITS 64
12 11 #define TARGET_FPREGS 64
13   -#define TARGET_FPREG_T double
14 12 #endif
  13 +#define TARGET_FPREG_T float
15 14  
16 15 #include "cpu-defs.h"
17 16  
... ... @@ -22,6 +21,7 @@
22 21 /*#define EXCP_INTERRUPT 0x100*/
23 22  
24 23 /* trap definitions */
  24 +#ifndef TARGET_SPARC64
25 25 #define TT_TFAULT 0x01
26 26 #define TT_ILL_INSN 0x02
27 27 #define TT_PRIV_INSN 0x03
... ... @@ -33,6 +33,21 @@
33 33 #define TT_EXTINT 0x10
34 34 #define TT_DIV_ZERO 0x2a
35 35 #define TT_TRAP 0x80
  36 +#else
  37 +#define TT_TFAULT 0x08
  38 +#define TT_ILL_INSN 0x10
  39 +#define TT_PRIV_INSN 0x11
  40 +#define TT_NFPU_INSN 0x20
  41 +#define TT_FP_EXCP 0x21
  42 +#define TT_CLRWIN 0x24
  43 +#define TT_DIV_ZERO 0x28
  44 +#define TT_DFAULT 0x30
  45 +#define TT_EXTINT 0x40
  46 +#define TT_SPILL 0x80
  47 +#define TT_FILL 0xc0
  48 +#define TT_WOTHER 0x10
  49 +#define TT_TRAP 0x100
  50 +#endif
36 51  
37 52 #define PSR_NEG (1<<23)
38 53 #define PSR_ZERO (1<<22)
... ... @@ -49,6 +64,13 @@
49 64 /* Trap base register */
50 65 #define TBR_BASE_MASK 0xfffff000
51 66  
  67 +#if defined(TARGET_SPARC64)
  68 +#define PS_PEF (1<<4)
  69 +#define PS_AM (1<<3)
  70 +#define PS_PRIV (1<<2)
  71 +#define PS_IE (1<<1)
  72 +#endif
  73 +
52 74 /* Fcc */
53 75 #define FSR_RD1 (1<<31)
54 76 #define FSR_RD0 (1<<30)
... ... @@ -119,15 +141,15 @@ typedef struct CPUSPARCState {
119 141 target_ulong npc; /* next program counter */
120 142 target_ulong y; /* multiply/divide register */
121 143 uint32_t psr; /* processor state register */
122   - uint32_t fsr; /* FPU state register */
  144 + target_ulong fsr; /* FPU state register */
123 145 uint32_t cwp; /* index of current register window (extracted
124 146 from PSR) */
125 147 uint32_t wim; /* window invalid mask */
126   - uint32_t tbr; /* trap base register */
  148 + target_ulong tbr; /* trap base register */
127 149 int psrs; /* supervisor mode (extracted from PSR) */
128 150 int psrps; /* previous supervisor mode */
129 151 int psret; /* enable traps */
130   - int psrpil; /* interrupt level */
  152 + uint32_t psrpil; /* interrupt level */
131 153 int psref; /* enable fpu */
132 154 jmp_buf jmp_env;
133 155 int user_mode_only;
... ... @@ -150,13 +172,43 @@ typedef struct CPUSPARCState {
150 172 CPUTLBEntry tlb_read[2][CPU_TLB_SIZE];
151 173 CPUTLBEntry tlb_write[2][CPU_TLB_SIZE];
152 174 /* MMU regs */
  175 +#if defined(TARGET_SPARC64)
  176 + uint64_t lsu;
  177 +#define DMMU_E 0x8
  178 +#define IMMU_E 0x4
  179 + uint64_t immuregs[16];
  180 + uint64_t dmmuregs[16];
  181 + uint64_t itlb_tag[64];
  182 + uint64_t itlb_tte[64];
  183 + uint64_t dtlb_tag[64];
  184 + uint64_t dtlb_tte[64];
  185 +#else
153 186 uint32_t mmuregs[16];
  187 +#endif
154 188 /* temporary float registers */
155   - float ft0, ft1, ft2;
156   - double dt0, dt1, dt2;
  189 + float ft0, ft1;
  190 + double dt0, dt1;
157 191 float_status fp_status;
158 192 #if defined(TARGET_SPARC64)
159   - target_ulong t0, t1, t2;
  193 +#define MAXTL 4
  194 + uint64_t t0, t1, t2;
  195 + uint64_t tpc[MAXTL];
  196 + uint64_t tnpc[MAXTL];
  197 + uint64_t tstate[MAXTL];
  198 + uint32_t tt[MAXTL];
  199 + uint32_t xcc; /* Extended integer condition codes */
  200 + uint32_t asi;
  201 + uint32_t pstate;
  202 + uint32_t tl;
  203 + uint32_t cansave, canrestore, otherwin, wstate, cleanwin;
  204 + target_ulong agregs[8]; /* alternate general registers */
  205 + target_ulong igregs[8]; /* interrupt general registers */
  206 + target_ulong mgregs[8]; /* mmu general registers */
  207 + uint64_t version;
  208 + uint64_t fprs;
  209 +#endif
  210 +#if !defined(TARGET_SPARC64) && !defined(reg_T2)
  211 + target_ulong t2;
160 212 #endif
161 213  
162 214 /* ice debug support */
... ... @@ -165,6 +217,24 @@ typedef struct CPUSPARCState {
165 217 int singlestep_enabled; /* XXX: should use CPU single step mode instead */
166 218  
167 219 } CPUSPARCState;
  220 +#if defined(TARGET_SPARC64)
  221 +#define GET_FSR32(env) (env->fsr & 0xcfc1ffff)
  222 +#define PUT_FSR32(env, val) do { uint32_t _tmp = val; \
  223 + env->fsr = (_tmp & 0xcfc1c3ff) | (env->fsr & 0x3f00000000ULL); \
  224 + } while (0)
  225 +#define GET_FSR64(env) (env->fsr & 0x3fcfc1ffffULL)
  226 +#define PUT_FSR64(env, val) do { uint64_t _tmp = val; \
  227 + env->fsr = _tmp & 0x3fcfc1c3ffULL; \
  228 + } while (0)
  229 +// Manuf 0x17, version 0x11, mask 0 (UltraSparc-II)
  230 +#define GET_VER(env) ((0x17ULL << 48) | (0x11ULL << 32) | \
  231 + (0 << 24) | (MAXTL << 8) | (NWINDOWS - 1))
  232 +#else
  233 +#define GET_FSR32(env) (env->fsr)
  234 +#define PUT_FSR32(env, val) do { uint32_t _tmp = val; \
  235 + env->fsr = _tmp & 0xcfc1ffff; \
  236 + } while (0)
  237 +#endif
168 238  
169 239 CPUSPARCState *cpu_sparc_init(void);
170 240 int cpu_sparc_exec(CPUSPARCState *s);
... ... @@ -194,6 +264,14 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
194 264 cpu_set_cwp(env, _tmp & PSR_CWP & (NWINDOWS - 1)); \
195 265 } while (0)
196 266  
  267 +#ifdef TARGET_SPARC64
  268 +#define GET_CCR(env) ((env->xcc << 4) | (env->psr & PSR_ICC))
  269 +#define PUT_CCR(env, val) do { int _tmp = val; \
  270 + env->xcc = _tmp >> 4; \
  271 + env->psr = (_tmp & 0xf) << 20; \
  272 + } while (0)
  273 +#endif
  274 +
197 275 struct siginfo;
198 276 int cpu_sparc_signal_handler(int hostsignum, struct siginfo *info, void *puc);
199 277  
... ...
target-sparc/exec.h
1 1 #ifndef EXEC_SPARC_H
2 2 #define EXEC_SPARC_H 1
3 3 #include "dyngen-exec.h"
  4 +#include "config.h"
4 5  
5 6 register struct CPUSPARCState *env asm(AREG0);
6 7 #ifdef TARGET_SPARC64
7 8 #define T0 (env->t0)
8 9 #define T1 (env->t1)
9 10 #define T2 (env->t2)
  11 +#define REGWPTR env->regwptr
10 12 #else
11 13 register uint32_t T0 asm(AREG1);
12 14 register uint32_t T1 asm(AREG2);
  15 +
  16 +#undef REG_REGWPTR // Broken
  17 +#ifdef REG_REGWPTR
  18 +register uint32_t *REGWPTR asm(AREG3);
  19 +#define reg_REGWPTR
  20 +
  21 +#ifdef AREG4
  22 +register uint32_t T2 asm(AREG4);
  23 +#define reg_T2
  24 +#else
  25 +#define T2 (env->t2)
  26 +#endif
  27 +
  28 +#else
  29 +#define REGWPTR env->regwptr
13 30 register uint32_t T2 asm(AREG3);
  31 +#define reg_T2
  32 +#endif
14 33 #endif
  34 +
15 35 #define FT0 (env->ft0)
16 36 #define FT1 (env->ft1)
17   -#define FT2 (env->ft2)
18 37 #define DT0 (env->dt0)
19 38 #define DT1 (env->dt1)
20   -#define DT2 (env->dt2)
21 39  
22 40 #include "cpu.h"
23 41 #include "exec-all.h"
... ... @@ -38,6 +56,16 @@ void do_fsqrts(void);
38 56 void do_fsqrtd(void);
39 57 void do_fcmps(void);
40 58 void do_fcmpd(void);
  59 +#ifdef TARGET_SPARC64
  60 +void do_fabsd(void);
  61 +void do_fcmps_fcc1(void);
  62 +void do_fcmpd_fcc1(void);
  63 +void do_fcmps_fcc2(void);
  64 +void do_fcmpd_fcc2(void);
  65 +void do_fcmps_fcc3(void);
  66 +void do_fcmpd_fcc3(void);
  67 +void do_popc();
  68 +#endif
41 69 void do_ldd_kernel(target_ulong addr);
42 70 void do_ldd_user(target_ulong addr);
43 71 void do_ldd_raw(target_ulong addr);
... ...
target-sparc/fbranch_template.h 0 โ†’ 100644
  1 +/* FCC1:FCC0: 0 =, 1 <, 2 >, 3 u */
  2 +
  3 +void OPPROTO glue(op_eval_fbne, FCC)(void)
  4 +{
  5 +// !0
  6 + T2 = FFLAG_SET(FSR_FCC0) | FFLAG_SET(FSR_FCC1); /* L or G or U */
  7 +}
  8 +
  9 +void OPPROTO glue(op_eval_fblg, FCC)(void)
  10 +{
  11 +// 1 or 2
  12 + T2 = FFLAG_SET(FSR_FCC0) ^ FFLAG_SET(FSR_FCC1);
  13 +}
  14 +
  15 +void OPPROTO glue(op_eval_fbul, FCC)(void)
  16 +{
  17 +// 1 or 3
  18 + T2 = FFLAG_SET(FSR_FCC0);
  19 +}
  20 +
  21 +void OPPROTO glue(op_eval_fbl, FCC)(void)
  22 +{
  23 +// 1
  24 + T2 = FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1);
  25 +}
  26 +
  27 +void OPPROTO glue(op_eval_fbug, FCC)(void)
  28 +{
  29 +// 2 or 3
  30 + T2 = FFLAG_SET(FSR_FCC1);
  31 +}
  32 +
  33 +void OPPROTO glue(op_eval_fbg, FCC)(void)
  34 +{
  35 +// 2
  36 + T2 = !FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1);
  37 +}
  38 +
  39 +void OPPROTO glue(op_eval_fbu, FCC)(void)
  40 +{
  41 +// 3
  42 + T2 = FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1);
  43 +}
  44 +
  45 +void OPPROTO glue(op_eval_fbe, FCC)(void)
  46 +{
  47 +// 0
  48 + T2 = !FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1);
  49 +}
  50 +
  51 +void OPPROTO glue(op_eval_fbue, FCC)(void)
  52 +{
  53 +// 0 or 3
  54 + T2 = !(FFLAG_SET(FSR_FCC1) ^ FFLAG_SET(FSR_FCC0));
  55 + FORCE_RET();
  56 +}
  57 +
  58 +void OPPROTO glue(op_eval_fbge, FCC)(void)
  59 +{
  60 +// 0 or 2
  61 + T2 = !FFLAG_SET(FSR_FCC0);
  62 +}
  63 +
  64 +void OPPROTO glue(op_eval_fbuge, FCC)(void)
  65 +{
  66 +// !1
  67 + T2 = !(FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1));
  68 +}
  69 +
  70 +void OPPROTO glue(op_eval_fble, FCC)(void)
  71 +{
  72 +// 0 or 1
  73 + T2 = !FFLAG_SET(FSR_FCC1);
  74 +}
  75 +
  76 +void OPPROTO glue(op_eval_fbule, FCC)(void)
  77 +{
  78 +// !2
  79 + T2 = !(!FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1));
  80 +}
  81 +
  82 +void OPPROTO glue(op_eval_fbo, FCC)(void)
  83 +{
  84 +// !3
  85 + T2 = !(FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1));
  86 +}
  87 +
  88 +#undef FCC
  89 +#undef FFLAG_SET
... ...
target-sparc/fop_template.h
... ... @@ -40,16 +40,6 @@ void OPPROTO glue(op_store_FT1_fpr_fpr, REGNAME)(void)
40 40 REG = FT1;
41 41 }
42 42  
43   -void OPPROTO glue(op_load_fpr_FT2_fpr, REGNAME)(void)
44   -{
45   - FT2 = REG;
46   -}
47   -
48   -void OPPROTO glue(op_store_FT2_fpr_fpr, REGNAME)(void)
49   -{
50   - REG = FT2;
51   -}
52   -
53 43 /* double floating point registers moves */
54 44 void OPPROTO glue(op_load_fpr_DT0_fpr, REGNAME)(void)
55 45 {
... ... @@ -87,23 +77,5 @@ void OPPROTO glue(op_store_DT1_fpr_fpr, REGNAME)(void)
87 77 *p = u.l.upper;
88 78 }
89 79  
90   -void OPPROTO glue(op_load_fpr_DT2_fpr, REGNAME)(void)
91   -{
92   - CPU_DoubleU u;
93   - uint32_t *p = (uint32_t *)&REG;
94   - u.l.lower = *(p +1);
95   - u.l.upper = *p;
96   - DT2 = u.d;
97   -}
98   -
99   -void OPPROTO glue(op_store_DT2_fpr_fpr, REGNAME)(void)
100   -{
101   - CPU_DoubleU u;
102   - uint32_t *p = (uint32_t *)&REG;
103   - u.d = DT2;
104   - *(p +1) = u.l.lower;
105   - *p = u.l.upper;
106   -}
107   -
108 80 #undef REG
109 81 #undef REGNAME
... ...
target-sparc/helper.c
... ... @@ -43,7 +43,6 @@ void cpu_unlock(void)
43 43 int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
44 44 int is_user, int is_softmmu)
45 45 {
46   - env->mmuregs[4] = address;
47 46 if (rw & 2)
48 47 env->exception_index = TT_TFAULT;
49 48 else
... ... @@ -102,6 +101,7 @@ void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
102 101 env = saved_env;
103 102 }
104 103  
  104 +#ifndef TARGET_SPARC64
105 105 static const int access_table[8][8] = {
106 106 { 0, 0, 0, 0, 2, 0, 3, 3 },
107 107 { 0, 0, 0, 0, 2, 0, 0, 0 },
... ... @@ -268,6 +268,136 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
268 268 return 1;
269 269 }
270 270 }
  271 +#else
  272 +static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot,
  273 + int *access_index, target_ulong address, int rw,
  274 + int is_user)
  275 +{
  276 + target_ulong mask;
  277 + unsigned int i;
  278 +
  279 + if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
  280 + *physical = address & 0xffffffff;
  281 + *prot = PAGE_READ | PAGE_WRITE;
  282 + return 0;
  283 + }
  284 +
  285 + for (i = 0; i < 64; i++) {
  286 + if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
  287 + switch (env->dtlb_tte[i] >> 60) {
  288 + default:
  289 + case 0x4: // 8k
  290 + mask = 0xffffffffffffe000ULL;
  291 + break;
  292 + case 0x5: // 64k
  293 + mask = 0xffffffffffff0000ULL;
  294 + break;
  295 + case 0x6: // 512k
  296 + mask = 0xfffffffffff80000ULL;
  297 + break;
  298 + case 0x7: // 4M
  299 + mask = 0xffffffffffc00000ULL;
  300 + break;
  301 + }
  302 + // ctx match, vaddr match?
  303 + if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
  304 + (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
  305 + // access ok?
  306 + if (((env->dtlb_tte[i] & 0x4) && !(env->pstate & PS_PRIV)) ||
  307 + (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
  308 + env->exception_index = TT_DFAULT;
  309 + return 1;
  310 + }
  311 + *physical = env->dtlb_tte[i] & 0xffffe000;
  312 + *prot = PAGE_READ;
  313 + if (env->dtlb_tte[i] & 0x2)
  314 + *prot |= PAGE_WRITE;
  315 + return 0;
  316 + }
  317 + }
  318 + }
  319 + env->exception_index = TT_DFAULT;
  320 + return 1;
  321 +}
  322 +
  323 +static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot,
  324 + int *access_index, target_ulong address, int rw,
  325 + int is_user)
  326 +{
  327 + target_ulong mask;
  328 + unsigned int i;
  329 +
  330 + if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
  331 + *physical = address & 0xffffffff;
  332 + *prot = PAGE_READ;
  333 + return 0;
  334 + }
  335 + for (i = 0; i < 64; i++) {
  336 + if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
  337 + switch (env->itlb_tte[i] >> 60) {
  338 + default:
  339 + case 0x4: // 8k
  340 + mask = 0xffffffffffffe000ULL;
  341 + break;
  342 + case 0x5: // 64k
  343 + mask = 0xffffffffffff0000ULL;
  344 + break;
  345 + case 0x6: // 512k
  346 + mask = 0xfffffffffff80000ULL;
  347 + break;
  348 + case 0x7: // 4M
  349 + mask = 0xffffffffffc00000ULL;
  350 + break;
  351 + }
  352 + // ctx match, vaddr match?
  353 + if (env->immuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
  354 + (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
  355 + // access ok?
  356 + if ((env->itlb_tte[i] & 0x4) && !(env->pstate & PS_PRIV)) {
  357 + env->exception_index = TT_TFAULT;
  358 + return 1;
  359 + }
  360 + *physical = env->itlb_tte[i] & 0xffffe000;
  361 + *prot = PAGE_READ;
  362 + return 0;
  363 + }
  364 + }
  365 + }
  366 + env->exception_index = TT_TFAULT;
  367 + return 1;
  368 +}
  369 +
  370 +int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot,
  371 + int *access_index, target_ulong address, int rw,
  372 + int is_user)
  373 +{
  374 + if (rw == 2)
  375 + return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user);
  376 + else
  377 + return get_physical_address_data(env, physical, prot, access_index, address, rw, is_user);
  378 +}
  379 +
  380 +/* Perform address translation */
  381 +int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
  382 + int is_user, int is_softmmu)
  383 +{
  384 + target_ulong virt_addr;
  385 + target_phys_addr_t paddr;
  386 + unsigned long vaddr;
  387 + int error_code = 0, prot, ret = 0, access_index;
  388 +
  389 + error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
  390 + if (error_code == 0) {
  391 + virt_addr = address & TARGET_PAGE_MASK;
  392 + vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
  393 + ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
  394 + return ret;
  395 + }
  396 + // XXX
  397 + return 1;
  398 +}
  399 +
  400 +#endif
271 401 #endif
272 402  
273 403 void memcpy32(target_ulong *dst, const target_ulong *src)
... ... @@ -292,17 +422,73 @@ void set_cwp(int new_cwp)
292 422 if (new_cwp == (NWINDOWS - 1))
293 423 memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
294 424 env->regwptr = env->regbase + (new_cwp * 16);
  425 + REGWPTR = env->regwptr;
295 426 }
296 427  
297 428 void cpu_set_cwp(CPUState *env1, int new_cwp)
298 429 {
299 430 CPUState *saved_env;
  431 +#ifdef reg_REGWPTR
  432 + target_ulong *saved_regwptr;
  433 +#endif
  434 +
300 435 saved_env = env;
  436 +#ifdef reg_REGWPTR
  437 + saved_regwptr = REGWPTR;
  438 +#endif
301 439 env = env1;
302 440 set_cwp(new_cwp);
303 441 env = saved_env;
  442 +#ifdef reg_REGWPTR
  443 + REGWPTR = saved_regwptr;
  444 +#endif
304 445 }
305 446  
  447 +#ifdef TARGET_SPARC64
  448 +void do_interrupt(int intno)
  449 +{
  450 +#ifdef DEBUG_PCALL
  451 + if (loglevel & CPU_LOG_INT) {
  452 + static int count;
  453 + fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
  454 + count, intno,
  455 + env->pc,
  456 + env->npc, env->regwptr[6]);
  457 + cpu_dump_state(env, logfile, fprintf, 0);
  458 +#if 0
  459 + {
  460 + int i;
  461 + uint8_t *ptr;
  462 +
  463 + fprintf(logfile, " code=");
  464 + ptr = (uint8_t *)env->pc;
  465 + for(i = 0; i < 16; i++) {
  466 + fprintf(logfile, " %02x", ldub(ptr + i));
  467 + }
  468 + fprintf(logfile, "\n");
  469 + }
  470 +#endif
  471 + count++;
  472 + }
  473 +#endif
  474 +#if !defined(CONFIG_USER_ONLY)
  475 + if (env->pstate & PS_IE) {
  476 + cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
  477 + return;
  478 + }
  479 +#endif
  480 + env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
  481 + ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff);
  482 + env->tpc[env->tl] = env->pc;
  483 + env->tnpc[env->tl] = env->npc;
  484 + env->tt[env->tl] = intno;
  485 + env->tbr = env->tbr | (env->tl > 1) ? 1 << 14 : 0 | (intno << 4);
  486 + env->tl++;
  487 + env->pc = env->tbr;
  488 + env->npc = env->pc + 4;
  489 + env->exception_index = 0;
  490 +}
  491 +#else
306 492 void do_interrupt(int intno)
307 493 {
308 494 int cwp;
... ... @@ -448,3 +634,4 @@ void dump_mmu(void)
448 634 printf("MMU dump ends\n");
449 635 }
450 636 #endif
  637 +#endif
... ...
target-sparc/op.c
... ... @@ -46,76 +46,76 @@
46 46 #define REG (env->gregs[7])
47 47 #include "op_template.h"
48 48 #define REGNAME i0
49   -#define REG (env->regwptr[16])
  49 +#define REG (REGWPTR[16])
50 50 #include "op_template.h"
51 51 #define REGNAME i1
52   -#define REG (env->regwptr[17])
  52 +#define REG (REGWPTR[17])
53 53 #include "op_template.h"
54 54 #define REGNAME i2
55   -#define REG (env->regwptr[18])
  55 +#define REG (REGWPTR[18])
56 56 #include "op_template.h"
57 57 #define REGNAME i3
58   -#define REG (env->regwptr[19])
  58 +#define REG (REGWPTR[19])
59 59 #include "op_template.h"
60 60 #define REGNAME i4
61   -#define REG (env->regwptr[20])
  61 +#define REG (REGWPTR[20])
62 62 #include "op_template.h"
63 63 #define REGNAME i5
64   -#define REG (env->regwptr[21])
  64 +#define REG (REGWPTR[21])
65 65 #include "op_template.h"
66 66 #define REGNAME i6
67   -#define REG (env->regwptr[22])
  67 +#define REG (REGWPTR[22])
68 68 #include "op_template.h"
69 69 #define REGNAME i7
70   -#define REG (env->regwptr[23])
  70 +#define REG (REGWPTR[23])
71 71 #include "op_template.h"
72 72 #define REGNAME l0
73   -#define REG (env->regwptr[8])
  73 +#define REG (REGWPTR[8])
74 74 #include "op_template.h"
75 75 #define REGNAME l1
76   -#define REG (env->regwptr[9])
  76 +#define REG (REGWPTR[9])
77 77 #include "op_template.h"
78 78 #define REGNAME l2
79   -#define REG (env->regwptr[10])
  79 +#define REG (REGWPTR[10])
80 80 #include "op_template.h"
81 81 #define REGNAME l3
82   -#define REG (env->regwptr[11])
  82 +#define REG (REGWPTR[11])
83 83 #include "op_template.h"
84 84 #define REGNAME l4
85   -#define REG (env->regwptr[12])
  85 +#define REG (REGWPTR[12])
86 86 #include "op_template.h"
87 87 #define REGNAME l5
88   -#define REG (env->regwptr[13])
  88 +#define REG (REGWPTR[13])
89 89 #include "op_template.h"
90 90 #define REGNAME l6
91   -#define REG (env->regwptr[14])
  91 +#define REG (REGWPTR[14])
92 92 #include "op_template.h"
93 93 #define REGNAME l7
94   -#define REG (env->regwptr[15])
  94 +#define REG (REGWPTR[15])
95 95 #include "op_template.h"
96 96 #define REGNAME o0
97   -#define REG (env->regwptr[0])
  97 +#define REG (REGWPTR[0])
98 98 #include "op_template.h"
99 99 #define REGNAME o1
100   -#define REG (env->regwptr[1])
  100 +#define REG (REGWPTR[1])
101 101 #include "op_template.h"
102 102 #define REGNAME o2
103   -#define REG (env->regwptr[2])
  103 +#define REG (REGWPTR[2])
104 104 #include "op_template.h"
105 105 #define REGNAME o3
106   -#define REG (env->regwptr[3])
  106 +#define REG (REGWPTR[3])
107 107 #include "op_template.h"
108 108 #define REGNAME o4
109   -#define REG (env->regwptr[4])
  109 +#define REG (REGWPTR[4])
110 110 #include "op_template.h"
111 111 #define REGNAME o5
112   -#define REG (env->regwptr[5])
  112 +#define REG (REGWPTR[5])
113 113 #include "op_template.h"
114 114 #define REGNAME o6
115   -#define REG (env->regwptr[6])
  115 +#define REG (REGWPTR[6])
116 116 #include "op_template.h"
117 117 #define REGNAME o7
118   -#define REG (env->regwptr[7])
  118 +#define REG (REGWPTR[7])
119 119 #include "op_template.h"
120 120  
121 121 #define REGNAME f0
... ... @@ -215,10 +215,106 @@
215 215 #define REG (env->fpr[31])
216 216 #include "fop_template.h"
217 217  
  218 +#ifdef TARGET_SPARC64
  219 +#define REGNAME f32
  220 +#define REG (env->fpr[32])
  221 +#include "fop_template.h"
  222 +#define REGNAME f34
  223 +#define REG (env->fpr[34])
  224 +#include "fop_template.h"
  225 +#define REGNAME f36
  226 +#define REG (env->fpr[36])
  227 +#include "fop_template.h"
  228 +#define REGNAME f38
  229 +#define REG (env->fpr[38])
  230 +#include "fop_template.h"
  231 +#define REGNAME f40
  232 +#define REG (env->fpr[40])
  233 +#include "fop_template.h"
  234 +#define REGNAME f42
  235 +#define REG (env->fpr[42])
  236 +#include "fop_template.h"
  237 +#define REGNAME f44
  238 +#define REG (env->fpr[44])
  239 +#include "fop_template.h"
  240 +#define REGNAME f46
  241 +#define REG (env->fpr[46])
  242 +#include "fop_template.h"
  243 +#define REGNAME f48
  244 +#define REG (env->fpr[47])
  245 +#include "fop_template.h"
  246 +#define REGNAME f50
  247 +#define REG (env->fpr[50])
  248 +#include "fop_template.h"
  249 +#define REGNAME f52
  250 +#define REG (env->fpr[52])
  251 +#include "fop_template.h"
  252 +#define REGNAME f54
  253 +#define REG (env->fpr[54])
  254 +#include "fop_template.h"
  255 +#define REGNAME f56
  256 +#define REG (env->fpr[56])
  257 +#include "fop_template.h"
  258 +#define REGNAME f58
  259 +#define REG (env->fpr[58])
  260 +#include "fop_template.h"
  261 +#define REGNAME f60
  262 +#define REG (env->fpr[60])
  263 +#include "fop_template.h"
  264 +#define REGNAME f62
  265 +#define REG (env->fpr[62])
  266 +#include "fop_template.h"
  267 +#endif
  268 +
  269 +#ifdef TARGET_SPARC64
  270 +#undef JUMP_TB
  271 +#define JUMP_TB(opname, tbparam, n, eip) \
  272 + do { \
  273 + GOTO_TB(opname, tbparam, n); \
  274 + T0 = (long)(tbparam) + (n); \
  275 + env->pc = (eip) & 0xffffffff; \
  276 + EXIT_TB(); \
  277 + } while (0)
  278 +
  279 +#ifdef WORDS_BIGENDIAN
  280 +typedef union UREG64 {
  281 + struct { uint16_t v3, v2, v1, v0; } w;
  282 + struct { uint32_t v1, v0; } l;
  283 + uint64_t q;
  284 +} UREG64;
  285 +#else
  286 +typedef union UREG64 {
  287 + struct { uint16_t v0, v1, v2, v3; } w;
  288 + struct { uint32_t v0, v1; } l;
  289 + uint64_t q;
  290 +} UREG64;
  291 +#endif
  292 +
  293 +#define PARAMQ1 \
  294 +({\
  295 + UREG64 __p;\
  296 + __p.l.v1 = PARAM1;\
  297 + __p.l.v0 = PARAM2;\
  298 + __p.q;\
  299 +})
  300 +
  301 +void OPPROTO op_movq_T0_im64(void)
  302 +{
  303 + T0 = PARAMQ1;
  304 +}
  305 +
  306 +void OPPROTO op_movq_T1_im64(void)
  307 +{
  308 + T1 = PARAMQ1;
  309 +}
  310 +
  311 +#define XFLAG_SET(x) ((env->xcc&x)?1:0)
  312 +
  313 +#else
218 314 #define EIP (env->pc)
  315 +#endif
219 316  
220 317 #define FLAG_SET(x) ((env->psr&x)?1:0)
221   -#define FFLAG_SET(x) ((env->fsr&x)?1:0)
222 318  
223 319 void OPPROTO op_movl_T0_0(void)
224 320 {
... ... @@ -227,17 +323,52 @@ void OPPROTO op_movl_T0_0(void)
227 323  
228 324 void OPPROTO op_movl_T0_im(void)
229 325 {
230   - T0 = PARAM1;
  326 + T0 = (uint32_t)PARAM1;
231 327 }
232 328  
233 329 void OPPROTO op_movl_T1_im(void)
234 330 {
235   - T1 = PARAM1;
  331 + T1 = (uint32_t)PARAM1;
236 332 }
237 333  
238 334 void OPPROTO op_movl_T2_im(void)
239 335 {
240   - T2 = PARAM1;
  336 + T2 = (uint32_t)PARAM1;
  337 +}
  338 +
  339 +void OPPROTO op_movl_T0_sim(void)
  340 +{
  341 + T0 = (int32_t)PARAM1;
  342 +}
  343 +
  344 +void OPPROTO op_movl_T1_sim(void)
  345 +{
  346 + T1 = (int32_t)PARAM1;
  347 +}
  348 +
  349 +void OPPROTO op_movl_T2_sim(void)
  350 +{
  351 + T2 = (int32_t)PARAM1;
  352 +}
  353 +
  354 +void OPPROTO op_movl_T0_env(void)
  355 +{
  356 + T0 = *(uint32_t *)((char *)env + PARAM1);
  357 +}
  358 +
  359 +void OPPROTO op_movl_env_T0(void)
  360 +{
  361 + *(uint32_t *)((char *)env + PARAM1) = T0;
  362 +}
  363 +
  364 +void OPPROTO op_movtl_T0_env(void)
  365 +{
  366 + T0 = *(target_ulong *)((char *)env + PARAM1);
  367 +}
  368 +
  369 +void OPPROTO op_movtl_env_T0(void)
  370 +{
  371 + *(target_ulong *)((char *)env + PARAM1) = T0;
241 372 }
242 373  
243 374 void OPPROTO op_add_T1_T0(void)
... ... @@ -252,6 +383,27 @@ void OPPROTO op_add_T1_T0_cc(void)
252 383 src1 = T0;
253 384 T0 += T1;
254 385 env->psr = 0;
  386 +#ifdef TARGET_SPARC64
  387 + if (!(T0 & 0xffffffff))
  388 + env->psr |= PSR_ZERO;
  389 + if ((int32_t) T0 < 0)
  390 + env->psr |= PSR_NEG;
  391 + if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
  392 + env->psr |= PSR_CARRY;
  393 + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
  394 + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
  395 + env->psr |= PSR_OVF;
  396 +
  397 + env->xcc = 0;
  398 + if (!T0)
  399 + env->xcc |= PSR_ZERO;
  400 + if ((int64_t) T0 < 0)
  401 + env->xcc |= PSR_NEG;
  402 + if (T0 < src1)
  403 + env->xcc |= PSR_CARRY;
  404 + if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
  405 + env->xcc |= PSR_OVF;
  406 +#else
255 407 if (!T0)
256 408 env->psr |= PSR_ZERO;
257 409 if ((int32_t) T0 < 0)
... ... @@ -260,7 +412,7 @@ void OPPROTO op_add_T1_T0_cc(void)
260 412 env->psr |= PSR_CARRY;
261 413 if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
262 414 env->psr |= PSR_OVF;
263   - /* V9 xcc */
  415 +#endif
264 416 FORCE_RET();
265 417 }
266 418  
... ... @@ -276,6 +428,27 @@ void OPPROTO op_addx_T1_T0_cc(void)
276 428 src1 = T0;
277 429 T0 += T1 + FLAG_SET(PSR_CARRY);
278 430 env->psr = 0;
  431 +#ifdef TARGET_SPARC64
  432 + if (!(T0 & 0xffffffff))
  433 + env->psr |= PSR_ZERO;
  434 + if ((int32_t) T0 < 0)
  435 + env->psr |= PSR_NEG;
  436 + if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
  437 + env->psr |= PSR_CARRY;
  438 + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
  439 + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
  440 + env->psr |= PSR_OVF;
  441 +
  442 + env->xcc = 0;
  443 + if (!T0)
  444 + env->xcc |= PSR_ZERO;
  445 + if ((int64_t) T0 < 0)
  446 + env->xcc |= PSR_NEG;
  447 + if (T0 < src1)
  448 + env->xcc |= PSR_CARRY;
  449 + if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
  450 + env->xcc |= PSR_OVF;
  451 +#else
279 452 if (!T0)
280 453 env->psr |= PSR_ZERO;
281 454 if ((int32_t) T0 < 0)
... ... @@ -284,7 +457,7 @@ void OPPROTO op_addx_T1_T0_cc(void)
284 457 env->psr |= PSR_CARRY;
285 458 if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
286 459 env->psr |= PSR_OVF;
287   - /* V9 xcc */
  460 +#endif
288 461 FORCE_RET();
289 462 }
290 463  
... ... @@ -300,6 +473,27 @@ void OPPROTO op_sub_T1_T0_cc(void)
300 473 src1 = T0;
301 474 T0 -= T1;
302 475 env->psr = 0;
  476 +#ifdef TARGET_SPARC64
  477 + if (!(T0 & 0xffffffff))
  478 + env->psr |= PSR_ZERO;
  479 + if ((int32_t) T0 < 0)
  480 + env->psr |= PSR_NEG;
  481 + if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
  482 + env->psr |= PSR_CARRY;
  483 + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
  484 + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
  485 + env->psr |= PSR_OVF;
  486 +
  487 + env->xcc = 0;
  488 + if (!T0)
  489 + env->xcc |= PSR_ZERO;
  490 + if ((int64_t) T0 < 0)
  491 + env->xcc |= PSR_NEG;
  492 + if (T0 < src1)
  493 + env->xcc |= PSR_CARRY;
  494 + if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
  495 + env->xcc |= PSR_OVF;
  496 +#else
303 497 if (!T0)
304 498 env->psr |= PSR_ZERO;
305 499 if ((int32_t) T0 < 0)
... ... @@ -308,7 +502,7 @@ void OPPROTO op_sub_T1_T0_cc(void)
308 502 env->psr |= PSR_CARRY;
309 503 if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
310 504 env->psr |= PSR_OVF;
311   - /* V9 xcc */
  505 +#endif
312 506 FORCE_RET();
313 507 }
314 508  
... ... @@ -324,6 +518,27 @@ void OPPROTO op_subx_T1_T0_cc(void)
324 518 src1 = T0;
325 519 T0 -= T1 + FLAG_SET(PSR_CARRY);
326 520 env->psr = 0;
  521 +#ifdef TARGET_SPARC64
  522 + if (!(T0 & 0xffffffff))
  523 + env->psr |= PSR_ZERO;
  524 + if ((int32_t) T0 < 0)
  525 + env->psr |= PSR_NEG;
  526 + if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
  527 + env->psr |= PSR_CARRY;
  528 + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
  529 + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
  530 + env->psr |= PSR_OVF;
  531 +
  532 + env->xcc = 0;
  533 + if (!T0)
  534 + env->xcc |= PSR_ZERO;
  535 + if ((int64_t) T0 < 0)
  536 + env->xcc |= PSR_NEG;
  537 + if (T0 < src1)
  538 + env->xcc |= PSR_CARRY;
  539 + if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
  540 + env->xcc |= PSR_OVF;
  541 +#else
327 542 if (!T0)
328 543 env->psr |= PSR_ZERO;
329 544 if ((int32_t) T0 < 0)
... ... @@ -332,7 +547,7 @@ void OPPROTO op_subx_T1_T0_cc(void)
332 547 env->psr |= PSR_CARRY;
333 548 if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
334 549 env->psr |= PSR_OVF;
335   - /* V9 xcc */
  550 +#endif
336 551 FORCE_RET();
337 552 }
338 553  
... ... @@ -449,24 +664,73 @@ void OPPROTO op_sdiv_T1_T0(void)
449 664 void OPPROTO op_div_cc(void)
450 665 {
451 666 env->psr = 0;
  667 +#ifdef TARGET_SPARC64
  668 + if (!T0)
  669 + env->psr |= PSR_ZERO;
  670 + if ((int32_t) T0 < 0)
  671 + env->psr |= PSR_NEG;
  672 + if (T1)
  673 + env->psr |= PSR_OVF;
  674 +
  675 + env->xcc = 0;
  676 + if (!T0)
  677 + env->xcc |= PSR_ZERO;
  678 + if ((int64_t) T0 < 0)
  679 + env->xcc |= PSR_NEG;
  680 +#else
452 681 if (!T0)
453 682 env->psr |= PSR_ZERO;
454 683 if ((int32_t) T0 < 0)
455 684 env->psr |= PSR_NEG;
456 685 if (T1)
457 686 env->psr |= PSR_OVF;
458   - /* V9 xcc */
  687 +#endif
459 688 FORCE_RET();
460 689 }
461 690  
  691 +#ifdef TARGET_SPARC64
  692 +void OPPROTO op_mulx_T1_T0(void)
  693 +{
  694 + T0 *= T1;
  695 + FORCE_RET();
  696 +}
  697 +
  698 +void OPPROTO op_udivx_T1_T0(void)
  699 +{
  700 + T0 /= T1;
  701 + FORCE_RET();
  702 +}
  703 +
  704 +void OPPROTO op_sdivx_T1_T0(void)
  705 +{
  706 + if (T0 == INT64_MIN && T1 == -1)
  707 + T0 = INT64_MIN;
  708 + else
  709 + T0 /= (target_long) T1;
  710 + FORCE_RET();
  711 +}
  712 +#endif
  713 +
462 714 void OPPROTO op_logic_T0_cc(void)
463 715 {
464 716 env->psr = 0;
  717 +#ifdef TARGET_SPARC64
  718 + if (!(T0 & 0xffffffff))
  719 + env->psr |= PSR_ZERO;
  720 + if ((int32_t) T0 < 0)
  721 + env->psr |= PSR_NEG;
  722 +
  723 + env->xcc = 0;
  724 + if (!T0)
  725 + env->xcc |= PSR_ZERO;
  726 + if ((int64_t) T0 < 0)
  727 + env->xcc |= PSR_NEG;
  728 +#else
465 729 if (!T0)
466 730 env->psr |= PSR_ZERO;
467 731 if ((int32_t) T0 < 0)
468 732 env->psr |= PSR_NEG;
469   - /* V9 xcc */
  733 +#endif
470 734 FORCE_RET();
471 735 }
472 736  
... ... @@ -475,6 +739,27 @@ void OPPROTO op_sll(void)
475 739 T0 <<= T1;
476 740 }
477 741  
  742 +#ifdef TARGET_SPARC64
  743 +void OPPROTO op_srl(void)
  744 +{
  745 + T0 = (T0 & 0xffffffff) >> T1;
  746 +}
  747 +
  748 +void OPPROTO op_srlx(void)
  749 +{
  750 + T0 >>= T1;
  751 +}
  752 +
  753 +void OPPROTO op_sra(void)
  754 +{
  755 + T0 = ((int32_t) (T0 & 0xffffffff)) >> T1;
  756 +}
  757 +
  758 +void OPPROTO op_srax(void)
  759 +{
  760 + T0 = ((int64_t) T0) >> T1;
  761 +}
  762 +#else
478 763 void OPPROTO op_srl(void)
479 764 {
480 765 T0 >>= T1;
... ... @@ -484,6 +769,7 @@ void OPPROTO op_sra(void)
484 769 {
485 770 T0 = ((int32_t) T0) >> T1;
486 771 }
  772 +#endif
487 773  
488 774 /* Load and store */
489 775 #define MEMSUFFIX _raw
... ... @@ -498,62 +784,137 @@ void OPPROTO op_sra(void)
498 784  
499 785 void OPPROTO op_ldfsr(void)
500 786 {
501   - env->fsr = *((uint32_t *) &FT0);
  787 + PUT_FSR32(env, *((uint32_t *) &FT0));
502 788 helper_ldfsr();
503 789 }
504 790  
505 791 void OPPROTO op_stfsr(void)
506 792 {
507   - *((uint32_t *) &FT0) = env->fsr;
  793 + *((uint32_t *) &FT0) = GET_FSR32(env);
508 794 }
509 795  
510   -void OPPROTO op_wry(void)
  796 +#ifndef TARGET_SPARC64
  797 +void OPPROTO op_rdpsr(void)
511 798 {
512   - env->y = T0;
  799 + do_rdpsr();
513 800 }
514 801  
515   -void OPPROTO op_rdy(void)
  802 +void OPPROTO op_wrpsr(void)
516 803 {
517   - T0 = env->y;
  804 + do_wrpsr();
  805 + FORCE_RET();
518 806 }
519 807  
520   -void OPPROTO op_rdwim(void)
  808 +void OPPROTO op_rett(void)
521 809 {
522   - T0 = env->wim;
  810 + helper_rett();
  811 + FORCE_RET();
523 812 }
524 813  
525   -void OPPROTO op_wrwim(void)
  814 +/* XXX: use another pointer for %iN registers to avoid slow wrapping
  815 + handling ? */
  816 +void OPPROTO op_save(void)
526 817 {
527   - env->wim = T0;
  818 + uint32_t cwp;
  819 + cwp = (env->cwp - 1) & (NWINDOWS - 1);
  820 + if (env->wim & (1 << cwp)) {
  821 + raise_exception(TT_WIN_OVF);
  822 + }
  823 + set_cwp(cwp);
528 824 FORCE_RET();
529 825 }
530 826  
531   -void OPPROTO op_rdpsr(void)
  827 +void OPPROTO op_restore(void)
532 828 {
533   - do_rdpsr();
  829 + uint32_t cwp;
  830 + cwp = (env->cwp + 1) & (NWINDOWS - 1);
  831 + if (env->wim & (1 << cwp)) {
  832 + raise_exception(TT_WIN_UNF);
  833 + }
  834 + set_cwp(cwp);
  835 + FORCE_RET();
  836 +}
  837 +#else
  838 +void OPPROTO op_rdccr(void)
  839 +{
  840 + T0 = GET_CCR(env);
534 841 }
535 842  
536   -void OPPROTO op_wrpsr(void)
  843 +void OPPROTO op_wrccr(void)
537 844 {
538   - do_wrpsr();
539   - FORCE_RET();
  845 + PUT_CCR(env, T0);
540 846 }
541 847  
542   -void OPPROTO op_rdtbr(void)
  848 +void OPPROTO op_rdtick(void)
543 849 {
544   - T0 = env->tbr;
  850 + T0 = 0; // XXX read cycle counter and bit 31
545 851 }
546 852  
547   -void OPPROTO op_wrtbr(void)
  853 +void OPPROTO op_wrtick(void)
548 854 {
549   - env->tbr = T0;
550   - FORCE_RET();
  855 + // XXX write cycle counter and bit 31
551 856 }
552 857  
553   -void OPPROTO op_rett(void)
  858 +void OPPROTO op_rdtpc(void)
554 859 {
555   - helper_rett();
556   - FORCE_RET();
  860 + T0 = env->tpc[env->tl];
  861 +}
  862 +
  863 +void OPPROTO op_wrtpc(void)
  864 +{
  865 + env->tpc[env->tl] = T0;
  866 +}
  867 +
  868 +void OPPROTO op_rdtnpc(void)
  869 +{
  870 + T0 = env->tnpc[env->tl];
  871 +}
  872 +
  873 +void OPPROTO op_wrtnpc(void)
  874 +{
  875 + env->tnpc[env->tl] = T0;
  876 +}
  877 +
  878 +void OPPROTO op_rdtstate(void)
  879 +{
  880 + T0 = env->tstate[env->tl];
  881 +}
  882 +
  883 +void OPPROTO op_wrtstate(void)
  884 +{
  885 + env->tstate[env->tl] = T0;
  886 +}
  887 +
  888 +void OPPROTO op_rdtt(void)
  889 +{
  890 + T0 = env->tt[env->tl];
  891 +}
  892 +
  893 +void OPPROTO op_wrtt(void)
  894 +{
  895 + env->tt[env->tl] = T0;
  896 +}
  897 +
  898 +void OPPROTO op_rdpstate(void)
  899 +{
  900 + T0 = env->pstate;
  901 +}
  902 +
  903 +void OPPROTO op_wrpstate(void)
  904 +{
  905 + env->pstate = T0 & 0x1f;
  906 +}
  907 +
  908 +// CWP handling is reversed in V9, but we still use the V8 register
  909 +// order.
  910 +void OPPROTO op_rdcwp(void)
  911 +{
  912 + T0 = NWINDOWS - 1 - env->cwp;
  913 +}
  914 +
  915 +void OPPROTO op_wrcwp(void)
  916 +{
  917 + env->cwp = NWINDOWS - 1 - T0;
557 918 }
558 919  
559 920 /* XXX: use another pointer for %iN registers to avoid slow wrapping
... ... @@ -562,10 +923,20 @@ void OPPROTO op_save(void)
562 923 {
563 924 uint32_t cwp;
564 925 cwp = (env->cwp - 1) & (NWINDOWS - 1);
565   - if (env->wim & (1 << cwp)) {
566   - raise_exception(TT_WIN_OVF);
  926 + if (env->cansave == 0) {
  927 + raise_exception(TT_SPILL | (env->otherwin != 0 ?
  928 + (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
  929 + ((env->wstate & 0x7) << 2)));
  930 + } else {
  931 + if (env->cleanwin - env->canrestore == 0) {
  932 + // XXX Clean windows without trap
  933 + raise_exception(TT_CLRWIN);
  934 + } else {
  935 + env->cansave--;
  936 + env->canrestore++;
  937 + set_cwp(cwp);
  938 + }
567 939 }
568   - set_cwp(cwp);
569 940 FORCE_RET();
570 941 }
571 942  
... ... @@ -573,12 +944,18 @@ void OPPROTO op_restore(void)
573 944 {
574 945 uint32_t cwp;
575 946 cwp = (env->cwp + 1) & (NWINDOWS - 1);
576   - if (env->wim & (1 << cwp)) {
577   - raise_exception(TT_WIN_UNF);
  947 + if (env->canrestore == 0) {
  948 + raise_exception(TT_FILL | (env->otherwin != 0 ?
  949 + (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
  950 + ((env->wstate & 0x7) << 2)));
  951 + } else {
  952 + env->cansave++;
  953 + env->canrestore--;
  954 + set_cwp(cwp);
578 955 }
579   - set_cwp(cwp);
580 956 FORCE_RET();
581 957 }
  958 +#endif
582 959  
583 960 void OPPROTO op_exception(void)
584 961 {
... ... @@ -629,6 +1006,11 @@ void OPPROTO op_exit_tb(void)
629 1006 EXIT_TB();
630 1007 }
631 1008  
  1009 +void OPPROTO op_eval_ba(void)
  1010 +{
  1011 + T2 = 1;
  1012 +}
  1013 +
632 1014 void OPPROTO op_eval_be(void)
633 1015 {
634 1016 T2 = FLAG_SET(PSR_ZERO);
... ... @@ -665,6 +1047,11 @@ void OPPROTO op_eval_bvs(void)
665 1047 T2 = FLAG_SET(PSR_OVF);
666 1048 }
667 1049  
  1050 +void OPPROTO op_eval_bn(void)
  1051 +{
  1052 + T2 = 0;
  1053 +}
  1054 +
668 1055 void OPPROTO op_eval_bneg(void)
669 1056 {
670 1057 T2 = FLAG_SET(PSR_NEG);
... ... @@ -711,101 +1098,156 @@ void OPPROTO op_eval_bvc(void)
711 1098 T2 = !FLAG_SET(PSR_OVF);
712 1099 }
713 1100  
714   -/* FCC1:FCC0: 0 =, 1 <, 2 >, 3 u */
  1101 +#ifdef TARGET_SPARC64
  1102 +void OPPROTO op_eval_xbe(void)
  1103 +{
  1104 + T2 = XFLAG_SET(PSR_ZERO);
  1105 +}
715 1106  
716   -void OPPROTO op_eval_fbne(void)
  1107 +void OPPROTO op_eval_xble(void)
717 1108 {
718   -// !0
719   - T2 = (env->fsr & (FSR_FCC1 | FSR_FCC0)); /* L or G or U */
  1109 + target_ulong Z = XFLAG_SET(PSR_ZERO), N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
  1110 +
  1111 + T2 = Z | (N ^ V);
720 1112 }
721 1113  
722   -void OPPROTO op_eval_fblg(void)
  1114 +void OPPROTO op_eval_xbl(void)
723 1115 {
724   -// 1 or 2
725   - T2 = FFLAG_SET(FSR_FCC0) ^ FFLAG_SET(FSR_FCC1);
  1116 + target_ulong N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
  1117 +
  1118 + T2 = N ^ V;
726 1119 }
727 1120  
728   -void OPPROTO op_eval_fbul(void)
  1121 +void OPPROTO op_eval_xbleu(void)
729 1122 {
730   -// 1 or 3
731   - T2 = FFLAG_SET(FSR_FCC0);
  1123 + target_ulong Z = XFLAG_SET(PSR_ZERO), C = XFLAG_SET(PSR_CARRY);
  1124 +
  1125 + T2 = C | Z;
732 1126 }
733 1127  
734   -void OPPROTO op_eval_fbl(void)
  1128 +void OPPROTO op_eval_xbcs(void)
735 1129 {
736   -// 1
737   - T2 = FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1);
  1130 + T2 = XFLAG_SET(PSR_CARRY);
738 1131 }
739 1132  
740   -void OPPROTO op_eval_fbug(void)
  1133 +void OPPROTO op_eval_xbvs(void)
741 1134 {
742   -// 2 or 3
743   - T2 = FFLAG_SET(FSR_FCC1);
  1135 + T2 = XFLAG_SET(PSR_OVF);
744 1136 }
745 1137  
746   -void OPPROTO op_eval_fbg(void)
  1138 +void OPPROTO op_eval_xbneg(void)
747 1139 {
748   -// 2
749   - T2 = !FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1);
  1140 + T2 = XFLAG_SET(PSR_NEG);
750 1141 }
751 1142  
752   -void OPPROTO op_eval_fbu(void)
  1143 +void OPPROTO op_eval_xbne(void)
753 1144 {
754   -// 3
755   - T2 = FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1);
  1145 + T2 = !XFLAG_SET(PSR_ZERO);
756 1146 }
757 1147  
758   -void OPPROTO op_eval_fbe(void)
  1148 +void OPPROTO op_eval_xbg(void)
759 1149 {
760   -// 0
761   - T2 = !FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1);
  1150 + target_ulong Z = XFLAG_SET(PSR_ZERO), N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
  1151 +
  1152 + T2 = !(Z | (N ^ V));
762 1153 }
763 1154  
764   -void OPPROTO op_eval_fbue(void)
  1155 +void OPPROTO op_eval_xbge(void)
765 1156 {
766   -// 0 or 3
767   - T2 = !(FFLAG_SET(FSR_FCC1) ^ FFLAG_SET(FSR_FCC0));
768   - FORCE_RET();
  1157 + target_ulong N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
  1158 +
  1159 + T2 = !(N ^ V);
  1160 +}
  1161 +
  1162 +void OPPROTO op_eval_xbgu(void)
  1163 +{
  1164 + target_ulong Z = XFLAG_SET(PSR_ZERO), C = XFLAG_SET(PSR_CARRY);
  1165 +
  1166 + T2 = !(C | Z);
  1167 +}
  1168 +
  1169 +void OPPROTO op_eval_xbcc(void)
  1170 +{
  1171 + T2 = !XFLAG_SET(PSR_CARRY);
  1172 +}
  1173 +
  1174 +void OPPROTO op_eval_xbpos(void)
  1175 +{
  1176 + T2 = !XFLAG_SET(PSR_NEG);
  1177 +}
  1178 +
  1179 +void OPPROTO op_eval_xbvc(void)
  1180 +{
  1181 + T2 = !XFLAG_SET(PSR_OVF);
  1182 +}
  1183 +#endif
  1184 +
  1185 +#define FCC
  1186 +#define FFLAG_SET(x) (env->fsr & x? 1: 0)
  1187 +#include "fbranch_template.h"
  1188 +
  1189 +#ifdef TARGET_SPARC64
  1190 +#define FCC _fcc1
  1191 +#define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 32))? 1: 0)
  1192 +#include "fbranch_template.h"
  1193 +#define FCC _fcc2
  1194 +#define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 34))? 1: 0)
  1195 +#include "fbranch_template.h"
  1196 +#define FCC _fcc3
  1197 +#define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 36))? 1: 0)
  1198 +#include "fbranch_template.h"
  1199 +#endif
  1200 +
  1201 +#ifdef TARGET_SPARC64
  1202 +void OPPROTO op_eval_brz(void)
  1203 +{
  1204 + T2 = T0;
769 1205 }
770 1206  
771   -void OPPROTO op_eval_fbge(void)
  1207 +void OPPROTO op_eval_brnz(void)
772 1208 {
773   -// 0 or 2
774   - T2 = !FFLAG_SET(FSR_FCC0);
  1209 + T2 = !T0;
775 1210 }
776 1211  
777   -void OPPROTO op_eval_fbuge(void)
  1212 +void OPPROTO op_eval_brlz(void)
778 1213 {
779   -// !1
780   - T2 = !(FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1));
  1214 + T2 = ((int64_t)T0 < 0);
781 1215 }
782 1216  
783   -void OPPROTO op_eval_fble(void)
  1217 +void OPPROTO op_eval_brlez(void)
784 1218 {
785   -// 0 or 1
786   - T2 = !FFLAG_SET(FSR_FCC1);
  1219 + T2 = ((int64_t)T0 <= 0);
787 1220 }
788 1221  
789   -void OPPROTO op_eval_fbule(void)
  1222 +void OPPROTO op_eval_brgz(void)
790 1223 {
791   -// !2
792   - T2 = !(!FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1));
  1224 + T2 = ((int64_t)T0 > 0);
793 1225 }
794 1226  
795   -void OPPROTO op_eval_fbo(void)
  1227 +void OPPROTO op_eval_brgez(void)
796 1228 {
797   -// !3
798   - T2 = !(FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1));
  1229 + T2 = ((int64_t)T0 >= 0);
799 1230 }
800 1231  
  1232 +void OPPROTO op_jmp_im64(void)
  1233 +{
  1234 + env->pc = PARAMQ1;
  1235 +}
  1236 +
  1237 +void OPPROTO op_movq_npc_im64(void)
  1238 +{
  1239 + env->npc = PARAMQ1;
  1240 +}
  1241 +#endif
  1242 +
801 1243 void OPPROTO op_jmp_im(void)
802 1244 {
803   - env->pc = PARAM1;
  1245 + env->pc = (uint32_t)PARAM1;
804 1246 }
805 1247  
806 1248 void OPPROTO op_movl_npc_im(void)
807 1249 {
808   - env->npc = PARAM1;
  1250 + env->npc = (uint32_t)PARAM1;
809 1251 }
810 1252  
811 1253 void OPPROTO op_movl_npc_T0(void)
... ... @@ -826,17 +1268,17 @@ void OPPROTO op_next_insn(void)
826 1268  
827 1269 void OPPROTO op_branch(void)
828 1270 {
829   - env->npc = PARAM3; /* XXX: optimize */
  1271 + env->npc = (uint32_t)PARAM3; /* XXX: optimize */
830 1272 JUMP_TB(op_branch, PARAM1, 0, PARAM2);
831 1273 }
832 1274  
833 1275 void OPPROTO op_branch2(void)
834 1276 {
835 1277 if (T2) {
836   - env->npc = PARAM2 + 4;
  1278 + env->npc = (uint32_t)PARAM2 + 4;
837 1279 JUMP_TB(op_branch2, PARAM1, 0, PARAM2);
838 1280 } else {
839   - env->npc = PARAM3 + 4;
  1281 + env->npc = (uint32_t)PARAM3 + 4;
840 1282 JUMP_TB(op_branch2, PARAM1, 1, PARAM3);
841 1283 }
842 1284 FORCE_RET();
... ... @@ -845,10 +1287,10 @@ void OPPROTO op_branch2(void)
845 1287 void OPPROTO op_branch_a(void)
846 1288 {
847 1289 if (T2) {
848   - env->npc = PARAM2; /* XXX: optimize */
  1290 + env->npc = (uint32_t)PARAM2; /* XXX: optimize */
849 1291 JUMP_TB(op_branch_a, PARAM1, 0, PARAM3);
850 1292 } else {
851   - env->npc = PARAM3 + 8; /* XXX: optimize */
  1293 + env->npc = (uint32_t)PARAM3 + 8; /* XXX: optimize */
852 1294 JUMP_TB(op_branch_a, PARAM1, 1, PARAM3 + 4);
853 1295 }
854 1296 FORCE_RET();
... ... @@ -857,9 +1299,9 @@ void OPPROTO op_branch_a(void)
857 1299 void OPPROTO op_generic_branch(void)
858 1300 {
859 1301 if (T2) {
860   - env->npc = PARAM1;
  1302 + env->npc = (uint32_t)PARAM1;
861 1303 } else {
862   - env->npc = PARAM2;
  1304 + env->npc = (uint32_t)PARAM2;
863 1305 }
864 1306 FORCE_RET();
865 1307 }
... ... @@ -879,6 +1321,18 @@ void OPPROTO op_fabss(void)
879 1321 do_fabss();
880 1322 }
881 1323  
  1324 +#ifdef TARGET_SPARC64
  1325 +void OPPROTO op_fnegd(void)
  1326 +{
  1327 + DT0 = -DT1;
  1328 +}
  1329 +
  1330 +void OPPROTO op_fabsd(void)
  1331 +{
  1332 + do_fabsd();
  1333 +}
  1334 +#endif
  1335 +
882 1336 void OPPROTO op_fsqrts(void)
883 1337 {
884 1338 do_fsqrts();
... ... @@ -944,6 +1398,38 @@ void OPPROTO op_fcmpd(void)
944 1398 do_fcmpd();
945 1399 }
946 1400  
  1401 +#ifdef TARGET_SPARC64
  1402 +void OPPROTO op_fcmps_fcc1(void)
  1403 +{
  1404 + do_fcmps_fcc1();
  1405 +}
  1406 +
  1407 +void OPPROTO op_fcmpd_fcc1(void)
  1408 +{
  1409 + do_fcmpd_fcc1();
  1410 +}
  1411 +
  1412 +void OPPROTO op_fcmps_fcc2(void)
  1413 +{
  1414 + do_fcmps_fcc2();
  1415 +}
  1416 +
  1417 +void OPPROTO op_fcmpd_fcc2(void)
  1418 +{
  1419 + do_fcmpd_fcc2();
  1420 +}
  1421 +
  1422 +void OPPROTO op_fcmps_fcc3(void)
  1423 +{
  1424 + do_fcmps_fcc3();
  1425 +}
  1426 +
  1427 +void OPPROTO op_fcmpd_fcc3(void)
  1428 +{
  1429 + do_fcmpd_fcc3();
  1430 +}
  1431 +#endif
  1432 +
947 1433 #ifdef USE_INT_TO_FLOAT_HELPERS
948 1434 void OPPROTO op_fitos(void)
949 1435 {
... ... @@ -964,6 +1450,18 @@ void OPPROTO op_fitod(void)
964 1450 {
965 1451 DT0 = (double) *((int32_t *)&FT1);
966 1452 }
  1453 +
  1454 +#ifdef TARGET_SPARC64
  1455 +void OPPROTO op_fxtos(void)
  1456 +{
  1457 + FT0 = (float) *((int64_t *)&DT1);
  1458 +}
  1459 +
  1460 +void OPPROTO op_fxtod(void)
  1461 +{
  1462 + DT0 = (double) *((int64_t *)&DT1);
  1463 +}
  1464 +#endif
967 1465 #endif
968 1466  
969 1467 void OPPROTO op_fdtos(void)
... ... @@ -986,6 +1484,102 @@ void OPPROTO op_fdtoi(void)
986 1484 *((int32_t *)&FT0) = (int32_t) DT1;
987 1485 }
988 1486  
  1487 +#ifdef TARGET_SPARC64
  1488 +void OPPROTO op_fstox(void)
  1489 +{
  1490 + *((int64_t *)&DT0) = (int64_t) FT1;
  1491 +}
  1492 +
  1493 +void OPPROTO op_fdtox(void)
  1494 +{
  1495 + *((int64_t *)&DT0) = (int64_t) DT1;
  1496 +}
  1497 +
  1498 +void OPPROTO op_fmovs_cc(void)
  1499 +{
  1500 + if (T2)
  1501 + FT0 = FT1;
  1502 +}
  1503 +
  1504 +void OPPROTO op_fmovd_cc(void)
  1505 +{
  1506 + if (T2)
  1507 + DT0 = DT1;
  1508 +}
  1509 +
  1510 +void OPPROTO op_mov_cc(void)
  1511 +{
  1512 + if (T2)
  1513 + T0 = T1;
  1514 +}
  1515 +
  1516 +void OPPROTO op_flushw(void)
  1517 +{
  1518 + if (env->cansave != NWINDOWS - 2) {
  1519 + raise_exception(TT_SPILL | (env->otherwin != 0 ?
  1520 + (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
  1521 + ((env->wstate & 0x7) << 2)));
  1522 + }
  1523 +}
  1524 +
  1525 +void OPPROTO op_saved(void)
  1526 +{
  1527 + env->cansave++;
  1528 + if (env->otherwin == 0)
  1529 + env->canrestore--;
  1530 +}
  1531 +
  1532 +void OPPROTO op_restored(void)
  1533 +{
  1534 + env->canrestore++;
  1535 + if (env->cleanwin < NWINDOWS - 1)
  1536 + env->cleanwin++;
  1537 + if (env->otherwin == 0)
  1538 + env->cansave--;
  1539 + else
  1540 + env->otherwin--;
  1541 +}
  1542 +
  1543 +void OPPROTO op_popc(void)
  1544 +{
  1545 + do_popc();
  1546 +}
  1547 +
  1548 +void OPPROTO op_done(void)
  1549 +{
  1550 + env->pc = env->tnpc[env->tl];
  1551 + env->npc = env->tnpc[env->tl] + 4;
  1552 + env->pstate = env->tstate[env->tl];
  1553 + env->tl--;
  1554 +}
  1555 +
  1556 +void OPPROTO op_retry(void)
  1557 +{
  1558 + env->pc = env->tpc[env->tl];
  1559 + env->npc = env->tnpc[env->tl];
  1560 + env->pstate = env->tstate[env->tl];
  1561 + env->tl--;
  1562 +}
  1563 +
  1564 +void OPPROTO op_sir(void)
  1565 +{
  1566 + // XXX
  1567 +
  1568 +}
  1569 +
  1570 +void OPPROTO op_ld_asi_reg()
  1571 +{
  1572 + T0 += PARAM1;
  1573 + helper_ld_asi(env->asi, PARAM2, PARAM3);
  1574 +}
  1575 +
  1576 +void OPPROTO op_st_asi_reg()
  1577 +{
  1578 + T0 += PARAM1;
  1579 + helper_st_asi(env->asi, PARAM2, PARAM3);
  1580 +}
  1581 +#endif
  1582 +
989 1583 void OPPROTO op_ld_asi()
990 1584 {
991 1585 helper_ld_asi(PARAM1, PARAM2, PARAM3);
... ...
target-sparc/op_helper.c
... ... @@ -25,6 +25,13 @@ void do_fabss(void)
25 25 FT0 = float32_abs(FT1);
26 26 }
27 27  
  28 +#ifdef TARGET_SPARC64
  29 +void do_fabsd(void)
  30 +{
  31 + DT0 = float64_abs(DT1);
  32 +}
  33 +#endif
  34 +
28 35 void do_fsqrts(void)
29 36 {
30 37 FT0 = float32_sqrt(FT1, &env->fp_status);
... ... @@ -35,48 +42,185 @@ void do_fsqrtd(void)
35 42 DT0 = float64_sqrt(DT1, &env->fp_status);
36 43 }
37 44  
  45 +#define FS 0
38 46 void do_fcmps (void)
39 47 {
  48 + env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
40 49 if (isnan(FT0) || isnan(FT1)) {
41   - T0 = FSR_FCC1 | FSR_FCC0;
42   - env->fsr &= ~(FSR_FCC1 | FSR_FCC0);
43   - env->fsr |= T0;
  50 + T0 = (FSR_FCC1 | FSR_FCC0) << FS;
44 51 if (env->fsr & FSR_NVM) {
  52 + env->fsr |= T0;
45 53 raise_exception(TT_FP_EXCP);
46 54 } else {
47 55 env->fsr |= FSR_NVA;
48 56 }
49 57 } else if (FT0 < FT1) {
50   - T0 = FSR_FCC0;
  58 + T0 = FSR_FCC0 << FS;
51 59 } else if (FT0 > FT1) {
52   - T0 = FSR_FCC1;
  60 + T0 = FSR_FCC1 << FS;
53 61 } else {
54 62 T0 = 0;
55 63 }
56   - env->fsr = T0;
  64 + env->fsr |= T0;
57 65 }
58 66  
59 67 void do_fcmpd (void)
60 68 {
  69 + env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
  70 + if (isnan(DT0) || isnan(DT1)) {
  71 + T0 = (FSR_FCC1 | FSR_FCC0) << FS;
  72 + if (env->fsr & FSR_NVM) {
  73 + env->fsr |= T0;
  74 + raise_exception(TT_FP_EXCP);
  75 + } else {
  76 + env->fsr |= FSR_NVA;
  77 + }
  78 + } else if (DT0 < DT1) {
  79 + T0 = FSR_FCC0 << FS;
  80 + } else if (DT0 > DT1) {
  81 + T0 = FSR_FCC1 << FS;
  82 + } else {
  83 + T0 = 0;
  84 + }
  85 + env->fsr |= T0;
  86 +}
  87 +
  88 +#ifdef TARGET_SPARC64
  89 +#undef FS
  90 +#define FS 22
  91 +void do_fcmps_fcc1 (void)
  92 +{
  93 + env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
  94 + if (isnan(FT0) || isnan(FT1)) {
  95 + T0 = (FSR_FCC1 | FSR_FCC0) << FS;
  96 + if (env->fsr & FSR_NVM) {
  97 + env->fsr |= T0;
  98 + raise_exception(TT_FP_EXCP);
  99 + } else {
  100 + env->fsr |= FSR_NVA;
  101 + }
  102 + } else if (FT0 < FT1) {
  103 + T0 = FSR_FCC0 << FS;
  104 + } else if (FT0 > FT1) {
  105 + T0 = FSR_FCC1 << FS;
  106 + } else {
  107 + T0 = 0;
  108 + }
  109 + env->fsr |= T0;
  110 +}
  111 +
  112 +void do_fcmpd_fcc1 (void)
  113 +{
  114 + env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
  115 + if (isnan(DT0) || isnan(DT1)) {
  116 + T0 = (FSR_FCC1 | FSR_FCC0) << FS;
  117 + if (env->fsr & FSR_NVM) {
  118 + env->fsr |= T0;
  119 + raise_exception(TT_FP_EXCP);
  120 + } else {
  121 + env->fsr |= FSR_NVA;
  122 + }
  123 + } else if (DT0 < DT1) {
  124 + T0 = FSR_FCC0 << FS;
  125 + } else if (DT0 > DT1) {
  126 + T0 = FSR_FCC1 << FS;
  127 + } else {
  128 + T0 = 0;
  129 + }
  130 + env->fsr |= T0;
  131 +}
  132 +
  133 +#undef FS
  134 +#define FS 24
  135 +void do_fcmps_fcc2 (void)
  136 +{
  137 + env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
  138 + if (isnan(FT0) || isnan(FT1)) {
  139 + T0 = (FSR_FCC1 | FSR_FCC0) << FS;
  140 + if (env->fsr & FSR_NVM) {
  141 + env->fsr |= T0;
  142 + raise_exception(TT_FP_EXCP);
  143 + } else {
  144 + env->fsr |= FSR_NVA;
  145 + }
  146 + } else if (FT0 < FT1) {
  147 + T0 = FSR_FCC0 << FS;
  148 + } else if (FT0 > FT1) {
  149 + T0 = FSR_FCC1 << FS;
  150 + } else {
  151 + T0 = 0;
  152 + }
  153 + env->fsr |= T0;
  154 +}
  155 +
  156 +void do_fcmpd_fcc2 (void)
  157 +{
  158 + env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
61 159 if (isnan(DT0) || isnan(DT1)) {
62   - T0 = FSR_FCC1 | FSR_FCC0;
63   - env->fsr &= ~(FSR_FCC1 | FSR_FCC0);
64   - env->fsr |= T0;
  160 + T0 = (FSR_FCC1 | FSR_FCC0) << FS;
65 161 if (env->fsr & FSR_NVM) {
  162 + env->fsr |= T0;
66 163 raise_exception(TT_FP_EXCP);
67 164 } else {
68 165 env->fsr |= FSR_NVA;
69 166 }
70 167 } else if (DT0 < DT1) {
71   - T0 = FSR_FCC0;
  168 + T0 = FSR_FCC0 << FS;
72 169 } else if (DT0 > DT1) {
73   - T0 = FSR_FCC1;
  170 + T0 = FSR_FCC1 << FS;
  171 + } else {
  172 + T0 = 0;
  173 + }
  174 + env->fsr |= T0;
  175 +}
  176 +
  177 +#undef FS
  178 +#define FS 26
  179 +void do_fcmps_fcc3 (void)
  180 +{
  181 + env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
  182 + if (isnan(FT0) || isnan(FT1)) {
  183 + T0 = (FSR_FCC1 | FSR_FCC0) << FS;
  184 + if (env->fsr & FSR_NVM) {
  185 + env->fsr |= T0;
  186 + raise_exception(TT_FP_EXCP);
  187 + } else {
  188 + env->fsr |= FSR_NVA;
  189 + }
  190 + } else if (FT0 < FT1) {
  191 + T0 = FSR_FCC0 << FS;
  192 + } else if (FT0 > FT1) {
  193 + T0 = FSR_FCC1 << FS;
74 194 } else {
75 195 T0 = 0;
76 196 }
77   - env->fsr = T0;
  197 + env->fsr |= T0;
78 198 }
79 199  
  200 +void do_fcmpd_fcc3 (void)
  201 +{
  202 + env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
  203 + if (isnan(DT0) || isnan(DT1)) {
  204 + T0 = (FSR_FCC1 | FSR_FCC0) << FS;
  205 + if (env->fsr & FSR_NVM) {
  206 + env->fsr |= T0;
  207 + raise_exception(TT_FP_EXCP);
  208 + } else {
  209 + env->fsr |= FSR_NVA;
  210 + }
  211 + } else if (DT0 < DT1) {
  212 + T0 = FSR_FCC0 << FS;
  213 + } else if (DT0 > DT1) {
  214 + T0 = FSR_FCC1 << FS;
  215 + } else {
  216 + T0 = 0;
  217 + }
  218 + env->fsr |= T0;
  219 +}
  220 +#undef FS
  221 +#endif
  222 +
  223 +#ifndef TARGET_SPARC64
80 224 void helper_ld_asi(int asi, int size, int sign)
81 225 {
82 226 uint32_t ret;
... ... @@ -235,6 +379,255 @@ void helper_st_asi(int asi, int size, int sign)
235 379 }
236 380 }
237 381  
  382 +#else
  383 +
  384 +void helper_ld_asi(int asi, int size, int sign)
  385 +{
  386 + uint64_t ret;
  387 +
  388 + if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
  389 + raise_exception(TT_PRIV_INSN);
  390 +
  391 + switch (asi) {
  392 + case 0x14: // Bypass
  393 + case 0x15: // Bypass, non-cacheable
  394 + {
  395 + cpu_physical_memory_read(T0, (void *) &ret, size);
  396 + if (size == 8)
  397 + tswap64s(&ret);
  398 + if (size == 4)
  399 + tswap32s((uint32_t *)&ret);
  400 + else if (size == 2)
  401 + tswap16s((uint16_t *)&ret);
  402 + break;
  403 + }
  404 + case 0x1c: // Bypass LE
  405 + case 0x1d: // Bypass, non-cacheable LE
  406 + // XXX
  407 + break;
  408 + case 0x45: // LSU
  409 + ret = env->lsu;
  410 + break;
  411 + case 0x50: // I-MMU regs
  412 + {
  413 + int reg = (T0 >> 3) & 0xf;
  414 +
  415 + ret = env->immuregs[reg];
  416 + break;
  417 + }
  418 + case 0x51: // I-MMU 8k TSB pointer
  419 + case 0x52: // I-MMU 64k TSB pointer
  420 + case 0x55: // I-MMU data access
  421 + case 0x56: // I-MMU tag read
  422 + break;
  423 + case 0x58: // D-MMU regs
  424 + {
  425 + int reg = (T0 >> 3) & 0xf;
  426 +
  427 + ret = env->dmmuregs[reg];
  428 + break;
  429 + }
  430 + case 0x59: // D-MMU 8k TSB pointer
  431 + case 0x5a: // D-MMU 64k TSB pointer
  432 + case 0x5b: // D-MMU data pointer
  433 + case 0x5d: // D-MMU data access
  434 + case 0x5e: // D-MMU tag read
  435 + break;
  436 + case 0x54: // I-MMU data in, WO
  437 + case 0x57: // I-MMU demap, WO
  438 + case 0x5c: // D-MMU data in, WO
  439 + case 0x5f: // D-MMU demap, WO
  440 + default:
  441 + ret = 0;
  442 + break;
  443 + }
  444 + T1 = ret;
  445 +}
  446 +
  447 +void helper_st_asi(int asi, int size, int sign)
  448 +{
  449 + if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
  450 + raise_exception(TT_PRIV_INSN);
  451 +
  452 + switch(asi) {
  453 + case 0x14: // Bypass
  454 + case 0x15: // Bypass, non-cacheable
  455 + {
  456 + target_ulong temp = T1;
  457 + if (size == 8)
  458 + tswap64s(&temp);
  459 + else if (size == 4)
  460 + tswap32s((uint32_t *)&temp);
  461 + else if (size == 2)
  462 + tswap16s((uint16_t *)&temp);
  463 + cpu_physical_memory_write(T0, (void *) &temp, size);
  464 + }
  465 + return;
  466 + case 0x1c: // Bypass LE
  467 + case 0x1d: // Bypass, non-cacheable LE
  468 + // XXX
  469 + return;
  470 + case 0x45: // LSU
  471 + {
  472 + uint64_t oldreg;
  473 +
  474 + oldreg = env->lsu;
  475 + env->lsu = T1 & (DMMU_E | IMMU_E);
  476 + // Mappings generated during D/I MMU disabled mode are
  477 + // invalid in normal mode
  478 + if (oldreg != env->lsu)
  479 + tlb_flush(env, 1);
  480 + return;
  481 + }
  482 + case 0x50: // I-MMU regs
  483 + {
  484 + int reg = (T0 >> 3) & 0xf;
  485 + uint64_t oldreg;
  486 +
  487 + oldreg = env->immuregs[reg];
  488 + switch(reg) {
  489 + case 0: // RO
  490 + case 4:
  491 + return;
  492 + case 1: // Not in I-MMU
  493 + case 2:
  494 + case 7:
  495 + case 8:
  496 + return;
  497 + case 3: // SFSR
  498 + if ((T1 & 1) == 0)
  499 + T1 = 0; // Clear SFSR
  500 + break;
  501 + case 5: // TSB access
  502 + case 6: // Tag access
  503 + default:
  504 + break;
  505 + }
  506 + env->immuregs[reg] = T1;
  507 +#ifdef DEBUG_MMU
  508 + if (oldreg != env->immuregs[reg]) {
  509 + printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->immuregs[reg]);
  510 + }
  511 + dump_mmu();
  512 +#endif
  513 + return;
  514 + }
  515 + case 0x54: // I-MMU data in
  516 + {
  517 + unsigned int i;
  518 +
  519 + // Try finding an invalid entry
  520 + for (i = 0; i < 64; i++) {
  521 + if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
  522 + env->itlb_tag[i] = env->immuregs[6];
  523 + env->itlb_tte[i] = T1;
  524 + return;
  525 + }
  526 + }
  527 + // Try finding an unlocked entry
  528 + for (i = 0; i < 64; i++) {
  529 + if ((env->itlb_tte[i] & 0x40) == 0) {
  530 + env->itlb_tag[i] = env->immuregs[6];
  531 + env->itlb_tte[i] = T1;
  532 + return;
  533 + }
  534 + }
  535 + // error state?
  536 + return;
  537 + }
  538 + case 0x55: // I-MMU data access
  539 + {
  540 + unsigned int i = (T0 >> 3) & 0x3f;
  541 +
  542 + env->itlb_tag[i] = env->immuregs[6];
  543 + env->itlb_tte[i] = T1;
  544 + return;
  545 + }
  546 + case 0x57: // I-MMU demap
  547 + return;
  548 + case 0x58: // D-MMU regs
  549 + {
  550 + int reg = (T0 >> 3) & 0xf;
  551 + uint64_t oldreg;
  552 +
  553 + oldreg = env->dmmuregs[reg];
  554 + switch(reg) {
  555 + case 0: // RO
  556 + case 4:
  557 + return;
  558 + case 3: // SFSR
  559 + if ((T1 & 1) == 0) {
  560 + T1 = 0; // Clear SFSR, Fault address
  561 + env->dmmuregs[4] = 0;
  562 + }
  563 + env->dmmuregs[reg] = T1;
  564 + break;
  565 + case 1: // Primary context
  566 + case 2: // Secondary context
  567 + case 5: // TSB access
  568 + case 6: // Tag access
  569 + case 7: // Virtual Watchpoint
  570 + case 8: // Physical Watchpoint
  571 + default:
  572 + break;
  573 + }
  574 + env->dmmuregs[reg] = T1;
  575 +#ifdef DEBUG_MMU
  576 + if (oldreg != env->dmmuregs[reg]) {
  577 + printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->dmmuregs[reg]);
  578 + }
  579 + dump_mmu();
  580 +#endif
  581 + return;
  582 + }
  583 + case 0x5c: // D-MMU data in
  584 + {
  585 + unsigned int i;
  586 +
  587 + // Try finding an invalid entry
  588 + for (i = 0; i < 64; i++) {
  589 + if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
  590 + env->dtlb_tag[i] = env->dmmuregs[6];
  591 + env->dtlb_tte[i] = T1;
  592 + return;
  593 + }
  594 + }
  595 + // Try finding an unlocked entry
  596 + for (i = 0; i < 64; i++) {
  597 + if ((env->dtlb_tte[i] & 0x40) == 0) {
  598 + env->dtlb_tag[i] = env->dmmuregs[6];
  599 + env->dtlb_tte[i] = T1;
  600 + return;
  601 + }
  602 + }
  603 + // error state?
  604 + return;
  605 + }
  606 + case 0x5d: // D-MMU data access
  607 + {
  608 + unsigned int i = (T0 >> 3) & 0x3f;
  609 +
  610 + env->dtlb_tag[i] = env->dmmuregs[6];
  611 + env->dtlb_tte[i] = T1;
  612 + return;
  613 + }
  614 + case 0x5f: // D-MMU demap
  615 + return;
  616 + case 0x51: // I-MMU 8k TSB pointer, RO
  617 + case 0x52: // I-MMU 64k TSB pointer, RO
  618 + case 0x56: // I-MMU tag read, RO
  619 + case 0x59: // D-MMU 8k TSB pointer, RO
  620 + case 0x5a: // D-MMU 64k TSB pointer, RO
  621 + case 0x5b: // D-MMU data pointer, RO
  622 + case 0x5e: // D-MMU tag read, RO
  623 + default:
  624 + return;
  625 + }
  626 +}
  627 +
  628 +#endif
  629 +
  630 +#ifndef TARGET_SPARC64
238 631 void helper_rett()
239 632 {
240 633 unsigned int cwp;
... ... @@ -247,6 +640,7 @@ void helper_rett()
247 640 set_cwp(cwp);
248 641 env->psrs = env->psrps;
249 642 }
  643 +#endif
250 644  
251 645 void helper_ldfsr(void)
252 646 {
... ... @@ -288,6 +682,7 @@ void helper_debug()
288 682 cpu_loop_exit();
289 683 }
290 684  
  685 +#ifndef TARGET_SPARC64
291 686 void do_wrpsr()
292 687 {
293 688 PUT_PSR(env, T0);
... ... @@ -297,3 +692,16 @@ void do_rdpsr()
297 692 {
298 693 T0 = GET_PSR(env);
299 694 }
  695 +
  696 +#else
  697 +
  698 +void do_popc()
  699 +{
  700 + T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
  701 + T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
  702 + T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
  703 + T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
  704 + T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
  705 + T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
  706 +}
  707 +#endif
... ...
target-sparc/op_mem.h
... ... @@ -2,9 +2,15 @@
2 2 #define SPARC_LD_OP(name, qp) \
3 3 void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void) \
4 4 { \
5   - T1 = glue(qp, MEMSUFFIX)(T0); \
  5 + T1 = (target_ulong)glue(qp, MEMSUFFIX)(T0); \
6 6 }
7 7  
  8 +#define SPARC_LD_OP_S(name, qp) \
  9 + void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void) \
  10 + { \
  11 + T1 = (target_long)glue(qp, MEMSUFFIX)(T0); \
  12 + }
  13 +
8 14 #define SPARC_ST_OP(name, op) \
9 15 void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void) \
10 16 { \
... ... @@ -14,8 +20,8 @@ void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void) \
14 20 SPARC_LD_OP(ld, ldl);
15 21 SPARC_LD_OP(ldub, ldub);
16 22 SPARC_LD_OP(lduh, lduw);
17   -SPARC_LD_OP(ldsb, ldsb);
18   -SPARC_LD_OP(ldsh, ldsw);
  23 +SPARC_LD_OP_S(ldsb, ldsb);
  24 +SPARC_LD_OP_S(ldsh, ldsw);
19 25  
20 26 /*** Integer store ***/
21 27 SPARC_ST_OP(st, stl);
... ... @@ -68,4 +74,51 @@ void OPPROTO glue(op_lddf, MEMSUFFIX) (void)
68 74 {
69 75 DT0 = glue(ldfq, MEMSUFFIX)(T0);
70 76 }
  77 +
  78 +#ifdef TARGET_SPARC64
  79 +/* XXX: Should be Atomically */
  80 +/* XXX: There are no cas[x] instructions, only cas[x]a */
  81 +void OPPROTO glue(op_cas, MEMSUFFIX)(void)
  82 +{
  83 + uint32_t tmp;
  84 +
  85 + tmp = glue(ldl, MEMSUFFIX)(T0);
  86 + T2 &= 0xffffffffULL;
  87 + if (tmp == (T1 & 0xffffffffULL)) {
  88 + glue(stl, MEMSUFFIX)(T0, T2);
  89 + }
  90 + T2 = tmp;
  91 +}
  92 +
  93 +void OPPROTO glue(op_casx, MEMSUFFIX)(void)
  94 +{
  95 + uint64_t tmp;
  96 +
  97 + // XXX
  98 + tmp = (uint64_t)glue(ldl, MEMSUFFIX)(T0) << 32;
  99 + tmp |= glue(ldl, MEMSUFFIX)(T0);
  100 + if (tmp == T1) {
  101 + glue(stq, MEMSUFFIX)(T0, T2);
  102 + }
  103 + T2 = tmp;
  104 +}
  105 +
  106 +void OPPROTO glue(op_ldsw, MEMSUFFIX)(void)
  107 +{
  108 + T1 = (int64_t)glue(ldl, MEMSUFFIX)(T0);
  109 +}
  110 +
  111 +void OPPROTO glue(op_ldx, MEMSUFFIX)(void)
  112 +{
  113 + // XXX
  114 + T1 = (uint64_t)glue(ldl, MEMSUFFIX)(T0) << 32;
  115 + T1 |= glue(ldl, MEMSUFFIX)(T0);
  116 +}
  117 +
  118 +void OPPROTO glue(op_stx, MEMSUFFIX)(void)
  119 +{
  120 + glue(stl, MEMSUFFIX)(T0, T1 >> 32);
  121 + glue(stl, MEMSUFFIX)(T0, T1 & 0xffffffff);
  122 +}
  123 +#endif
71 124 #undef MEMSUFFIX
... ...
target-sparc/translate.c
... ... @@ -2,7 +2,7 @@
2 2 SPARC translation
3 3  
4 4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5   - Copyright (C) 2003 Fabrice Bellard
  5 + Copyright (C) 2003-2005 Fabrice Bellard
6 6  
7 7 This library is free software; you can redistribute it and/or
8 8 modify it under the terms of the GNU Lesser General Public
... ... @@ -22,12 +22,12 @@
22 22 /*
23 23 TODO-list:
24 24  
  25 + Rest of V9 instructions, VIS instructions
25 26 NPC/PC static optimisations (use JUMP_TB when possible)
26   - FPU-Instructions
27   - Privileged instructions
28   - Coprocessor-Instructions
29 27 Optimize synthetic instructions
30   - Optional alignment and privileged instruction check
  28 + Optional alignment check
  29 + 128-bit float
  30 + Tagged add/sub
31 31 */
32 32  
33 33 #include <stdarg.h>
... ... @@ -69,9 +69,29 @@ enum {
69 69  
70 70 #include "gen-op.h"
71 71  
  72 +// This function uses non-native bit order
72 73 #define GET_FIELD(X, FROM, TO) \
73 74 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
74 75  
  76 +// This function uses the order in the manuals, i.e. bit 0 is 2^0
  77 +#define GET_FIELD_SP(X, FROM, TO) \
  78 + GET_FIELD(X, 31 - (TO), 31 - (FROM))
  79 +
  80 +#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
  81 +#define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), 32 - ((b) - (a) + 1))
  82 +
  83 +#ifdef TARGET_SPARC64
  84 +#define DFPREG(r) (((r & 1) << 6) | (r & 0x1e))
  85 +#else
  86 +#define DFPREG(r) (r)
  87 +#endif
  88 +
  89 +static int sign_extend(int x, int len)
  90 +{
  91 + len = 32 - len;
  92 + return (x << len) >> len;
  93 +}
  94 +
75 95 #define IS_IMM (insn & (1<<13))
76 96  
77 97 static void disas_sparc_insn(DisasContext * dc);
... ... @@ -258,6 +278,34 @@ static GenOpFunc1 *gen_op_movl_TN_im[3] = {
258 278 gen_op_movl_T2_im
259 279 };
260 280  
  281 +// Sign extending version
  282 +static GenOpFunc1 * const gen_op_movl_TN_sim[3] = {
  283 + gen_op_movl_T0_sim,
  284 + gen_op_movl_T1_sim,
  285 + gen_op_movl_T2_sim
  286 +};
  287 +
  288 +#ifdef TARGET_SPARC64
  289 +#define GEN32(func, NAME) \
  290 +static GenOpFunc *NAME ## _table [64] = { \
  291 +NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
  292 +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
  293 +NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
  294 +NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
  295 +NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
  296 +NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
  297 +NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
  298 +NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
  299 +NAME ## 32, 0, NAME ## 34, 0, NAME ## 36, 0, NAME ## 38, 0, \
  300 +NAME ## 40, 0, NAME ## 42, 0, NAME ## 44, 0, NAME ## 46, 0, \
  301 +NAME ## 48, 0, NAME ## 50, 0, NAME ## 52, 0, NAME ## 54, 0, \
  302 +NAME ## 56, 0, NAME ## 58, 0, NAME ## 60, 0, NAME ## 62, 0, \
  303 +}; \
  304 +static inline void func(int n) \
  305 +{ \
  306 + NAME ## _table[n](); \
  307 +}
  308 +#else
261 309 #define GEN32(func, NAME) \
262 310 static GenOpFunc *NAME ## _table [32] = { \
263 311 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
... ... @@ -273,22 +321,77 @@ static inline void func(int n) \
273 321 { \
274 322 NAME ## _table[n](); \
275 323 }
  324 +#endif
276 325  
277 326 /* floating point registers moves */
278 327 GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fprf);
279 328 GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fprf);
280   -GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fprf);
281 329 GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fprf);
282 330 GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fprf);
283   -GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fprf);
284 331  
285 332 GEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fprf);
286 333 GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
287   -GEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fprf);
288 334 GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
289 335 GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
290   -GEN32(gen_op_store_DT2_fpr, gen_op_store_DT2_fpr_fprf);
291 336  
  337 +#ifdef TARGET_SPARC64
  338 +// 'a' versions allowed to user depending on asi
  339 +#if defined(CONFIG_USER_ONLY)
  340 +#define supervisor(dc) 0
  341 +#define gen_op_ldst(name) gen_op_##name##_raw()
  342 +#define OP_LD_TABLE(width) \
  343 + static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
  344 + { \
  345 + int asi, offset; \
  346 + \
  347 + if (IS_IMM) { \
  348 + offset = GET_FIELD(insn, 25, 31); \
  349 + if (is_ld) \
  350 + gen_op_ld_asi_reg(offset, size, sign); \
  351 + else \
  352 + gen_op_st_asi_reg(offset, size, sign); \
  353 + return; \
  354 + } \
  355 + asi = GET_FIELD(insn, 19, 26); \
  356 + switch (asi) { \
  357 + case 0x80: /* Primary address space */ \
  358 + gen_op_##width##_raw(); \
  359 + break; \
  360 + default: \
  361 + break; \
  362 + } \
  363 + }
  364 +
  365 +#else
  366 +#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
  367 +#define OP_LD_TABLE(width) \
  368 + static GenOpFunc *gen_op_##width[] = { \
  369 + &gen_op_##width##_user, \
  370 + &gen_op_##width##_kernel, \
  371 + }; \
  372 + \
  373 + static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
  374 + { \
  375 + int asi, offset; \
  376 + \
  377 + if (IS_IMM) { \
  378 + offset = GET_FIELD(insn, 25, 31); \
  379 + if (is_ld) \
  380 + gen_op_ld_asi_reg(offset, size, sign); \
  381 + else \
  382 + gen_op_st_asi_reg(offset, size, sign); \
  383 + return; \
  384 + } \
  385 + asi = GET_FIELD(insn, 19, 26); \
  386 + if (is_ld) \
  387 + gen_op_ld_asi(asi, size, sign); \
  388 + else \
  389 + gen_op_st_asi(asi, size, sign); \
  390 + }
  391 +
  392 +#define supervisor(dc) (dc->mem_idx == 1)
  393 +#endif
  394 +#else
292 395 #if defined(CONFIG_USER_ONLY)
293 396 #define gen_op_ldst(name) gen_op_##name##_raw()
294 397 #define OP_LD_TABLE(width)
... ... @@ -330,6 +433,7 @@ static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
330 433  
331 434 #define supervisor(dc) (dc->mem_idx == 1)
332 435 #endif
  436 +#endif
333 437  
334 438 OP_LD_TABLE(ld);
335 439 OP_LD_TABLE(st);
... ... @@ -348,21 +452,44 @@ OP_LD_TABLE(stdf);
348 452 OP_LD_TABLE(ldf);
349 453 OP_LD_TABLE(lddf);
350 454  
351   -static inline void gen_movl_imm_TN(int reg, int imm)
  455 +#ifdef TARGET_SPARC64
  456 +OP_LD_TABLE(ldsw);
  457 +OP_LD_TABLE(ldx);
  458 +OP_LD_TABLE(stx);
  459 +OP_LD_TABLE(cas);
  460 +OP_LD_TABLE(casx);
  461 +#endif
  462 +
  463 +static inline void gen_movl_imm_TN(int reg, uint32_t imm)
352 464 {
353 465 gen_op_movl_TN_im[reg] (imm);
354 466 }
355 467  
356   -static inline void gen_movl_imm_T1(int val)
  468 +static inline void gen_movl_imm_T1(uint32_t val)
357 469 {
358 470 gen_movl_imm_TN(1, val);
359 471 }
360 472  
361   -static inline void gen_movl_imm_T0(int val)
  473 +static inline void gen_movl_imm_T0(uint32_t val)
362 474 {
363 475 gen_movl_imm_TN(0, val);
364 476 }
365 477  
  478 +static inline void gen_movl_simm_TN(int reg, int32_t imm)
  479 +{
  480 + gen_op_movl_TN_sim[reg](imm);
  481 +}
  482 +
  483 +static inline void gen_movl_simm_T1(int32_t val)
  484 +{
  485 + gen_movl_simm_TN(1, val);
  486 +}
  487 +
  488 +static inline void gen_movl_simm_T0(int32_t val)
  489 +{
  490 + gen_movl_simm_TN(0, val);
  491 +}
  492 +
366 493 static inline void gen_movl_reg_TN(int reg, int t)
367 494 {
368 495 if (reg)
... ... @@ -411,19 +538,45 @@ static inline void flush_T2(DisasContext * dc)
411 538 }
412 539 }
413 540  
  541 +static inline void gen_jmp_im(target_ulong pc)
  542 +{
  543 +#ifdef TARGET_SPARC64
  544 + if (pc == (uint32_t)pc) {
  545 + gen_op_jmp_im(pc);
  546 + } else {
  547 + gen_op_jmp_im64(pc >> 32, pc);
  548 + }
  549 +#else
  550 + gen_op_jmp_im(pc);
  551 +#endif
  552 +}
  553 +
  554 +static inline void gen_movl_npc_im(target_ulong npc)
  555 +{
  556 +#ifdef TARGET_SPARC64
  557 + if (npc == (uint32_t)npc) {
  558 + gen_op_movl_npc_im(npc);
  559 + } else {
  560 + gen_op_movq_npc_im64(npc >> 32, npc);
  561 + }
  562 +#else
  563 + gen_op_movl_npc_im(npc);
  564 +#endif
  565 +}
  566 +
414 567 static inline void save_npc(DisasContext * dc)
415 568 {
416 569 if (dc->npc == JUMP_PC) {
417 570 gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
418 571 dc->npc = DYNAMIC_PC;
419 572 } else if (dc->npc != DYNAMIC_PC) {
420   - gen_op_movl_npc_im(dc->npc);
  573 + gen_movl_npc_im(dc->npc);
421 574 }
422 575 }
423 576  
424 577 static inline void save_state(DisasContext * dc)
425 578 {
426   - gen_op_jmp_im(dc->pc);
  579 + gen_jmp_im(dc->pc);
427 580 save_npc(dc);
428 581 }
429 582  
... ... @@ -441,110 +594,159 @@ static inline void gen_mov_pc_npc(DisasContext * dc)
441 594 }
442 595 }
443 596  
444   -static void gen_cond(int cond)
445   -{
446   - switch (cond) {
447   - case 0x1:
448   - gen_op_eval_be();
449   - break;
450   - case 0x2:
451   - gen_op_eval_ble();
452   - break;
453   - case 0x3:
454   - gen_op_eval_bl();
455   - break;
456   - case 0x4:
457   - gen_op_eval_bleu();
458   - break;
459   - case 0x5:
460   - gen_op_eval_bcs();
461   - break;
462   - case 0x6:
463   - gen_op_eval_bneg();
464   - break;
465   - case 0x7:
466   - gen_op_eval_bvs();
467   - break;
468   - case 0x9:
469   - gen_op_eval_bne();
470   - break;
471   - case 0xa:
472   - gen_op_eval_bg();
473   - break;
474   - case 0xb:
475   - gen_op_eval_bge();
476   - break;
477   - case 0xc:
478   - gen_op_eval_bgu();
479   - break;
480   - case 0xd:
481   - gen_op_eval_bcc();
482   - break;
483   - case 0xe:
484   - gen_op_eval_bpos();
485   - break;
486   - default:
487   - case 0xf:
488   - gen_op_eval_bvc();
489   - break;
490   - }
491   -}
  597 +static GenOpFunc * const gen_cond[2][16] = {
  598 + {
  599 + gen_op_eval_ba,
  600 + gen_op_eval_be,
  601 + gen_op_eval_ble,
  602 + gen_op_eval_bl,
  603 + gen_op_eval_bleu,
  604 + gen_op_eval_bcs,
  605 + gen_op_eval_bneg,
  606 + gen_op_eval_bvs,
  607 + gen_op_eval_bn,
  608 + gen_op_eval_bne,
  609 + gen_op_eval_bg,
  610 + gen_op_eval_bge,
  611 + gen_op_eval_bgu,
  612 + gen_op_eval_bcc,
  613 + gen_op_eval_bpos,
  614 + gen_op_eval_bvc,
  615 + },
  616 + {
  617 +#ifdef TARGET_SPARC64
  618 + gen_op_eval_ba,
  619 + gen_op_eval_xbe,
  620 + gen_op_eval_xble,
  621 + gen_op_eval_xbl,
  622 + gen_op_eval_xbleu,
  623 + gen_op_eval_xbcs,
  624 + gen_op_eval_xbneg,
  625 + gen_op_eval_xbvs,
  626 + gen_op_eval_bn,
  627 + gen_op_eval_xbne,
  628 + gen_op_eval_xbg,
  629 + gen_op_eval_xbge,
  630 + gen_op_eval_xbgu,
  631 + gen_op_eval_xbcc,
  632 + gen_op_eval_xbpos,
  633 + gen_op_eval_xbvc,
  634 +#endif
  635 + },
  636 +};
  637 +
  638 +static GenOpFunc * const gen_fcond[4][16] = {
  639 + {
  640 + gen_op_eval_ba,
  641 + gen_op_eval_fbne,
  642 + gen_op_eval_fblg,
  643 + gen_op_eval_fbul,
  644 + gen_op_eval_fbl,
  645 + gen_op_eval_fbug,
  646 + gen_op_eval_fbg,
  647 + gen_op_eval_fbu,
  648 + gen_op_eval_bn,
  649 + gen_op_eval_fbe,
  650 + gen_op_eval_fbue,
  651 + gen_op_eval_fbge,
  652 + gen_op_eval_fbuge,
  653 + gen_op_eval_fble,
  654 + gen_op_eval_fbule,
  655 + gen_op_eval_fbo,
  656 + },
  657 +#ifdef TARGET_SPARC64
  658 + {
  659 + gen_op_eval_ba,
  660 + gen_op_eval_fbne_fcc1,
  661 + gen_op_eval_fblg_fcc1,
  662 + gen_op_eval_fbul_fcc1,
  663 + gen_op_eval_fbl_fcc1,
  664 + gen_op_eval_fbug_fcc1,
  665 + gen_op_eval_fbg_fcc1,
  666 + gen_op_eval_fbu_fcc1,
  667 + gen_op_eval_bn,
  668 + gen_op_eval_fbe_fcc1,
  669 + gen_op_eval_fbue_fcc1,
  670 + gen_op_eval_fbge_fcc1,
  671 + gen_op_eval_fbuge_fcc1,
  672 + gen_op_eval_fble_fcc1,
  673 + gen_op_eval_fbule_fcc1,
  674 + gen_op_eval_fbo_fcc1,
  675 + },
  676 + {
  677 + gen_op_eval_ba,
  678 + gen_op_eval_fbne_fcc2,
  679 + gen_op_eval_fblg_fcc2,
  680 + gen_op_eval_fbul_fcc2,
  681 + gen_op_eval_fbl_fcc2,
  682 + gen_op_eval_fbug_fcc2,
  683 + gen_op_eval_fbg_fcc2,
  684 + gen_op_eval_fbu_fcc2,
  685 + gen_op_eval_bn,
  686 + gen_op_eval_fbe_fcc2,
  687 + gen_op_eval_fbue_fcc2,
  688 + gen_op_eval_fbge_fcc2,
  689 + gen_op_eval_fbuge_fcc2,
  690 + gen_op_eval_fble_fcc2,
  691 + gen_op_eval_fbule_fcc2,
  692 + gen_op_eval_fbo_fcc2,
  693 + },
  694 + {
  695 + gen_op_eval_ba,
  696 + gen_op_eval_fbne_fcc3,
  697 + gen_op_eval_fblg_fcc3,
  698 + gen_op_eval_fbul_fcc3,
  699 + gen_op_eval_fbl_fcc3,
  700 + gen_op_eval_fbug_fcc3,
  701 + gen_op_eval_fbg_fcc3,
  702 + gen_op_eval_fbu_fcc3,
  703 + gen_op_eval_bn,
  704 + gen_op_eval_fbe_fcc3,
  705 + gen_op_eval_fbue_fcc3,
  706 + gen_op_eval_fbge_fcc3,
  707 + gen_op_eval_fbuge_fcc3,
  708 + gen_op_eval_fble_fcc3,
  709 + gen_op_eval_fbule_fcc3,
  710 + gen_op_eval_fbo_fcc3,
  711 + },
  712 +#else
  713 + {}, {}, {},
  714 +#endif
  715 +};
492 716  
493   -static void gen_fcond(int cond)
  717 +#ifdef TARGET_SPARC64
  718 +static void gen_cond_reg(int cond)
494 719 {
495 720 switch (cond) {
496 721 case 0x1:
497   - gen_op_eval_fbne();
  722 + gen_op_eval_brz();
498 723 break;
499 724 case 0x2:
500   - gen_op_eval_fblg();
  725 + gen_op_eval_brlez();
501 726 break;
502 727 case 0x3:
503   - gen_op_eval_fbul();
504   - break;
505   - case 0x4:
506   - gen_op_eval_fbl();
  728 + gen_op_eval_brlz();
507 729 break;
508 730 case 0x5:
509   - gen_op_eval_fbug();
  731 + gen_op_eval_brnz();
510 732 break;
511 733 case 0x6:
512   - gen_op_eval_fbg();
513   - break;
514   - case 0x7:
515   - gen_op_eval_fbu();
516   - break;
517   - case 0x9:
518   - gen_op_eval_fbe();
519   - break;
520   - case 0xa:
521   - gen_op_eval_fbue();
522   - break;
523   - case 0xb:
524   - gen_op_eval_fbge();
525   - break;
526   - case 0xc:
527   - gen_op_eval_fbuge();
528   - break;
529   - case 0xd:
530   - gen_op_eval_fble();
531   - break;
532   - case 0xe:
533   - gen_op_eval_fbule();
  734 + gen_op_eval_brgz();
534 735 break;
535 736 default:
536   - case 0xf:
537   - gen_op_eval_fbo();
  737 + case 0x7:
  738 + gen_op_eval_brgez();
538 739 break;
539 740 }
540 741 }
  742 +#endif
541 743  
542 744 /* XXX: potentially incorrect if dynamic npc */
543   -static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn)
  745 +static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
544 746 {
545 747 unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
546 748 target_ulong target = dc->pc + offset;
547   -
  749 +
548 750 if (cond == 0x0) {
549 751 /* unconditional not taken */
550 752 if (a) {
... ... @@ -565,7 +767,7 @@ static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn)
565 767 }
566 768 } else {
567 769 flush_T2(dc);
568   - gen_cond(cond);
  770 + gen_cond[cc][cond]();
569 771 if (a) {
570 772 gen_op_branch_a((long)dc->tb, target, dc->npc);
571 773 dc->is_br = 1;
... ... @@ -579,7 +781,7 @@ static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn)
579 781 }
580 782  
581 783 /* XXX: potentially incorrect if dynamic npc */
582   -static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn)
  784 +static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
583 785 {
584 786 unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
585 787 target_ulong target = dc->pc + offset;
... ... @@ -604,7 +806,7 @@ static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn)
604 806 }
605 807 } else {
606 808 flush_T2(dc);
607   - gen_fcond(cond);
  809 + gen_fcond[cc][cond]();
608 810 if (a) {
609 811 gen_op_branch_a((long)dc->tb, target, dc->npc);
610 812 dc->is_br = 1;
... ... @@ -617,14 +819,41 @@ static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn)
617 819 }
618 820 }
619 821  
620   -#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
621   -
622   -static int sign_extend(int x, int len)
  822 +#ifdef TARGET_SPARC64
  823 +/* XXX: potentially incorrect if dynamic npc */
  824 +static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn)
623 825 {
624   - len = 32 - len;
625   - return (x << len) >> len;
  826 + unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
  827 + target_ulong target = dc->pc + offset;
  828 +
  829 + flush_T2(dc);
  830 + gen_cond_reg(cond);
  831 + if (a) {
  832 + gen_op_branch_a((long)dc->tb, target, dc->npc);
  833 + dc->is_br = 1;
  834 + } else {
  835 + dc->pc = dc->npc;
  836 + dc->jump_pc[0] = target;
  837 + dc->jump_pc[1] = dc->npc + 4;
  838 + dc->npc = JUMP_PC;
  839 + }
626 840 }
627 841  
  842 +static GenOpFunc * const gen_fcmps[4] = {
  843 + gen_op_fcmps,
  844 + gen_op_fcmps_fcc1,
  845 + gen_op_fcmps_fcc2,
  846 + gen_op_fcmps_fcc3,
  847 +};
  848 +
  849 +static GenOpFunc * const gen_fcmpd[4] = {
  850 + gen_op_fcmpd,
  851 + gen_op_fcmpd_fcc1,
  852 + gen_op_fcmpd_fcc2,
  853 + gen_op_fcmpd_fcc3,
  854 +};
  855 +#endif
  856 +
628 857 /* before an instruction, dc->pc must be static */
629 858 static void disas_sparc_insn(DisasContext * dc)
630 859 {
... ... @@ -639,19 +868,54 @@ static void disas_sparc_insn(DisasContext * dc)
639 868 {
640 869 unsigned int xop = GET_FIELD(insn, 7, 9);
641 870 int32_t target;
642   - target = GET_FIELD(insn, 10, 31);
643 871 switch (xop) {
644   - case 0x0: /* UNIMPL */
  872 +#ifdef TARGET_SPARC64
645 873 case 0x1: /* V9 BPcc */
  874 + {
  875 + int cc;
  876 +
  877 + target = GET_FIELD_SP(insn, 0, 18);
  878 + target <<= 2;
  879 + target = sign_extend(target, 18);
  880 + cc = GET_FIELD_SP(insn, 20, 21);
  881 + if (cc == 0)
  882 + do_branch(dc, target, insn, 0);
  883 + else if (cc == 2)
  884 + do_branch(dc, target, insn, 1);
  885 + else
  886 + goto illegal_insn;
  887 + goto jmp_insn;
  888 + }
646 889 case 0x3: /* V9 BPr */
  890 + {
  891 + target = GET_FIELD_SP(insn, 0, 13) |
  892 + (GET_FIELD_SP(insn, 20, 21) >> 7);
  893 + target <<= 2;
  894 + target = sign_extend(target, 16);
  895 + rs1 = GET_FIELD(insn, 13, 17);
  896 + gen_movl_T0_reg(rs1);
  897 + do_branch_reg(dc, target, insn);
  898 + goto jmp_insn;
  899 + }
647 900 case 0x5: /* V9 FBPcc */
648   - default:
649   - goto illegal_insn;
  901 + {
  902 + int cc = GET_FIELD_SP(insn, 20, 21);
  903 +#if !defined(CONFIG_USER_ONLY)
  904 + gen_op_trap_ifnofpu();
  905 +#endif
  906 + target = GET_FIELD_SP(insn, 0, 18);
  907 + target <<= 2;
  908 + target = sign_extend(target, 19);
  909 + do_fbranch(dc, target, insn, cc);
  910 + goto jmp_insn;
  911 + }
  912 +#endif
650 913 case 0x2: /* BN+x */
651 914 {
  915 + target = GET_FIELD(insn, 10, 31);
652 916 target <<= 2;
653 917 target = sign_extend(target, 22);
654   - do_branch(dc, target, insn);
  918 + do_branch(dc, target, insn, 0);
655 919 goto jmp_insn;
656 920 }
657 921 case 0x6: /* FBN+x */
... ... @@ -659,9 +923,10 @@ static void disas_sparc_insn(DisasContext * dc)
659 923 #if !defined(CONFIG_USER_ONLY)
660 924 gen_op_trap_ifnofpu();
661 925 #endif
  926 + target = GET_FIELD(insn, 10, 31);
662 927 target <<= 2;
663 928 target = sign_extend(target, 22);
664   - do_fbranch(dc, target, insn);
  929 + do_fbranch(dc, target, insn, 0);
665 930 goto jmp_insn;
666 931 }
667 932 case 0x4: /* SETHI */
... ... @@ -669,12 +934,16 @@ static void disas_sparc_insn(DisasContext * dc)
669 934 #if defined(OPTIM)
670 935 if (rd) { // nop
671 936 #endif
672   - gen_movl_imm_T0(target << 10);
  937 + uint32_t value = GET_FIELD(insn, 10, 31);
  938 + gen_movl_imm_T0(value << 10);
673 939 gen_movl_T0_reg(rd);
674 940 #if defined(OPTIM)
675 941 }
676 942 #endif
677 943 break;
  944 + case 0x0: /* UNIMPL */
  945 + default:
  946 + goto illegal_insn;
678 947 }
679 948 break;
680 949 }
... ... @@ -695,6 +964,7 @@ static void disas_sparc_insn(DisasContext * dc)
695 964 unsigned int xop = GET_FIELD(insn, 7, 12);
696 965 if (xop == 0x3a) { /* generate trap */
697 966 int cond;
  967 +
698 968 rs1 = GET_FIELD(insn, 13, 17);
699 969 gen_movl_reg_T0(rs1);
700 970 if (IS_IMM) {
... ... @@ -702,7 +972,7 @@ static void disas_sparc_insn(DisasContext * dc)
702 972 #if defined(OPTIM)
703 973 if (rs2 != 0) {
704 974 #endif
705   - gen_movl_imm_T1(rs2);
  975 + gen_movl_simm_T1(rs2);
706 976 gen_op_add_T1_T0();
707 977 #if defined(OPTIM)
708 978 }
... ... @@ -719,51 +989,141 @@ static void disas_sparc_insn(DisasContext * dc)
719 989 #endif
720 990 }
721 991 save_state(dc);
722   - /* V9 icc/xcc */
723 992 cond = GET_FIELD(insn, 3, 6);
724 993 if (cond == 0x8) {
725 994 gen_op_trap_T0();
726 995 dc->is_br = 1;
727 996 goto jmp_insn;
728 997 } else if (cond != 0) {
729   - gen_cond(cond);
  998 +#ifdef TARGET_SPARC64
  999 + /* V9 icc/xcc */
  1000 + int cc = GET_FIELD_SP(insn, 11, 12);
  1001 + if (cc == 0)
  1002 + gen_cond[0][cond]();
  1003 + else if (cc == 2)
  1004 + gen_cond[1][cond]();
  1005 + else
  1006 + goto illegal_insn;
  1007 +#else
  1008 + gen_cond[0][cond]();
  1009 +#endif
730 1010 gen_op_trapcc_T0();
731 1011 }
732 1012 } else if (xop == 0x28) {
733 1013 rs1 = GET_FIELD(insn, 13, 17);
734 1014 switch(rs1) {
735 1015 case 0: /* rdy */
736   - gen_op_rdy();
  1016 + gen_op_movtl_T0_env(offsetof(CPUSPARCState, y));
737 1017 gen_movl_T0_reg(rd);
738 1018 break;
739 1019 case 15: /* stbar / V9 membar */
740 1020 break; /* no effect? */
741   - default:
  1021 +#ifdef TARGET_SPARC64
742 1022 case 0x2: /* V9 rdccr */
  1023 + gen_op_rdccr();
  1024 + gen_movl_T0_reg(rd);
  1025 + break;
743 1026 case 0x3: /* V9 rdasi */
  1027 + gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));
  1028 + gen_movl_T0_reg(rd);
  1029 + break;
744 1030 case 0x4: /* V9 rdtick */
  1031 + gen_op_rdtick();
  1032 + gen_movl_T0_reg(rd);
  1033 + break;
745 1034 case 0x5: /* V9 rdpc */
  1035 + gen_op_movl_T0_im(dc->pc);
  1036 + gen_movl_T0_reg(rd);
  1037 + break;
746 1038 case 0x6: /* V9 rdfprs */
  1039 + gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
  1040 + gen_movl_T0_reg(rd);
  1041 + break;
  1042 +#endif
  1043 + default:
747 1044 goto illegal_insn;
748 1045 }
749 1046 #if !defined(CONFIG_USER_ONLY)
750   - } else if (xop == 0x29) {
  1047 +#ifndef TARGET_SPARC64
  1048 + } else if (xop == 0x29) { /* rdpsr / V9 unimp */
751 1049 if (!supervisor(dc))
752 1050 goto priv_insn;
753 1051 gen_op_rdpsr();
754 1052 gen_movl_T0_reg(rd);
755 1053 break;
756   - } else if (xop == 0x2a) {
  1054 +#endif
  1055 + } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
757 1056 if (!supervisor(dc))
758 1057 goto priv_insn;
759   - gen_op_rdwim();
  1058 +#ifdef TARGET_SPARC64
  1059 + rs1 = GET_FIELD(insn, 13, 17);
  1060 + switch (rs1) {
  1061 + case 0: // tpc
  1062 + gen_op_rdtpc();
  1063 + break;
  1064 + case 1: // tnpc
  1065 + gen_op_rdtnpc();
  1066 + break;
  1067 + case 2: // tstate
  1068 + gen_op_rdtstate();
  1069 + break;
  1070 + case 3: // tt
  1071 + gen_op_rdtt();
  1072 + break;
  1073 + case 4: // tick
  1074 + gen_op_rdtick();
  1075 + break;
  1076 + case 5: // tba
  1077 + gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
  1078 + break;
  1079 + case 6: // pstate
  1080 + gen_op_rdpstate();
  1081 + break;
  1082 + case 7: // tl
  1083 + gen_op_movl_T0_env(offsetof(CPUSPARCState, tl));
  1084 + break;
  1085 + case 8: // pil
  1086 + gen_op_movl_T0_env(offsetof(CPUSPARCState, psrpil));
  1087 + break;
  1088 + case 9: // cwp
  1089 + gen_op_rdcwp();
  1090 + break;
  1091 + case 10: // cansave
  1092 + gen_op_movl_T0_env(offsetof(CPUSPARCState, cansave));
  1093 + break;
  1094 + case 11: // canrestore
  1095 + gen_op_movl_T0_env(offsetof(CPUSPARCState, canrestore));
  1096 + break;
  1097 + case 12: // cleanwin
  1098 + gen_op_movl_T0_env(offsetof(CPUSPARCState, cleanwin));
  1099 + break;
  1100 + case 13: // otherwin
  1101 + gen_op_movl_T0_env(offsetof(CPUSPARCState, otherwin));
  1102 + break;
  1103 + case 14: // wstate
  1104 + gen_op_movl_T0_env(offsetof(CPUSPARCState, wstate));
  1105 + break;
  1106 + case 31: // ver
  1107 + gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));
  1108 + break;
  1109 + case 15: // fq
  1110 + default:
  1111 + goto illegal_insn;
  1112 + }
  1113 +#else
  1114 + gen_op_movl_T0_env(offsetof(CPUSPARCState, wim));
  1115 +#endif
760 1116 gen_movl_T0_reg(rd);
761 1117 break;
762   - } else if (xop == 0x2b) {
  1118 + } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
  1119 +#ifdef TARGET_SPARC64
  1120 + gen_op_flushw();
  1121 +#else
763 1122 if (!supervisor(dc))
764 1123 goto priv_insn;
765   - gen_op_rdtbr();
  1124 + gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
766 1125 gen_movl_T0_reg(rd);
  1126 +#endif
767 1127 break;
768 1128 #endif
769 1129 } else if (xop == 0x34) { /* FPU Operations */
... ... @@ -794,9 +1154,9 @@ static void disas_sparc_insn(DisasContext * dc)
794 1154 gen_op_store_FT0_fpr(rd);
795 1155 break;
796 1156 case 0x2a: /* fsqrtd */
797   - gen_op_load_fpr_DT1(rs2);
  1157 + gen_op_load_fpr_DT1(DFPREG(rs2));
798 1158 gen_op_fsqrtd();
799   - gen_op_store_DT0_fpr(rd);
  1159 + gen_op_store_DT0_fpr(DFPREG(rd));
800 1160 break;
801 1161 case 0x2b: /* fsqrtq */
802 1162 goto nfpu_insn;
... ... @@ -807,10 +1167,10 @@ static void disas_sparc_insn(DisasContext * dc)
807 1167 gen_op_store_FT0_fpr(rd);
808 1168 break;
809 1169 case 0x42:
810   - gen_op_load_fpr_DT0(rs1);
811   - gen_op_load_fpr_DT1(rs2);
  1170 + gen_op_load_fpr_DT0(DFPREG(rs1));
  1171 + gen_op_load_fpr_DT1(DFPREG(rs2));
812 1172 gen_op_faddd();
813   - gen_op_store_DT0_fpr(rd);
  1173 + gen_op_store_DT0_fpr(DFPREG(rd));
814 1174 break;
815 1175 case 0x43: /* faddq */
816 1176 goto nfpu_insn;
... ... @@ -821,10 +1181,10 @@ static void disas_sparc_insn(DisasContext * dc)
821 1181 gen_op_store_FT0_fpr(rd);
822 1182 break;
823 1183 case 0x46:
824   - gen_op_load_fpr_DT0(rs1);
825   - gen_op_load_fpr_DT1(rs2);
  1184 + gen_op_load_fpr_DT0(DFPREG(rs1));
  1185 + gen_op_load_fpr_DT1(DFPREG(rs2));
826 1186 gen_op_fsubd();
827   - gen_op_store_DT0_fpr(rd);
  1187 + gen_op_store_DT0_fpr(DFPREG(rd));
828 1188 break;
829 1189 case 0x47: /* fsubq */
830 1190 goto nfpu_insn;
... ... @@ -835,8 +1195,8 @@ static void disas_sparc_insn(DisasContext * dc)
835 1195 gen_op_store_FT0_fpr(rd);
836 1196 break;
837 1197 case 0x4a:
838   - gen_op_load_fpr_DT0(rs1);
839   - gen_op_load_fpr_DT1(rs2);
  1198 + gen_op_load_fpr_DT0(DFPREG(rs1));
  1199 + gen_op_load_fpr_DT1(DFPREG(rs2));
840 1200 gen_op_fmuld();
841 1201 gen_op_store_DT0_fpr(rd);
842 1202 break;
... ... @@ -849,10 +1209,10 @@ static void disas_sparc_insn(DisasContext * dc)
849 1209 gen_op_store_FT0_fpr(rd);
850 1210 break;
851 1211 case 0x4e:
852   - gen_op_load_fpr_DT0(rs1);
853   - gen_op_load_fpr_DT1(rs2);
  1212 + gen_op_load_fpr_DT0(DFPREG(rs1));
  1213 + gen_op_load_fpr_DT1(DFPREG(rs2));
854 1214 gen_op_fdivd();
855   - gen_op_store_DT0_fpr(rd);
  1215 + gen_op_store_DT0_fpr(DFPREG(rd));
856 1216 break;
857 1217 case 0x4f: /* fdivq */
858 1218 goto nfpu_insn;
... ... @@ -860,7 +1220,7 @@ static void disas_sparc_insn(DisasContext * dc)
860 1220 gen_op_load_fpr_FT0(rs1);
861 1221 gen_op_load_fpr_FT1(rs2);
862 1222 gen_op_fsmuld();
863   - gen_op_store_DT0_fpr(rd);
  1223 + gen_op_store_DT0_fpr(DFPREG(rd));
864 1224 break;
865 1225 case 0x6e: /* fdmulq */
866 1226 goto nfpu_insn;
... ... @@ -870,7 +1230,7 @@ static void disas_sparc_insn(DisasContext * dc)
870 1230 gen_op_store_FT0_fpr(rd);
871 1231 break;
872 1232 case 0xc6:
873   - gen_op_load_fpr_DT1(rs2);
  1233 + gen_op_load_fpr_DT1(DFPREG(rs2));
874 1234 gen_op_fdtos();
875 1235 gen_op_store_FT0_fpr(rd);
876 1236 break;
... ... @@ -879,12 +1239,12 @@ static void disas_sparc_insn(DisasContext * dc)
879 1239 case 0xc8:
880 1240 gen_op_load_fpr_FT1(rs2);
881 1241 gen_op_fitod();
882   - gen_op_store_DT0_fpr(rd);
  1242 + gen_op_store_DT0_fpr(DFPREG(rd));
883 1243 break;
884 1244 case 0xc9:
885 1245 gen_op_load_fpr_FT1(rs2);
886 1246 gen_op_fstod();
887   - gen_op_store_DT0_fpr(rd);
  1247 + gen_op_store_DT0_fpr(DFPREG(rd));
888 1248 break;
889 1249 case 0xcb: /* fqtod */
890 1250 goto nfpu_insn;
... ... @@ -906,55 +1266,248 @@ static void disas_sparc_insn(DisasContext * dc)
906 1266 break;
907 1267 case 0xd3: /* fqtoi */
908 1268 goto nfpu_insn;
909   - default:
  1269 +#ifdef TARGET_SPARC64
910 1270 case 0x2: /* V9 fmovd */
  1271 + gen_op_load_fpr_DT0(DFPREG(rs2));
  1272 + gen_op_store_DT0_fpr(DFPREG(rd));
  1273 + break;
911 1274 case 0x6: /* V9 fnegd */
  1275 + gen_op_load_fpr_DT1(DFPREG(rs2));
  1276 + gen_op_fnegd();
  1277 + gen_op_store_DT0_fpr(DFPREG(rd));
  1278 + break;
912 1279 case 0xa: /* V9 fabsd */
  1280 + gen_op_load_fpr_DT1(DFPREG(rs2));
  1281 + gen_op_fabsd();
  1282 + gen_op_store_DT0_fpr(DFPREG(rd));
  1283 + break;
913 1284 case 0x81: /* V9 fstox */
  1285 + gen_op_load_fpr_FT1(rs2);
  1286 + gen_op_fstox();
  1287 + gen_op_store_DT0_fpr(DFPREG(rd));
  1288 + break;
914 1289 case 0x82: /* V9 fdtox */
  1290 + gen_op_load_fpr_DT1(DFPREG(rs2));
  1291 + gen_op_fdtox();
  1292 + gen_op_store_DT0_fpr(DFPREG(rd));
  1293 + break;
915 1294 case 0x84: /* V9 fxtos */
  1295 + gen_op_load_fpr_DT1(DFPREG(rs2));
  1296 + gen_op_fxtos();
  1297 + gen_op_store_FT0_fpr(rd);
  1298 + break;
916 1299 case 0x88: /* V9 fxtod */
917   -
  1300 + gen_op_load_fpr_DT1(DFPREG(rs2));
  1301 + gen_op_fxtod();
  1302 + gen_op_store_DT0_fpr(DFPREG(rd));
  1303 + break;
918 1304 case 0x3: /* V9 fmovq */
919 1305 case 0x7: /* V9 fnegq */
920 1306 case 0xb: /* V9 fabsq */
921 1307 case 0x83: /* V9 fqtox */
922 1308 case 0x8c: /* V9 fxtoq */
  1309 + goto nfpu_insn;
  1310 +#endif
  1311 + default:
923 1312 goto illegal_insn;
924 1313 }
925 1314 } else if (xop == 0x35) { /* FPU Operations */
  1315 +#ifdef TARGET_SPARC64
  1316 + int cond;
  1317 +#endif
926 1318 #if !defined(CONFIG_USER_ONLY)
927 1319 gen_op_trap_ifnofpu();
928 1320 #endif
929 1321 rs1 = GET_FIELD(insn, 13, 17);
930 1322 rs2 = GET_FIELD(insn, 27, 31);
931 1323 xop = GET_FIELD(insn, 18, 26);
932   - /* V9 fmovscc: x5, cond = x >> 1 */
933   - /* V9 fmovdcc: x6, cond = x >> 1 */
934   -
935   - /* V9 fmovqcc: x7, cond = x >> 1 */
  1324 +#ifdef TARGET_SPARC64
  1325 + if ((xop & 0x11f) == 0x005) { // V9 fmovsr
  1326 + cond = GET_FIELD_SP(insn, 14, 17);
  1327 + gen_op_load_fpr_FT0(rd);
  1328 + gen_op_load_fpr_FT1(rs2);
  1329 + rs1 = GET_FIELD(insn, 13, 17);
  1330 + gen_movl_reg_T0(rs1);
  1331 + flush_T2(dc);
  1332 + gen_cond_reg(cond);
  1333 + gen_op_fmovs_cc();
  1334 + gen_op_store_FT0_fpr(rd);
  1335 + break;
  1336 + } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
  1337 + cond = GET_FIELD_SP(insn, 14, 17);
  1338 + gen_op_load_fpr_DT0(rd);
  1339 + gen_op_load_fpr_DT1(rs2);
  1340 + flush_T2(dc);
  1341 + rs1 = GET_FIELD(insn, 13, 17);
  1342 + gen_movl_reg_T0(rs1);
  1343 + gen_cond_reg(cond);
  1344 + gen_op_fmovs_cc();
  1345 + gen_op_store_DT0_fpr(rd);
  1346 + break;
  1347 + } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
  1348 + goto nfpu_insn;
  1349 + }
  1350 +#endif
936 1351 switch (xop) {
937   - case 0x51:
  1352 +#ifdef TARGET_SPARC64
  1353 + case 0x001: /* V9 fmovscc %fcc0 */
  1354 + cond = GET_FIELD_SP(insn, 14, 17);
  1355 + gen_op_load_fpr_FT0(rd);
  1356 + gen_op_load_fpr_FT1(rs2);
  1357 + flush_T2(dc);
  1358 + gen_fcond[0][cond]();
  1359 + gen_op_fmovs_cc();
  1360 + gen_op_store_FT0_fpr(rd);
  1361 + break;
  1362 + case 0x002: /* V9 fmovdcc %fcc0 */
  1363 + cond = GET_FIELD_SP(insn, 14, 17);
  1364 + gen_op_load_fpr_DT0(rd);
  1365 + gen_op_load_fpr_DT1(rs2);
  1366 + flush_T2(dc);
  1367 + gen_fcond[0][cond]();
  1368 + gen_op_fmovd_cc();
  1369 + gen_op_store_DT0_fpr(rd);
  1370 + break;
  1371 + case 0x003: /* V9 fmovqcc %fcc0 */
  1372 + goto nfpu_insn;
  1373 + case 0x041: /* V9 fmovscc %fcc1 */
  1374 + cond = GET_FIELD_SP(insn, 14, 17);
  1375 + gen_op_load_fpr_FT0(rd);
  1376 + gen_op_load_fpr_FT1(rs2);
  1377 + flush_T2(dc);
  1378 + gen_fcond[1][cond]();
  1379 + gen_op_fmovs_cc();
  1380 + gen_op_store_FT0_fpr(rd);
  1381 + break;
  1382 + case 0x042: /* V9 fmovdcc %fcc1 */
  1383 + cond = GET_FIELD_SP(insn, 14, 17);
  1384 + gen_op_load_fpr_DT0(rd);
  1385 + gen_op_load_fpr_DT1(rs2);
  1386 + flush_T2(dc);
  1387 + gen_fcond[1][cond]();
  1388 + gen_op_fmovd_cc();
  1389 + gen_op_store_DT0_fpr(rd);
  1390 + break;
  1391 + case 0x043: /* V9 fmovqcc %fcc1 */
  1392 + goto nfpu_insn;
  1393 + case 0x081: /* V9 fmovscc %fcc2 */
  1394 + cond = GET_FIELD_SP(insn, 14, 17);
  1395 + gen_op_load_fpr_FT0(rd);
  1396 + gen_op_load_fpr_FT1(rs2);
  1397 + flush_T2(dc);
  1398 + gen_fcond[2][cond]();
  1399 + gen_op_fmovs_cc();
  1400 + gen_op_store_FT0_fpr(rd);
  1401 + break;
  1402 + case 0x082: /* V9 fmovdcc %fcc2 */
  1403 + cond = GET_FIELD_SP(insn, 14, 17);
  1404 + gen_op_load_fpr_DT0(rd);
  1405 + gen_op_load_fpr_DT1(rs2);
  1406 + flush_T2(dc);
  1407 + gen_fcond[2][cond]();
  1408 + gen_op_fmovd_cc();
  1409 + gen_op_store_DT0_fpr(rd);
  1410 + break;
  1411 + case 0x083: /* V9 fmovqcc %fcc2 */
  1412 + goto nfpu_insn;
  1413 + case 0x0c1: /* V9 fmovscc %fcc3 */
  1414 + cond = GET_FIELD_SP(insn, 14, 17);
  1415 + gen_op_load_fpr_FT0(rd);
  1416 + gen_op_load_fpr_FT1(rs2);
  1417 + flush_T2(dc);
  1418 + gen_fcond[3][cond]();
  1419 + gen_op_fmovs_cc();
  1420 + gen_op_store_FT0_fpr(rd);
  1421 + break;
  1422 + case 0x0c2: /* V9 fmovdcc %fcc3 */
  1423 + cond = GET_FIELD_SP(insn, 14, 17);
  1424 + gen_op_load_fpr_DT0(rd);
  1425 + gen_op_load_fpr_DT1(rs2);
  1426 + flush_T2(dc);
  1427 + gen_fcond[3][cond]();
  1428 + gen_op_fmovd_cc();
  1429 + gen_op_store_DT0_fpr(rd);
  1430 + break;
  1431 + case 0x0c3: /* V9 fmovqcc %fcc3 */
  1432 + goto nfpu_insn;
  1433 + case 0x101: /* V9 fmovscc %icc */
  1434 + cond = GET_FIELD_SP(insn, 14, 17);
  1435 + gen_op_load_fpr_FT0(rd);
  1436 + gen_op_load_fpr_FT1(rs2);
  1437 + flush_T2(dc);
  1438 + gen_cond[0][cond]();
  1439 + gen_op_fmovs_cc();
  1440 + gen_op_store_FT0_fpr(rd);
  1441 + break;
  1442 + case 0x102: /* V9 fmovdcc %icc */
  1443 + cond = GET_FIELD_SP(insn, 14, 17);
  1444 + gen_op_load_fpr_DT0(rd);
  1445 + gen_op_load_fpr_DT1(rs2);
  1446 + flush_T2(dc);
  1447 + gen_cond[0][cond]();
  1448 + gen_op_fmovd_cc();
  1449 + gen_op_store_DT0_fpr(rd);
  1450 + break;
  1451 + case 0x103: /* V9 fmovqcc %icc */
  1452 + goto nfpu_insn;
  1453 + case 0x181: /* V9 fmovscc %xcc */
  1454 + cond = GET_FIELD_SP(insn, 14, 17);
  1455 + gen_op_load_fpr_FT0(rd);
  1456 + gen_op_load_fpr_FT1(rs2);
  1457 + flush_T2(dc);
  1458 + gen_cond[1][cond]();
  1459 + gen_op_fmovs_cc();
  1460 + gen_op_store_FT0_fpr(rd);
  1461 + break;
  1462 + case 0x182: /* V9 fmovdcc %xcc */
  1463 + cond = GET_FIELD_SP(insn, 14, 17);
  1464 + gen_op_load_fpr_DT0(rd);
  1465 + gen_op_load_fpr_DT1(rs2);
  1466 + flush_T2(dc);
  1467 + gen_cond[1][cond]();
  1468 + gen_op_fmovd_cc();
  1469 + gen_op_store_DT0_fpr(rd);
  1470 + break;
  1471 + case 0x183: /* V9 fmovqcc %xcc */
  1472 + goto nfpu_insn;
  1473 +#endif
  1474 + case 0x51: /* V9 %fcc */
938 1475 gen_op_load_fpr_FT0(rs1);
939 1476 gen_op_load_fpr_FT1(rs2);
  1477 +#ifdef TARGET_SPARC64
  1478 + gen_fcmps[rd & 3]();
  1479 +#else
940 1480 gen_op_fcmps();
  1481 +#endif
941 1482 break;
942   - case 0x52:
943   - gen_op_load_fpr_DT0(rs1);
944   - gen_op_load_fpr_DT1(rs2);
  1483 + case 0x52: /* V9 %fcc */
  1484 + gen_op_load_fpr_DT0(DFPREG(rs1));
  1485 + gen_op_load_fpr_DT1(DFPREG(rs2));
  1486 +#ifdef TARGET_SPARC64
  1487 + gen_fcmpd[rd & 3]();
  1488 +#else
945 1489 gen_op_fcmpd();
  1490 +#endif
946 1491 break;
947 1492 case 0x53: /* fcmpq */
948 1493 goto nfpu_insn;
949   - case 0x55: /* fcmpes */
  1494 + case 0x55: /* fcmpes, V9 %fcc */
950 1495 gen_op_load_fpr_FT0(rs1);
951 1496 gen_op_load_fpr_FT1(rs2);
  1497 +#ifdef TARGET_SPARC64
  1498 + gen_fcmps[rd & 3]();
  1499 +#else
952 1500 gen_op_fcmps(); /* XXX should trap if qNaN or sNaN */
  1501 +#endif
953 1502 break;
954   - case 0x56: /* fcmped */
955   - gen_op_load_fpr_DT0(rs1);
956   - gen_op_load_fpr_DT1(rs2);
  1503 + case 0x56: /* fcmped, V9 %fcc */
  1504 + gen_op_load_fpr_DT0(DFPREG(rs1));
  1505 + gen_op_load_fpr_DT1(DFPREG(rs2));
  1506 +#ifdef TARGET_SPARC64
  1507 + gen_fcmpd[rd & 3]();
  1508 +#else
957 1509 gen_op_fcmpd(); /* XXX should trap if qNaN or sNaN */
  1510 +#endif
958 1511 break;
959 1512 case 0x57: /* fcmpeq */
960 1513 goto nfpu_insn;
... ... @@ -970,7 +1523,7 @@ static void disas_sparc_insn(DisasContext * dc)
970 1523 // or %g0, x, y -> mov T1, x; mov y, T1
971 1524 if (IS_IMM) { /* immediate */
972 1525 rs2 = GET_FIELDs(insn, 19, 31);
973   - gen_movl_imm_T1(rs2);
  1526 + gen_movl_simm_T1(rs2);
974 1527 } else { /* register */
975 1528 rs2 = GET_FIELD(insn, 27, 31);
976 1529 gen_movl_reg_T1(rs2);
... ... @@ -982,7 +1535,7 @@ static void disas_sparc_insn(DisasContext * dc)
982 1535 // or x, #0, y -> mov T1, x; mov y, T1
983 1536 rs2 = GET_FIELDs(insn, 19, 31);
984 1537 if (rs2 != 0) {
985   - gen_movl_imm_T1(rs2);
  1538 + gen_movl_simm_T1(rs2);
986 1539 gen_op_or_T1_T0();
987 1540 }
988 1541 } else { /* register */
... ... @@ -1001,7 +1554,7 @@ static void disas_sparc_insn(DisasContext * dc)
1001 1554 gen_movl_reg_T0(rs1);
1002 1555 if (IS_IMM) { /* immediate */
1003 1556 rs2 = GET_FIELDs(insn, 19, 31);
1004   - gen_movl_imm_T1(rs2);
  1557 + gen_movl_simm_T1(rs2);
1005 1558 } else { /* register */
1006 1559 rs2 = GET_FIELD(insn, 27, 31);
1007 1560 gen_movl_reg_T1(rs2);
... ... @@ -1083,13 +1636,21 @@ static void disas_sparc_insn(DisasContext * dc)
1083 1636 gen_op_div_cc();
1084 1637 break;
1085 1638 default:
1086   - case 0x9: /* V9 mulx */
1087   - case 0xd: /* V9 udivx */
1088 1639 goto illegal_insn;
1089 1640 }
1090 1641 gen_movl_T0_reg(rd);
1091 1642 } else {
1092 1643 switch (xop) {
  1644 +#ifdef TARGET_SPARC64
  1645 + case 0x9: /* V9 mulx */
  1646 + gen_op_mulx_T1_T0();
  1647 + gen_movl_T0_reg(rd);
  1648 + break;
  1649 + case 0xd: /* V9 udivx */
  1650 + gen_op_udivx_T1_T0();
  1651 + gen_movl_T0_reg(rd);
  1652 + break;
  1653 +#endif
1093 1654 case 0x20: /* taddcc */
1094 1655 case 0x21: /* tsubcc */
1095 1656 case 0x22: /* taddcctv */
... ... @@ -1099,30 +1660,67 @@ static void disas_sparc_insn(DisasContext * dc)
1099 1660 gen_op_mulscc_T1_T0();
1100 1661 gen_movl_T0_reg(rd);
1101 1662 break;
1102   - case 0x25: /* sll, V9 sllx */
1103   - gen_op_sll();
  1663 + case 0x25: /* sll, V9 sllx ( == sll) */
  1664 + gen_op_sll();
1104 1665 gen_movl_T0_reg(rd);
1105 1666 break;
1106 1667 case 0x26: /* srl, V9 srlx */
1107   - gen_op_srl();
  1668 +#ifdef TARGET_SPARC64
  1669 + if (insn & (1 << 12))
  1670 + gen_op_srlx();
  1671 + else
  1672 + gen_op_srl();
  1673 +#else
  1674 + gen_op_srl();
  1675 +#endif
1108 1676 gen_movl_T0_reg(rd);
1109 1677 break;
1110 1678 case 0x27: /* sra, V9 srax */
1111   - gen_op_sra();
  1679 +#ifdef TARGET_SPARC64
  1680 + if (insn & (1 << 12))
  1681 + gen_op_srax();
  1682 + else
  1683 + gen_op_sra();
  1684 +#else
  1685 + gen_op_sra();
  1686 +#endif
1112 1687 gen_movl_T0_reg(rd);
1113 1688 break;
1114 1689 case 0x30:
1115 1690 {
1116   - gen_op_xor_T1_T0();
1117 1691 switch(rd) {
1118   - case 0:
1119   - gen_op_wry();
  1692 + case 0: /* wry */
  1693 + gen_op_xor_T1_T0();
  1694 + gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
1120 1695 break;
1121   - default:
  1696 +#ifdef TARGET_SPARC64
1122 1697 case 0x2: /* V9 wrccr */
  1698 + gen_op_wrccr();
  1699 + break;
1123 1700 case 0x3: /* V9 wrasi */
  1701 + gen_op_movl_env_T0(offsetof(CPUSPARCState, asi));
  1702 + break;
1124 1703 case 0x6: /* V9 wrfprs */
1125   - case 0xf: /* V9 sir */
  1704 + gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));
  1705 + break;
  1706 + case 0xf: /* V9 sir, nop if user */
  1707 +#if !defined(CONFIG_USER_ONLY)
  1708 + if (supervisor(dc))
  1709 + gen_op_sir();
  1710 +#endif
  1711 + break;
  1712 +#endif
  1713 + case 0x10: /* Performance Control */
  1714 + case 0x11: /* Performance Instrumentation Counter */
  1715 + case 0x12: /* Dispatch Control */
  1716 + case 0x13: /* Graphics Status */
  1717 + case 0x14: /* Softint set */
  1718 + case 0x15: /* Softint clear */
  1719 + case 0x16: /* Softint write */
  1720 + case 0x17: /* Tick compare */
  1721 + case 0x18: /* System tick */
  1722 + case 0x19: /* System tick compare */
  1723 + default:
1126 1724 goto illegal_insn;
1127 1725 }
1128 1726 }
... ... @@ -1132,8 +1730,21 @@ static void disas_sparc_insn(DisasContext * dc)
1132 1730 {
1133 1731 if (!supervisor(dc))
1134 1732 goto priv_insn;
  1733 +#ifdef TARGET_SPARC64
  1734 + switch (rd) {
  1735 + case 0:
  1736 + gen_op_saved();
  1737 + break;
  1738 + case 1:
  1739 + gen_op_restored();
  1740 + break;
  1741 + default:
  1742 + goto illegal_insn;
  1743 + }
  1744 +#else
1135 1745 gen_op_xor_T1_T0();
1136 1746 gen_op_wrpsr();
  1747 +#endif
1137 1748 }
1138 1749 break;
1139 1750 case 0x32: /* wrwim, V9 wrpr */
... ... @@ -1141,28 +1752,179 @@ static void disas_sparc_insn(DisasContext * dc)
1141 1752 if (!supervisor(dc))
1142 1753 goto priv_insn;
1143 1754 gen_op_xor_T1_T0();
1144   - gen_op_wrwim();
  1755 +#ifdef TARGET_SPARC64
  1756 + switch (rd) {
  1757 + case 0: // tpc
  1758 + gen_op_wrtpc();
  1759 + break;
  1760 + case 1: // tnpc
  1761 + gen_op_wrtnpc();
  1762 + break;
  1763 + case 2: // tstate
  1764 + gen_op_wrtstate();
  1765 + break;
  1766 + case 3: // tt
  1767 + gen_op_wrtt();
  1768 + break;
  1769 + case 4: // tick
  1770 + gen_op_wrtick();
  1771 + break;
  1772 + case 5: // tba
  1773 + gen_op_movl_env_T0(offsetof(CPUSPARCState, tbr));
  1774 + break;
  1775 + case 6: // pstate
  1776 + gen_op_wrpstate();
  1777 + break;
  1778 + case 7: // tl
  1779 + gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));
  1780 + break;
  1781 + case 8: // pil
  1782 + gen_op_movl_env_T0(offsetof(CPUSPARCState, psrpil));
  1783 + break;
  1784 + case 9: // cwp
  1785 + gen_op_wrcwp();
  1786 + break;
  1787 + case 10: // cansave
  1788 + gen_op_movl_env_T0(offsetof(CPUSPARCState, cansave));
  1789 + break;
  1790 + case 11: // canrestore
  1791 + gen_op_movl_env_T0(offsetof(CPUSPARCState, canrestore));
  1792 + break;
  1793 + case 12: // cleanwin
  1794 + gen_op_movl_env_T0(offsetof(CPUSPARCState, cleanwin));
  1795 + break;
  1796 + case 13: // otherwin
  1797 + gen_op_movl_env_T0(offsetof(CPUSPARCState, otherwin));
  1798 + break;
  1799 + case 14: // wstate
  1800 + gen_op_movl_env_T0(offsetof(CPUSPARCState, wstate));
  1801 + break;
  1802 + default:
  1803 + goto illegal_insn;
  1804 + }
  1805 +#else
  1806 + gen_op_movl_env_T0(offsetof(CPUSPARCState, wim));
  1807 +#endif
1145 1808 }
1146 1809 break;
1147   - case 0x33:
  1810 +#ifndef TARGET_SPARC64
  1811 + case 0x33: /* wrtbr, V9 unimp */
1148 1812 {
1149 1813 if (!supervisor(dc))
1150 1814 goto priv_insn;
1151 1815 gen_op_xor_T1_T0();
1152   - gen_op_wrtbr();
  1816 + gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
1153 1817 }
1154 1818 break;
1155 1819 #endif
1156   - default:
1157   - case 0x2a: /* V9 rdpr */
1158   - case 0x2b: /* V9 flushw */
  1820 +#endif
  1821 +#ifdef TARGET_SPARC64
1159 1822 case 0x2c: /* V9 movcc */
  1823 + {
  1824 + int cc = GET_FIELD_SP(insn, 11, 12);
  1825 + int cond = GET_FIELD_SP(insn, 14, 17);
  1826 + if (IS_IMM) { /* immediate */
  1827 + rs2 = GET_FIELD_SPs(insn, 0, 10);
  1828 + gen_movl_simm_T1(rs2);
  1829 + }
  1830 + else {
  1831 + rs2 = GET_FIELD_SP(insn, 0, 4);
  1832 + gen_movl_reg_T1(rs2);
  1833 + }
  1834 + gen_movl_reg_T0(rd);
  1835 + flush_T2(dc);
  1836 + if (insn & (1 << 18)) {
  1837 + if (cc == 0)
  1838 + gen_cond[0][cond]();
  1839 + else if (cc == 2)
  1840 + gen_cond[1][cond]();
  1841 + else
  1842 + goto illegal_insn;
  1843 + } else {
  1844 + gen_fcond[cc][cond]();
  1845 + }
  1846 + gen_op_mov_cc();
  1847 + gen_movl_T0_reg(rd);
  1848 + break;
  1849 + }
1160 1850 case 0x2d: /* V9 sdivx */
  1851 + gen_op_sdivx_T1_T0();
  1852 + gen_movl_T0_reg(rd);
  1853 + break;
1161 1854 case 0x2e: /* V9 popc */
  1855 + {
  1856 + if (IS_IMM) { /* immediate */
  1857 + rs2 = GET_FIELD_SPs(insn, 0, 12);
  1858 + gen_movl_simm_T1(rs2);
  1859 + // XXX optimize: popc(constant)
  1860 + }
  1861 + else {
  1862 + rs2 = GET_FIELD_SP(insn, 0, 4);
  1863 + gen_movl_reg_T1(rs2);
  1864 + }
  1865 + gen_op_popc();
  1866 + gen_movl_T0_reg(rd);
  1867 + }
1162 1868 case 0x2f: /* V9 movr */
  1869 + {
  1870 + int cond = GET_FIELD_SP(insn, 10, 12);
  1871 + rs1 = GET_FIELD(insn, 13, 17);
  1872 + flush_T2(dc);
  1873 + gen_movl_reg_T0(rs1);
  1874 + gen_cond_reg(cond);
  1875 + if (IS_IMM) { /* immediate */
  1876 + rs2 = GET_FIELD_SPs(insn, 0, 10);
  1877 + gen_movl_simm_T1(rs2);
  1878 + }
  1879 + else {
  1880 + rs2 = GET_FIELD_SP(insn, 0, 4);
  1881 + gen_movl_reg_T1(rs2);
  1882 + }
  1883 + gen_movl_reg_T0(rd);
  1884 + gen_op_mov_cc();
  1885 + gen_movl_T0_reg(rd);
  1886 + break;
  1887 + }
  1888 + case 0x36: /* UltraSparc shutdown, VIS */
  1889 + {
  1890 + // XXX
  1891 + }
  1892 +#endif
  1893 + default:
1163 1894 goto illegal_insn;
1164 1895 }
1165 1896 }
  1897 +#ifdef TARGET_SPARC64
  1898 + } else if (xop == 0x39) { /* V9 return */
  1899 + gen_op_restore();
  1900 + rs1 = GET_FIELD(insn, 13, 17);
  1901 + gen_movl_reg_T0(rs1);
  1902 + if (IS_IMM) { /* immediate */
  1903 + rs2 = GET_FIELDs(insn, 19, 31);
  1904 +#if defined(OPTIM)
  1905 + if (rs2) {
  1906 +#endif
  1907 + gen_movl_simm_T1(rs2);
  1908 + gen_op_add_T1_T0();
  1909 +#if defined(OPTIM)
  1910 + }
  1911 +#endif
  1912 + } else { /* register */
  1913 + rs2 = GET_FIELD(insn, 27, 31);
  1914 +#if defined(OPTIM)
  1915 + if (rs2) {
  1916 +#endif
  1917 + gen_movl_reg_T1(rs2);
  1918 + gen_op_add_T1_T0();
  1919 +#if defined(OPTIM)
  1920 + }
  1921 +#endif
  1922 + }
  1923 + gen_mov_pc_npc(dc);
  1924 + gen_op_movl_npc_T0();
  1925 + dc->npc = DYNAMIC_PC;
  1926 + goto jmp_insn;
  1927 +#endif
1166 1928 } else {
1167 1929 rs1 = GET_FIELD(insn, 13, 17);
1168 1930 gen_movl_reg_T0(rs1);
... ... @@ -1171,7 +1933,7 @@ static void disas_sparc_insn(DisasContext * dc)
1171 1933 #if defined(OPTIM)
1172 1934 if (rs2) {
1173 1935 #endif
1174   - gen_movl_imm_T1(rs2);
  1936 + gen_movl_simm_T1(rs2);
1175 1937 gen_op_add_T1_T0();
1176 1938 #if defined(OPTIM)
1177 1939 }
... ... @@ -1199,7 +1961,7 @@ static void disas_sparc_insn(DisasContext * dc)
1199 1961 dc->npc = DYNAMIC_PC;
1200 1962 }
1201 1963 goto jmp_insn;
1202   -#if !defined(CONFIG_USER_ONLY)
  1964 +#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1203 1965 case 0x39: /* rett, V9 return */
1204 1966 {
1205 1967 if (!supervisor(dc))
... ... @@ -1224,8 +1986,27 @@ static void disas_sparc_insn(DisasContext * dc)
1224 1986 gen_op_restore();
1225 1987 gen_movl_T0_reg(rd);
1226 1988 break;
1227   - default:
  1989 +#if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
1228 1990 case 0x3e: /* V9 done/retry */
  1991 + {
  1992 + switch (rd) {
  1993 + case 0:
  1994 + if (!supervisor(dc))
  1995 + goto priv_insn;
  1996 + gen_op_done();
  1997 + break;
  1998 + case 1:
  1999 + if (!supervisor(dc))
  2000 + goto priv_insn;
  2001 + gen_op_retry();
  2002 + break;
  2003 + default:
  2004 + goto illegal_insn;
  2005 + }
  2006 + }
  2007 + break;
  2008 +#endif
  2009 + default:
1229 2010 goto illegal_insn;
1230 2011 }
1231 2012 }
... ... @@ -1242,7 +2023,7 @@ static void disas_sparc_insn(DisasContext * dc)
1242 2023 #if defined(OPTIM)
1243 2024 if (rs2 != 0) {
1244 2025 #endif
1245   - gen_movl_imm_T1(rs2);
  2026 + gen_movl_simm_T1(rs2);
1246 2027 gen_op_add_T1_T0();
1247 2028 #if defined(OPTIM)
1248 2029 }
... ... @@ -1258,8 +2039,9 @@ static void disas_sparc_insn(DisasContext * dc)
1258 2039 }
1259 2040 #endif
1260 2041 }
1261   - if (xop < 4 || (xop > 7 && xop < 0x14) || \
1262   - (xop > 0x17 && xop < 0x20)) {
  2042 + if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || \
  2043 + (xop > 0x17 && xop < 0x1d ) || \
  2044 + (xop > 0x2c && xop < 0x33) || xop == 0x1f) {
1263 2045 switch (xop) {
1264 2046 case 0x0: /* load word */
1265 2047 gen_op_ldst(ld);
... ... @@ -1287,72 +2069,115 @@ static void disas_sparc_insn(DisasContext * dc)
1287 2069 gen_movl_reg_T1(rd);
1288 2070 gen_op_ldst(swap);
1289 2071 break;
1290   -#if !defined(CONFIG_USER_ONLY)
  2072 +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
1291 2073 case 0x10: /* load word alternate */
  2074 +#ifndef TARGET_SPARC64
1292 2075 if (!supervisor(dc))
1293 2076 goto priv_insn;
  2077 +#endif
1294 2078 gen_op_lda(insn, 1, 4, 0);
1295 2079 break;
1296 2080 case 0x11: /* load unsigned byte alternate */
  2081 +#ifndef TARGET_SPARC64
1297 2082 if (!supervisor(dc))
1298 2083 goto priv_insn;
  2084 +#endif
1299 2085 gen_op_lduba(insn, 1, 1, 0);
1300 2086 break;
1301 2087 case 0x12: /* load unsigned halfword alternate */
  2088 +#ifndef TARGET_SPARC64
1302 2089 if (!supervisor(dc))
1303 2090 goto priv_insn;
  2091 +#endif
1304 2092 gen_op_lduha(insn, 1, 2, 0);
1305 2093 break;
1306 2094 case 0x13: /* load double word alternate */
  2095 +#ifndef TARGET_SPARC64
1307 2096 if (!supervisor(dc))
1308 2097 goto priv_insn;
  2098 +#endif
1309 2099 gen_op_ldda(insn, 1, 8, 0);
1310 2100 gen_movl_T0_reg(rd + 1);
1311 2101 break;
1312 2102 case 0x19: /* load signed byte alternate */
  2103 +#ifndef TARGET_SPARC64
1313 2104 if (!supervisor(dc))
1314 2105 goto priv_insn;
  2106 +#endif
1315 2107 gen_op_ldsba(insn, 1, 1, 1);
1316 2108 break;
1317 2109 case 0x1a: /* load signed halfword alternate */
  2110 +#ifndef TARGET_SPARC64
1318 2111 if (!supervisor(dc))
1319 2112 goto priv_insn;
  2113 +#endif
1320 2114 gen_op_ldsha(insn, 1, 2 ,1);
1321 2115 break;
1322 2116 case 0x1d: /* ldstuba -- XXX: should be atomically */
  2117 +#ifndef TARGET_SPARC64
1323 2118 if (!supervisor(dc))
1324 2119 goto priv_insn;
  2120 +#endif
1325 2121 gen_op_ldstuba(insn, 1, 1, 0);
1326 2122 break;
1327 2123 case 0x1f: /* swap reg with alt. memory. Also atomically */
  2124 +#ifndef TARGET_SPARC64
1328 2125 if (!supervisor(dc))
1329 2126 goto priv_insn;
  2127 +#endif
1330 2128 gen_movl_reg_T1(rd);
1331 2129 gen_op_swapa(insn, 1, 4, 0);
1332 2130 break;
1333   -
  2131 +
  2132 +#ifndef TARGET_SPARC64
1334 2133 /* avoid warnings */
1335 2134 (void) &gen_op_stfa;
1336 2135 (void) &gen_op_stdfa;
1337 2136 (void) &gen_op_ldfa;
1338 2137 (void) &gen_op_lddfa;
  2138 +#else
  2139 +#if !defined(CONFIG_USER_ONLY)
  2140 + (void) &gen_op_cas;
  2141 + (void) &gen_op_casx;
1339 2142 #endif
1340   - default:
  2143 +#endif
  2144 +#endif
  2145 +#ifdef TARGET_SPARC64
1341 2146 case 0x08: /* V9 ldsw */
  2147 + gen_op_ldst(ldsw);
  2148 + break;
1342 2149 case 0x0b: /* V9 ldx */
  2150 + gen_op_ldst(ldx);
  2151 + break;
1343 2152 case 0x18: /* V9 ldswa */
  2153 + gen_op_ldswa(insn, 1, 4, 1);
  2154 + break;
1344 2155 case 0x1b: /* V9 ldxa */
1345   - case 0x2d: /* V9 prefetch */
  2156 + gen_op_ldxa(insn, 1, 8, 0);
  2157 + break;
  2158 + case 0x2d: /* V9 prefetch, no effect */
  2159 + goto skip_move;
1346 2160 case 0x30: /* V9 ldfa */
  2161 + gen_op_ldfa(insn, 1, 8, 0); // XXX
  2162 + break;
1347 2163 case 0x33: /* V9 lddfa */
1348   - case 0x3d: /* V9 prefetcha */
  2164 + gen_op_lddfa(insn, 1, 8, 0); // XXX
1349 2165  
  2166 + break;
  2167 + case 0x3d: /* V9 prefetcha, no effect */
  2168 + goto skip_move;
1350 2169 case 0x32: /* V9 ldqfa */
  2170 + goto nfpu_insn;
  2171 +#endif
  2172 + default:
1351 2173 goto illegal_insn;
1352 2174 }
1353 2175 gen_movl_T1_reg(rd);
  2176 +#ifdef TARGET_SPARC64
  2177 + skip_move: ;
  2178 +#endif
1354 2179 } else if (xop >= 0x20 && xop < 0x24) {
1355   -#if !defined(CONFIG_USER_ONLY)
  2180 +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
1356 2181 gen_op_trap_ifnofpu();
1357 2182 #endif
1358 2183 switch (xop) {
... ... @@ -1368,12 +2193,13 @@ static void disas_sparc_insn(DisasContext * dc)
1368 2193 goto nfpu_insn;
1369 2194 case 0x23: /* load double fpreg */
1370 2195 gen_op_ldst(lddf);
1371   - gen_op_store_DT0_fpr(rd);
  2196 + gen_op_store_DT0_fpr(DFPREG(rd));
1372 2197 break;
1373 2198 default:
1374 2199 goto illegal_insn;
1375 2200 }
1376   - } else if (xop < 8 || (xop >= 0x14 && xop < 0x18)) {
  2201 + } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
  2202 + xop == 0xe || xop == 0x1e) {
1377 2203 gen_movl_reg_T1(rd);
1378 2204 switch (xop) {
1379 2205 case 0x4:
... ... @@ -1390,33 +2216,47 @@ static void disas_sparc_insn(DisasContext * dc)
1390 2216 gen_movl_reg_T2(rd + 1);
1391 2217 gen_op_ldst(std);
1392 2218 break;
1393   -#if !defined(CONFIG_USER_ONLY)
  2219 +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
1394 2220 case 0x14:
  2221 +#ifndef TARGET_SPARC64
1395 2222 if (!supervisor(dc))
1396 2223 goto priv_insn;
  2224 +#endif
1397 2225 gen_op_sta(insn, 0, 4, 0);
1398 2226 break;
1399 2227 case 0x15:
  2228 +#ifndef TARGET_SPARC64
1400 2229 if (!supervisor(dc))
1401 2230 goto priv_insn;
  2231 +#endif
1402 2232 gen_op_stba(insn, 0, 1, 0);
1403 2233 break;
1404 2234 case 0x16:
  2235 +#ifndef TARGET_SPARC64
1405 2236 if (!supervisor(dc))
1406 2237 goto priv_insn;
  2238 +#endif
1407 2239 gen_op_stha(insn, 0, 2, 0);
1408 2240 break;
1409 2241 case 0x17:
  2242 +#ifndef TARGET_SPARC64
1410 2243 if (!supervisor(dc))
1411 2244 goto priv_insn;
  2245 +#endif
1412 2246 flush_T2(dc);
1413 2247 gen_movl_reg_T2(rd + 1);
1414 2248 gen_op_stda(insn, 0, 8, 0);
1415 2249 break;
1416 2250 #endif
1417   - default:
  2251 +#ifdef TARGET_SPARC64
1418 2252 case 0x0e: /* V9 stx */
  2253 + gen_op_ldst(stx);
  2254 + break;
1419 2255 case 0x1e: /* V9 stxa */
  2256 + gen_op_stxa(insn, 0, 8, 0); // XXX
  2257 + break;
  2258 +#endif
  2259 + default:
1420 2260 goto illegal_insn;
1421 2261 }
1422 2262 } else if (xop > 0x23 && xop < 0x28) {
... ... @@ -1430,26 +2270,41 @@ static void disas_sparc_insn(DisasContext * dc)
1430 2270 break;
1431 2271 case 0x25: /* stfsr, V9 stxfsr */
1432 2272 gen_op_load_fpr_FT0(rd);
  2273 + // XXX
1433 2274 gen_op_stfsr();
1434 2275 break;
1435 2276 case 0x26: /* stdfq */
1436 2277 goto nfpu_insn;
1437 2278 case 0x27:
1438   - gen_op_load_fpr_DT0(rd);
  2279 + gen_op_load_fpr_DT0(DFPREG(rd));
1439 2280 gen_op_ldst(stdf);
1440 2281 break;
1441 2282 default:
  2283 + goto illegal_insn;
  2284 + }
  2285 + } else if (xop > 0x33 && xop < 0x3f) {
  2286 +#ifdef TARGET_SPARC64
  2287 + switch (xop) {
1442 2288 case 0x34: /* V9 stfa */
  2289 + gen_op_stfa(insn, 0, 0, 0); // XXX
  2290 + break;
1443 2291 case 0x37: /* V9 stdfa */
  2292 + gen_op_stdfa(insn, 0, 0, 0); // XXX
  2293 + break;
1444 2294 case 0x3c: /* V9 casa */
  2295 + gen_op_casa(insn, 0, 4, 0); // XXX
  2296 + break;
1445 2297 case 0x3e: /* V9 casxa */
1446   -
  2298 + gen_op_casxa(insn, 0, 8, 0); // XXX
  2299 + break;
1447 2300 case 0x36: /* V9 stqfa */
  2301 + goto nfpu_insn;
  2302 + default:
1448 2303 goto illegal_insn;
1449 2304 }
1450   - } else if (xop > 0x33 && xop < 0x38) {
1451   - /* Co-processor */
  2305 +#else
1452 2306 goto illegal_insn;
  2307 +#endif
1453 2308 }
1454 2309 else
1455 2310 goto illegal_insn;
... ... @@ -1540,6 +2395,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
1540 2395 }
1541 2396 last_pc = dc->pc;
1542 2397 disas_sparc_insn(dc);
  2398 +
1543 2399 if (dc->is_br)
1544 2400 break;
1545 2401 /* if the next PC is different, we abort now */
... ... @@ -1552,7 +2408,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
1552 2408 /* if single step mode, we generate only one instruction and
1553 2409 generate an exception */
1554 2410 if (env->singlestep_enabled) {
1555   - gen_op_jmp_im(dc->pc);
  2411 + gen_jmp_im(dc->pc);
1556 2412 gen_op_movl_T0_0();
1557 2413 gen_op_exit_tb();
1558 2414 break;
... ... @@ -1568,7 +2424,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
1568 2424 gen_op_branch((long)tb, dc->pc, dc->npc);
1569 2425 } else {
1570 2426 if (dc->pc != DYNAMIC_PC)
1571   - gen_op_jmp_im(dc->pc);
  2427 + gen_jmp_im(dc->pc);
1572 2428 save_npc(dc);
1573 2429 gen_op_movl_T0_0();
1574 2430 gen_op_exit_tb();
... ... @@ -1633,8 +2489,13 @@ void cpu_reset(CPUSPARCState *env)
1633 2489 env->psrps = 1;
1634 2490 env->pc = 0xffd00000;
1635 2491 env->gregs[1] = ram_size;
1636   - env->mmuregs[0] = (0x04 << 24); /* Impl 0, ver 4, MMU disabled */
1637 2492 env->npc = env->pc + 4;
  2493 +#ifdef TARGET_SPARC64
  2494 + env->pstate = PS_AM | PS_PRIV; // XXX: Force AM
  2495 + env->version = GET_VER(env);
  2496 +#else
  2497 + env->mmuregs[0] = (0x04 << 24); /* Impl 0, ver 4, MMU disabled */
  2498 +#endif
1638 2499 #endif
1639 2500 }
1640 2501  
... ... @@ -1692,7 +2553,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
1692 2553 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1693 2554 env->psrs?'S':'-', env->psrps?'P':'-',
1694 2555 env->psret?'E':'-', env->wim);
1695   - cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);
  2556 + cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
1696 2557 }
1697 2558  
1698 2559 #if defined(CONFIG_USER_ONLY)
... ...
... ... @@ -2375,12 +2375,14 @@ void cpu_save(QEMUFile *f, void *opaque)
2375 2375 qemu_put_betls(f, &env->y);
2376 2376 tmp = GET_PSR(env);
2377 2377 qemu_put_be32(f, tmp);
2378   - qemu_put_be32s(f, &env->fsr);
  2378 + qemu_put_betls(f, &env->fsr);
  2379 + qemu_put_betls(f, &env->tbr);
  2380 +#ifndef TARGET_SPARC64
2379 2381 qemu_put_be32s(f, &env->wim);
2380   - qemu_put_be32s(f, &env->tbr);
2381 2382 /* MMU */
2382 2383 for(i = 0; i < 16; i++)
2383 2384 qemu_put_be32s(f, &env->mmuregs[i]);
  2385 +#endif
2384 2386 }
2385 2387  
2386 2388 int cpu_load(QEMUFile *f, void *opaque, int version_id)
... ... @@ -2411,13 +2413,14 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
2411 2413 env->cwp = 0; /* needed to ensure that the wrapping registers are
2412 2414 correctly updated */
2413 2415 PUT_PSR(env, tmp);
2414   - qemu_get_be32s(f, &env->fsr);
  2416 + qemu_get_betls(f, &env->fsr);
  2417 + qemu_get_betls(f, &env->tbr);
  2418 +#ifndef TARGET_SPARC64
2415 2419 qemu_get_be32s(f, &env->wim);
2416   - qemu_get_be32s(f, &env->tbr);
2417 2420 /* MMU */
2418 2421 for(i = 0; i < 16; i++)
2419 2422 qemu_get_be32s(f, &env->mmuregs[i]);
2420   -
  2423 +#endif
2421 2424 tlb_flush(env, 1);
2422 2425 return 0;
2423 2426 }
... ... @@ -2577,6 +2580,7 @@ typedef struct QEMUResetEntry {
2577 2580 static QEMUResetEntry *first_reset_entry;
2578 2581 static int reset_requested;
2579 2582 static int shutdown_requested;
  2583 +static int powerdown_requested;
2580 2584  
2581 2585 void qemu_register_reset(QEMUResetHandler *func, void *opaque)
2582 2586 {
... ... @@ -2614,6 +2618,12 @@ void qemu_system_shutdown_request(void)
2614 2618 cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
2615 2619 }
2616 2620  
  2621 +void qemu_system_powerdown_request(void)
  2622 +{
  2623 + powerdown_requested = 1;
  2624 + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
  2625 +}
  2626 +
2617 2627 static void main_cpu_reset(void *opaque)
2618 2628 {
2619 2629 #if defined(TARGET_I386) || defined(TARGET_SPARC)
... ... @@ -2728,20 +2738,25 @@ int main_loop(void)
2728 2738 if (vm_running) {
2729 2739 ret = cpu_exec(env);
2730 2740 if (shutdown_requested) {
2731   - ret = EXCP_INTERRUPT;
  2741 + ret = EXCP_INTERRUPT;
2732 2742 break;
2733 2743 }
2734 2744 if (reset_requested) {
2735 2745 reset_requested = 0;
2736 2746 qemu_system_reset();
2737   - ret = EXCP_INTERRUPT;
  2747 + ret = EXCP_INTERRUPT;
  2748 + }
  2749 + if (powerdown_requested) {
  2750 + powerdown_requested = 0;
  2751 + qemu_system_powerdown();
  2752 + ret = EXCP_INTERRUPT;
2738 2753 }
2739 2754 if (ret == EXCP_DEBUG) {
2740 2755 vm_stop(EXCP_DEBUG);
2741 2756 }
2742 2757 /* if hlt instruction, we wait until the next IRQ */
2743 2758 /* XXX: use timeout computed from timers */
2744   - if (ret == EXCP_HLT)
  2759 + if (ret == EXCP_HLT)
2745 2760 timeout = 10;
2746 2761 else
2747 2762 timeout = 0;
... ... @@ -3044,8 +3059,12 @@ void register_machines(void)
3044 3059 qemu_register_machine(&core99_machine);
3045 3060 qemu_register_machine(&prep_machine);
3046 3061 #elif defined(TARGET_SPARC)
  3062 +#ifdef TARGET_SPARC64
  3063 + qemu_register_machine(&sun4u_machine);
  3064 +#else
3047 3065 qemu_register_machine(&sun4m_machine);
3048 3066 #endif
  3067 +#endif
3049 3068 }
3050 3069  
3051 3070 #define NET_IF_TUN 0
... ...
... ... @@ -110,6 +110,13 @@ typedef void QEMUResetHandler(void *opaque);
110 110 void qemu_register_reset(QEMUResetHandler *func, void *opaque);
111 111 void qemu_system_reset_request(void);
112 112 void qemu_system_shutdown_request(void);
  113 +void qemu_system_powerdown_request(void);
  114 +#if !defined(TARGET_SPARC)
  115 +// Please implement a power failure function to signal the OS
  116 +#define qemu_system_powerdown() do{}while(0)
  117 +#else
  118 +void qemu_system_powerdown(void);
  119 +#endif
113 120  
114 121 void main_loop_wait(int timeout);
115 122  
... ... @@ -753,9 +760,16 @@ void slavio_timer_init(uint32_t addr1, int irq1, uint32_t addr2, int irq2);
753 760 SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2);
754 761 void slavio_serial_ms_kbd_init(int base, int irq);
755 762  
  763 +/* slavio_misc.c */
  764 +void *slavio_misc_init(uint32_t base, int irq);
  765 +void slavio_set_power_fail(void *opaque, int power_failing);
  766 +
756 767 /* esp.c */
757 768 void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr);
758 769  
  770 +/* sun4u.c */
  771 +extern QEMUMachine sun4u_machine;
  772 +
759 773 /* NVRAM helpers */
760 774 #include "hw/m48t59.h"
761 775  
... ...