sparc emulation target (thanx to Thomas M. Ogrisegg)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@386 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2003-09-30 20:36:07 +00:00
parent 2c0262afa7
commit 7a3f194486
7 changed files with 1581 additions and 0 deletions

View File

@ -0,0 +1,7 @@
struct target_pt_regs {
target_ulong psr;
target_ulong pc;
target_ulong npc;
target_ulong y;
target_ulong u_regs[16];
};

View File

@ -0,0 +1,220 @@
#define TARGET_NR_exit 1 /* Common */
#define TARGET_NR_fork 2 /* Common */
#define TARGET_NR_read 3 /* Common */
#define TARGET_NR_write 4 /* Common */
#define TARGET_NR_open 5 /* Common */
#define TARGET_NR_close 6 /* Common */
#define TARGET_NR_wait4 7 /* Common */
#define TARGET_NR_creat 8 /* Common */
#define TARGET_NR_link 9 /* Common */
#define TARGET_NR_unlink 10 /* Common */
#define TARGET_NR_execv 11 /* SunOS Specific */
#define TARGET_NR_chdir 12 /* Common */
#define TARGET_NR_chown 13 /* Common */
#define TARGET_NR_mknod 14 /* Common */
#define TARGET_NR_chmod 15 /* Common */
#define TARGET_NR_lchown 16 /* Common */
#define TARGET_NR_brk 17 /* Common */
#define TARGET_NR_perfctr 18 /* Performance counter operations */
#define TARGET_NR_lseek 19 /* Common */
#define TARGET_NR_getpid 20 /* Common */
#define TARGET_NR_capget 21 /* Linux Specific */
#define TARGET_NR_capset 22 /* Linux Specific */
#define TARGET_NR_setuid 23 /* Implemented via setreuid in SunOS */
#define TARGET_NR_getuid 24 /* Common */
#define TARGET_NR_ptrace 26 /* Common */
#define TARGET_NR_alarm 27 /* Implemented via setitimer in SunOS */
#define TARGET_NR_sigaltstack 28 /* Common */
#define TARGET_NR_pause 29 /* Is sigblock(0)->sigpause() in SunOS */
#define TARGET_NR_utime 30 /* Implemented via utimes() under SunOS */
#define TARGET_NR_lchown32 31 /* Linux sparc32 specific */
#define TARGET_NR_fchown32 32 /* Linux sparc32 specific */
#define TARGET_NR_access 33 /* Common */
#define TARGET_NR_nice 34 /* Implemented via get/setpriority() in SunOS */
#define TARGET_NR_chown32 35 /* Linux sparc32 specific */
#define TARGET_NR_sync 36 /* Common */
#define TARGET_NR_kill 37 /* Common */
#define TARGET_NR_stat 38 /* Common */
#define TARGET_NR_sendfile 39 /* Linux Specific */
#define TARGET_NR_lstat 40 /* Common */
#define TARGET_NR_dup 41 /* Common */
#define TARGET_NR_pipe 42 /* Common */
#define TARGET_NR_times 43 /* Implemented via getrusage() in SunOS */
#define TARGET_NR_getuid32 44 /* Linux sparc32 specific */
#define TARGET_NR_umount2 45 /* Linux Specific */
#define TARGET_NR_setgid 46 /* Implemented via setregid() in SunOS */
#define TARGET_NR_getgid 47 /* Common */
#define TARGET_NR_signal 48 /* Implemented via sigvec() in SunOS */
#define TARGET_NR_geteuid 49 /* SunOS calls getuid() */
#define TARGET_NR_getegid 50 /* SunOS calls getgid() */
#define TARGET_NR_acct 51 /* Common */
#define TARGET_NR_getgid32 53 /* Linux sparc32 specific */
#define TARGET_NR_ioctl 54 /* Common */
#define TARGET_NR_reboot 55 /* Common */
#define TARGET_NR_mmap2 56 /* Linux sparc32 Specific */
#define TARGET_NR_symlink 57 /* Common */
#define TARGET_NR_readlink 58 /* Common */
#define TARGET_NR_execve 59 /* Common */
#define TARGET_NR_umask 60 /* Common */
#define TARGET_NR_chroot 61 /* Common */
#define TARGET_NR_fstat 62 /* Common */
#define TARGET_NR_fstat64 63 /* Linux sparc32 Specific */
#define TARGET_NR_getpagesize 64 /* Common */
#define TARGET_NR_msync 65 /* Common in newer 1.3.x revs... */
#define TARGET_NR_vfork 66 /* Common */
#define TARGET_NR_pread 67 /* Linux Specific */
#define TARGET_NR_pwrite 68 /* Linux Specific */
#define TARGET_NR_geteuid32 69 /* Linux sparc32, sbrk under SunOS */
#define TARGET_NR_getegid32 70 /* Linux sparc32, sstk under SunOS */
#define TARGET_NR_mmap 71 /* Common */
#define TARGET_NR_setreuid32 72 /* Linux sparc32, vadvise under SunOS */
#define TARGET_NR_munmap 73 /* Common */
#define TARGET_NR_mprotect 74 /* Common */
#define TARGET_NR_madvise 75 /* Common */
#define TARGET_NR_vhangup 76 /* Common */
#define TARGET_NR_truncate64 77 /* Linux sparc32 Specific */
#define TARGET_NR_mincore 78 /* Common */
#define TARGET_NR_getgroups 79 /* Common */
#define TARGET_NR_setgroups 80 /* Common */
#define TARGET_NR_getpgrp 81 /* Common */
#define TARGET_NR_setgroups32 82 /* Linux sparc32, setpgrp under SunOS */
#define TARGET_NR_setitimer 83 /* Common */
#define TARGET_NR_ftruncate64 84 /* Linux sparc32 Specific */
#define TARGET_NR_swapon 85 /* Common */
#define TARGET_NR_getitimer 86 /* Common */
#define TARGET_NR_setuid32 87 /* Linux sparc32, gethostname under SunOS */
#define TARGET_NR_sethostname 88 /* Common */
#define TARGET_NR_setgid32 89 /* Linux sparc32, getdtablesize under SunOS */
#define TARGET_NR_dup2 90 /* Common */
#define TARGET_NR_setfsuid32 91 /* Linux sparc32, getdopt under SunOS */
#define TARGET_NR_fcntl 92 /* Common */
#define TARGET_NR_select 93 /* Common */
#define TARGET_NR_setfsgid32 94 /* Linux sparc32, setdopt under SunOS */
#define TARGET_NR_fsync 95 /* Common */
#define TARGET_NR_setpriority 96 /* Common */
#define TARGET_NR_socket 97 /* Common */
#define TARGET_NR_connect 98 /* Common */
#define TARGET_NR_accept 99 /* Common */
#define TARGET_NR_getpriority 100 /* Common */
#define TARGET_NR_rt_sigreturn 101 /* Linux Specific */
#define TARGET_NR_rt_sigaction 102 /* Linux Specific */
#define TARGET_NR_rt_sigprocmask 103 /* Linux Specific */
#define TARGET_NR_rt_sigpending 104 /* Linux Specific */
#define TARGET_NR_rt_sigtimedwait 105 /* Linux Specific */
#define TARGET_NR_rt_sigqueueinfo 106 /* Linux Specific */
#define TARGET_NR_rt_sigsuspend 107 /* Linux Specific */
#define TARGET_NR_setresuid32 108 /* Linux Specific, sigvec under SunOS */
#define TARGET_NR_getresuid32 109 /* Linux Specific, sigblock under SunOS */
#define TARGET_NR_setresgid32 110 /* Linux Specific, sigsetmask under SunOS */
#define TARGET_NR_getresgid32 111 /* Linux Specific, sigpause under SunOS */
#define TARGET_NR_setregid32 112 /* Linux sparc32, sigstack under SunOS */
#define TARGET_NR_recvmsg 113 /* Common */
#define TARGET_NR_sendmsg 114 /* Common */
#define TARGET_NR_getgroups32 115 /* Linux sparc32, vtrace under SunOS */
#define TARGET_NR_gettimeofday 116 /* Common */
#define TARGET_NR_getrusage 117 /* Common */
#define TARGET_NR_getsockopt 118 /* Common */
#define TARGET_NR_getcwd 119 /* Linux Specific */
#define TARGET_NR_readv 120 /* Common */
#define TARGET_NR_writev 121 /* Common */
#define TARGET_NR_settimeofday 122 /* Common */
#define TARGET_NR_fchown 123 /* Common */
#define TARGET_NR_fchmod 124 /* Common */
#define TARGET_NR_recvfrom 125 /* Common */
#define TARGET_NR_setreuid 126 /* Common */
#define TARGET_NR_setregid 127 /* Common */
#define TARGET_NR_rename 128 /* Common */
#define TARGET_NR_truncate 129 /* Common */
#define TARGET_NR_ftruncate 130 /* Common */
#define TARGET_NR_flock 131 /* Common */
#define TARGET_NR_lstat64 132 /* Linux sparc32 Specific */
#define TARGET_NR_sendto 133 /* Common */
#define TARGET_NR_shutdown 134 /* Common */
#define TARGET_NR_socketpair 135 /* Common */
#define TARGET_NR_mkdir 136 /* Common */
#define TARGET_NR_rmdir 137 /* Common */
#define TARGET_NR_utimes 138 /* SunOS Specific */
#define TARGET_NR_stat64 139 /* Linux sparc32 Specific */
#define TARGET_NR_getpeername 141 /* Common */
#define TARGET_NR_gettid 143 /* ENOSYS under SunOS */
#define TARGET_NR_getrlimit 144 /* Common */
#define TARGET_NR_setrlimit 145 /* Common */
#define TARGET_NR_pivot_root 146 /* Linux Specific, killpg under SunOS */
#define TARGET_NR_prctl 147 /* ENOSYS under SunOS */
#define TARGET_NR_pciconfig_read 148 /* ENOSYS under SunOS */
#define TARGET_NR_pciconfig_write 149 /* ENOSYS under SunOS */
#define TARGET_NR_getsockname 150 /* Common */
#define TARGET_NR_poll 153 /* Common */
#define TARGET_NR_getdents64 154 /* Linux specific */
#define TARGET_NR_fcntl64 155 /* Linux sparc32 Specific */
#define TARGET_NR_statfs 157 /* Common */
#define TARGET_NR_fstatfs 158 /* Common */
#define TARGET_NR_umount 159 /* Common */
#define TARGET_NR_getdomainname 162 /* SunOS Specific */
#define TARGET_NR_setdomainname 163 /* Common */
#define TARGET_NR_quotactl 165 /* Common */
#define TARGET_NR_mount 167 /* Common */
#define TARGET_NR_ustat 168 /* Common */
#define TARGET_NR_getdents 174 /* Common */
#define TARGET_NR_setsid 175 /* Common */
#define TARGET_NR_fchdir 176 /* Common */
#define TARGET_NR_sigpending 183 /* Common */
#define TARGET_NR_query_module 184 /* Linux Specific */
#define TARGET_NR_setpgid 185 /* Common */
#define TARGET_NR_tkill 187 /* SunOS: fpathconf */
#define TARGET_NR_exit_group 188 /* Linux specific, sysconf undef SunOS */
#define TARGET_NR_uname 189 /* Linux Specific */
#define TARGET_NR_init_module 190 /* Linux Specific */
#define TARGET_NR_personality 191 /* Linux Specific */
#define TARGET_NR_getppid 197 /* Linux Specific */
#define TARGET_NR_sigaction 198 /* Linux Specific */
#define TARGET_NR_sgetmask 199 /* Linux Specific */
#define TARGET_NR_ssetmask 200 /* Linux Specific */
#define TARGET_NR_sigsuspend 201 /* Linux Specific */
#define TARGET_NR_oldlstat 202 /* Linux Specific */
#define TARGET_NR_uselib 203 /* Linux Specific */
#define TARGET_NR_readdir 204 /* Linux Specific */
#define TARGET_NR_readahead 205 /* Linux Specific */
#define TARGET_NR_socketcall 206 /* Linux Specific */
#define TARGET_NR_syslog 207 /* Linux Specific */
#define TARGET_NR_waitpid 212 /* Linux Specific */
#define TARGET_NR_swapoff 213 /* Linux Specific */
#define TARGET_NR_sysinfo 214 /* Linux Specific */
#define TARGET_NR_ipc 215 /* Linux Specific */
#define TARGET_NR_sigreturn 216 /* Linux Specific */
#define TARGET_NR_clone 217 /* Linux Specific */
#define TARGET_NR_adjtimex 219 /* Linux Specific */
#define TARGET_NR_sigprocmask 220 /* Linux Specific */
#define TARGET_NR_create_module 221 /* Linux Specific */
#define TARGET_NR_delete_module 222 /* Linux Specific */
#define TARGET_NR_get_kernel_syms 223 /* Linux Specific */
#define TARGET_NR_getpgid 224 /* Linux Specific */
#define TARGET_NR_bdflush 225 /* Linux Specific */
#define TARGET_NR_sysfs 226 /* Linux Specific */
#define TARGET_NR_afs_syscall 227 /* Linux Specific */
#define TARGET_NR_setfsuid 228 /* Linux Specific */
#define TARGET_NR_setfsgid 229 /* Linux Specific */
#define TARGET_NR__newselect 230 /* Linux Specific */
#define TARGET_NR_time 231 /* Linux Specific */
#define TARGET_NR_stime 233 /* Linux Specific */
#define TARGET_NR__llseek 236 /* Linux Specific */
#define TARGET_NR_mlock 237
#define TARGET_NR_munlock 238
#define TARGET_NR_mlockall 239
#define TARGET_NR_munlockall 240
#define TARGET_NR_sched_setparam 241
#define TARGET_NR_sched_getparam 242
#define TARGET_NR_sched_setscheduler 243
#define TARGET_NR_sched_getscheduler 244
#define TARGET_NR_sched_yield 245
#define TARGET_NR_sched_get_priority_max 246
#define TARGET_NR_sched_get_priority_min 247
#define TARGET_NR_sched_rr_get_interval 248
#define TARGET_NR_nanosleep 249
#define TARGET_NR_mremap 250
#define TARGET_NR__sysctl 251
#define TARGET_NR_getsid 252
#define TARGET_NR_fdatasync 253
#define TARGET_NR_nfsservctl 254
#define TARGET_NR_aplib 255
#define TARGET_NR__exit TARGET_NR_exit

