Commit fdf9b3e8 authored by bellard's avatar bellard
Browse files

sh4 target (Samuel Tardieu)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1861 c046a42c-6fe2-441c-8c8c-71466251a162
parent 66a93e0f
......@@ -225,6 +225,10 @@ ifeq ($(TARGET_BASE_ARCH), arm)
LIBOBJS+= op_helper.o helper.o
endif
ifeq ($(TARGET_BASE_ARCH), sh4)
LIBOBJS+= op_helper.o helper.o
endif
# NOTE: the disassembler code is only needed for debugging
LIBOBJS+=disas.o
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
......@@ -254,6 +258,9 @@ endif
ifeq ($(findstring m68k, $(TARGET_ARCH) $(ARCH)),m68k)
LIBOBJS+=m68k-dis.o
endif
ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4)
LIBOBJS+=sh4-dis.o
endif
ifdef CONFIG_GDBSTUB
OBJS+=gdbstub.o
......@@ -341,6 +348,9 @@ ifeq ($(TARGET_BASE_ARCH), arm)
VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
VL_OBJS+= pl011.o pl050.o pl080.o pl110.o pl190.o
endif
ifeq ($(TARGET_BASE_ARCH), sh4)
VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
endif
ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o
endif
......@@ -462,6 +472,16 @@ endif
loader.o: loader.c elf_ops.h
ifeq ($(TARGET_ARCH), sh4)
op.o: op.c op_mem.c cpu.h
op_helper.o: op_helper.c exec.h cpu.h
helper.o: helper.c exec.h cpu.h
sh7750.o: sh7750.c sh7750.h sh7750_regs.h sh7750_regnames.h cpu.h
shix.o: shix.c sh7750.h sh7750_regs.h sh7750_regnames.h tc58128.h
sh7750_regnames.o: sh7750_regnames.c sh7750_regnames.h sh7750_regs.h
tc58128.o: tc58128.c tc58128.h sh7750.h
endif
%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
......
......@@ -359,7 +359,7 @@ if test -z "$target_list" ; then
fi
# the following are Linux specific
if [ "$user" = "yes" ] ; then
target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user $target_list"
target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user sh4-user $target_list"
fi
else
target_list=`echo "$target_list" | sed -e 's/,/ /g'`
......@@ -807,6 +807,10 @@ elif test "$target_cpu" = "mips" -o "$target_cpu" = "mipsel" ; then
echo "TARGET_ARCH=mips" >> $config_mak
echo "#define TARGET_ARCH \"mips\"" >> $config_h
echo "#define TARGET_MIPS 1" >> $config_h
elif test "$target_cpu" = "sh4" ; then
echo "TARGET_ARCH=sh4" >> $config_mak
echo "#define TARGET_ARCH \"sh4\"" >> $config_h
echo "#define TARGET_SH4 1" >> $config_h
else
echo "Unsupported target CPU"
exit 1
......
......@@ -732,6 +732,13 @@ void page_unprotect_range(target_ulong data, target_ulong data_size);
#define cpu_gen_code cpu_mips_gen_code
#define cpu_signal_handler cpu_mips_signal_handler
#elif defined(TARGET_SH4)
#define CPUState CPUSH4State
#define cpu_init cpu_sh4_init
#define cpu_exec cpu_sh4_exec
#define cpu_gen_code cpu_sh4_gen_code
#define cpu_signal_handler cpu_sh4_signal_handler
#else
#error unsupported target CPU
......
......@@ -190,6 +190,10 @@ static inline TranslationBlock *tb_find_fast(void)
flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
cs_base = 0;
pc = env->PC;
#elif defined(TARGET_SH4)
flags = env->sr & (SR_MD | SR_RB);
cs_base = 0; /* XXXXX */
pc = env->pc;
#else
#error unsupported CPU
#endif
......@@ -363,6 +367,8 @@ int cpu_exec(CPUState *env1)
#endif
#elif defined(TARGET_PPC)
#elif defined(TARGET_MIPS)
#elif defined(TARGET_SH4)
/* XXXXX */
#else
#error unsupported target CPU
#endif
......@@ -407,6 +413,8 @@ int cpu_exec(CPUState *env1)
do_interrupt(env->exception_index);
#elif defined(TARGET_ARM)
do_interrupt(env);
#elif defined(TARGET_SH4)
do_interrupt(env);
#endif
}
env->exception_index = -1;
......@@ -550,6 +558,8 @@ int cpu_exec(CPUState *env1)
env->exception_index = EXCP_IRQ;
do_interrupt(env);
}
#elif defined(TARGET_SH4)
/* XXXXX */
#endif
if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
......@@ -608,6 +618,8 @@ int cpu_exec(CPUState *env1)
cpu_dump_state(env, logfile, fprintf, 0);
#elif defined(TARGET_MIPS)
cpu_dump_state(env, logfile, fprintf, 0);
#elif defined(TARGET_SH4)
cpu_dump_state(env, logfile, fprintf, 0);
#else
#error unsupported target CPU
#endif
......@@ -817,6 +829,8 @@ int cpu_exec(CPUState *env1)
#endif
#elif defined(TARGET_PPC)
#elif defined(TARGET_MIPS)
#elif defined(TARGET_SH4)
/* XXXXX */
#else
#error unsupported target CPU
#endif
......@@ -1121,6 +1135,55 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
return 1;
}
#elif defined (TARGET_SH4)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
int is_write, sigset_t *old_set,
void *puc)
{
TranslationBlock *tb;
int ret;
if (cpu_single_env)
env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
pc, address, is_write, *(unsigned long *)old_set);
#endif
/* XXX: locking issue */
if (is_write && page_unprotect(h2g(address), pc, puc)) {
return 1;
}
/* see if it is an MMU fault */
ret = cpu_sh4_handle_mmu_fault(env, address, is_write, 1, 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
return 1; /* the MMU fault was handled without causing real CPU fault */
/* now we have a real cpu fault */
tb = tb_find_pc(pc);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
cpu_restore_state(tb, env, pc, puc);
}
if (ret == 1) {
#if 0
printf("PF exception: NIP=0x%08x error=0x%x %p\n",
env->nip, env->error_code, tb);
#endif
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
// do_raise_exception_err(env->exception_index, env->error_code);
} else {
/* activate soft MMU for this block */
cpu_resume_from_signal(env, puc);
}
/* never comes here */
return 1;
}
#else
#error unsupported target CPU
#endif
......
......@@ -163,10 +163,23 @@ enum bfd_architecture
#define bfd_mach_z8002 2
bfd_arch_h8500, /* Hitachi H8/500 */
bfd_arch_sh, /* Hitachi SH */
#define bfd_mach_sh 0
#define bfd_mach_sh 1
#define bfd_mach_sh2 0x20
#define bfd_mach_sh_dsp 0x2d
#define bfd_mach_sh2a 0x2a
#define bfd_mach_sh2a_nofpu 0x2b
#define bfd_mach_sh2e 0x2e
#define bfd_mach_sh3 0x30
#define bfd_mach_sh3_nommu 0x31
#define bfd_mach_sh3_dsp 0x3d
#define bfd_mach_sh3e 0x3e
#define bfd_mach_sh4 0x40
#define bfd_mach_sh4_nofpu 0x41
#define bfd_mach_sh4_nommu_nofpu 0x42
#define bfd_mach_sh4a 0x4a
#define bfd_mach_sh4a_nofpu 0x4b
#define bfd_mach_sh4al_dsp 0x4d
#define bfd_mach_sh5 0x50
bfd_arch_alpha, /* Dec Alpha */
bfd_arch_arm, /* Advanced Risc Machines ARM */
#define bfd_mach_arm_2 1
......
......@@ -73,7 +73,7 @@ generic_print_address (addr, info)
bfd_vma addr;
struct disassemble_info *info;
{
(*info->fprintf_func) (info->stream, "0x%llx", addr);
(*info->fprintf_func) (info->stream, "0x%llx", addr);
}
/* Just return the given address. */
......@@ -194,6 +194,9 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
#endif
#elif defined(TARGET_M68K)
print_insn = print_insn_m68k;
#elif defined(TARGET_SH4)
disasm_info.mach = bfd_mach_sh4;
print_insn = print_insn_sh;
#else
fprintf(out, "0x" TARGET_FMT_lx
": Asm output not supported on this arch\n", code);
......
......@@ -560,6 +560,8 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
is_user = (env->psrs == 0);
#elif defined (TARGET_ARM)
is_user = ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR);
#elif defined (TARGET_SH4)
is_user = ((env->sr & SR_MD) == 0);
#else
#error unimplemented CPU
#endif
......
......@@ -487,6 +487,45 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
env->PC = tswapl(*(uint32_t *)ptr);
ptr += 4;
}
#elif defined (TARGET_SH4)
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
uint32_t *ptr = (uint32_t *)mem_buf;
int i;
#define SAVE(x) *ptr++=tswapl(x)
for (i = 0; i < 16; i++) SAVE(env->gregs[i]);
SAVE (env->pc);
SAVE (env->pr);
SAVE (env->gbr);
SAVE (env->vbr);
SAVE (env->mach);
SAVE (env->macl);
SAVE (env->sr);
SAVE (0); /* TICKS */
SAVE (0); /* STALLS */
SAVE (0); /* CYCLES */
SAVE (0); /* INSTS */
SAVE (0); /* PLR */
return ((uint8_t *)ptr - mem_buf);
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
uint32_t *ptr = (uint32_t *)mem_buf;
int i;
#define LOAD(x) (x)=*ptr++;
for (i = 0; i < 16; i++) LOAD(env->gregs[i]);
LOAD (env->pc);
LOAD (env->pr);
LOAD (env->gbr);
LOAD (env->vbr);
LOAD (env->mach);
LOAD (env->macl);
LOAD (env->sr);
}
#else
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
......@@ -531,6 +570,8 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
env->npc = addr + 4;
#elif defined (TARGET_ARM)
env->regs[15] = addr;
#elif defined (TARGET_SH4)
env->pc = addr;
#endif
}
#ifdef CONFIG_USER_ONLY
......@@ -551,6 +592,8 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
env->npc = addr + 4;
#elif defined (TARGET_ARM)
env->regs[15] = addr;
#elif defined (TARGET_SH4)
env->pc = addr;
#endif
}
cpu_single_step(env, 1);
......
......@@ -274,6 +274,30 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#endif /* TARGET_MIPS */
#ifdef TARGET_SH4
#define ELF_START_MMAP 0x80000000
#define elf_check_arch(x) ( (x) == EM_SH )
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_SH
#define ELF_PLAT_INIT(_r) /* XXXXX */
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
/* Check other registers XXXXX */
regs->pc = infop->entry;
regs->regs[15] = infop->start_stack - 16 * 4;
}
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
#endif
#ifndef ELF_PLATFORM
#define ELF_PLATFORM (NULL)
#endif
......
......@@ -1387,6 +1387,38 @@ void cpu_loop(CPUMIPSState *env)
}
#endif
#ifdef TARGET_SH4
void cpu_loop (CPUState *env)
{
int trapnr, ret;
// target_siginfo_t info;
while (1) {
trapnr = cpu_sh4_exec (env);
switch (trapnr) {
case 0x160:
ret = do_syscall(env,
env->gregs[0x13],
env->gregs[0x14],
env->gregs[0x15],
env->gregs[0x16],
env->gregs[0x17],
env->gregs[0x10],
0);
env->gregs[0x10] = ret;
env->pc += 2;
break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
exit (1);
}
process_pending_signals (env);
}
}
#endif
void usage(void)
{
printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2005 Fabrice Bellard\n"
......@@ -1665,6 +1697,15 @@ int main(int argc, char **argv)
}
env->PC = regs->cp0_epc;
}
#elif defined(TARGET_SH4)
{
int i;
for(i = 0; i < 16; i++) {
env->gregs[i] = regs->regs[i];
}
env->pc = regs->pc;
}
#else
#error unsupported target CPU
#endif
......
struct target_pt_regs {
unsigned long regs[16];
unsigned long pc;
unsigned long pr;
unsigned long sr;
unsigned long gbr;
unsigned long mach;
unsigned long macl;
long tra;
};
#define UNAME_MACHINE "sh4"
/*
* This file contains the system call numbers.
*/
#define TARGET_NR_restart_syscall 0
#define TARGET_NR_exit 1
#define TARGET_NR_fork 2
#define TARGET_NR_read 3
#define TARGET_NR_write 4
#define TARGET_NR_open 5
#define TARGET_NR_close 6
#define TARGET_NR_waitpid 7
#define TARGET_NR_creat 8
#define TARGET_NR_link 9
#define TARGET_NR_unlink 10
#define TARGET_NR_execve 11
#define TARGET_NR_chdir 12
#define TARGET_NR_time 13
#define TARGET_NR_mknod 14
#define TARGET_NR_chmod 15
#define TARGET_NR_lchown 16
#define TARGET_NR_break 17
#define TARGET_NR_oldstat 18
#define TARGET_NR_lseek 19
#define TARGET_NR_getpid 20
#define TARGET_NR_mount 21
#define TARGET_NR_umount 22
#define TARGET_NR_setuid 23
#define TARGET_NR_getuid 24
#define TARGET_NR_stime 25
#define TARGET_NR_ptrace 26
#define TARGET_NR_alarm 27
#define TARGET_NR_oldfstat 28
#define TARGET_NR_pause 29
#define TARGET_NR_utime 30
#define TARGET_NR_stty 31
#define TARGET_NR_gtty 32
#define TARGET_NR_access 33
#define TARGET_NR_nice 34
#define TARGET_NR_ftime 35
#define TARGET_NR_sync 36
#define TARGET_NR_kill 37
#define TARGET_NR_rename 38
#define TARGET_NR_mkdir 39
#define TARGET_NR_rmdir 40
#define TARGET_NR_dup 41
#define TARGET_NR_pipe 42
#define TARGET_NR_times 43
#define TARGET_NR_prof 44
#define TARGET_NR_brk 45
#define TARGET_NR_setgid 46
#define TARGET_NR_getgid 47
#define TARGET_NR_signal 48
#define TARGET_NR_geteuid 49
#define TARGET_NR_getegid 50
#define TARGET_NR_acct 51
#define TARGET_NR_umount2 52
#define TARGET_NR_lock 53
#define TARGET_NR_ioctl 54
#define TARGET_NR_fcntl 55
#define TARGET_NR_mpx 56
#define TARGET_NR_setpgid 57
#define TARGET_NR_ulimit 58
#define TARGET_NR_oldolduname 59
#define TARGET_NR_umask 60
#define TARGET_NR_chroot 61
#define TARGET_NR_ustat 62
#define TARGET_NR_dup2 63
#define TARGET_NR_getppid 64
#define TARGET_NR_getpgrp 65
#define TARGET_NR_setsid 66
#define TARGET_NR_sigaction 67
#define TARGET_NR_sgetmask 68
#define TARGET_NR_ssetmask 69
#define TARGET_NR_setreuid 70
#define TARGET_NR_setregid 71
#define TARGET_NR_sigsuspend 72
#define TARGET_NR_sigpending 73
#define TARGET_NR_sethostname 74
#define TARGET_NR_setrlimit 75
#define TARGET_NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
#define TARGET_NR_getrusage 77
#define TARGET_NR_gettimeofday 78
#define TARGET_NR_settimeofday 79
#define TARGET_NR_getgroups 80
#define TARGET_NR_setgroups 81
#define TARGET_NR_select 82
#define TARGET_NR_symlink 83
#define TARGET_NR_oldlstat 84
#define TARGET_NR_readlink 85
#define TARGET_NR_uselib 86
#define TARGET_NR_swapon 87
#define TARGET_NR_reboot 88
#define TARGET_NR_readdir 89
#define TARGET_NR_mmap 90
#define TARGET_NR_munmap 91
#define TARGET_NR_truncate 92
#define TARGET_NR_ftruncate 93
#define TARGET_NR_fchmod 94
#define TARGET_NR_fchown 95
#define TARGET_NR_getpriority 96
#define TARGET_NR_setpriority 97
#define TARGET_NR_profil 98
#define TARGET_NR_statfs 99
#define TARGET_NR_fstatfs 100
#define TARGET_NR_ioperm 101
#define TARGET_NR_socketcall 102
#define TARGET_NR_syslog 103
#define TARGET_NR_setitimer 104
#define TARGET_NR_getitimer 105
#define TARGET_NR_stat 106
#define TARGET_NR_lstat 107
#define TARGET_NR_fstat 108
#define TARGET_NR_olduname 109
#define TARGET_NR_iopl 110
#define TARGET_NR_vhangup 111
#define TARGET_NR_idle 112
#define TARGET_NR_vm86old 113
#define TARGET_NR_wait4 114
#define TARGET_NR_swapoff 115
#define TARGET_NR_sysinfo 116
#define TARGET_NR_ipc 117
#define TARGET_NR_fsync 118
#define TARGET_NR_sigreturn 119
#define TARGET_NR_clone 120
#define TARGET_NR_setdomainname 121
#define TARGET_NR_uname 122
#define TARGET_NR_modify_ldt 123
#define TARGET_NR_adjtimex 124
#define TARGET_NR_mprotect 125
#define TARGET_NR_sigprocmask 126
#define TARGET_NR_create_module 127
#define TARGET_NR_init_module 128
#define TARGET_NR_delete_module 129
#define TARGET_NR_get_kernel_syms 130
#define TARGET_NR_quotactl 131
#define TARGET_NR_getpgid 132
#define TARGET_NR_fchdir 133
#define TARGET_NR_bdflush 134
#define TARGET_NR_sysfs 135
#define TARGET_NR_personality 136
#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */
#define TARGET_NR_setfsuid 138
#define TARGET_NR_setfsgid 139
#define TARGET_NR__llseek 140
#define TARGET_NR_getdents 141
#define TARGET_NR__newselect 142
#define TARGET_NR_flock 143
#define TARGET_NR_msync 144
#define TARGET_NR_readv 145
#define TARGET_NR_writev 146
#define TARGET_NR_getsid 147
#define TARGET_NR_fdatasync 148
#define TARGET_NR__sysctl 149
#define TARGET_NR_mlock 150
#define TARGET_NR_munlock 151
#define TARGET_NR_mlockall 152
#define TARGET_NR_munlockall 153
#define TARGET_NR_sched_setparam 154
#define TARGET_NR_sched_getparam 155
#define TARGET_NR_sched_setscheduler 156
#define TARGET_NR_sched_getscheduler 157
#define TARGET_NR_sched_yield 158
#define TARGET_NR_sched_get_priority_max 159
#define TARGET_NR_sched_get_priority_min 160
#define TARGET_NR_sched_rr_get_interval 161
#define TARGET_NR_nanosleep 162
#define TARGET_NR_mremap 163
#define TARGET_NR_setresuid 164
#define TARGET_NR_getresuid 165
#define TARGET_NR_vm86 166
#define TARGET_NR_query_module 167
#define TARGET_NR_poll 168
#define TARGET_NR_nfsservctl 169
#define TARGET_NR_setresgid 170
#define TARGET_NR_getresgid 171
#define TARGET_NR_prctl 172
#define TARGET_NR_rt_sigreturn 173
#define TARGET_NR_rt_sigaction 174
#define TARGET_NR_rt_sigprocmask 175
#define TARGET_NR_rt_sigpending 176
#define TARGET_NR_rt_sigtimedwait 177
#define TARGET_NR_rt_sigqueueinfo 178
#define TARGET_NR_rt_sigsuspend 179
#define TARGET_NR_pread64 180
#define TARGET_NR_pwrite64 181
#define TARGET_NR_chown 182
#define TARGET_NR_getcwd 183
#define TARGET_NR_capget 184
#define TARGET_NR_capset 185
#define TARGET_NR_sigaltstack 186
#define TARGET_NR_sendfile 187
#define TARGET_NR_streams1 188 /* some people actually want it */
#define TARGET_NR_streams2 189 /* some people actually want it */
#define TARGET_NR_vfork 190
#define TARGET_NR_ugetrlimit 191 /* SuS compliant getrlimit */
#define TARGET_NR_mmap2 192
#define TARGET_NR_truncate64 193
#define TARGET_NR_ftruncate64 194
#define TARGET_NR_stat64 195
#define TARGET_NR_lstat64 196
#define TARGET_NR_fstat64 197
#define TARGET_NR_lchown32 198
#define TARGET_NR_getuid32 199
#define TARGET_NR_getgid32 200
#define TARGET_NR_geteuid32 201
#define TARGET_NR_getegid32 202
#define TARGET_NR_setreuid32 203
#define TARGET_NR_setregid32 204
#define TARGET_NR_getgroups32 205
#define TARGET_NR_setgroups32 206
#define TARGET_NR_fchown32 207
#define TARGET_NR_setresuid32 208
#define TARGET_NR_getresuid32 209
#define TARGET_NR_setresgid32 210
#define TARGET_NR_getresgid32 211
#define TARGET_NR_chown32 212
#define TARGET_NR_setuid32 213
#define TARGET_NR_setgid32 214
#define TARGET_NR_setfsuid32 215
#define TARGET_NR_setfsgid32 216
#define TARGET_NR_pivot_root 217
#define TARGET_NR_mincore 218
#define TARGET_NR_madvise 219
#define TARGET_NR_getdents64 220
#define TARGET_NR_fcntl64 221
/* 223 is unused */
#define TARGET_NR_gettid 224
#define TARGET_NR_setxattr 226