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

Too many changes to show.

To preserve performance only 23 of 26 files are displayed.

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
... ...