46
target-sparc/cpu.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef CPU_SPARC_H
#define CPU_SPARC_H
#include <setjmp.h>
#include "config.h"
#include "cpu-defs.h"
/*#define EXCP_INTERRUPT 0x100*/
#define PSR_NEG (1<<23)
#define PSR_ZERO (1<<22)
#define PSR_OVF (1<<21)
#define PSR_CARRY (1<<20)
typedef struct CPUSPARCState {
uint32_t gregs[8]; /* general registers */
uint32_t *regwptr; /* pointer to current register window */
double *regfptr; /* floating point registers */
uint32_t pc; /* program counter */
uint32_t npc; /* next program counter */
uint32_t sp; /* stack pointer */
uint32_t y; /* multiply/divide register */
uint32_t psr; /* processor state register */
uint32_t T2;
jmp_buf jmp_env;
int user_mode_only;
int exception_index;
int interrupt_index;
int interrupt_request;
struct TranslationBlock *current_tb;
void *opaque;
} CPUSPARCState;
CPUSPARCState *cpu_sparc_init(void);
int cpu_sparc_exec(CPUSPARCState *s);
int cpu_sparc_close(CPUSPARCState *s);
struct siginfo;
int cpu_sparc_signal_handler(int hostsignum, struct siginfo *info, void *puc);
void cpu_sparc_dump_state(CPUSPARCState *env, FILE *f, int flags);
#define TARGET_PAGE_BITS 13
#include "cpu-all.h"
#endif

16
target-sparc/exec.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef EXEC_SPARC_H
#define EXEC_SPARC_H 1
#include "dyngen-exec.h"
register struct CPUSPARCState *env asm(AREG0);
register uint32_t T0 asm(AREG1);
register uint32_t T1 asm(AREG2);
register uint32_t T2 asm(AREG3);
#include "cpu.h"
#include "exec-all.h"
void cpu_lock(void);
void cpu_unlock(void);
void cpu_loop_exit(void);
#endif

500
target-sparc/op.c Normal file
View File

@ -0,0 +1,500 @@
/*
SPARC micro operations
Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "exec.h"
/*XXX*/
#define REGNAME g0
#define REG (env->gregs[0])
#include "op_template.h"
#define REGNAME g1
#define REG (env->gregs[1])
#include "op_template.h"
#define REGNAME g2
#define REG (env->gregs[2])
#include "op_template.h"
#define REGNAME g3
#define REG (env->gregs[3])
#include "op_template.h"
#define REGNAME g4
#define REG (env->gregs[4])
#include "op_template.h"
#define REGNAME g5
#define REG (env->gregs[5])
#include "op_template.h"
#define REGNAME g6
#define REG (env->gregs[6])
#include "op_template.h"
#define REGNAME g7
#define REG (env->gregs[7])
#include "op_template.h"
#define REGNAME i0
#define REG (env->regwptr[16])
#include "op_template.h"
#define REGNAME i1
#define REG (env->regwptr[17])
#include "op_template.h"
#define REGNAME i2
#define REG (env->regwptr[18])
#include "op_template.h"
#define REGNAME i3
#define REG (env->regwptr[19])
#include "op_template.h"
#define REGNAME i4
#define REG (env->regwptr[20])
#include "op_template.h"
#define REGNAME i5
#define REG (env->regwptr[21])
#include "op_template.h"
#define REGNAME i6
#define REG (env->regwptr[22])
#include "op_template.h"
#define REGNAME i7
#define REG (env->regwptr[23])
#include "op_template.h"
#define REGNAME l0
#define REG (env->regwptr[8])
#include "op_template.h"
#define REGNAME l1
#define REG (env->regwptr[9])
#include "op_template.h"
#define REGNAME l2
#define REG (env->regwptr[10])
#include "op_template.h"
#define REGNAME l3
#define REG (env->regwptr[11])
#include "op_template.h"
#define REGNAME l4
#define REG (env->regwptr[12])
#include "op_template.h"
#define REGNAME l5
#define REG (env->regwptr[13])
#include "op_template.h"
#define REGNAME l6
#define REG (env->regwptr[14])
#include "op_template.h"
#define REGNAME l7
#define REG (env->regwptr[15])
#include "op_template.h"
#define REGNAME o0
#define REG (env->regwptr[0])
#include "op_template.h"
#define REGNAME o1
#define REG (env->regwptr[1])
#include "op_template.h"
#define REGNAME o2
#define REG (env->regwptr[2])
#include "op_template.h"
#define REGNAME o3
#define REG (env->regwptr[3])
#include "op_template.h"
#define REGNAME o4
#define REG (env->regwptr[4])
#include "op_template.h"
#define REGNAME o5
#define REG (env->regwptr[5])
#include "op_template.h"
#define REGNAME o6
#define REG (env->regwptr[6])
#include "op_template.h"
#define REGNAME o7
#define REG (env->regwptr[7])
#include "op_template.h"
#define EIP (env->pc)
void OPPROTO op_movl_T0_0(void)
{
T0 = 0;
}
void OPPROTO op_movl_T0_1(void)
{
T0 = 1;
}
void OPPROTO op_movl_T0_im(void)
{
T0 = PARAM1;
}
void OPPROTO op_movl_T1_im(void)
{
T1 = PARAM1;
}
void OPPROTO op_movl_T2_im(void)
{
T2 = PARAM1;
}
void OPPROTO op_addl_T1_im(void)
{
T1 += PARAM1;
}
void OPPROTO op_addl_T1_T2(void)
{
T1 += T2;
}
void OPPROTO op_subl_T1_T2(void)
{
T1 -= T2;
}
void OPPROTO op_add_T1_T0 (void)
{
T0 += T1;
}
void OPPROTO op_and_T1_T0 (void)
{
T0 &= T1;
}
void OPPROTO op_or_T1_T0 (void)
{
T0 |= T1;
}
void OPPROTO op_xor_T1_T0 (void)
{
T0 ^= T1;
}
void OPPROTO op_sub_T1_T0 (void)
{
T0 -= T1;
}
void OPPROTO op_andn_T1_T0 (void)
{
T0 &= ~T1;
}
void OPPROTO op_orn_T1_T0 (void)
{
T0 |= ~T1;
}
void OPPROTO op_xnor_T1_T0 (void)
{
T0 ^= ~T1;
}
void OPPROTO op_addx_T1_T0 (void)
{
T0 += T1+((env->psr & PSR_CARRY)?1:0);
}
void OPPROTO op_umul_T1_T0 (void)
{
unsigned long long res = T0*T1;
T0 = res & 0xffffffff;
env->y = res >> 32;
}
void OPPROTO op_smul_T1_T0 (void)
{
long long res = T0*T1;
T0 = res & 0xffffffff;
env->y = res >> 32;
}
void OPPROTO op_udiv_T1_T0 (void)
{
unsigned long long x0 = T0 * env->y;
unsigned int x1 = T1;
T0 = x0 / x1;
}
void OPPROTO op_sdiv_T1_T0 (void)
{
long long x0 = T0 * env->y;
int x1 = T1;
T0 = x0 / x1;
}
void OPPROTO op_subx_T1_T0 (void)
{
T0 -= T1+((env->psr & PSR_CARRY)?1:0);
}
void OPPROTO op_set_flags (void)
{
env->psr = 0;
if (!T0) env->psr |= PSR_ZERO;
if ((unsigned int) T0 < (unsigned int) T1) env->psr |= PSR_CARRY;
if ((int) T0 < (int) T1) env->psr |= PSR_OVF;
if ((int) T0 < 0) env->psr |= PSR_NEG;
}
void OPPROTO op_sll (void)
{
T0 <<= T1;
}
void OPPROTO op_srl (void)
{
T0 >>= T1;
}
void OPPROTO op_sra (void)
{
int x = T0 >> T1;
T0 = x;
}
void OPPROTO op_st (void)
{
stl ((void *) T0, T1);
}
void OPPROTO op_stb (void)
{
stb ((void *) T0, T1);
}
void OPPROTO op_sth (void)
{
stw ((void *) T0, T1);
}
void OPPROTO op_ld (void)
{
T1 = ldl ((void *) T0);
}
void OPPROTO op_ldub (void)
{
T1 = ldub ((void *) T0);
}
void OPPROTO op_lduh (void)
{
T1 = lduw ((void *) T0);
}
void OPPROTO op_ldsb (void)
{
T1 = ldsb ((void *) T0);
}
void OPPROTO op_ldsh (void)
{
T1 = ldsw ((void *) T0);
}
void OPPROTO op_ldstub (void)
{
T1 = ldub ((void *) T0);
stb ((void *) T0, 0xff); /* XXX: Should be Atomically */
}
void OPPROTO op_swap (void)
{
unsigned int tmp = ldl ((void *) T0);
stl ((void *) T0, T1); /* XXX: Should be Atomically */
T1 = tmp;
}
void OPPROTO op_ldd (void)
{
T1 = ldl ((void *) T0);
T0 = ldl ((void *) T0+4);
}
void OPPROTO op_wry (void)
{
env->y = T0^T1;
}
void OPPROTO op_rdy (void)
{
T0 = env->y;
}
#define regwptr (env->regwptr)
void OPPROTO op_save (void)
{
regwptr -= 16;
}
void OPPROTO op_restore (void)
{
regwptr += 16;
}
void OPPROTO op_trap (void)
{
env->exception_index = PARAM1;
cpu_loop_exit ();
}
void OPPROTO op_exit_tb (void)
{
EXIT_TB ();
}
void OPPROTO op_eval_be (void)
{
T0 = (env->psr & PSR_ZERO);
}
#define FLAG_SET(x) (env->psr&x)?1:0
#define GET_FLAGS unsigned int Z = FLAG_SET(PSR_ZERO), N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF), C = FLAG_SET(PSR_CARRY)
void OPPROTO op_eval_ble (void)
{
GET_FLAGS;
T0 = Z | (N^V);
}
void OPPROTO op_eval_bl (void)
{
GET_FLAGS;
T0 = N^V;
}
void OPPROTO op_eval_bleu (void)
{
GET_FLAGS;
T0 = C|Z;
}
void OPPROTO op_eval_bcs (void)
{
T0 = (env->psr & PSR_CARRY);
}
void OPPROTO op_eval_bvs (void)
{
T0 = (env->psr & PSR_OVF);
}
void OPPROTO op_eval_bneg (void)
{
T0 = (env->psr & PSR_NEG);
}
void OPPROTO op_eval_bne (void)
{
T0 = !(env->psr & PSR_ZERO);
}
void OPPROTO op_eval_bg (void)
{
GET_FLAGS;
T0 = !(Z | (N^V));
}
/*XXX: This seems to be documented wrong in the SPARC V8 Manual
The manual states: !(N^V)
but I assume Z | !(N^V) to be correct */
void OPPROTO op_eval_bge (void)
{
GET_FLAGS;
T0 = Z | !(N^V);
}
void OPPROTO op_eval_bgu (void)
{
GET_FLAGS;
T0 = !(C | Z);
}
void OPPROTO op_eval_bcc (void)
{
T0 = !(env->psr & PSR_CARRY);
}
void OPPROTO op_eval_bpos (void)
{
T0 = !(env->psr & PSR_NEG);
}
void OPPROTO op_eval_bvc (void)
{
T0 = !(env->psr & PSR_OVF);
}
void OPPROTO op_jmp_im (void)
{
env->pc = PARAM1;
}
void OPPROTO op_call (void)
{
regwptr[7] = PARAM1-4;
env->pc = PARAM1+PARAM2;
}
void OPPROTO op_jmpl (void)
{
env->npc = T0;
}
void OPPROTO op_generic_jmp_1 (void)
{
T1 = PARAM1;
env->pc = PARAM1+PARAM2;
}
void OPPROTO op_generic_jmp_2 (void)
{
T1 = PARAM1;
env->pc = env->npc;
}
unsigned long old_T0;
void OPPROTO op_save_T0 (void)
{
old_T0 = T0;
}
void OPPROTO op_restore_T0 (void)
{
T0 = old_T0;
}
void OPPROTO op_generic_branch (void)
{
if (T0)
JUMP_TB (__func__, PARAM1, 0, PARAM2);
else
JUMP_TB (__func__, PARAM1, 1, PARAM3);
FORCE_RET ();
}
void OPPROTO op_generic_branch_a (void)
{
if (T0)
env->npc = PARAM3;
else
JUMP_TB (__func__, PARAM1, 0, PARAM2);
FORCE_RET ();
}
void OPPROTO op_noop (void)
{
}

View File

@ -0,0 +1,48 @@
/*
* SPARC micro operations (templates for various register related
* operations)
*
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
void OPPROTO glue(op_movl_T0_, REGNAME)(void)
{
T0 = REG;
}
void OPPROTO glue(op_movl_T1_, REGNAME)(void)
{
T1 = REG;
}
void OPPROTO glue(op_movl_T2_, REGNAME)(void)
{
T2 = REG;
}
void OPPROTO glue(glue(op_movl_, REGNAME), _T0)(void)
{
REG = T0;
}
void OPPROTO glue(glue(op_movl_, REGNAME), _T1)(void)
{
REG = T1;
}
#undef REG
#undef REGNAME

744
target-sparc/translate.c Normal file
View File

@ -0,0 +1,744 @@
/*
SPARC translation
Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
SPARC has two pitfalls: Delay slots and (a)nullification.
This is currently solved as follows:
'call' instructions simply execute the delay slot before the actual
control transfer instructions.
'jmpl' instructions execute calculate the destination, then execute
the delay slot and then do the control transfer.
(conditional) branch instructions are the most difficult ones, as the
delay slot may be nullified (ie. not executed). This happens when a
conditional branch is not executed (thus no control transfer happens)
and the 'anull' bit in the branch instruction opcode is set. This is
currently solved by doing a jump after the delay slot instruction.
There is also one big (currently unsolved) bug in the branch code:
If a delay slot modifies the condition codes then the new condition
codes, instead of the old ones will be used.
TODO-list:
FPU-Instructions
Coprocessor-Instructions
Fix above bug
Check signedness issues
Privileged instructions
Register window overflow/underflow check
Optimize synthetic instructions
Optional alignment and privileged instruction check
-- TMO, 09/03/03
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "cpu.h"
#include "exec-all.h"
#include "disas.h"
#define DEBUG_DISAS
typedef struct DisasContext {
uint8_t *pc;
uint8_t *npc;
void (*branch) (struct DisasContext *, uint32_t, uint32_t);
unsigned int delay_slot:2;
uint32_t insn;
uint32_t target;
int is_br;
struct TranslationBlock *tb;
} DisasContext;
static uint16_t *gen_opc_ptr;
static uint32_t *gen_opparam_ptr;
extern FILE *logfile;
extern int loglevel;
enum {
#define DEF(s,n,copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
NB_OPS
};
#include "gen-op.h"
#define GET_FIELD(X, FROM, TO) \
((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
#define IS_IMM (insn & (1<<13))
static void disas_sparc_insn (DisasContext *dc);
typedef void (GenOpFunc)(void);
typedef void (GenOpFunc1)(long);
typedef void (GenOpFunc2)(long, long);
typedef void (GenOpFunc3)(long, long, long);
static GenOpFunc *gen_op_movl_TN_reg[2][32] = {
{
gen_op_movl_g0_T0,
gen_op_movl_g1_T0,
gen_op_movl_g2_T0,
gen_op_movl_g3_T0,
gen_op_movl_g4_T0,
gen_op_movl_g5_T0,
gen_op_movl_g6_T0,
gen_op_movl_g7_T0,
gen_op_movl_o0_T0,
gen_op_movl_o1_T0,
gen_op_movl_o2_T0,
gen_op_movl_o3_T0,
gen_op_movl_o4_T0,
gen_op_movl_o5_T0,
gen_op_movl_o6_T0,
gen_op_movl_o7_T0,
gen_op_movl_l0_T0,
gen_op_movl_l1_T0,
gen_op_movl_l2_T0,
gen_op_movl_l3_T0,
gen_op_movl_l4_T0,
gen_op_movl_l5_T0,
gen_op_movl_l6_T0,
gen_op_movl_l7_T0,
gen_op_movl_i0_T0,
gen_op_movl_i1_T0,
gen_op_movl_i2_T0,
gen_op_movl_i3_T0,
gen_op_movl_i4_T0,
gen_op_movl_i5_T0,
gen_op_movl_i6_T0,
gen_op_movl_i7_T0,
},
{
gen_op_movl_g0_T1,
gen_op_movl_g1_T1,
gen_op_movl_g2_T1,
gen_op_movl_g3_T1,
gen_op_movl_g4_T1,
gen_op_movl_g5_T1,
gen_op_movl_g6_T1,
gen_op_movl_g7_T1,
gen_op_movl_o0_T1,
gen_op_movl_o1_T1,
gen_op_movl_o2_T1,
gen_op_movl_o3_T1,
gen_op_movl_o4_T1,
gen_op_movl_o5_T1,
gen_op_movl_o6_T1,
gen_op_movl_o7_T1,
gen_op_movl_l0_T1,
gen_op_movl_l1_T1,
gen_op_movl_l2_T1,
gen_op_movl_l3_T1,
gen_op_movl_l4_T1,
gen_op_movl_l5_T1,
gen_op_movl_l6_T1,
gen_op_movl_l7_T1,
gen_op_movl_i0_T1,
gen_op_movl_i1_T1,
gen_op_movl_i2_T1,
gen_op_movl_i3_T1,
gen_op_movl_i4_T1,
gen_op_movl_i5_T1,
gen_op_movl_i6_T1,
gen_op_movl_i7_T1,
}
};
static GenOpFunc *gen_op_movl_reg_TN[3][32] = {
{
gen_op_movl_T0_g0,
gen_op_movl_T0_g1,
gen_op_movl_T0_g2,
gen_op_movl_T0_g3,
gen_op_movl_T0_g4,
gen_op_movl_T0_g5,
gen_op_movl_T0_g6,
gen_op_movl_T0_g7,
gen_op_movl_T0_o0,
gen_op_movl_T0_o1,
gen_op_movl_T0_o2,
gen_op_movl_T0_o3,
gen_op_movl_T0_o4,
gen_op_movl_T0_o5,
gen_op_movl_T0_o6,
gen_op_movl_T0_o7,
gen_op_movl_T0_l0,
gen_op_movl_T0_l1,
gen_op_movl_T0_l2,
gen_op_movl_T0_l3,
gen_op_movl_T0_l4,
gen_op_movl_T0_l5,
gen_op_movl_T0_l6,
gen_op_movl_T0_l7,
gen_op_movl_T0_i0,
gen_op_movl_T0_i1,
gen_op_movl_T0_i2,
gen_op_movl_T0_i3,
gen_op_movl_T0_i4,
gen_op_movl_T0_i5,
gen_op_movl_T0_i6,
gen_op_movl_T0_i7,
},
{
gen_op_movl_T1_g0,
gen_op_movl_T1_g1,
gen_op_movl_T1_g2,
gen_op_movl_T1_g3,
gen_op_movl_T1_g4,
gen_op_movl_T1_g5,
gen_op_movl_T1_g6,
gen_op_movl_T1_g7,
gen_op_movl_T1_o0,
gen_op_movl_T1_o1,
gen_op_movl_T1_o2,
gen_op_movl_T1_o3,
gen_op_movl_T1_o4,
gen_op_movl_T1_o5,
gen_op_movl_T1_o6,
gen_op_movl_T1_o7,
gen_op_movl_T1_l0,
gen_op_movl_T1_l1,
gen_op_movl_T1_l2,
gen_op_movl_T1_l3,
gen_op_movl_T1_l4,
gen_op_movl_T1_l5,
gen_op_movl_T1_l6,
gen_op_movl_T1_l7,
gen_op_movl_T1_i0,
gen_op_movl_T1_i1,
gen_op_movl_T1_i2,
gen_op_movl_T1_i3,
gen_op_movl_T1_i4,
gen_op_movl_T1_i5,
gen_op_movl_T1_i6,
gen_op_movl_T1_i7,
},
{
gen_op_movl_T2_g0,
gen_op_movl_T2_g1,
gen_op_movl_T2_g2,
gen_op_movl_T2_g3,
gen_op_movl_T2_g4,
gen_op_movl_T2_g5,
gen_op_movl_T2_g6,
gen_op_movl_T2_g7,
gen_op_movl_T2_o0,
gen_op_movl_T2_o1,
gen_op_movl_T2_o2,
gen_op_movl_T2_o3,
gen_op_movl_T2_o4,
gen_op_movl_T2_o5,
gen_op_movl_T2_o6,
gen_op_movl_T2_o7,
gen_op_movl_T2_l0,
gen_op_movl_T2_l1,
gen_op_movl_T2_l2,
gen_op_movl_T2_l3,
gen_op_movl_T2_l4,
gen_op_movl_T2_l5,
gen_op_movl_T2_l6,
gen_op_movl_T2_l7,
gen_op_movl_T2_i0,
gen_op_movl_T2_i1,
gen_op_movl_T2_i2,
gen_op_movl_T2_i3,
gen_op_movl_T2_i4,
gen_op_movl_T2_i5,
gen_op_movl_T2_i6,
gen_op_movl_T2_i7,
}
};
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
gen_op_movl_T0_im,
gen_op_movl_T1_im,
gen_op_movl_T2_im
};
static inline void gen_movl_imm_TN (int reg, int imm)
{
gen_op_movl_TN_im[reg](imm);
}
static inline void gen_movl_imm_T1 (int val)
{
gen_movl_imm_TN (1, val);
}
static inline void gen_movl_imm_T0 (int val)
{
gen_movl_imm_TN (0, val);
}
static inline void gen_movl_reg_TN (int reg, int t)
{
if (reg) gen_op_movl_reg_TN[t][reg]();
else gen_movl_imm_TN (t, 0);
}
static inline void gen_movl_reg_T0 (int reg)
{
gen_movl_reg_TN (reg, 0);
}
static inline void gen_movl_reg_T1 (int reg)
{
gen_movl_reg_TN (reg, 1);
}
static inline void gen_movl_reg_T2 (int reg)
{
gen_movl_reg_TN (reg, 2);
}
static inline void gen_movl_TN_reg (int reg, int t)
{
if (reg) gen_op_movl_TN_reg[t][reg]();
}
static inline void gen_movl_T0_reg (int reg)
{
gen_movl_TN_reg (reg, 0);
}
static inline void gen_movl_T1_reg (int reg)
{
gen_movl_TN_reg (reg, 1);
}
static void do_branch (DisasContext *dc, uint32_t target, uint32_t insn)
{
unsigned int cond = GET_FIELD (insn, 3, 6), a = (insn & (1<<29)), ib = 0;
target += (uint32_t) dc->pc-4;
if (!a) disas_sparc_insn (dc);
switch (cond) {
case 0x0: gen_op_movl_T0_0 (); break;
case 0x1: gen_op_eval_be (); break;
case 0x2: gen_op_eval_ble (); break;
case 0x3: gen_op_eval_bl (); break;
case 0x4: gen_op_eval_bleu (); break;
case 0x5: gen_op_eval_bcs (); break;
case 0x6: gen_op_eval_bneg (); break;
case 0x7: gen_op_eval_bvs (); break;
case 0x8: gen_op_movl_T0_1 (); break;
case 0x9: gen_op_eval_bne (); break;
case 0xa: gen_op_eval_bg (); break;
case 0xb: gen_op_eval_bge (); break;
case 0xc: gen_op_eval_bgu (); break;
case 0xd: gen_op_eval_bcc (); break;
case 0xe: gen_op_eval_bpos (); break;
case 0xf: gen_op_eval_bvc (); break;
}
if (a && ((cond|0x8) != 0x8)) {
gen_op_generic_branch_a ((uint32_t) dc->tb,
(uint32_t) dc->pc+4, target);
disas_sparc_insn (dc);
ib = 1;
}
else
if (cond && !a) {
gen_op_generic_branch ((uint32_t) dc->tb, (uint32_t) target,
(uint32_t) dc->pc);
ib = 1;
}
if (ib) dc->is_br = DISAS_JUMP;
}
/* target == 0x1 means CALL- else JMPL-instruction */
static void do_jump (DisasContext *dc, uint32_t target, uint32_t rd)
{
uint32_t orig_pc = (uint32_t) dc->pc-8;
if (target != 0x1)
gen_op_generic_jmp_1 (orig_pc, target);
else
gen_op_generic_jmp_2 (orig_pc);
gen_movl_T1_reg (rd);
dc->is_br = DISAS_JUMP;
gen_op_movl_T0_0 ();
}
#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), b-a)
static int
sign_extend (x, len)
int x, len;
{
int signbit = (1 << (len - 1));
int mask = (signbit << 1) - 1;
return ((x & mask) ^ signbit) - signbit;
}
static void disas_sparc_insn (DisasContext *dc)
{
unsigned int insn, opc, rs1, rs2, rd;
if (dc->delay_slot == 1) {
insn = dc->insn;
} else {
if (dc->delay_slot) dc->delay_slot--;
insn = htonl (*(unsigned int *) (dc->pc));
dc->pc += 4;
}
opc = GET_FIELD (insn, 0, 1);
rd = GET_FIELD (insn, 2, 6);
switch (opc) {
case 0: /* branches/sethi */
{
unsigned int xop = GET_FIELD (insn, 7, 9);
int target;
target = GET_FIELD (insn, 10, 31);
switch (xop) {
case 0x0: case 0x1: /* UNIMPL */
printf ("UNIMPLEMENTED: %p\n", dc->pc-4);
exit (23);
break;
case 0x2: /* BN+x */
{
target <<= 2;
target = sign_extend (target, 22);
do_branch (dc, target, insn);
break;
}
case 0x3: /* FBN+x */
break;
case 0x4: /* SETHI */
gen_movl_imm_T0 (target<<10);
gen_movl_T0_reg (rd);
break;
case 0x5: /*CBN+x*/
break;
}
break;
}
case 1: /*CALL*/
{
unsigned int target = GET_FIELDs (insn, 2, 31) << 2;
if (dc->delay_slot) {
do_jump (dc, target, 15);
dc->delay_slot = 0;
} else {
dc->insn = insn;
dc->delay_slot = 2;
}
break;
}
case 2: /* FPU & Logical Operations */
{
unsigned int xop = GET_FIELD (insn, 7, 12);
if (xop == 58) { /* generate trap */
dc->is_br = DISAS_JUMP;
gen_op_jmp_im ((uint32_t) dc->pc);
if (IS_IMM) gen_op_trap (GET_FIELD (insn, 25, 31));
/* else XXX*/
gen_op_movl_T0_0 ();
break;
}
if (xop == 0x34 || xop == 0x35) { /* FPU Operations */
exit (33);
}
rs1 = GET_FIELD (insn, 13, 17);
gen_movl_reg_T0 (rs1);
if (IS_IMM) { /* immediate */
rs2 = GET_FIELDs (insn, 20, 31);
gen_movl_imm_T1 (rs2);
} else { /* register */
rs2 = GET_FIELD (insn, 27, 31);
gen_movl_reg_T1 (rs2);
}
if (xop < 0x20) {
switch (xop &~ 0x10) {
case 0x0:
gen_op_add_T1_T0 ();
break;
case 0x1:
gen_op_and_T1_T0 ();
break;
case 0x2:
gen_op_or_T1_T0 ();
break;
case 0x3:
gen_op_xor_T1_T0 ();
break;
case 0x4:
gen_op_sub_T1_T0 ();
break;
case 0x5:
gen_op_andn_T1_T0 ();
break;
case 0x6:
gen_op_orn_T1_T0 ();
break;
case 0x7:
gen_op_xnor_T1_T0 ();
break;
case 0x8:
gen_op_addx_T1_T0 ();
break;
case 0xa:
gen_op_umul_T1_T0 ();
break;
case 0xb:
gen_op_smul_T1_T0 ();
break;
case 0xc:
gen_op_subx_T1_T0 ();
break;
case 0xe:
gen_op_udiv_T1_T0 ();
break;
case 0xf:
gen_op_sdiv_T1_T0 ();
break;
default:
exit (17);
break;
}
gen_movl_T0_reg (rd);
if (xop & 0x10) {
gen_op_set_flags ();
}
} else {
switch (xop) {
case 0x25: /* SLL */
gen_op_sll ();
break;
case 0x26:
gen_op_srl ();
break;
case 0x27:
gen_op_sra ();
break;
case 0x28: case 0x30:
{
unsigned int rdi = GET_FIELD (insn, 13, 17);
if (!rdi) (xop==0x28?gen_op_rdy ():gen_op_wry());
/* else gen_op_su_trap (); */
break;
}
/* Problem with jmpl: if restore is executed in the delay
slot, then the wrong registers are beeing used */
case 0x38: /* jmpl */
{
if (dc->delay_slot) {
gen_op_add_T1_T0 ();
do_jump (dc, 1, rd);
dc->delay_slot = 0;
} else {
gen_op_add_T1_T0 ();
gen_op_jmpl ();
dc->insn = insn;
dc->delay_slot = 2;
}
break;
}
case 0x3c: /* save */
gen_op_add_T1_T0 ();
gen_op_save ();
gen_movl_T0_reg (rd);
break;
case 0x3d: /* restore */
gen_op_add_T1_T0 ();
gen_op_restore ();
gen_movl_T0_reg (rd);
break;
}
}
break;
}
case 3: /* load/store instructions */
{
unsigned int xop = GET_FIELD (insn, 7, 12);
rs1 = GET_FIELD (insn, 13, 17);
gen_movl_reg_T0 (rs1);
if (IS_IMM) { /* immediate */
rs2 = GET_FIELDs (insn, 20, 31);
gen_movl_imm_T1 (rs2);
} else { /* register */
rs2 = GET_FIELD (insn, 27, 31);
gen_movl_reg_T1 (rs2);
}
gen_op_add_T1_T0 ();
if (xop < 4 || xop > 7) {
switch (xop) {
case 0x0: /* load word */
gen_op_ld ();
break;
case 0x1: /* load unsigned byte */
gen_op_ldub ();
break;
case 0x2: /* load unsigned halfword */
gen_op_lduh ();
break;
case 0x3: /* load double word */
gen_op_ldd ();
gen_movl_T0_reg (rd+1);
break;
case 0x9: /* load signed byte */
gen_op_ldsb ();
break;
case 0xa: /* load signed halfword */
gen_op_ldsh ();
break;
case 0xd: /* ldstub -- XXX: should be atomically */
gen_op_ldstub ();
break;
case 0x0f: /* swap register with memory. Also atomically */
gen_op_swap ();
break;
}
gen_movl_T1_reg (rd);
} else if (xop < 8) {
gen_movl_reg_T1 (rd);
switch (xop) {
case 0x4:
gen_op_st ();
break;
case 0x5:
gen_op_stb ();
break;
case 0x6:
gen_op_sth ();
break;
case 0x7:
gen_op_st ();
gen_movl_reg_T1 (rd+1);
gen_op_st ();
break;
}
}
}
}
}
static inline int gen_intermediate_code_internal (TranslationBlock *tb, int spc)
{
uint8_t *pc_start = (uint8_t *) tb->pc;
uint16_t *gen_opc_end;
DisasContext dc;
memset (&dc, 0, sizeof (dc));
if (spc) {
printf ("SearchPC not yet supported\n");
exit (0);
}
dc.tb = tb;
dc.pc = pc_start;
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
do {
disas_sparc_insn (&dc);
} while (!dc.is_br && (gen_opc_ptr < gen_opc_end) &&
(dc.pc - pc_start) < (TARGET_PAGE_SIZE - 32));
switch (dc.is_br) {
case DISAS_JUMP:
case DISAS_TB_JUMP:
gen_op_exit_tb ();
break;
}
*gen_opc_ptr = INDEX_op_end;
#ifdef DEBUG_DISAS
if (loglevel) {
fprintf (logfile, "--------------\n");
fprintf (logfile, "IN: %s\n", lookup_symbol (pc_start));
disas(logfile, pc_start, dc.pc - pc_start, 0, 0);
fprintf(logfile, "\n");
fprintf(logfile, "OP:\n");
dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n");
}
#endif
return 0;
}
int gen_intermediate_code (CPUSPARCState *env, TranslationBlock *tb)
{
return gen_intermediate_code_internal(tb, 0);
}
int gen_intermediate_code_pc (CPUSPARCState *env, TranslationBlock *tb)
{
return gen_intermediate_code_internal(tb, 1);
}
void *mycpu;
CPUSPARCState *cpu_sparc_init (void)
{
CPUSPARCState *env;
cpu_exec_init ();
if (!(env = malloc (sizeof(CPUSPARCState))))
return (NULL);
memset (env, 0, sizeof (*env));
if (!(env->regwptr = malloc (0x2000)))
return (NULL);
memset (env->regwptr, 0, 0x2000);
env->regwptr += 127;
env->user_mode_only = 1;
mycpu = env;
return (env);
}
#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
void cpu_sparc_dump_state (CPUSPARCState *env, FILE *f, int flags)
{
int i, x;
fprintf (f, "@PC: %p\n", (void *) env->pc);
fprintf (f, "General Registers:\n");
for (i=0;i<4;i++)
fprintf (f, "%%g%c: %%%08x\t", i+'0', env->gregs[i]);
fprintf (f, "\n");
for (;i<8;i++)
fprintf (f, "%%g%c: %%%08x\t", i+'0', env->gregs[i]);
fprintf (f, "\nCurrent Register Window:\n");
for (x=0;x<3;x++) {
for (i=0;i<4;i++)
fprintf (f, "%%%c%d: %%%08x\t", (x==0?'o':(x==1?'l':'i')), i, env->regwptr[i+x*8]);
fprintf (f, "\n");
for (;i<8;i++)
fprintf (f, "%%%c%d: %%%08x\t", (x==0?'o':x==1?'l':'i'), i, env->regwptr[i+x*8]);
fprintf (f, "\n");
}
fprintf (f, "PSR: %x -> %c%c%c%c\n", env->psr,
GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'));
}