Commit 79aceca54a8f12a70e23f418ae584e85093c8907

Authored by bellard
1 parent 6a8c397d

PowerPC support (Jocelyn Mayer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@472 c046a42c-6fe2-441c-8c8c-71466251a162
linux-user/ppc/syscall.h 0 → 100644
  1 +/*
  2 + * PPC emulation for qemu: syscall definitions.
  3 + *
  4 + * Copyright (c) 2003 Jocelyn Mayer
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +
  21 +/* XXX: ABSOLUTELY BUGGY:
  22 + * for now, this is quite just a cut-and-paste from i386 target...
  23 + */
  24 +
  25 +/* default linux values for the selectors */
  26 +#define __USER_DS (1)
  27 +
  28 +struct target_pt_regs {
  29 + unsigned long gpr[32];
  30 + unsigned long nip;
  31 + unsigned long msr;
  32 + unsigned long orig_gpr3; /* Used for restarting system calls */
  33 + unsigned long ctr;
  34 + unsigned long link;
  35 + unsigned long xer;
  36 + unsigned long ccr;
  37 + unsigned long mq; /* 601 only (not used at present) */
  38 + /* Used on APUS to hold IPL value. */
  39 + unsigned long trap; /* Reason for being here */
  40 + unsigned long dar; /* Fault registers */
  41 + unsigned long dsisr;
  42 + unsigned long result; /* Result of a system call */
  43 +};
  44 +
  45 +/* ioctls */
  46 +struct target_revectored_struct {
  47 + target_ulong __map[8]; /* 256 bits */
  48 +};
  49 +
  50 +/*
  51 + * flags masks
  52 + */
  53 +
  54 +/* ipcs */
  55 +
  56 +#define TARGET_SEMOP 1
  57 +#define TARGET_SEMGET 2
  58 +#define TARGET_SEMCTL 3
  59 +#define TARGET_MSGSND 11
  60 +#define TARGET_MSGRCV 12
  61 +#define TARGET_MSGGET 13
  62 +#define TARGET_MSGCTL 14
  63 +#define TARGET_SHMAT 21
  64 +#define TARGET_SHMDT 22
  65 +#define TARGET_SHMGET 23
  66 +#define TARGET_SHMCTL 24
  67 +
  68 +struct target_msgbuf {
  69 + int mtype;
  70 + char mtext[1];
  71 +};
  72 +
  73 +struct target_ipc_kludge {
  74 + unsigned int msgp; /* Really (struct msgbuf *) */
  75 + int msgtyp;
  76 +};
  77 +
  78 +struct target_ipc_perm {
  79 + int key;
  80 + unsigned short uid;
  81 + unsigned short gid;
  82 + unsigned short cuid;
  83 + unsigned short cgid;
  84 + unsigned short mode;
  85 + unsigned short seq;
  86 +};
  87 +
  88 +struct target_msqid_ds {
  89 + struct target_ipc_perm msg_perm;
  90 + unsigned int msg_first; /* really struct target_msg* */
  91 + unsigned int msg_last; /* really struct target_msg* */
  92 + unsigned int msg_stime; /* really target_time_t */
  93 + unsigned int msg_rtime; /* really target_time_t */
  94 + unsigned int msg_ctime; /* really target_time_t */
  95 + unsigned int wwait; /* really struct wait_queue* */
  96 + unsigned int rwait; /* really struct wait_queue* */
  97 + unsigned short msg_cbytes;
  98 + unsigned short msg_qnum;
  99 + unsigned short msg_qbytes;
  100 + unsigned short msg_lspid;
  101 + unsigned short msg_lrpid;
  102 +};
  103 +
  104 +struct target_shmid_ds {
  105 + struct target_ipc_perm shm_perm;
  106 + int shm_segsz;
  107 + unsigned int shm_atime; /* really target_time_t */
  108 + unsigned int shm_dtime; /* really target_time_t */
  109 + unsigned int shm_ctime; /* really target_time_t */
  110 + unsigned short shm_cpid;
  111 + unsigned short shm_lpid;
  112 + short shm_nattch;
  113 + unsigned short shm_npages;
  114 + unsigned long *shm_pages;
  115 + void *attaches; /* really struct shm_desc * */
  116 +};
  117 +
  118 +#define TARGET_IPC_RMID 0
  119 +#define TARGET_IPC_SET 1
  120 +#define TARGET_IPC_STAT 2
  121 +
  122 +union target_semun {
  123 + int val;
  124 + unsigned int buf; /* really struct semid_ds * */
  125 + unsigned int array; /* really unsigned short * */
  126 + unsigned int __buf; /* really struct seminfo * */
  127 + unsigned int __pad; /* really void* */
  128 +};
  129 +
... ...
linux-user/ppc/syscall_nr.h 0 → 100644
  1 +/*
  2 + * This file contains the system call numbers.
  3 + */
  4 +#define TARGET_NR_restart_syscall 0
  5 +#define TARGET_NR_exit 1
  6 +#define TARGET_NR_fork 2
  7 +#define TARGET_NR_read 3
  8 +#define TARGET_NR_write 4
  9 +#define TARGET_NR_open 5
  10 +#define TARGET_NR_close 6
  11 +#define TARGET_NR_waitpid 7
  12 +#define TARGET_NR_creat 8
  13 +#define TARGET_NR_link 9
  14 +#define TARGET_NR_unlink 10
  15 +#define TARGET_NR_execve 11
  16 +#define TARGET_NR_chdir 12
  17 +#define TARGET_NR_time 13
  18 +#define TARGET_NR_mknod 14
  19 +#define TARGET_NR_chmod 15
  20 +#define TARGET_NR_lchown32 16
  21 +#define TARGET_NR_break 17
  22 +#define TARGET_NR_oldstat 18
  23 +#define TARGET_NR_lseek 19
  24 +#define TARGET_NR_getpid 20
  25 +#define TARGET_NR_mount 21
  26 +#define TARGET_NR_umount 22
  27 +#define TARGET_NR_setuid32 23
  28 +#define TARGET_NR_getuid32 24
  29 +#define TARGET_NR_stime 25
  30 +#define TARGET_NR_ptrace 26
  31 +#define TARGET_NR_alarm 27
  32 +#define TARGET_NR_oldfstat 28
  33 +#define TARGET_NR_pause 29
  34 +#define TARGET_NR_utime 30
  35 +#define TARGET_NR_stty 31
  36 +#define TARGET_NR_gtty 32
  37 +#define TARGET_NR_access 33
  38 +#define TARGET_NR_nice 34
  39 +#define TARGET_NR_ftime 35
  40 +#define TARGET_NR_sync 36
  41 +#define TARGET_NR_kill 37
  42 +#define TARGET_NR_rename 38
  43 +#define TARGET_NR_mkdir 39
  44 +#define TARGET_NR_rmdir 40
  45 +#define TARGET_NR_dup 41
  46 +#define TARGET_NR_pipe 42
  47 +#define TARGET_NR_times 43
  48 +#define TARGET_NR_prof 44
  49 +#define TARGET_NR_brk 45
  50 +#define TARGET_NR_setgid32 46
  51 +#define TARGET_NR_getgid32 47
  52 +#define TARGET_NR_signal 48
  53 +#define TARGET_NR_geteuid32 49
  54 +#define TARGET_NR_getegid32 50
  55 +#define TARGET_NR_acct 51
  56 +#define TARGET_NR_umount2 52
  57 +#define TARGET_NR_lock 53
  58 +#define TARGET_NR_ioctl 54
  59 +#define TARGET_NR_fcntl 55
  60 +#define TARGET_NR_mpx 56
  61 +#define TARGET_NR_setpgid 57
  62 +#define TARGET_NR_ulimit 58
  63 +#define TARGET_NR_oldolduname 59
  64 +#define TARGET_NR_umask 60
  65 +#define TARGET_NR_chroot 61
  66 +#define TARGET_NR_ustat 62
  67 +#define TARGET_NR_dup2 63
  68 +#define TARGET_NR_getppid 64
  69 +#define TARGET_NR_getpgrp 65
  70 +#define TARGET_NR_setsid 66
  71 +#define TARGET_NR_sigaction 67
  72 +#define TARGET_NR_sgetmask 68
  73 +#define TARGET_NR_ssetmask 69
  74 +#define TARGET_NR_setreuid32 70
  75 +#define TARGET_NR_setregid32 71
  76 +#define TARGET_NR_sigsuspend 72
  77 +#define TARGET_NR_sigpending 73
  78 +#define TARGET_NR_sethostname 74
  79 +#define TARGET_NR_setrlimit 75
  80 +#define TARGET_NR_getrlimit 76
  81 +#define TARGET_NR_getrusage 77
  82 +#define TARGET_NR_gettimeofday 78
  83 +#define TARGET_NR_settimeofday 79
  84 +#define TARGET_NR_getgroups32 80
  85 +#define TARGET_NR_setgroups32 81
  86 +#define TARGET_NR_select 82
  87 +#define TARGET_NR_symlink 83
  88 +#define TARGET_NR_oldlstat 84
  89 +#define TARGET_NR_readlink 85
  90 +#define TARGET_NR_uselib 86
  91 +#define TARGET_NR_swapon 87
  92 +#define TARGET_NR_reboot 88
  93 +#define TARGET_NR_readdir 89
  94 +#define TARGET_NR_mmap 90
  95 +#define TARGET_NR_munmap 91
  96 +#define TARGET_NR_truncate 92
  97 +#define TARGET_NR_ftruncate 93
  98 +#define TARGET_NR_fchmod 94
  99 +#define TARGET_NR_fchown32 95
  100 +#define TARGET_NR_getpriority 96
  101 +#define TARGET_NR_setpriority 97
  102 +#define TARGET_NR_profil 98
  103 +#define TARGET_NR_statfs 99
  104 +#define TARGET_NR_fstatfs 100
  105 +#define TARGET_NR_ioperm 101
  106 +#define TARGET_NR_socketcall 102
  107 +#define TARGET_NR_syslog 103
  108 +#define TARGET_NR_setitimer 104
  109 +#define TARGET_NR_getitimer 105
  110 +#define TARGET_NR_stat 106
  111 +#define TARGET_NR_lstat 107
  112 +#define TARGET_NR_fstat 108
  113 +#define TARGET_NR_olduname 109
  114 +#define TARGET_NR_iopl 110
  115 +#define TARGET_NR_vhangup 111
  116 +#define TARGET_NR_idle 112
  117 +#define TARGET_NR_vm86 113
  118 +#define TARGET_NR_wait4 114
  119 +#define TARGET_NR_swapoff 115
  120 +#define TARGET_NR_sysinfo 116
  121 +#define TARGET_NR_ipc 117
  122 +#define TARGET_NR_fsync 118
  123 +#define TARGET_NR_sigreturn 119
  124 +#define TARGET_NR_clone 120
  125 +#define TARGET_NR_setdomainname 121
  126 +#define TARGET_NR_uname 122
  127 +#define TARGET_NR_modify_ldt 123
  128 +#define TARGET_NR_adjtimex 124
  129 +#define TARGET_NR_mprotect 125
  130 +#define TARGET_NR_sigprocmask 126
  131 +#define TARGET_NR_create_module 127
  132 +#define TARGET_NR_init_module 128
  133 +#define TARGET_NR_delete_module 129
  134 +#define TARGET_NR_get_kernel_syms 130
  135 +#define TARGET_NR_quotactl 131
  136 +#define TARGET_NR_getpgid 132
  137 +#define TARGET_NR_fchdir 133
  138 +#define TARGET_NR_bdflush 134
  139 +#define TARGET_NR_sysfs 135
  140 +#define TARGET_NR_personality 136
  141 +#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */
  142 +#define TARGET_NR_setfsuid32 138
  143 +#define TARGET_NR_setfsgid32 139
  144 +#define TARGET_NR__llseek 140
  145 +#define TARGET_NR_getdents 141
  146 +#define TARGET_NR__newselect 142
  147 +#define TARGET_NR_flock 143
  148 +#define TARGET_NR_msync 144
  149 +#define TARGET_NR_readv 145
  150 +#define TARGET_NR_writev 146
  151 +#define TARGET_NR_getsid 147
  152 +#define TARGET_NR_fdatasync 148
  153 +#define TARGET_NR__sysctl 149
  154 +#define TARGET_NR_mlock 150
  155 +#define TARGET_NR_munlock 151
  156 +#define TARGET_NR_mlockall 152
  157 +#define TARGET_NR_munlockall 153
  158 +#define TARGET_NR_sched_setparam 154
  159 +#define TARGET_NR_sched_getparam 155
  160 +#define TARGET_NR_sched_setscheduler 156
  161 +#define TARGET_NR_sched_getscheduler 157
  162 +#define TARGET_NR_sched_yield 158
  163 +#define TARGET_NR_sched_get_priority_max 159
  164 +#define TARGET_NR_sched_get_priority_min 160
  165 +#define TARGET_NR_sched_rr_get_interval 161
  166 +#define TARGET_NR_nanosleep 162
  167 +#define TARGET_NR_mremap 163
  168 +#define TARGET_NR_setresuid32 164
  169 +#define TARGET_NR_getresuid32 165
  170 +#define TARGET_NR_query_module 166
  171 +#define TARGET_NR_poll 167
  172 +#define TARGET_NR_nfsservctl 168
  173 +#define TARGET_NR_setresgid32 169
  174 +#define TARGET_NR_getresgid32 170
  175 +#define TARGET_NR_prctl 171
  176 +#define TARGET_NR_rt_sigreturn 172
  177 +#define TARGET_NR_rt_sigaction 173
  178 +#define TARGET_NR_rt_sigprocmask 174
  179 +#define TARGET_NR_rt_sigpending 175
  180 +#define TARGET_NR_rt_sigtimedwait 176
  181 +#define TARGET_NR_rt_sigqueueinfo 177
  182 +#define TARGET_NR_rt_sigsuspend 178
  183 +#define TARGET_NR_pread64 179
  184 +#define TARGET_NR_pwrite64 180
  185 +#define TARGET_NR_chown32 181
  186 +#define TARGET_NR_getcwd 182
  187 +#define TARGET_NR_capget 183
  188 +#define TARGET_NR_capset 184
  189 +#define TARGET_NR_sigaltstack 185
  190 +#define TARGET_NR_sendfile 186
  191 +#define TARGET_NR_getpmsg 187 /* some people actually want streams */
  192 +#define TARGET_NR_putpmsg 188 /* some people actually want streams */
  193 +#define TARGET_NR_vfork 189
  194 +#define TARGET_NR_ugetrlimit 190 /* SuS compliant getrlimit */
  195 +#define TARGET_NR_readahead 191
  196 +#define TARGET_NR_mmap2 192
  197 +#define TARGET_NR_truncate64 193
  198 +#define TARGET_NR_ftruncate64 194
  199 +#define TARGET_NR_stat64 195
  200 +#define TARGET_NR_lstat64 196
  201 +#define TARGET_NR_fstat64 197
  202 +#define TARGET_NR_pciconfig_read 198
  203 +#define TARGET_NR_pciconfig_write 199
  204 +#define TARGET_NR_pciconfig_iobase 200
  205 +#define TARGET_NR_multiplexer 201
  206 +#define TARGET_NR_getdents64 202
  207 +#define TARGET_NR_pivot_root 203
  208 +#define TARGET_NR_fcntl64 204
  209 +#define TARGET_NR_madvise 205
  210 +#define TARGET_NR_mincore 206
  211 +#define TARGET_NR_gettid 207
  212 +#define TARGET_NR_tkill 208
  213 +#define TARGET_NR_setxattr 209
  214 +#define TARGET_NR_lsetxattr 210
  215 +#define TARGET_NR_fsetxattr 211
  216 +#define TARGET_NR_getxattr 212
  217 +#define TARGET_NR_lgetxattr 213
  218 +#define TARGET_NR_fgetxattr 214
  219 +#define TARGET_NR_listxattr 215
  220 +#define TARGET_NR_llistxattr 216
  221 +#define TARGET_NR_flistxattr 217
  222 +#define TARGET_NR_removexattr 218
  223 +#define TARGET_NR_lremovexattr 219
  224 +#define TARGET_NR_fremovexattr 220
  225 +#define TARGET_NR_futex 221
  226 +#define TARGET_NR_sched_setaffinity 222
  227 +#define TARGET_NR_sched_getaffinity 223
  228 +/* 224 currently unused */
  229 +#define TARGET_NR_tuxcall 225
  230 +#define TARGET_NR_sendfile64 226
  231 +#define TARGET_NR_io_setup 227
  232 +#define TARGET_NR_io_destroy 228
  233 +#define TARGET_NR_io_getevents 229
  234 +#define TARGET_NR_io_submit 230
  235 +#define TARGET_NR_io_cancel 231
  236 +#define TARGET_NR_set_tid_address 232
  237 +#define TARGET_NR_fadvise64 233
  238 +#define TARGET_NR_exit_group 234
  239 +#define TARGET_NR_lookup_dcookie 235
  240 +#define TARGET_NR_epoll_create 236
  241 +#define TARGET_NR_epoll_ctl 237
  242 +#define TARGET_NR_epoll_wait 238
  243 +#define TARGET_NR_remap_file_pages 239
  244 +#define TARGET_NR_timer_create 240
  245 +#define TARGET_NR_timer_settime 241
  246 +#define TARGET_NR_timer_gettime 242
  247 +#define TARGET_NR_timer_getoverrun 243
  248 +#define TARGET_NR_timer_delete 244
  249 +#define TARGET_NR_clock_settime 245
  250 +#define TARGET_NR_clock_gettime 246
  251 +#define TARGET_NR_clock_getres 247
  252 +#define TARGET_NR_clock_nanosleep 248
  253 +#define TARGET_NR_swapcontext 249
  254 +#define TARGET_NR_tgkill 250
  255 +#define TARGET_NR_utimes 251
  256 +#define TARGET_NR_statfs64 252
  257 +#define TARGET_NR_fstatfs64 253
  258 +#define TARGET_NR_fadvise64_64 254
... ...
target-ppc/cpu.h 0 → 100644
  1 +/*
  2 + * PPC emulation cpu definitions for qemu.
  3 + *
  4 + * Copyright (c) 2003 Jocelyn Mayer
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +#if !defined (__CPU_PPC_H__)
  21 +#define __CPU_PPC_H__
  22 +
  23 +#include <endian.h>
  24 +#include <asm/byteorder.h>
  25 +
  26 +#include "cpu-defs.h"
  27 +
  28 +/*** Sign extend constants ***/
  29 +/* 8 to 32 bits */
  30 +static inline int32_t s_ext8 (uint8_t value)
  31 +{
  32 + int8_t *tmp = &value;
  33 +
  34 + return *tmp;
  35 +}
  36 +
  37 +/* 16 to 32 bits */
  38 +static inline int32_t s_ext16 (uint16_t value)
  39 +{
  40 + int16_t *tmp = &value;
  41 +
  42 + return *tmp;
  43 +}
  44 +
  45 +/* 24 to 32 bits */
  46 +static inline int32_t s_ext24 (uint32_t value)
  47 +{
  48 + uint16_t utmp = (value >> 8) & 0xFFFF;
  49 + int16_t *tmp = &utmp;
  50 +
  51 + return (*tmp << 8) | (value & 0xFF);
  52 +}
  53 +
  54 +#include "config.h"
  55 +#include <setjmp.h>
  56 +
  57 +/* Floting point status and control register */
  58 +#define FPSCR_FX 31
  59 +#define FPSCR_FEX 30
  60 +#define FPSCR_VX 29
  61 +#define FPSCR_OX 28
  62 +#define FPSCR_UX 27
  63 +#define FPSCR_ZX 26
  64 +#define FPSCR_XX 25
  65 +#define FPSCR_VXSNAN 24
  66 +#define FPSCR_VXISI 26
  67 +#define FPSCR_VXIDI 25
  68 +#define FPSCR_VXZDZ 21
  69 +#define FPSCR_VXIMZ 20
  70 +
  71 +#define FPSCR_VXVC 18
  72 +#define FPSCR_FR 17
  73 +#define FPSCR_FI 16
  74 +#define FPSCR_FPRF 11
  75 +#define FPSCR_VXSOFT 9
  76 +#define FPSCR_VXSQRT 8
  77 +#define FPSCR_VXCVI 7
  78 +#define FPSCR_OE 6
  79 +#define FPSCR_UE 5
  80 +#define FPSCR_ZE 4
  81 +#define FPSCR_XE 3
  82 +#define FPSCR_NI 2
  83 +#define FPSCR_RN 0
  84 +#define fpscr_fx env->fpscr[FPSCR_FX]
  85 +#define fpscr_fex env->fpscr[FPSCR_FEX]
  86 +#define fpscr_vx env->fpscr[FPSCR_VX]
  87 +#define fpscr_ox env->fpscr[FPSCR_OX]
  88 +#define fpscr_ux env->fpscr[FPSCR_UX]
  89 +#define fpscr_zx env->fpscr[FPSCR_ZX]
  90 +#define fpscr_xx env->fpscr[FPSCR_XX]
  91 +#define fpscr_vsxnan env->fpscr[FPSCR_VXSNAN]
  92 +#define fpscr_vxisi env->fpscr[FPSCR_VXISI]
  93 +#define fpscr_vxidi env->fpscr[FPSCR_VXIDI]
  94 +#define fpscr_vxzdz env->fpscr[FPSCR_VXZDZ]
  95 +#define fpscr_vximz env->fpscr[FPSCR_VXIMZ]
  96 +#define fpscr_fr env->fpscr[FPSCR_FR]
  97 +#define fpscr_fi env->fpscr[FPSCR_FI]
  98 +#define fpscr_fprf env->fpscr[FPSCR_FPRF]
  99 +#define fpscr_vxsoft env->fpscr[FPSCR_VXSOFT]
  100 +#define fpscr_vxsqrt env->fpscr[FPSCR_VXSQRT]
  101 +#define fpscr_oe env->fpscr[FPSCR_OE]
  102 +#define fpscr_ue env->fpscr[FPSCR_UE]
  103 +#define fpscr_ze env->fpscr[FPSCR_ZE]
  104 +#define fpscr_xe env->fpscr[FPSCR_XE]
  105 +#define fpscr_ni env->fpscr[FPSCR_NI]
  106 +#define fpscr_rn env->fpscr[FPSCR_RN]
  107 +
  108 +/* Supervisor mode registers */
  109 +/* Machine state register */
  110 +#define MSR_POW 18
  111 +#define MSR_ILE 16
  112 +#define MSR_EE 15
  113 +#define MSR_PR 14
  114 +#define MSR_FP 13
  115 +#define MSR_ME 12
  116 +#define MSR_FE0 11
  117 +#define MSR_SE 10
  118 +#define MSR_BE 9
  119 +#define MSR_FE1 8
  120 +#define MSR_IP 6
  121 +#define MSR_IR 5
  122 +#define MSR_DR 4
  123 +#define MSR_RI 1
  124 +#define MSR_LE 0
  125 +#define msr_pow env->msr[MSR_POW]
  126 +#define msr_ile env->msr[MSR_ILE]
  127 +#define msr_ee env->msr[MSR_EE]
  128 +#define msr_pr env->msr[MSR_PR]
  129 +#define msr_fp env->msr[MSR_FP]
  130 +#define msr_me env->msr[MSR_ME]
  131 +#define msr_fe0 env->msr[MSR_FE0]
  132 +#define msr_se env->msr[MSR_SE]
  133 +#define msr_be env->msr[MSR_BE]
  134 +#define msr_fe1 env->msr[MSR_FE1]
  135 +#define msr_ip env->msr[MSR_IP]
  136 +#define msr_ir env->msr[MSR_IR]
  137 +#define msr_dr env->msr[MSR_DR]
  138 +#define msr_ri env->msr[MSR_RI]
  139 +#define msr_le env->msr[MSR_LE]
  140 +
  141 +/* Segment registers */
  142 +typedef struct ppc_sr_t {
  143 + uint32_t t:1;
  144 + uint32_t ks:1;
  145 + uint32_t kp:1;
  146 + uint32_t n:1;
  147 + uint32_t res:4;
  148 + uint32_t vsid:24;
  149 +} ppc_sr_t;
  150 +
  151 +typedef struct CPUPPCState {
  152 + /* general purpose registers */
  153 + uint32_t gpr[32];
  154 + /* floating point registers */
  155 + uint64_t fpr[32];
  156 + /* segment registers */
  157 + ppc_sr_t sr[16];
  158 + /* special purpose registers */
  159 + uint32_t spr[1024];
  160 + /* XER */
  161 + uint8_t xer[32];
  162 + /* Reservation address */
  163 + uint32_t reserve;
  164 + /* machine state register */
  165 + uint8_t msr[32];
  166 + /* condition register */
  167 + uint8_t crf[8];
  168 + /* floating point status and control register */
  169 + uint8_t fpscr[32];
  170 + uint32_t nip;
  171 + /* CPU exception code */
  172 + uint32_t exception;
  173 +
  174 + /* qemu dedicated */
  175 + int interrupt_request;
  176 + jmp_buf jmp_env;
  177 + int exception_index;
  178 + int error_code;
  179 + int user_mode_only; /* user mode only simulation */
  180 + struct TranslationBlock *current_tb; /* currently executing TB */
  181 +
  182 + /* user data */
  183 + void *opaque;
  184 +} CPUPPCState;
  185 +
  186 +CPUPPCState *cpu_ppc_init(void);
  187 +int cpu_ppc_exec(CPUPPCState *s);
  188 +void cpu_ppc_close(CPUPPCState *s);
  189 +/* you can call this signal handler from your SIGBUS and SIGSEGV
  190 + signal handlers to inform the virtual CPU of exceptions. non zero
  191 + is returned if the signal was handled by the virtual CPU. */
  192 +struct siginfo;
  193 +int cpu_ppc_signal_handler(int host_signum, struct siginfo *info,
  194 + void *puc);
  195 +
  196 +void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags);
  197 +
  198 +#define TARGET_PAGE_BITS 12
  199 +#include "cpu-all.h"
  200 +
  201 +#define ugpr(n) (env->gpr[n])
  202 +#define fpr(n) (env->fpr[n])
  203 +
  204 +#define SPR_ENCODE(sprn) \
  205 +(((sprn) >> 5) | (((sprn) & 0x1F) << 5))
  206 +
  207 +/* User mode SPR */
  208 +#define spr(n) env->spr[n]
  209 +//#define XER spr[1]
  210 +#define XER env->xer
  211 +#define XER_SO 31
  212 +#define XER_OV 30
  213 +#define XER_CA 29
  214 +#define XER_BC 0
  215 +#define xer_so env->xer[XER_SO]
  216 +#define xer_ov env->xer[XER_OV]
  217 +#define xer_ca env->xer[XER_CA]
  218 +#define xer_bc env->xer[XER_BC]
  219 +
  220 +#define LR spr[SPR_ENCODE(8)]
  221 +#define CTR spr[SPR_ENCODE(9)]
  222 +/* VEA mode SPR */
  223 +#define V_TBL spr[SPR_ENCODE(268)]
  224 +#define V_TBU spr[SPR_ENCODE(269)]
  225 +/* supervisor mode SPR */
  226 +#define DSISR spr[SPR_ENCODE(18)]
  227 +#define DAR spr[SPR_ENCODE(19)]
  228 +#define DEC spr[SPR_ENCODE(22)]
  229 +#define SDR1 spr[SPR_ENCODE(25)]
  230 +typedef struct ppc_sdr1_t {
  231 + uint32_t htaborg:16;
  232 + uint32_t res:7;
  233 + uint32_t htabmask:9;
  234 +} ppc_sdr1_t;
  235 +#define SRR0 spr[SPR_ENCODE(26)]
  236 +#define SRR0_MASK 0xFFFFFFFC
  237 +#define SRR1 spr[SPR_ENCODE(27)]
  238 +#define SPRG0 spr[SPR_ENCODE(272)]
  239 +#define SPRG1 spr[SPR_ENCODE(273)]
  240 +#define SPRG2 spr[SPR_ENCODE(274)]
  241 +#define SPRG3 spr[SPR_ENCODE(275)]
  242 +#define EAR spr[SPR_ENCODE(282)]
  243 +typedef struct ppc_ear_t {
  244 + uint32_t e:1;
  245 + uint32_t res:25;
  246 + uint32_t rid:6;
  247 +} ppc_ear_t;
  248 +#define TBL spr[SPR_ENCODE(284)]
  249 +#define TBU spr[SPR_ENCODE(285)]
  250 +#define PVR spr[SPR_ENCODE(287)]
  251 +typedef struct ppc_pvr_t {
  252 + uint32_t version:16;
  253 + uint32_t revision:16;
  254 +} ppc_pvr_t;
  255 +#define IBAT0U spr[SPR_ENCODE(528)]
  256 +#define IBAT0L spr[SPR_ENCODE(529)]
  257 +#define IBAT1U spr[SPR_ENCODE(530)]
  258 +#define IBAT1L spr[SPR_ENCODE(531)]
  259 +#define IBAT2U spr[SPR_ENCODE(532)]
  260 +#define IBAT2L spr[SPR_ENCODE(533)]
  261 +#define IBAT3U spr[SPR_ENCODE(534)]
  262 +#define IBAT3L spr[SPR_ENCODE(535)]
  263 +#define DBAT0U spr[SPR_ENCODE(536)]
  264 +#define DBAT0L spr[SPR_ENCODE(537)]
  265 +#define DBAT1U spr[SPR_ENCODE(538)]
  266 +#define DBAT1L spr[SPR_ENCODE(539)]
  267 +#define DBAT2U spr[SPR_ENCODE(540)]
  268 +#define DBAT2L spr[SPR_ENCODE(541)]
  269 +#define DBAT3U spr[SPR_ENCODE(542)]
  270 +#define DBAT3L spr[SPR_ENCODE(543)]
  271 +typedef struct ppc_ubat_t {
  272 + uint32_t bepi:15;
  273 + uint32_t res:4;
  274 + uint32_t bl:11;
  275 + uint32_t vs:1;
  276 + uint32_t vp:1;
  277 +} ppc_ubat_t;
  278 +typedef struct ppc_lbat_t {
  279 + uint32_t brpn:15;
  280 + uint32_t res0:10;
  281 + uint32_t w:1;
  282 + uint32_t i:1;
  283 + uint32_t m:1;
  284 + uint32_t g:1;
  285 + uint32_t res1:1;
  286 + uint32_t pp:2;
  287 +} ppc_lbat_t;
  288 +#define DABR spr[SPR_ENCODE(1013)]
  289 +#define DABR_MASK 0xFFFFFFF8
  290 +typedef struct ppc_dabr_t {
  291 + uint32_t dab:29;
  292 + uint32_t bt:1;
  293 + uint32_t dw:1;
  294 + uint32_t dr:1;
  295 +} ppc_dabr_t;
  296 +#define FPECR spr[SPR_ENCODE(1022)]
  297 +#define PIR spr[SPR_ENCODE(1023)]
  298 +
  299 +#define TARGET_PAGE_BITS 12
  300 +#include "cpu-all.h"
  301 +
  302 +CPUPPCState *cpu_ppc_init(void);
  303 +int cpu_ppc_exec(CPUPPCState *s);
  304 +void cpu_ppc_close(CPUPPCState *s);
  305 +void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags);
  306 +
  307 +/* Exeptions */
  308 +enum {
  309 + EXCP_NONE = 0x00,
  310 + /* PPC hardware exceptions : exception vector / 0x100 */
  311 + EXCP_RESET = 0x01, /* System reset */
  312 + EXCP_MACHINE_CHECK = 0x02, /* Machine check exception */
  313 + EXCP_DSI = 0x03, /* Impossible memory access */
  314 + EXCP_ISI = 0x04, /* Impossible instruction fetch */
  315 + EXCP_EXTERNAL = 0x05, /* External interruption */
  316 + EXCP_ALIGN = 0x06, /* Alignment exception */
  317 + EXCP_PROGRAM = 0x07, /* Program exception */
  318 + EXCP_NO_FP = 0x08, /* No floating point */
  319 + EXCP_DECR = 0x09, /* Decrementer exception */
  320 + EXCP_RESA = 0x0A, /* Implementation specific */
  321 + EXCP_RESB = 0x0B, /* Implementation specific */
  322 + EXCP_SYSCALL = 0x0C, /* System call */
  323 + EXCP_TRACE = 0x0D, /* Trace exception (optional) */
  324 + EXCP_FP_ASSIST = 0x0E, /* Floating-point assist (optional) */
  325 +#if 0
  326 + /* Exeption subtypes for EXCP_DSI */
  327 + EXCP_DSI_TRANSLATE = 0x10301, /* Data address can't be translated */
  328 + EXCP_DSI_NOTSUP = 0x10302, /* Access type not supported */
  329 + EXCP_DSI_PROT = 0x10303, /* Memory protection violation */
  330 + EXCP_DSI_EXTERNAL = 0x10304, /* External access disabled */
  331 + EXCP_DSI_DABR = 0x10305, /* Data address breakpoint */
  332 + /* Exeption subtypes for EXCP_ISI */
  333 + EXCP_ISI_TRANSLATE = 0x10401, /* Code address can't be translated */
  334 + EXCP_ISI_NOTSUP = 0x10402, /* Access type not supported */
  335 + EXCP_ISI_PROT = 0x10403, /* Memory protection violation */
  336 + EXCP_ISI_GUARD = 0x10404, /* Fetch into guarded memory */
  337 + /* Exeption subtypes for EXCP_ALIGN */
  338 + EXCP_ALIGN_FP = 0x10601, /* FP alignment exception */
  339 + EXCP_ALIGN_LST = 0x10602, /* Unaligned memory load/store */
  340 + EXCP_ALIGN_LE = 0x10603, /* Unaligned little-endian access */
  341 + EXCP_ALIGN_PROT = 0x10604, /* Access cross protection boundary */
  342 + EXCP_ALIGN_BAT = 0x10605, /* Access cross a BAT/seg boundary */
  343 + EXCP_ALIGN_CACHE = 0x10606, /* Impossible dcbz access */
  344 + /* Exeption subtypes for EXCP_PROGRAM */
  345 + /* FP exceptions */
  346 + EXCP_FP_OX = 0x10701, /* FP overflow */
  347 + EXCP_FP_UX = 0x10702, /* FP underflow */
  348 + EXCP_FP_ZX = 0x10703, /* FP divide by zero */
  349 + EXCP_FP_XX = 0x10704, /* FP inexact */
  350 + EXCP_FP_VXNAN = 0x10705, /* FP invalid SNaN op */
  351 + EXCP_FP_VXISI = 0x10706, /* FP invalid infinite substraction */
  352 + EXCP_FP_VXIDI = 0x10707, /* FP invalid infinite divide */
  353 + EXCP_FP_VXZDZ = 0x10708, /* FP invalid zero divide */
  354 + EXCP_FP_VXIMZ = 0x10709, /* FP invalid infinite * zero */
  355 + EXCP_FP_VXVC = 0x1070A, /* FP invalid compare */
  356 + EXCP_FP_VXSOFT = 0x1070B, /* FP invalid operation */
  357 + EXCP_FP_VXSQRT = 0x1070C, /* FP invalid square root */
  358 + EXCP_FP_VXCVI = 0x1070D, /* FP invalid integer conversion */
  359 + /* Invalid instruction */
  360 + EXCP_INVAL_INVAL = 0x10711, /* Invalid instruction */
  361 + EXCP_INVAL_LSWX = 0x10712, /* Invalid lswx instruction */
  362 + EXCP_INVAL_SPR = 0x10713, /* Invalid SPR access */
  363 + EXCP_INVAL_FP = 0x10714, /* Unimplemented mandatory fp instr */
  364 +#endif
  365 + EXCP_INVAL = 0x70, /* Invalid instruction */
  366 + /* Privileged instruction */
  367 + EXCP_PRIV = 0x71, /* Privileged instruction */
  368 + /* Trap */
  369 + EXCP_TRAP = 0x72, /* Trap */
  370 + /* Special cases where we want to stop translation */
  371 + EXCP_MTMSR = 0x103, /* mtmsr instruction: */
  372 + /* may change privilege level */
  373 + EXCP_BRANCH = 0x104, /* branch instruction */
  374 +};
  375 +
  376 +/*
  377 + * We need to put in some extra aux table entries to tell glibc what
  378 + * the cache block size is, so it can use the dcbz instruction safely.
  379 + */
  380 +#define AT_DCACHEBSIZE 19
  381 +#define AT_ICACHEBSIZE 20
  382 +#define AT_UCACHEBSIZE 21
  383 +/* A special ignored type value for PPC, for glibc compatibility. */
  384 +#define AT_IGNOREPPC 22
  385 +/*
  386 + * The requirements here are:
  387 + * - keep the final alignment of sp (sp & 0xf)
  388 + * - make sure the 32-bit value at the first 16 byte aligned position of
  389 + * AUXV is greater than 16 for glibc compatibility.
  390 + * AT_IGNOREPPC is used for that.
  391 + * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
  392 + * even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
  393 + */
  394 +#define DLINFO_ARCH_ITEMS 3
  395 +#define ARCH_DLINFO \
  396 +do { \
  397 + /* \
  398 + * Now handle glibc compatibility. \
  399 + */ \
  400 + NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
  401 + NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
  402 + \
  403 + NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \
  404 + NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \
  405 + NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \
  406 + } while (0)
  407 +#endif /* !defined (__CPU_PPC_H__) */
... ...
target-ppc/exec.h 0 → 100644
  1 +/*
  2 + * PPC emulation definitions for qemu.
  3 + *
  4 + * Copyright (c) 2003 Jocelyn Mayer
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +#if !defined (__PPC_H__)
  21 +#define __PPC_H__
  22 +
  23 +#include "dyngen-exec.h"
  24 +
  25 +register struct CPUPPCState *env asm(AREG0);
  26 +register uint32_t T0 asm(AREG1);
  27 +register uint32_t T1 asm(AREG2);
  28 +register uint32_t T2 asm(AREG3);
  29 +
  30 +#define PARAM(n) ((uint32_t)PARAM##n)
  31 +#define SPARAM(n) ((int32_t)PARAM##n)
  32 +
  33 +#define RETURN() __asm__ __volatile__("");
  34 +
  35 +#include "cpu.h"
  36 +#include "exec-all.h"
  37 +
  38 +static inline uint8_t ld8 (uint32_t EA)
  39 +{
  40 + return *((uint8_t *)EA);
  41 +}
  42 +
  43 +static inline uint16_t ld16 (uint32_t EA)
  44 +{
  45 + return __be16_to_cpu(*((uint16_t *)EA));
  46 +}
  47 +
  48 +static inline uint16_t ld16r (uint32_t EA)
  49 +{
  50 + return __le16_to_cpu(*((uint16_t *)EA));
  51 +}
  52 +
  53 +static inline uint32_t ld32 (uint32_t EA)
  54 +{
  55 + return __be32_to_cpu(*((uint32_t *)EA));
  56 +}
  57 +
  58 +static inline uint32_t ld32r (uint32_t EA)
  59 +{
  60 + return __le32_to_cpu(*((uint32_t *)EA));
  61 +}
  62 +
  63 +static inline uint64_t ld64 (uint32_t EA)
  64 +{
  65 + return __be64_to_cpu(*((uint64_t *)EA));
  66 +}
  67 +
  68 +static inline uint64_t ld64r (uint32_t EA)
  69 +{
  70 + return __le64_to_cpu(*((uint64_t *)EA));
  71 +}
  72 +
  73 +static inline void st8 (uint32_t EA, uint8_t data)
  74 +{
  75 + *((uint8_t *)EA) = data;
  76 +}
  77 +
  78 +static inline void st16 (uint32_t EA, uint16_t data)
  79 +{
  80 + *((uint16_t *)EA) = __cpu_to_be16(data);
  81 +}
  82 +
  83 +static inline void st16r (uint32_t EA, uint16_t data)
  84 +{
  85 + *((uint16_t *)EA) = __cpu_to_le16(data);
  86 +}
  87 +
  88 +static inline void st32 (uint32_t EA, uint32_t data)
  89 +{
  90 + *((uint32_t *)EA) = __cpu_to_be32(data);
  91 +}
  92 +
  93 +static inline void st32r (uint32_t EA, uint32_t data)
  94 +{
  95 + *((uint32_t *)EA) = __cpu_to_le32(data);
  96 +}
  97 +
  98 +static inline void st64 (uint32_t EA, uint64_t data)
  99 +{
  100 + *((uint64_t *)EA) = __cpu_to_be64(data);
  101 +}
  102 +
  103 +static inline void st64r (uint32_t EA, uint64_t data)
  104 +{
  105 + *((uint64_t *)EA) = __cpu_to_le64(data);
  106 +}
  107 +
  108 +static inline void set_CRn(int n, uint8_t value)
  109 +{
  110 + env->crf[n] = value;
  111 +}
  112 +
  113 +static inline void set_carry (void)
  114 +{
  115 + xer_ca = 1;
  116 +}
  117 +
  118 +static inline void reset_carry (void)
  119 +{
  120 + xer_ca = 0;
  121 +}
  122 +
  123 +static inline void set_overflow (void)
  124 +{
  125 + xer_so = 1;
  126 + xer_ov = 1;
  127 +}
  128 +
  129 +static inline void reset_overflow (void)
  130 +{
  131 + xer_ov = 0;
  132 +}
  133 +
  134 +static inline uint32_t rotl (uint32_t i, int n)
  135 +{
  136 + return ((i << n) | (i >> (32 - n)));
  137 +}
  138 +
  139 +void raise_exception (int exception_index);
  140 +void raise_exception_err (int exception_index, int error_code);
  141 +
  142 +uint32_t do_load_cr (void);
  143 +void do_store_cr (uint32_t crn, uint32_t value);
  144 +uint32_t do_load_xer (void);
  145 +void do_store_xer (uint32_t value);
  146 +uint32_t do_load_msr (void);
  147 +void do_store_msr (uint32_t msr_value);
  148 +uint32_t do_load_fpscr (void);
  149 +void do_store_fpscr (uint8_t mask, uint32_t fp);
  150 +
  151 +int32_t do_sraw(int32_t Ta, uint32_t Tb);
  152 +void do_lmw (int reg, uint32_t src);
  153 +void do_stmw (int reg, uint32_t dest);
  154 +void do_lsw (uint32_t reg, int count, uint32_t src);
  155 +void do_stsw (uint32_t reg, int count, uint32_t dest);
  156 +
  157 +#endif /* !defined (__PPC_H__) */
... ...
target-ppc/helper.c 0 → 100644
  1 +/*
  2 + * PPC emulation helpers for qemu.
  3 + *
  4 + * Copyright (c) 2003 Jocelyn Mayer
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +#include "exec.h"
  21 +
  22 +extern FILE *logfile;
  23 +
  24 +void cpu_loop_exit(void)
  25 +{
  26 + longjmp(env->jmp_env, 1);
  27 +}
  28 +
  29 +/* shortcuts to generate exceptions */
  30 +void raise_exception_err (int exception_index, int error_code)
  31 +{
  32 + env->exception_index = exception_index;
  33 + env->error_code = error_code;
  34 +
  35 + cpu_loop_exit();
  36 +}
  37 +
  38 +void raise_exception (int exception_index)
  39 +{
  40 + env->exception_index = exception_index;
  41 + env->error_code = 0;
  42 +
  43 + cpu_loop_exit();
  44 +}
  45 +
  46 +/* Helpers for "fat" micro operations */
  47 +uint32_t do_load_cr (void)
  48 +{
  49 + return (env->crf[0] << 28) |
  50 + (env->crf[1] << 24) |
  51 + (env->crf[2] << 20) |
  52 + (env->crf[3] << 16) |
  53 + (env->crf[4] << 12) |
  54 + (env->crf[5] << 8) |
  55 + (env->crf[6] << 4) |
  56 + (env->crf[7] << 0);
  57 +}
  58 +
  59 +void do_store_cr (uint32_t crn, uint32_t value)
  60 +{
  61 + int i, sh;
  62 +
  63 + for (i = 0, sh = 7; i < 8; i++, sh --) {
  64 + if (crn & (1 << sh))
  65 + env->crf[i] = (value >> (sh * 4)) & 0xF;
  66 + }
  67 +}
  68 +
  69 +uint32_t do_load_xer (void)
  70 +{
  71 + return (xer_so << XER_SO) |
  72 + (xer_ov << XER_OV) |
  73 + (xer_ca << XER_CA) |
  74 + (xer_bc << XER_BC);
  75 +}
  76 +
  77 +void do_store_xer (uint32_t value)
  78 +{
  79 + xer_so = (value >> XER_SO) & 0x01;
  80 + xer_ov = (value >> XER_OV) & 0x01;
  81 + xer_ca = (value >> XER_CA) & 0x01;
  82 + xer_bc = (value >> XER_BC) & 0x1f;
  83 +}
  84 +
  85 +uint32_t do_load_msr (void)
  86 +{
  87 + return (msr_pow << MSR_POW) |
  88 + (msr_ile << MSR_ILE) |
  89 + (msr_ee << MSR_EE) |
  90 + (msr_pr << MSR_PR) |
  91 + (msr_fp << MSR_FP) |
  92 + (msr_me << MSR_ME) |
  93 + (msr_fe0 << MSR_FE0) |
  94 + (msr_se << MSR_SE) |
  95 + (msr_be << MSR_BE) |
  96 + (msr_fe1 << MSR_FE1) |
  97 + (msr_ip << MSR_IP) |
  98 + (msr_ir << MSR_IR) |
  99 + (msr_dr << MSR_DR) |
  100 + (msr_ri << MSR_RI) |
  101 + (msr_le << MSR_LE);
  102 +}
  103 +
  104 +void do_store_msr (uint32_t msr_value)
  105 +{
  106 + msr_pow = (msr_value >> MSR_POW) & 0x03;
  107 + msr_ile = (msr_value >> MSR_ILE) & 0x01;
  108 + msr_ee = (msr_value >> MSR_EE) & 0x01;
  109 + msr_pr = (msr_value >> MSR_PR) & 0x01;
  110 + msr_fp = (msr_value >> MSR_FP) & 0x01;
  111 + msr_me = (msr_value >> MSR_ME) & 0x01;
  112 + msr_fe0 = (msr_value >> MSR_FE0) & 0x01;
  113 + msr_se = (msr_value >> MSR_SE) & 0x01;
  114 + msr_be = (msr_value >> MSR_BE) & 0x01;
  115 + msr_fe1 = (msr_value >> MSR_FE1) & 0x01;
  116 + msr_ip = (msr_value >> MSR_IP) & 0x01;
  117 + msr_ir = (msr_value >> MSR_IR) & 0x01;
  118 + msr_dr = (msr_value >> MSR_DR) & 0x01;
  119 + msr_ri = (msr_value >> MSR_RI) & 0x01;
  120 + msr_le = (msr_value >> MSR_LE) & 0x01;
  121 +}
  122 +
  123 +/* The 32 MSB of the target fpr are undefined. They'll be zero... */
  124 +uint32_t do_load_fpscr (void)
  125 +{
  126 + return (fpscr_fx << FPSCR_FX) |
  127 + (fpscr_fex << FPSCR_FEX) |
  128 + (fpscr_vx << FPSCR_VX) |
  129 + (fpscr_ox << FPSCR_OX) |
  130 + (fpscr_ux << FPSCR_UX) |
  131 + (fpscr_zx << FPSCR_ZX) |
  132 + (fpscr_xx << FPSCR_XX) |
  133 + (fpscr_vsxnan << FPSCR_VXSNAN) |
  134 + (fpscr_vxisi << FPSCR_VXISI) |
  135 + (fpscr_vxidi << FPSCR_VXIDI) |
  136 + (fpscr_vxzdz << FPSCR_VXZDZ) |
  137 + (fpscr_vximz << FPSCR_VXIMZ) |
  138 + (fpscr_fr << FPSCR_FR) |
  139 + (fpscr_fi << FPSCR_FI) |
  140 + (fpscr_fprf << FPSCR_FPRF) |
  141 + (fpscr_vxsoft << FPSCR_VXSOFT) |
  142 + (fpscr_vxsqrt << FPSCR_VXSQRT) |
  143 + (fpscr_oe << FPSCR_OE) |
  144 + (fpscr_ue << FPSCR_UE) |
  145 + (fpscr_ze << FPSCR_ZE) |
  146 + (fpscr_xe << FPSCR_XE) |
  147 + (fpscr_ni << FPSCR_NI) |
  148 + (fpscr_rn << FPSCR_RN);
  149 +}
  150 +
  151 +/* We keep only 32 bits of input... */
  152 +/* For now, this is COMPLETELY BUGGY ! */
  153 +void do_store_fpscr (uint8_t mask, uint32_t fp)
  154 +{
  155 + int i;
  156 +
  157 + for (i = 0; i < 7; i++) {
  158 + if ((mask & (1 << i)) == 0)
  159 + fp &= ~(0xf << (4 * i));
  160 + }
  161 + if ((mask & 80) != 0)
  162 + fpscr_fx = (fp >> FPSCR_FX) & 0x01;
  163 + fpscr_fex = (fp >> FPSCR_FEX) & 0x01;
  164 + fpscr_vx = (fp >> FPSCR_VX) & 0x01;
  165 + fpscr_ox = (fp >> FPSCR_OX) & 0x01;
  166 + fpscr_ux = (fp >> FPSCR_UX) & 0x01;
  167 + fpscr_zx = (fp >> FPSCR_ZX) & 0x01;
  168 + fpscr_xx = (fp >> FPSCR_XX) & 0x01;
  169 + fpscr_vsxnan = (fp >> FPSCR_VXSNAN) & 0x01;
  170 + fpscr_vxisi = (fp >> FPSCR_VXISI) & 0x01;
  171 + fpscr_vxidi = (fp >> FPSCR_VXIDI) & 0x01;
  172 + fpscr_vxzdz = (fp >> FPSCR_VXZDZ) & 0x01;
  173 + fpscr_vximz = (fp >> FPSCR_VXIMZ) & 0x01;
  174 + fpscr_fr = (fp >> FPSCR_FR) & 0x01;
  175 + fpscr_fi = (fp >> FPSCR_FI) & 0x01;
  176 + fpscr_fprf = (fp >> FPSCR_FPRF) & 0x1F;
  177 + fpscr_vxsoft = (fp >> FPSCR_VXSOFT) & 0x01;
  178 + fpscr_vxsqrt = (fp >> FPSCR_VXSQRT) & 0x01;
  179 + fpscr_oe = (fp >> FPSCR_OE) & 0x01;
  180 + fpscr_ue = (fp >> FPSCR_UE) & 0x01;
  181 + fpscr_ze = (fp >> FPSCR_ZE) & 0x01;
  182 + fpscr_xe = (fp >> FPSCR_XE) & 0x01;
  183 + fpscr_ni = (fp >> FPSCR_NI) & 0x01;
  184 + fpscr_rn = (fp >> FPSCR_RN) & 0x03;
  185 +}
  186 +
  187 +int32_t do_sraw(int32_t value, uint32_t shift)
  188 +{
  189 + int32_t ret;
  190 +
  191 + xer_ca = 0;
  192 + if (shift & 0x20) {
  193 + ret = (-1) * ((uint32_t)value >> 31);
  194 + if (ret < 0)
  195 + xer_ca = 1;
  196 + } else {
  197 + ret = value >> (shift & 0x1f);
  198 + if (ret < 0 && (value & ((1 << shift) - 1)) != 0)
  199 + xer_ca = 1;
  200 + }
  201 +
  202 + return ret;
  203 +}
  204 +
  205 +void do_lmw (int reg, uint32_t src)
  206 +{
  207 + for (; reg <= 31; reg++, src += 4)
  208 + ugpr(reg) = ld32(src);
  209 +}
  210 +
  211 +void do_stmw (int reg, uint32_t dest)
  212 +{
  213 + for (; reg <= 31; reg++, dest += 4)
  214 + st32(dest, ugpr(reg));
  215 +}
  216 +
  217 +void do_lsw (uint32_t reg, int count, uint32_t src)
  218 +{
  219 + uint32_t tmp;
  220 + int sh;
  221 +
  222 + for (; count > 3; count -= 4, src += 4) {
  223 + if (reg == 32)
  224 + reg = 0;
  225 + ugpr(reg++) = ld32(src);
  226 + }
  227 + if (count > 0) {
  228 + for (sh = 24, tmp = 0; count > 0; count--, src++, sh -= 8) {
  229 + if (reg == 32)
  230 + reg = 0;
  231 + tmp |= ld8(src) << sh;
  232 + if (sh == 0) {
  233 + sh = 32;
  234 + ugpr(reg++) = tmp;
  235 + tmp = 0;
  236 + }
  237 + }
  238 + ugpr(reg) = tmp;
  239 + }
  240 +}
  241 +
  242 +void do_stsw (uint32_t reg, int count, uint32_t dest)
  243 +{
  244 + int sh;
  245 +
  246 + for (; count > 3; count -= 4, dest += 4) {
  247 + if (reg == 32)
  248 + reg = 0;
  249 + st32(dest, ugpr(reg++));
  250 + }
  251 + if (count > 0) {
  252 + for (sh = 24; count > 0; count--, dest++, sh -= 8) {
  253 + if (reg == 32)
  254 + reg = 0;
  255 + st8(dest, (ugpr(reg) >> sh) & 0xFF);
  256 + if (sh == 0) {
  257 + sh = 32;
  258 + reg++;
  259 + }
  260 + }
  261 + }
  262 +}
... ...
target-ppc/op.c 0 → 100644
  1 +/*
  2 + * PPC emulation micro-operations for qemu.
  3 + *
  4 + * Copyright (c) 2003 Jocelyn Mayer
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +
  21 +#include "config.h"
  22 +#include "exec.h"
  23 +
  24 +#define regs (env)
  25 +extern uint32_t __a;
  26 +extern uint32_t __b;
  27 +extern uint32_t __c;
  28 +extern uint32_t __d;
  29 +extern uint32_t __e;
  30 +extern uint32_t __f;
  31 +#define Ts0 (int32_t)T0
  32 +#define Ts1 (int32_t)T1
  33 +#define Ts2 (int32_t)T2
  34 +
  35 +#include "op-multi.c"
  36 +
  37 +#define PPC_OP(name) void op_##name(void)
  38 +
  39 +/* PPC state maintenance operations */
  40 +/* set_Rc0 */
  41 +PPC_OP(set_Rc0)
  42 +{
  43 + uint32_t tmp;
  44 +
  45 + if (Ts0 < 0) {
  46 + tmp = 0x08;
  47 + } else if (Ts0 > 0) {
  48 + tmp = 0x04;
  49 + } else {
  50 + tmp = 0x02;
  51 + }
  52 + set_CRn(0, tmp);
  53 + RETURN();
  54 +}
  55 +
  56 +PPC_OP(set_Rc0_ov)
  57 +{
  58 + uint32_t tmp;
  59 +
  60 + if (Ts0 < 0) {
  61 + tmp = 0x08;
  62 + } else if (Ts0 > 0) {
  63 + tmp = 0x04;
  64 + } else {
  65 + tmp = 0x02;
  66 + }
  67 + tmp |= xer_ov;
  68 + set_CRn(0, tmp);
  69 + RETURN();
  70 +}
  71 +
  72 +/* reset_Rc0 */
  73 +PPC_OP(reset_Rc0)
  74 +{
  75 + set_CRn(0, 0x02 | xer_ov);
  76 + RETURN();
  77 +}
  78 +
  79 +/* set_Rc0_1 */
  80 +PPC_OP(set_Rc0_1)
  81 +{
  82 + set_CRn(0, 0x04 | xer_ov);
  83 + RETURN();
  84 +}
  85 +
  86 +PPC_OP(set_T0)
  87 +{
  88 + T0 = PARAM(1);
  89 + RETURN();
  90 +}
  91 +
  92 +PPC_OP(set_T1)
  93 +{
  94 + T1 = PARAM(1);
  95 + RETURN();
  96 +}
  97 +
  98 +PPC_OP(set_T2)
  99 +{
  100 + T2 = PARAM(1);
  101 + RETURN();
  102 +}
  103 +
  104 +/* Update time base */
  105 +PPC_OP(update_tb)
  106 +{
  107 + T0 = regs->spr[SPR_ENCODE(268)];
  108 + T1 = T0;
  109 + T0 += PARAM(1);
  110 + if (T0 < T1) {
  111 + T1 = regs->spr[SPR_ENCODE(269)] + 1;
  112 + regs->spr[SPR_ENCODE(269)] = T1;
  113 + }
  114 + regs->spr[SPR_ENCODE(268)] = T0;
  115 + RETURN();
  116 +}
  117 +
  118 +PPC_OP(raise_exception)
  119 +{
  120 + raise_exception(PARAM(1));
  121 + RETURN();
  122 +}
  123 +
  124 +PPC_OP(exit_tb)
  125 +{
  126 + EXIT_TB();
  127 +}
  128 +
  129 +PPC_OP(load_cr)
  130 +{
  131 + T0 = do_load_cr();
  132 + RETURN();
  133 +}
  134 +
  135 +PPC_OP(store_cr)
  136 +{
  137 + do_store_cr(PARAM(1), T0);
  138 + RETURN();
  139 +}
  140 +
  141 +PPC_OP(load_xer_cr)
  142 +{
  143 + T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
  144 + RETURN();
  145 +}
  146 +
  147 +PPC_OP(clear_xer_cr)
  148 +{
  149 + xer_so = 0;
  150 + xer_ov = 0;
  151 + xer_ca = 0;
  152 + RETURN();
  153 +}
  154 +
  155 +PPC_OP(load_xer_bc)
  156 +{
  157 + T0 = xer_bc;
  158 + RETURN();
  159 +}
  160 +
  161 +PPC_OP(load_xer)
  162 +{
  163 + T0 = do_load_xer();
  164 + RETURN();
  165 +}
  166 +
  167 +PPC_OP(store_xer)
  168 +{
  169 + do_store_xer(T0);
  170 + RETURN();
  171 +}
  172 +
  173 +PPC_OP(load_msr)
  174 +{
  175 + T0 = do_load_msr();
  176 + RETURN();
  177 +}
  178 +
  179 +PPC_OP(store_msr)
  180 +{
  181 + do_store_msr(T0);
  182 + RETURN();
  183 +}
  184 +
  185 +PPC_OP(load_lr)
  186 +{
  187 + regs->LR = PARAM(1);
  188 + RETURN();
  189 +}
  190 +
  191 +/* Set reservation */
  192 +PPC_OP(set_reservation)
  193 +{
  194 + regs->reserve = T1 & ~0x03;
  195 + RETURN();
  196 +}
  197 +
  198 +/* Reset reservation */
  199 +PPC_OP(reset_reservation)
  200 +{
  201 + regs->reserve = 0;
  202 + RETURN();
  203 +}
  204 +
  205 +/* crf operations */
  206 +PPC_OP(getbit_T0)
  207 +{
  208 + T0 = (T0 >> PARAM(1)) & 1;
  209 + RETURN();
  210 +}
  211 +
  212 +PPC_OP(getbit_T1)
  213 +{
  214 + T1 = (T1 >> PARAM(1)) & 1;
  215 + RETURN();
  216 +}
  217 +
  218 +PPC_OP(setcrfbit)
  219 +{
  220 + T1 = (T1 & PARAM(1)) | (T0 << PARAM(2));
  221 + RETURN();
  222 +}
  223 +
  224 +/* Branch */
  225 +#define __PPC_OP_B(name, target) \
  226 +PPC_OP(name) \
  227 +{ \
  228 + regs->nip = (target); \
  229 + RETURN(); \
  230 +}
  231 +
  232 +#define __PPC_OP_BL(name, target) \
  233 +PPC_OP(name) \
  234 +{ \
  235 + regs->LR = PARAM(1); \
  236 + regs->nip = (target); \
  237 + RETURN(); \
  238 +}
  239 +
  240 +#define PPC_OP_B(name, target) \
  241 +__PPC_OP_B(name, target); \
  242 +__PPC_OP_BL(name##l, target)
  243 +
  244 +#define __PPC_OP_BC(name, cond, target) \
  245 +PPC_OP(name) \
  246 +{ \
  247 + if (cond) { \
  248 + T0 = (target); \
  249 + } else { \
  250 + T0 = PARAM(1); \
  251 + } \
  252 + regs->nip = T0; \
  253 + RETURN(); \
  254 +}
  255 +
  256 +#define __PPC_OP_BCL(name, cond, target) \
  257 +PPC_OP(name) \
  258 +{ \
  259 + if (cond) { \
  260 + T0 = (target); \
  261 + regs->LR = PARAM(1); \
  262 + } else { \
  263 + T0 = PARAM(1); \
  264 + } \
  265 + regs->nip = T0; \
  266 + RETURN(); \
  267 +}
  268 +
  269 +#define _PPC_OP_BC(name, namel, cond, target) \
  270 +__PPC_OP_BC(name, cond, target); \
  271 +__PPC_OP_BCL(namel, cond, target)
  272 +
  273 +/* Branch to target */
  274 +#define PPC_OP_BC(name, cond) \
  275 +_PPC_OP_BC(b_##name, bl_##name, cond, PARAM(2))
  276 +
  277 +PPC_OP_B(b, PARAM(1));
  278 +PPC_OP_BC(ctr, (regs->CTR != 0));
  279 +PPC_OP_BC(ctr_true, (regs->CTR != 0 && (T0 & PARAM(3)) != 0));
  280 +PPC_OP_BC(ctr_false, (regs->CTR != 0 && (T0 & PARAM(3)) == 0));
  281 +PPC_OP_BC(ctrz, (regs->CTR == 0));
  282 +PPC_OP_BC(ctrz_true, (regs->CTR == 0 && (T0 & PARAM(3)) != 0));
  283 +PPC_OP_BC(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(3)) == 0));
  284 +PPC_OP_BC(true, ((T0 & PARAM(3)) != 0));
  285 +PPC_OP_BC(false, ((T0 & PARAM(3)) == 0));
  286 +
  287 +/* Branch to CTR */
  288 +#define PPC_OP_BCCTR(name, cond) \
  289 +_PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->CTR & ~0x03)
  290 +
  291 +PPC_OP_B(bctr, regs->CTR & ~0x03);
  292 +PPC_OP_BCCTR(ctr, (regs->CTR != 0));
  293 +PPC_OP_BCCTR(ctr_true, (regs->CTR != 0 && (T0 & PARAM(2)) != 0));
  294 +PPC_OP_BCCTR(ctr_false, (regs->CTR != 0 && (T0 & PARAM(2)) == 0));
  295 +PPC_OP_BCCTR(ctrz, (regs->CTR == 0));
  296 +PPC_OP_BCCTR(ctrz_true, (regs->CTR == 0 && (T0 & PARAM(2)) != 0));
  297 +PPC_OP_BCCTR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0));
  298 +PPC_OP_BCCTR(true, ((T0 & PARAM(2)) != 0));
  299 +PPC_OP_BCCTR(false, ((T0 & PARAM(2)) == 0));
  300 +
  301 +/* Branch to LR */
  302 +#define PPC_OP_BCLR(name, cond) \
  303 +_PPC_OP_BC(blr_##name, blrl_##name, cond, regs->LR & ~0x03)
  304 +
  305 +PPC_OP_B(blr, regs->LR & ~0x03);
  306 +PPC_OP_BCLR(ctr, (regs->CTR != 0));
  307 +PPC_OP_BCLR(ctr_true, (regs->CTR != 0 && (T0 & PARAM(2)) != 0));
  308 +PPC_OP_BCLR(ctr_false, (regs->CTR != 0 && (T0 & PARAM(2)) == 0));
  309 +PPC_OP_BCLR(ctrz, (regs->CTR == 0));
  310 +PPC_OP_BCLR(ctrz_true, (regs->CTR == 0 && (T0 & PARAM(2)) != 0));
  311 +PPC_OP_BCLR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0));
  312 +PPC_OP_BCLR(true, ((T0 & PARAM(2)) != 0));
  313 +PPC_OP_BCLR(false, ((T0 & PARAM(2)) == 0));
  314 +
  315 +/* CTR maintenance */
  316 +PPC_OP(dec_ctr)
  317 +{
  318 + regs->CTR--;
  319 + RETURN();
  320 +}
  321 +
  322 +/*** Integer arithmetic ***/
  323 +/* add */
  324 +PPC_OP(add)
  325 +{
  326 + T0 += T1;
  327 + RETURN();
  328 +}
  329 +
  330 +PPC_OP(addo)
  331 +{
  332 + T2 = T0;
  333 + T0 += T1;
  334 + if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
  335 + xer_so = 1;
  336 + xer_ov = 1;
  337 + } else {
  338 + xer_ov = 0;
  339 + }
  340 + RETURN();
  341 +}
  342 +
  343 +/* add carrying */
  344 +PPC_OP(addc)
  345 +{
  346 + T2 = T0;
  347 + T0 += T1;
  348 + if (T0 < T2) {
  349 + xer_ca = 1;
  350 + } else {
  351 + xer_ca = 0;
  352 + }
  353 + RETURN();
  354 +}
  355 +
  356 +PPC_OP(addco)
  357 +{
  358 + T2 = T0;
  359 + T0 += T1;
  360 + if (T0 < T2) {
  361 + xer_ca = 1;
  362 + } else {
  363 + xer_ca = 0;
  364 + }
  365 + if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
  366 + xer_so = 1;
  367 + xer_ov = 1;
  368 + } else {
  369 + xer_ov = 0;
  370 + }
  371 + RETURN();
  372 +}
  373 +
  374 +/* add extended */
  375 +/* candidate for helper (too long) */
  376 +PPC_OP(adde)
  377 +{
  378 + T2 = T0;
  379 + T0 += T1 + xer_ca;
  380 + if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
  381 + xer_ca = 1;
  382 + } else {
  383 + xer_ca = 0;
  384 + }
  385 + RETURN();
  386 +}
  387 +
  388 +PPC_OP(addeo)
  389 +{
  390 + T2 = T0;
  391 + T0 += T1 + xer_ca;
  392 + if (T0 < T2 || (xer_ca == 1 && T0 == T2)) {
  393 + xer_ca = 1;
  394 + } else {
  395 + xer_ca = 0;
  396 + }
  397 + if ((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)) {
  398 + xer_so = 1;
  399 + xer_ov = 1;
  400 + } else {
  401 + xer_ov = 0;
  402 + }
  403 + RETURN();
  404 +}
  405 +
  406 +/* add immediate */
  407 +PPC_OP(addi)
  408 +{
  409 + T0 += PARAM(1);
  410 + RETURN();
  411 +}
  412 +
  413 +/* add immediate carrying */
  414 +PPC_OP(addic)
  415 +{
  416 + T1 = T0;
  417 + T0 += PARAM(1);
  418 + if (T0 < T1) {
  419 + xer_ca = 1;
  420 + } else {
  421 + xer_ca = 0;
  422 + }
  423 + RETURN();
  424 +}
  425 +
  426 +/* add to minus one extended */
  427 +PPC_OP(addme)
  428 +{
  429 + T1 = T0;
  430 + T0 += xer_ca + (-1);
  431 + if (T1 != 0)
  432 + xer_ca = 1;
  433 + RETURN();
  434 +}
  435 +
  436 +PPC_OP(addmeo)
  437 +{
  438 + T1 = T0;
  439 + T0 += xer_ca + (-1);
  440 + if (T1 & (T1 ^ T0) & (1 << 31)) {
  441 + xer_so = 1;
  442 + xer_ov = 1;
  443 + } else {
  444 + xer_ov = 0;
  445 + }
  446 + if (T1 != 0)
  447 + xer_ca = 1;
  448 + RETURN();
  449 +}
  450 +
  451 +/* add to zero extended */
  452 +PPC_OP(addze)
  453 +{
  454 + T1 = T0;
  455 + T0 += xer_ca;
  456 + if (T0 < T1) {
  457 + xer_ca = 1;
  458 + } else {
  459 + xer_ca = 0;
  460 + }
  461 + RETURN();
  462 +}
  463 +
  464 +PPC_OP(addzeo)
  465 +{
  466 + T1 = T0;
  467 + T0 += xer_ca;
  468 + if ((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)) {
  469 + xer_so = 1;
  470 + xer_ov = 1;
  471 + } else {
  472 + xer_ov = 0;
  473 + }
  474 + if (T0 < T1) {
  475 + xer_ca = 1;
  476 + } else {
  477 + xer_ca = 0;
  478 + }
  479 + RETURN();
  480 +}
  481 +
  482 +/* divide word */
  483 +/* candidate for helper (too long) */
  484 +PPC_OP(divw)
  485 +{
  486 + if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
  487 + Ts0 = (-1) * (T0 >> 31);
  488 + } else {
  489 + Ts0 /= Ts1;
  490 + }
  491 + RETURN();
  492 +}
  493 +
  494 +PPC_OP(divwo)
  495 +{
  496 + if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
  497 + xer_so = 1;
  498 + xer_ov = 1;
  499 + T0 = (-1) * (T0 >> 31);
  500 + } else {
  501 + xer_ov = 0;
  502 + Ts0 /= Ts1;
  503 + }
  504 + RETURN();
  505 +}
  506 +
  507 +/* divide word unsigned */
  508 +PPC_OP(divwu)
  509 +{
  510 + if (T1 == 0) {
  511 + T0 = 0;
  512 + } else {
  513 + T0 /= T1;
  514 + }
  515 + RETURN();
  516 +}
  517 +
  518 +PPC_OP(divwuo)
  519 +{
  520 + if (T1 == 0) {
  521 + xer_so = 1;
  522 + xer_ov = 1;
  523 + T0 = 0;
  524 + } else {
  525 + xer_ov = 0;
  526 + T0 /= T1;
  527 + }
  528 + RETURN();
  529 +}
  530 +
  531 +/* multiply high word */
  532 +PPC_OP(mulhw)
  533 +{
  534 + Ts0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
  535 + RETURN();
  536 +}
  537 +
  538 +/* multiply high word unsigned */
  539 +PPC_OP(mulhwu)
  540 +{
  541 + T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
  542 + RETURN();
  543 +}
  544 +
  545 +/* multiply low immediate */
  546 +PPC_OP(mulli)
  547 +{
  548 + Ts0 *= SPARAM(1);
  549 + RETURN();
  550 +}
  551 +
  552 +/* multiply low word */
  553 +PPC_OP(mullw)
  554 +{
  555 + T0 *= T1;
  556 + RETURN();
  557 +}
  558 +
  559 +PPC_OP(mullwo)
  560 +{
  561 + int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
  562 +
  563 + if ((int32_t)res != res) {
  564 + xer_ov = 1;
  565 + xer_so = 1;
  566 + } else {
  567 + xer_ov = 0;
  568 + }
  569 + Ts0 = res;
  570 + RETURN();
  571 +}
  572 +
  573 +/* negate */
  574 +PPC_OP(neg)
  575 +{
  576 + if (T0 != 0x80000000) {
  577 + Ts0 = -Ts0;
  578 + }
  579 + RETURN();
  580 +}
  581 +
  582 +PPC_OP(nego)
  583 +{
  584 + if (T0 == 0x80000000) {
  585 + xer_ov = 1;
  586 + xer_so = 1;
  587 + } else {
  588 + xer_ov = 0;
  589 + Ts0 = -Ts0;
  590 + }
  591 + RETURN();
  592 +}
  593 +
  594 +/* substract from */
  595 +PPC_OP(subf)
  596 +{
  597 + T0 = T1 - T0;
  598 + RETURN();
  599 +}
  600 +
  601 +PPC_OP(subfo)
  602 +{
  603 + T2 = T0;
  604 + T0 = T1 - T0;
  605 + if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
  606 + xer_so = 1;
  607 + xer_ov = 1;
  608 + } else {
  609 + xer_ov = 0;
  610 + }
  611 + RETURN();
  612 +}
  613 +
  614 +/* substract from carrying */
  615 +PPC_OP(subfc)
  616 +{
  617 + T0 = T1 - T0;
  618 + if (T0 <= T1) {
  619 + xer_ca = 1;
  620 + } else {
  621 + xer_ca = 0;
  622 + }
  623 + RETURN();
  624 +}
  625 +
  626 +PPC_OP(subfco)
  627 +{
  628 + T2 = T0;
  629 + T0 = T1 - T0;
  630 + if (T0 <= T1) {
  631 + xer_ca = 1;
  632 + } else {
  633 + xer_ca = 0;
  634 + }
  635 + if (((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)) {
  636 + xer_so = 1;
  637 + xer_ov = 1;
  638 + } else {
  639 + xer_ov = 0;
  640 + }
  641 + RETURN();
  642 +}
  643 +
  644 +/* substract from extended */
  645 +/* candidate for helper (too long) */
  646 +PPC_OP(subfe)
  647 +{
  648 + T0 = T1 + ~T0 + xer_ca;
  649 + if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
  650 + xer_ca = 1;
  651 + } else {
  652 + xer_ca = 0;
  653 + }
  654 + RETURN();
  655 +}
  656 +
  657 +PPC_OP(subfeo)
  658 +{
  659 + T2 = T0;
  660 + T0 = T1 + ~T0 + xer_ca;
  661 + if ((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)) {
  662 + xer_so = 1;
  663 + xer_ov = 1;
  664 + } else {
  665 + xer_ov = 0;
  666 + }
  667 + if (T0 < T1 || (xer_ca == 1 && T0 == T1)) {
  668 + xer_ca = 1;
  669 + } else {
  670 + xer_ca = 0;
  671 + }
  672 + RETURN();
  673 +}
  674 +
  675 +/* substract from immediate carrying */
  676 +PPC_OP(subfic)
  677 +{
  678 + T0 = PARAM(1) + ~T0 + 1;
  679 + if (T0 <= PARAM(1)) {
  680 + xer_ca = 1;
  681 + } else {
  682 + xer_ca = 0;
  683 + }
  684 + RETURN();
  685 +}
  686 +
  687 +/* substract from minus one extended */
  688 +PPC_OP(subfme)
  689 +{
  690 + T0 = ~T0 + xer_ca - 1;
  691 +
  692 + if (T0 != -1)
  693 + xer_ca = 1;
  694 + RETURN();
  695 +}
  696 +
  697 +PPC_OP(subfmeo)
  698 +{
  699 + T1 = T0;
  700 + T0 = ~T0 + xer_ca - 1;
  701 + if (~T1 & (~T1 ^ T0) & (1 << 31)) {
  702 + xer_so = 1;
  703 + xer_ov = 1;
  704 + } else {
  705 + xer_ov = 0;
  706 + }
  707 + if (T1 != -1)
  708 + xer_ca = 1;
  709 + RETURN();
  710 +}
  711 +
  712 +/* substract from zero extended */
  713 +PPC_OP(subfze)
  714 +{
  715 + T1 = ~T0;
  716 + T0 = T1 + xer_ca;
  717 + if (T0 < T1) {
  718 + xer_ca = 1;
  719 + } else {
  720 + xer_ca = 0;
  721 + }
  722 + RETURN();
  723 +}
  724 +
  725 +PPC_OP(subfzeo)
  726 +{
  727 + T1 = T0;
  728 + T0 = ~T0 + xer_ca;
  729 + if ((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)) {
  730 + xer_ov = 1;
  731 + xer_so = 1;
  732 + } else {
  733 + xer_ov = 0;
  734 + }
  735 + if (T0 < ~T1) {
  736 + xer_ca = 1;
  737 + } else {
  738 + xer_ca = 0;
  739 + }
  740 + RETURN();
  741 +}
  742 +
  743 +/*** Integer comparison ***/
  744 +/* compare */
  745 +PPC_OP(cmp)
  746 +{
  747 + if (Ts0 < Ts1) {
  748 + T0 = 0x08;
  749 + } else if (Ts0 > Ts1) {
  750 + T0 = 0x04;
  751 + } else {
  752 + T0 = 0x02;
  753 + }
  754 + RETURN();
  755 +}
  756 +
  757 +/* compare immediate */
  758 +PPC_OP(cmpi)
  759 +{
  760 + if (Ts0 < SPARAM(1)) {
  761 + T0 = 0x08;
  762 + } else if (Ts0 > SPARAM(1)) {
  763 + T0 = 0x04;
  764 + } else {
  765 + T0 = 0x02;
  766 + }
  767 + RETURN();
  768 +}
  769 +
  770 +/* compare logical */
  771 +PPC_OP(cmpl)
  772 +{
  773 + if (T0 < T1) {
  774 + T0 = 0x08;
  775 + } else if (T0 > T1) {
  776 + T0 = 0x04;
  777 + } else {
  778 + T0 = 0x02;
  779 + }
  780 + RETURN();
  781 +}
  782 +
  783 +/* compare logical immediate */
  784 +PPC_OP(cmpli)
  785 +{
  786 + if (T0 < PARAM(1)) {
  787 + T0 = 0x08;
  788 + } else if (T0 > PARAM(1)) {
  789 + T0 = 0x04;
  790 + } else {
  791 + T0 = 0x02;
  792 + }
  793 + RETURN();
  794 +}
  795 +
  796 +/*** Integer logical ***/
  797 +/* and */
  798 +PPC_OP(and)
  799 +{
  800 + T0 &= T1;
  801 + RETURN();
  802 +}
  803 +
  804 +/* andc */
  805 +PPC_OP(andc)
  806 +{
  807 + T0 &= ~T1;
  808 + RETURN();
  809 +}
  810 +
  811 +/* andi. */
  812 +PPC_OP(andi_)
  813 +{
  814 + T0 &= PARAM(1);
  815 + RETURN();
  816 +}
  817 +
  818 +/* count leading zero */
  819 +PPC_OP(cntlzw)
  820 +{
  821 + T1 = T0;
  822 + for (T0 = 32; T1 > 0; T0--)
  823 + T1 = T1 >> 1;
  824 + RETURN();
  825 +}
  826 +
  827 +/* eqv */
  828 +PPC_OP(eqv)
  829 +{
  830 + T0 = ~(T0 ^ T1);
  831 + RETURN();
  832 +}
  833 +
  834 +/* extend sign byte */
  835 +PPC_OP(extsb)
  836 +{
  837 + Ts0 = s_ext8(Ts0);
  838 + RETURN();
  839 +}
  840 +
  841 +/* extend sign half word */
  842 +PPC_OP(extsh)
  843 +{
  844 + Ts0 = s_ext16(Ts0);
  845 + RETURN();
  846 +}
  847 +
  848 +/* nand */
  849 +PPC_OP(nand)
  850 +{
  851 + T0 = ~(T0 & T1);
  852 + RETURN();
  853 +}
  854 +
  855 +/* nor */
  856 +PPC_OP(nor)
  857 +{
  858 + T0 = ~(T0 | T1);
  859 + RETURN();
  860 +}
  861 +
  862 +/* or */
  863 +PPC_OP(or)
  864 +{
  865 + T0 |= T1;
  866 + RETURN();
  867 +}
  868 +
  869 +/* orc */
  870 +PPC_OP(orc)
  871 +{
  872 + T0 |= ~T1;
  873 + RETURN();
  874 +}
  875 +
  876 +/* ori */
  877 +PPC_OP(ori)
  878 +{
  879 + T0 |= PARAM(1);
  880 + RETURN();
  881 +}
  882 +
  883 +/* xor */
  884 +PPC_OP(xor)
  885 +{
  886 + T0 ^= T1;
  887 + RETURN();
  888 +}
  889 +
  890 +/* xori */
  891 +PPC_OP(xori)
  892 +{
  893 + T0 ^= PARAM(1);
  894 + RETURN();
  895 +}
  896 +
  897 +/*** Integer rotate ***/
  898 +/* rotate left word immediate then mask insert */
  899 +PPC_OP(rlwimi)
  900 +{
  901 + T0 = rotl(T0, PARAM(1) & PARAM(2)) | (T0 & PARAM(3));
  902 + RETURN();
  903 +}
  904 +
  905 +/* rotate left immediate then and with mask insert */
  906 +PPC_OP(rotlwi)
  907 +{
  908 + T0 = rotl(T0, PARAM(1));
  909 + RETURN();
  910 +}
  911 +
  912 +PPC_OP(slwi)
  913 +{
  914 + T0 = T0 << PARAM(1);
  915 + RETURN();
  916 +}
  917 +
  918 +PPC_OP(srwi)
  919 +{
  920 + T0 = T0 >> PARAM(1);
  921 + RETURN();
  922 +}
  923 +
  924 +/* rotate left word then and with mask insert */
  925 +PPC_OP(rlwinm)
  926 +{
  927 + T0 = rotl(T0, PARAM(1)) & PARAM(2);
  928 + RETURN();
  929 +}
  930 +
  931 +PPC_OP(rotl)
  932 +{
  933 + T0 = rotl(T0, T1);
  934 + RETURN();
  935 +}
  936 +
  937 +PPC_OP(rlwnm)
  938 +{
  939 + T0 = rotl(T0, T1) & PARAM(1);
  940 + RETURN();
  941 +}
  942 +
  943 +/*** Integer shift ***/
  944 +/* shift left word */
  945 +PPC_OP(slw)
  946 +{
  947 + if (T1 & 0x20) {
  948 + T0 = 0;
  949 + } else {
  950 + T0 = T0 << T1;
  951 + }
  952 + RETURN();
  953 +}
  954 +
  955 +/* shift right algebraic word */
  956 +PPC_OP(sraw)
  957 +{
  958 + Ts0 = do_sraw(Ts0, T1);
  959 + RETURN();
  960 +}
  961 +
  962 +/* shift right algebraic word immediate */
  963 +PPC_OP(srawi)
  964 +{
  965 + Ts1 = Ts0;
  966 + Ts0 = Ts0 >> PARAM(1);
  967 + if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
  968 + xer_ca = 1;
  969 + } else {
  970 + xer_ca = 0;
  971 + }
  972 + RETURN();
  973 +}
  974 +
  975 +/* shift right word */
  976 +PPC_OP(srw)
  977 +{
  978 + if (T1 & 0x20) {
  979 + T0 = 0;
  980 + } else {
  981 + T0 = T0 >> T1;
  982 + }
  983 + RETURN();
  984 +}
  985 +
  986 +/*** Floating-Point arithmetic ***/
  987 +
  988 +/*** Floating-Point multiply-and-add ***/
  989 +
  990 +/*** Floating-Point round & convert ***/
  991 +
  992 +/*** Floating-Point compare ***/
  993 +
  994 +/*** Floating-Point status & ctrl register ***/
  995 +
  996 +/*** Integer load ***/
  997 +#define ld16x(x) s_ext16(ld16(x))
  998 +#define PPC_ILD_OPX(name, op) \
  999 +PPC_OP(l##name##x_z) \
  1000 +{ \
  1001 + T1 = op(T0); \
  1002 + RETURN(); \
  1003 +} \
  1004 +PPC_OP(l##name##x) \
  1005 +{ \
  1006 + T0 += T1; \
  1007 + T1 = op(T0); \
  1008 + RETURN(); \
  1009 +}
  1010 +
  1011 +#define PPC_ILD_OP(name, op) \
  1012 +PPC_OP(l##name##_z) \
  1013 +{ \
  1014 + T1 = op(SPARAM(1)); \
  1015 + RETURN(); \
  1016 +} \
  1017 +PPC_OP(l##name) \
  1018 +{ \
  1019 + T0 += SPARAM(1); \
  1020 + T1 = op(T0); \
  1021 + RETURN(); \
  1022 +} \
  1023 +PPC_ILD_OPX(name, op)
  1024 +
  1025 +PPC_ILD_OP(bz, ld8);
  1026 +PPC_ILD_OP(ha, ld16x);
  1027 +PPC_ILD_OP(hz, ld16);
  1028 +PPC_ILD_OP(wz, ld32);
  1029 +
  1030 +/*** Integer store ***/
  1031 +#define PPC_IST_OPX(name, op) \
  1032 +PPC_OP(st##name##x_z) \
  1033 +{ \
  1034 + op(T0, T1); \
  1035 + RETURN(); \
  1036 +} \
  1037 +PPC_OP(st##name##x) \
  1038 +{ \
  1039 + T0 += T1; \
  1040 + op(T0, T2); \
  1041 + RETURN(); \
  1042 +}
  1043 +
  1044 +#define PPC_IST_OP(name, op) \
  1045 +PPC_OP(st##name##_z) \
  1046 +{ \
  1047 + op(SPARAM(1), T0); \
  1048 + RETURN(); \
  1049 +} \
  1050 +PPC_OP(st##name) \
  1051 +{ \
  1052 + T0 += SPARAM(1); \
  1053 + op(T0, T1); \
  1054 + RETURN(); \
  1055 +} \
  1056 +PPC_IST_OPX(name, op);
  1057 +
  1058 +PPC_IST_OP(b, st8);
  1059 +PPC_IST_OP(h, st16);
  1060 +PPC_IST_OP(w, st32);
  1061 +
  1062 +/*** Integer load and store with byte reverse ***/
  1063 +PPC_ILD_OPX(hbr, ld16r);
  1064 +PPC_ILD_OPX(wbr, ld32r);
  1065 +PPC_IST_OPX(hbr, st16r);
  1066 +PPC_IST_OPX(wbr, st32r);
  1067 +
  1068 +/*** Integer load and store multiple ***/
  1069 +PPC_OP(lmw)
  1070 +{
  1071 + do_lmw(PARAM(1), SPARAM(2) + T0);
  1072 + RETURN();
  1073 +}
  1074 +
  1075 +PPC_OP(stmw)
  1076 +{
  1077 + do_stmw(PARAM(1), SPARAM(2) + T0);
  1078 + RETURN();
  1079 +}
  1080 +
  1081 +/*** Integer load and store strings ***/
  1082 +PPC_OP(lswi)
  1083 +{
  1084 + do_lsw(PARAM(1), PARAM(2), T0);
  1085 + RETURN();
  1086 +}
  1087 +
  1088 +PPC_OP(lswx)
  1089 +{
  1090 + do_lsw(PARAM(1), T0, T1 + T2);
  1091 + RETURN();
  1092 +}
  1093 +
  1094 +PPC_OP(stswi_z)
  1095 +{
  1096 + do_stsw(PARAM(1), PARAM(2), 0);
  1097 + RETURN();
  1098 +}
  1099 +
  1100 +PPC_OP(stswi)
  1101 +{
  1102 + do_stsw(PARAM(1), PARAM(2), T0);
  1103 + RETURN();
  1104 +}
  1105 +
  1106 +PPC_OP(stswx_z)
  1107 +{
  1108 + do_stsw(PARAM(1), T0, T1);
  1109 + RETURN();
  1110 +}
  1111 +
  1112 +PPC_OP(stswx)
  1113 +{
  1114 + do_stsw(PARAM(1), T0, T1 + T2);
  1115 + RETURN();
  1116 +}
... ...
target-ppc/op.tpl 0 → 100644
  1 +/*
  2 + * PPC emulation micro-operations for qemu.
  3 + *
  4 + * Copyright (c) 2003 Jocelyn Mayer
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +
  21 +/* Host registers definitions */
  22 +$DEFH T 3
  23 +/* PPC registers definitions */
  24 +$DEF gpr 32
  25 +$DEF fpr 32
  26 +$DEF crf 8
  27 +$DEF spr 1024
  28 +
  29 +/* PPC registers <-> host registers move */
  30 +/* GPR */
  31 +$OP load_gpr_T0 gpr
  32 +{
  33 + T0 = regs->gpra;
  34 + RETURN();
  35 +}
  36 +$ENDOP
  37 +
  38 +$OP load_gpr_T1 gpr
  39 +{
  40 + T1 = regs->gpra;
  41 + RETURN();
  42 +}
  43 +$ENDOP
  44 +
  45 +$OP load_gpr_T2 gpr
  46 +{
  47 + T2 = regs->gpra;
  48 + RETURN();
  49 +}
  50 +$ENDOP
  51 +
  52 +$OP store_T0_gpr gpr
  53 +{
  54 + regs->gpra = T0;
  55 + RETURN();
  56 +}
  57 +$ENDOP
  58 +
  59 +$OP store_T1_gpr gpr
  60 +{
  61 + regs->gpra = T1;
  62 + RETURN();
  63 +}
  64 +$ENDOP
  65 +
  66 +$OP store_gpr_P gpr PARAM
  67 +{
  68 + regs->gpra = PARAM(1);
  69 + RETURN();
  70 +}
  71 +$ENDOP
  72 +
  73 +/* crf */
  74 +$OP load_crf_T0 crf
  75 +{
  76 + T0 = regs->crfa;
  77 + RETURN();
  78 +}
  79 +$ENDOP
  80 +
  81 +$OP load_crf_T1 crf
  82 +{
  83 + T1 = regs->crfa;
  84 + RETURN();
  85 +}
  86 +$ENDOP
  87 +
  88 +$OP store_T0_crf crf
  89 +{
  90 + regs->crfa = T0;
  91 + RETURN();
  92 +}
  93 +$ENDOP
  94 +
  95 +$OP store_T1_crf crf
  96 +{
  97 + regs->crfa = T1;
  98 + RETURN();
  99 +}
  100 +$ENDOP
  101 +
  102 +/* SPR */
  103 +$OP load_spr spr
  104 +{
  105 + T0 = regs->spra;
  106 + RETURN();
  107 +}
  108 +$ENDOP
  109 +
  110 +$OP store_spr spr
  111 +{
  112 + regs->spra = T0;
  113 + RETURN();
  114 +}
  115 +$ENDOP
  116 +
  117 +/* FPSCR */
  118 +$OP load_fpscr fpr
  119 +{
  120 + regs->fpra = do_load_fpscr();
  121 + RETURN();
  122 +}
  123 +$ENDOP
  124 +
  125 +$OP store_fpscr fpr PARAM
  126 +{
  127 + do_store_fpscr(PARAM(1), regs->fpra);
  128 + RETURN();
  129 +}
  130 +$ENDOP
  131 +
  132 +/*** Floating-point store ***/
  133 +/* candidate for helper (too long on x86 host) */
  134 +$OP stfd_z fpr PARAM
  135 +{
  136 + st64(SPARAM(1), regs->fpra);
  137 + RETURN();
  138 +}
  139 +$ENDOP
  140 +
  141 +/* candidate for helper (too long on x86 host) */
  142 +$OP stfd fpr PARAM
  143 +{
  144 + T0 += SPARAM(1);
  145 + st64(T0, regs->fpra);
  146 + RETURN();
  147 +}
  148 +$ENDOP
  149 +
  150 +/* candidate for helper (too long on x86 host) */
  151 +$OP stfdx_z fpr
  152 +{
  153 + st64(T0, regs->fpra);
  154 + RETURN();
  155 +}
  156 +$ENDOP
  157 +/* candidate for helper (too long on x86 host) */
  158 +$OP stfdx fpr
  159 +{
  160 + T0 += T1;
  161 + st64(T0, regs->fpra);
  162 + RETURN();
  163 +}
  164 +$ENDOP
  165 +
  166 +/* candidate for helper (too long on x86 host) */
  167 +$OP lfd_z fpr PARAM
  168 +{
  169 + regs->fpra = ld64(SPARAM(1));
  170 + RETURN();
  171 +}
  172 +$ENDOP
  173 +
  174 +/* candidate for helper (too long) */
  175 +$OP lfd fpr PARAM
  176 +{
  177 + T0 += SPARAM(1);
  178 + regs->fpra = ld64(T0);
  179 + RETURN();
  180 +}
  181 +$ENDOP
  182 +
  183 +$OP lfdx_z fpr
  184 +{
  185 + regs->fpra = ld64(T0);
  186 + RETURN();
  187 +}
  188 +$ENDOP
  189 +
  190 +$OP lfdx fpr
  191 +{
  192 + T0 += T1;
  193 + regs->fpra = ld64(T0);
  194 + RETURN();
  195 +}
  196 +$ENDOP
  197 +/*****************************************************************************/
... ...
target-ppc/translate.c 0 → 100644
  1 +/*
  2 + * PPC emulation for qemu: main translation routines.
  3 + *
  4 + * Copyright (c) 2003 Jocelyn Mayer
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +#include "dyngen-exec.h"
  21 +#include "cpu.h"
  22 +#include "exec.h"
  23 +#include "disas.h"
  24 +
  25 +//#define DO_SINGLE_STEP
  26 +//#define DO_STEP_FLUSH
  27 +
  28 +enum {
  29 +#define DEF(s, n, copy_size) INDEX_op_ ## s,
  30 +#include "opc.h"
  31 +#undef DEF
  32 + NB_OPS,
  33 +};
  34 +
  35 +static uint16_t *gen_opc_ptr;
  36 +static uint32_t *gen_opparam_ptr;
  37 +
  38 +#include "gen-op.h"
  39 +#include "select.h"
  40 +
  41 +static uint8_t spr_access[1024 / 2];
  42 +
  43 +/* internal defines */
  44 +typedef struct DisasContext {
  45 + struct TranslationBlock *tb;
  46 + uint32_t *nip;
  47 + uint32_t opcode;
  48 + int exception;
  49 + int retcode;
  50 + /* Time base */
  51 + uint32_t tb_offset;
  52 + int supervisor;
  53 +} DisasContext;
  54 +
  55 +typedef struct opc_handler_t {
  56 + /* invalid bits */
  57 + uint32_t inval;
  58 + /* handler */
  59 + void (*handler)(DisasContext *ctx);
  60 +} opc_handler_t;
  61 +
  62 +#define SET_RETVAL(n) \
  63 +do { \
  64 + if ((n) != 0) { \
  65 + ctx->exception = (n); \
  66 + } \
  67 + return; \
  68 +} while (0)
  69 +
  70 +#define GET_RETVAL(func, __opcode) \
  71 +({ \
  72 + (func)(&ctx); \
  73 + ctx.exception; \
  74 +})
  75 +
  76 +#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
  77 +static void gen_##name (DisasContext *ctx); \
  78 +GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
  79 +static void gen_##name (DisasContext *ctx)
  80 +
  81 +/* Instruction types */
  82 +enum {
  83 + PPC_INTEGER = 0x0001, /* CPU has integer operations instructions */
  84 + PPC_FLOAT = 0x0002, /* CPU has floating point operations instructions */
  85 + PPC_FLOW = 0x0004, /* CPU has flow control instructions */
  86 + PPC_MEM = 0x0008, /* CPU has virtual memory instructions */
  87 + PPC_MISC = 0x0010, /* CPU has spr/msr access instructions */
  88 + PPC_EXTERN = 0x0020, /* CPU has external control instructions */
  89 + PPC_SEGMENT = 0x0040, /* CPU has memory segment instructions */
  90 +};
  91 +
  92 +typedef struct opcode_t {
  93 + unsigned char opc1, opc2, opc3;
  94 + uint32_t type;
  95 + opc_handler_t handler;
  96 +} opcode_t;
  97 +
  98 +/* XXX: move that elsewhere */
  99 +extern FILE *logfile;
  100 +extern int loglevel;
  101 +
  102 +/* XXX: shouldn't stay all alone here ! */
  103 +static int reserve = 0;
  104 +
  105 +/*** Instruction decoding ***/
  106 +#define EXTRACT_HELPER(name, shift, nb) \
  107 +static inline uint32_t name (uint32_t opcode) \
  108 +{ \
  109 + return (opcode >> (shift)) & ((1 << (nb)) - 1); \
  110 +}
  111 +
  112 +#define EXTRACT_SHELPER(name, shift, nb) \
  113 +static inline int32_t name (uint32_t opcode) \
  114 +{ \
  115 + return s_ext16((opcode >> (shift)) & ((1 << (nb)) - 1)); \
  116 +}
  117 +
  118 +/* Opcode part 1 */
  119 +EXTRACT_HELPER(opc1, 26, 6);
  120 +/* Opcode part 2 */
  121 +EXTRACT_HELPER(opc2, 1, 5);
  122 +/* Opcode part 3 */
  123 +EXTRACT_HELPER(opc3, 6, 5);
  124 +/* Update Cr0 flags */
  125 +EXTRACT_HELPER(Rc, 0, 1);
  126 +/* Destination */
  127 +EXTRACT_HELPER(rD, 21, 5);
  128 +/* Source */
  129 +EXTRACT_HELPER(rS, 21, 5);
  130 +/* First operand */
  131 +EXTRACT_HELPER(rA, 16, 5);
  132 +/* Second operand */
  133 +EXTRACT_HELPER(rB, 11, 5);
  134 +/* Third operand */
  135 +EXTRACT_HELPER(rC, 6, 5);
  136 +/*** Get CRn ***/
  137 +EXTRACT_HELPER(crfD, 23, 3);
  138 +EXTRACT_HELPER(crfS, 18, 3);
  139 +EXTRACT_HELPER(crbD, 21, 5);
  140 +EXTRACT_HELPER(crbA, 16, 5);
  141 +EXTRACT_HELPER(crbB, 11, 5);
  142 +/* SPR / TBL */
  143 +EXTRACT_HELPER(SPR, 11, 10);
  144 +/*** Get constants ***/
  145 +EXTRACT_HELPER(IMM, 12, 8);
  146 +/* 16 bits signed immediate value */
  147 +EXTRACT_SHELPER(SIMM, 0, 16);
  148 +/* 16 bits unsigned immediate value */
  149 +EXTRACT_HELPER(UIMM, 0, 16);
  150 +/* Bit count */
  151 +EXTRACT_HELPER(NB, 11, 5);
  152 +/* Shift count */
  153 +EXTRACT_HELPER(SH, 11, 5);
  154 +/* Mask start */
  155 +EXTRACT_HELPER(MB, 6, 5);
  156 +/* Mask end */
  157 +EXTRACT_HELPER(ME, 1, 5);
  158 +
  159 +EXTRACT_HELPER(CRM, 12, 8);
  160 +EXTRACT_HELPER(FM, 17, 8);
  161 +EXTRACT_HELPER(SR, 16, 4);
  162 +/*** Jump target decoding ***/
  163 +/* Displacement */
  164 +EXTRACT_SHELPER(d, 0, 16);
  165 +/* Immediate address */
  166 +static inline uint32_t LI (uint32_t opcode)
  167 +{
  168 + return (opcode >> 0) & 0x03FFFFFC;
  169 +}
  170 +
  171 +static inline uint32_t BD (uint32_t opcode)
  172 +{
  173 + return (opcode >> 0) & 0xFFFC;
  174 +}
  175 +
  176 +EXTRACT_HELPER(BO, 21, 5);
  177 +EXTRACT_HELPER(BI, 16, 5);
  178 +/* Absolute/relative address */
  179 +EXTRACT_HELPER(AA, 1, 1);
  180 +/* Link */
  181 +EXTRACT_HELPER(LK, 0, 1);
  182 +
  183 +/* Create a mask between <start> and <end> bits */
  184 +static inline uint32_t MASK (uint32_t start, uint32_t end)
  185 +{
  186 + uint32_t ret;
  187 +
  188 + ret = (((uint32_t)(-1)) >> (start)) ^ (((uint32_t)(-1) >> (end)) >> 1);
  189 + if (start > end)
  190 + return ~ret;
  191 +
  192 + return ret;
  193 +}
  194 +
  195 +#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
  196 +__attribute__ ((section(".opcodes"), unused)) \
  197 +static opcode_t opc_##name = { \
  198 + .opc1 = op1, \
  199 + .opc2 = op2, \
  200 + .opc3 = op3, \
  201 + .type = _typ, \
  202 + .handler = { \
  203 + .inval = invl, \
  204 + .handler = &gen_##name, \
  205 + }, \
  206 +}
  207 +
  208 +#define GEN_OPCODE_MARK(name) \
  209 +__attribute__ ((section(".opcodes"), unused)) \
  210 +static opcode_t opc_##name = { \
  211 + .opc1 = 0xFF, \
  212 + .opc2 = 0xFF, \
  213 + .opc3 = 0xFF, \
  214 + .type = 0x00, \
  215 + .handler = { \
  216 + .inval = 0x00000000, \
  217 + .handler = NULL, \
  218 + }, \
  219 +}
  220 +
  221 +/* Start opcode list */
  222 +GEN_OPCODE_MARK(start);
  223 +
  224 +/* Invalid instruction */
  225 +GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, 0)
  226 +{
  227 + /* Branch to next instruction to force nip update */
  228 + gen_op_b((uint32_t)ctx->nip);
  229 + SET_RETVAL(EXCP_INVAL);
  230 +}
  231 +
  232 +static opc_handler_t invalid_handler = {
  233 + .inval = 0xFFFFFFFF,
  234 + .handler = gen_invalid,
  235 +};
  236 +
  237 +/*** Integer arithmetic ***/
  238 +#define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval) \
  239 +GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
  240 +{ \
  241 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  242 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  243 + gen_op_##name(); \
  244 + if (Rc(ctx->opcode) != 0) \
  245 + gen_op_set_Rc0(); \
  246 + gen_op_store_T0_gpr(rD(ctx->opcode)); \
  247 + SET_RETVAL(0); \
  248 +}
  249 +
  250 +#define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval) \
  251 +GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
  252 +{ \
  253 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  254 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  255 + gen_op_##name(); \
  256 + if (Rc(ctx->opcode) != 0) \
  257 + gen_op_set_Rc0_ov(); \
  258 + gen_op_store_T0_gpr(rD(ctx->opcode)); \
  259 + SET_RETVAL(0); \
  260 +}
  261 +
  262 +#define __GEN_INT_ARITH1(name, opc1, opc2, opc3) \
  263 +GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
  264 +{ \
  265 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  266 + gen_op_##name(); \
  267 + if (Rc(ctx->opcode) != 0) \
  268 + gen_op_set_Rc0(); \
  269 + gen_op_store_T0_gpr(rD(ctx->opcode)); \
  270 + SET_RETVAL(0); \
  271 +}
  272 +#define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3) \
  273 +GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
  274 +{ \
  275 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  276 + gen_op_##name(); \
  277 + if (Rc(ctx->opcode) != 0) \
  278 + gen_op_set_Rc0_ov(); \
  279 + gen_op_store_T0_gpr(rD(ctx->opcode)); \
  280 + SET_RETVAL(0); \
  281 +}
  282 +
  283 +/* Two operands arithmetic functions */
  284 +#define GEN_INT_ARITH2(name, opc1, opc2, opc3) \
  285 +__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000) \
  286 +__GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000)
  287 +
  288 +/* Two operands arithmetic functions with no overflow allowed */
  289 +#define GEN_INT_ARITHN(name, opc1, opc2, opc3) \
  290 +__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400)
  291 +
  292 +/* One operand arithmetic functions */
  293 +#define GEN_INT_ARITH1(name, opc1, opc2, opc3) \
  294 +__GEN_INT_ARITH1(name, opc1, opc2, opc3) \
  295 +__GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10)
  296 +
  297 +/* add add. addo addo. */
  298 +GEN_INT_ARITH2 (add, 0x1F, 0x0A, 0x08);
  299 +/* addc addc. addco addco. */
  300 +GEN_INT_ARITH2 (addc, 0x1F, 0x0A, 0x00);
  301 +/* adde adde. addeo addeo. */
  302 +GEN_INT_ARITH2 (adde, 0x1F, 0x0A, 0x04);
  303 +/* addme addme. addmeo addmeo. */
  304 +GEN_INT_ARITH1 (addme, 0x1F, 0x0A, 0x07);
  305 +/* addze addze. addzeo addzeo. */
  306 +GEN_INT_ARITH1 (addze, 0x1F, 0x0A, 0x06);
  307 +/* divw divw. divwo divwo. */
  308 +GEN_INT_ARITH2 (divw, 0x1F, 0x0B, 0x0F);
  309 +/* divwu divwu. divwuo divwuo. */
  310 +GEN_INT_ARITH2 (divwu, 0x1F, 0x0B, 0x0E);
  311 +/* mulhw mulhw. */
  312 +GEN_INT_ARITHN (mulhw, 0x1F, 0x0B, 0x02);
  313 +/* mulhwu mulhwu. */
  314 +GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00);
  315 +/* mullw mullw. mullwo mullwo. */
  316 +GEN_INT_ARITH2 (mullw, 0x1F, 0x0B, 0x07);
  317 +/* neg neg. nego nego. */
  318 +GEN_INT_ARITH1 (neg, 0x1F, 0x08, 0x03);
  319 +/* subf subf. subfo subfo. */
  320 +GEN_INT_ARITH2 (subf, 0x1F, 0x08, 0x01);
  321 +/* subfc subfc. subfco subfco. */
  322 +GEN_INT_ARITH2 (subfc, 0x1F, 0x08, 0x00);
  323 +/* subfe subfe. subfeo subfeo. */
  324 +GEN_INT_ARITH2 (subfe, 0x1F, 0x08, 0x04);
  325 +/* subfme subfme. subfmeo subfmeo. */
  326 +GEN_INT_ARITH1 (subfme, 0x1F, 0x08, 0x07);
  327 +/* subfze subfze. subfzeo subfzeo. */
  328 +GEN_INT_ARITH1 (subfze, 0x1F, 0x08, 0x06);
  329 +/* addi */
  330 +GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  331 +{
  332 + int32_t simm = SIMM(ctx->opcode);
  333 +
  334 + if (rA(ctx->opcode) == 0) {
  335 + gen_op_set_T0(simm);
  336 + } else {
  337 + gen_op_load_gpr_T0(rA(ctx->opcode));
  338 + gen_op_addi(simm);
  339 + }
  340 + gen_op_store_T0_gpr(rD(ctx->opcode));
  341 + SET_RETVAL(0);
  342 +}
  343 +/* addic */
  344 +GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  345 +{
  346 + gen_op_load_gpr_T0(rA(ctx->opcode));
  347 + gen_op_addic(SIMM(ctx->opcode));
  348 + gen_op_store_T0_gpr(rD(ctx->opcode));
  349 + SET_RETVAL(0);
  350 +}
  351 +/* addic. */
  352 +GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  353 +{
  354 + gen_op_load_gpr_T0(rA(ctx->opcode));
  355 + gen_op_addic(SIMM(ctx->opcode));
  356 + gen_op_set_Rc0();
  357 + gen_op_store_T0_gpr(rD(ctx->opcode));
  358 + SET_RETVAL(0);
  359 +}
  360 +/* addis */
  361 +GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  362 +{
  363 + int32_t simm = SIMM(ctx->opcode);
  364 +
  365 + if (rA(ctx->opcode) == 0) {
  366 + gen_op_set_T0(simm << 16);
  367 + } else {
  368 + gen_op_load_gpr_T0(rA(ctx->opcode));
  369 + gen_op_addi(simm << 16);
  370 + }
  371 + gen_op_store_T0_gpr(rD(ctx->opcode));
  372 + SET_RETVAL(0);
  373 +}
  374 +/* mulli */
  375 +GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  376 +{
  377 + gen_op_load_gpr_T0(rA(ctx->opcode));
  378 + gen_op_mulli(SIMM(ctx->opcode));
  379 + gen_op_store_T0_gpr(rD(ctx->opcode));
  380 + SET_RETVAL(0);
  381 +}
  382 +/* subfic */
  383 +GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  384 +{
  385 + gen_op_load_gpr_T0(rA(ctx->opcode));
  386 + gen_op_subfic(SIMM(ctx->opcode));
  387 + gen_op_store_T0_gpr(rD(ctx->opcode));
  388 + SET_RETVAL(0);
  389 +}
  390 +
  391 +/*** Integer comparison ***/
  392 +#define GEN_CMP(name, opc) \
  393 +GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, PPC_INTEGER) \
  394 +{ \
  395 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  396 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  397 + gen_op_##name(); \
  398 + gen_op_store_T0_crf(crfD(ctx->opcode)); \
  399 + SET_RETVAL(0); \
  400 +}
  401 +
  402 +/* cmp */
  403 +GEN_CMP(cmp, 0x00);
  404 +/* cmpi */
  405 +GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
  406 +{
  407 + gen_op_load_gpr_T0(rA(ctx->opcode));
  408 + gen_op_cmpi(SIMM(ctx->opcode));
  409 + gen_op_store_T0_crf(crfD(ctx->opcode));
  410 + SET_RETVAL(0);
  411 +}
  412 +/* cmpl */
  413 +GEN_CMP(cmpl, 0x01);
  414 +/* cmpli */
  415 +GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
  416 +{
  417 + gen_op_load_gpr_T0(rA(ctx->opcode));
  418 + gen_op_cmpli(UIMM(ctx->opcode));
  419 + gen_op_store_T0_crf(crfD(ctx->opcode));
  420 + SET_RETVAL(0);
  421 +}
  422 +
  423 +/*** Integer logical ***/
  424 +#define __GEN_LOGICAL2(name, opc2, opc3) \
  425 +GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, PPC_INTEGER) \
  426 +{ \
  427 + gen_op_load_gpr_T0(rS(ctx->opcode)); \
  428 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  429 + gen_op_##name(); \
  430 + if (Rc(ctx->opcode) != 0) \
  431 + gen_op_set_Rc0(); \
  432 + gen_op_store_T0_gpr(rA(ctx->opcode)); \
  433 + SET_RETVAL(0); \
  434 +}
  435 +#define GEN_LOGICAL2(name, opc) \
  436 +__GEN_LOGICAL2(name, 0x1C, opc)
  437 +
  438 +#define GEN_LOGICAL1(name, opc) \
  439 +GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, PPC_INTEGER) \
  440 +{ \
  441 + gen_op_load_gpr_T0(rS(ctx->opcode)); \
  442 + gen_op_##name(); \
  443 + if (Rc(ctx->opcode) != 0) \
  444 + gen_op_set_Rc0(); \
  445 + gen_op_store_T0_gpr(rA(ctx->opcode)); \
  446 + SET_RETVAL(0); \
  447 +}
  448 +
  449 +/* and & and. */
  450 +GEN_LOGICAL2(and, 0x00);
  451 +/* andc & andc. */
  452 +GEN_LOGICAL2(andc, 0x01);
  453 +/* andi. */
  454 +GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  455 +{
  456 + gen_op_load_gpr_T0(rS(ctx->opcode));
  457 + gen_op_andi_(UIMM(ctx->opcode));
  458 + gen_op_set_Rc0();
  459 + gen_op_store_T0_gpr(rA(ctx->opcode));
  460 + SET_RETVAL(0);
  461 +}
  462 +/* andis. */
  463 +GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  464 +{
  465 + gen_op_load_gpr_T0(rS(ctx->opcode));
  466 + gen_op_andi_(UIMM(ctx->opcode) << 16);
  467 + gen_op_set_Rc0();
  468 + gen_op_store_T0_gpr(rA(ctx->opcode));
  469 + SET_RETVAL(0);
  470 +}
  471 +
  472 +/* cntlzw */
  473 +GEN_LOGICAL1(cntlzw, 0x00);
  474 +/* eqv & eqv. */
  475 +GEN_LOGICAL2(eqv, 0x08);
  476 +/* extsb & extsb. */
  477 +GEN_LOGICAL1(extsb, 0x1D);
  478 +/* extsh & extsh. */
  479 +GEN_LOGICAL1(extsh, 0x1C);
  480 +/* nand & nand. */
  481 +GEN_LOGICAL2(nand, 0x0E);
  482 +/* nor & nor. */
  483 +GEN_LOGICAL2(nor, 0x03);
  484 +/* or & or. */
  485 +GEN_LOGICAL2(or, 0x0D);
  486 +/* orc & orc. */
  487 +GEN_LOGICAL2(orc, 0x0C);
  488 +/* xor & xor. */
  489 +GEN_LOGICAL2(xor, 0x09);
  490 +/* ori */
  491 +GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  492 +{
  493 + uint32_t uimm = UIMM(ctx->opcode);
  494 +
  495 +#if 0
  496 + if (uimm == 0) {
  497 + if (rA(ctx->opcode) != rS(ctx->opcode)) {
  498 + gen_op_load_gpr_T0(rS(ctx->opcode));
  499 + gen_op_store_T0_gpr(rA(ctx->opcode));
  500 + }
  501 + } else
  502 +#endif
  503 + {
  504 + gen_op_load_gpr_T0(rS(ctx->opcode));
  505 + gen_op_ori(uimm);
  506 + gen_op_store_T0_gpr(rA(ctx->opcode));
  507 + }
  508 + SET_RETVAL(0);
  509 +}
  510 +/* oris */
  511 +GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  512 +{
  513 + uint32_t uimm = UIMM(ctx->opcode);
  514 +
  515 +#if 0
  516 + if (uimm == 0) {
  517 + if (rA(ctx->opcode) != rS(ctx->opcode)) {
  518 + gen_op_load_gpr_T0(rS(ctx->opcode));
  519 + gen_op_store_T0_gpr(rA(ctx->opcode));
  520 + }
  521 + } else
  522 +#endif
  523 + {
  524 + gen_op_load_gpr_T0(rS(ctx->opcode));
  525 + gen_op_ori(uimm << 16);
  526 + gen_op_store_T0_gpr(rA(ctx->opcode));
  527 + }
  528 + SET_RETVAL(0);
  529 +}
  530 +/* xori */
  531 +GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  532 +{
  533 + gen_op_load_gpr_T0(rS(ctx->opcode));
  534 + gen_op_xori(UIMM(ctx->opcode));
  535 + gen_op_store_T0_gpr(rA(ctx->opcode));
  536 + SET_RETVAL(0);
  537 +}
  538 +
  539 +/* xoris */
  540 +GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  541 +{
  542 + gen_op_load_gpr_T0(rS(ctx->opcode));
  543 + gen_op_xori(UIMM(ctx->opcode) << 16);
  544 + gen_op_store_T0_gpr(rA(ctx->opcode));
  545 + SET_RETVAL(0);
  546 +}
  547 +
  548 +/*** Integer rotate ***/
  549 +/* rlwimi & rlwimi. */
  550 +GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  551 +{
  552 + uint32_t mb, me;
  553 +
  554 + mb = MB(ctx->opcode);
  555 + me = ME(ctx->opcode);
  556 + gen_op_load_gpr_T0(rS(ctx->opcode));
  557 + gen_op_rlwimi(SH(ctx->opcode), MASK(mb, me), ~MASK(mb, me));
  558 + if (Rc(ctx->opcode) != 0)
  559 + gen_op_set_Rc0();
  560 + gen_op_store_T0_gpr(rA(ctx->opcode));
  561 + SET_RETVAL(0);
  562 +}
  563 +/* rlwinm & rlwinm. */
  564 +GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  565 +{
  566 + uint32_t mb, me, sh;
  567 +
  568 + sh = SH(ctx->opcode);
  569 + mb = MB(ctx->opcode);
  570 + me = ME(ctx->opcode);
  571 + gen_op_load_gpr_T0(rS(ctx->opcode));
  572 + if (loglevel > 0) {
  573 + fprintf(logfile, "%s sh=%u mb=%u me=%u MASK=0x%08x\n",
  574 + __func__, sh, mb, me, MASK(mb, me));
  575 + }
  576 + if (mb == 0) {
  577 + if (me == 31) {
  578 + gen_op_rotlwi(sh);
  579 + goto store;
  580 + } else if (me == (31 - sh)) {
  581 + gen_op_slwi(sh);
  582 + goto store;
  583 + } else if (sh == 0) {
  584 + gen_op_andi_(MASK(0, me));
  585 + goto store;
  586 + }
  587 + } else if (me == 31) {
  588 + if (sh == (32 - mb)) {
  589 + gen_op_srwi(mb);
  590 + goto store;
  591 + } else if (sh == 0) {
  592 + gen_op_andi_(MASK(mb, 31));
  593 + goto store;
  594 + }
  595 + }
  596 + gen_op_rlwinm(sh, MASK(mb, me));
  597 +store:
  598 + if (Rc(ctx->opcode) != 0)
  599 + gen_op_set_Rc0();
  600 + gen_op_store_T0_gpr(rA(ctx->opcode));
  601 + SET_RETVAL(0);
  602 +}
  603 +/* rlwnm & rlwnm. */
  604 +GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  605 +{
  606 + uint32_t mb, me;
  607 +
  608 + mb = MB(ctx->opcode);
  609 + me = ME(ctx->opcode);
  610 + gen_op_load_gpr_T0(rS(ctx->opcode));
  611 + gen_op_load_gpr_T1(rB(ctx->opcode));
  612 + if (mb == 0 && me == 31) {
  613 + gen_op_rotl();
  614 + } else
  615 + {
  616 + gen_op_rlwnm(MASK(mb, me));
  617 + }
  618 + if (Rc(ctx->opcode) != 0)
  619 + gen_op_set_Rc0();
  620 + gen_op_store_T0_gpr(rA(ctx->opcode));
  621 + SET_RETVAL(0);
  622 +}
  623 +
  624 +/*** Integer shift ***/
  625 +/* slw & slw. */
  626 +__GEN_LOGICAL2(slw, 0x18, 0x00);
  627 +/* sraw & sraw. */
  628 +__GEN_LOGICAL2(sraw, 0x18, 0x18);
  629 +/* srawi & srawi. */
  630 +GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
  631 +{
  632 + gen_op_load_gpr_T0(rS(ctx->opcode));
  633 + gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31));
  634 + if (Rc(ctx->opcode) != 0)
  635 + gen_op_set_Rc0();
  636 + gen_op_store_T0_gpr(rA(ctx->opcode));
  637 + SET_RETVAL(0);
  638 +}
  639 +/* srw & srw. */
  640 +__GEN_LOGICAL2(srw, 0x18, 0x10);
  641 +
  642 +/*** Floating-Point arithmetic ***/
  643 +/* fadd */
  644 +GEN_HANDLER(fadd, 0x3F, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)
  645 +{
  646 + SET_RETVAL(EXCP_INVAL);
  647 +}
  648 +
  649 +/* fadds */
  650 +GEN_HANDLER(fadds, 0x3B, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)
  651 +{
  652 + SET_RETVAL(EXCP_INVAL);
  653 +}
  654 +
  655 +/* fdiv */
  656 +GEN_HANDLER(fdiv, 0x3F, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)
  657 +{
  658 + SET_RETVAL(EXCP_INVAL);
  659 +}
  660 +
  661 +/* fdivs */
  662 +GEN_HANDLER(fdivs, 0x3B, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)
  663 +{
  664 + SET_RETVAL(EXCP_INVAL);
  665 +}
  666 +
  667 +/* fmul */
  668 +GEN_HANDLER(fmul, 0x3F, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)
  669 +{
  670 + SET_RETVAL(EXCP_INVAL);
  671 +}
  672 +
  673 +/* fmuls */
  674 +GEN_HANDLER(fmuls, 0x3B, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)
  675 +{
  676 + SET_RETVAL(EXCP_INVAL);
  677 +}
  678 +
  679 +/* fres */
  680 +GEN_HANDLER(fres, 0x3B, 0x18, 0xFF, 0x001807C0, PPC_FLOAT)
  681 +{
  682 + SET_RETVAL(EXCP_INVAL);
  683 +}
  684 +
  685 +/* frsqrte */
  686 +GEN_HANDLER(frsqrte, 0x3F, 0x1A, 0xFF, 0x001807C0, PPC_FLOAT)
  687 +{
  688 + SET_RETVAL(EXCP_INVAL);
  689 +}
  690 +
  691 +/* fsel */
  692 +GEN_HANDLER(fsel, 0x3F, 0x17, 0xFF, 0x00000000, PPC_FLOAT)
  693 +{
  694 + SET_RETVAL(EXCP_INVAL);
  695 +}
  696 +
  697 +/* fsub */
  698 +GEN_HANDLER(fsub, 0x3F, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)
  699 +{
  700 + SET_RETVAL(EXCP_INVAL);
  701 +}
  702 +
  703 +/* fsubs */
  704 +GEN_HANDLER(fsubs, 0x3B, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)
  705 +{
  706 + SET_RETVAL(EXCP_INVAL);
  707 +}
  708 +
  709 +/* Optional: */
  710 +/* fsqrt */
  711 +GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001807C0, PPC_FLOAT)
  712 +{
  713 + SET_RETVAL(EXCP_INVAL);
  714 +}
  715 +
  716 +/* fsqrts */
  717 +GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001807C0, PPC_FLOAT)
  718 +{
  719 + SET_RETVAL(EXCP_INVAL);
  720 +}
  721 +
  722 +/*** Floating-Point multiply-and-add ***/
  723 +/* fmadd */
  724 +GEN_HANDLER(fmadd, 0x3F, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)
  725 +{
  726 + SET_RETVAL(EXCP_INVAL);
  727 +}
  728 +
  729 +/* fmadds */
  730 +GEN_HANDLER(fmadds, 0x3B, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)
  731 +{
  732 + SET_RETVAL(EXCP_INVAL);
  733 +}
  734 +
  735 +/* fmsub */
  736 +GEN_HANDLER(fmsub, 0x3F, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)
  737 +{
  738 + SET_RETVAL(EXCP_INVAL);
  739 +}
  740 +
  741 +/* fmsubs */
  742 +GEN_HANDLER(fmsubs, 0x3B, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)
  743 +{
  744 + SET_RETVAL(EXCP_INVAL);
  745 +}
  746 +
  747 +/* fnmadd */
  748 +GEN_HANDLER(fnmadd, 0x3F, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)
  749 +{
  750 + SET_RETVAL(EXCP_INVAL);
  751 +}
  752 +
  753 +/* fnmadds */
  754 +GEN_HANDLER(fnmadds, 0x3B, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)
  755 +{
  756 + SET_RETVAL(EXCP_INVAL);
  757 +}
  758 +
  759 +/* fnmsub */
  760 +GEN_HANDLER(fnmsub, 0x3F, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)
  761 +{
  762 + SET_RETVAL(EXCP_INVAL);
  763 +}
  764 +
  765 +/* fnmsubs */
  766 +GEN_HANDLER(fnmsubs, 0x3B, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)
  767 +{
  768 + SET_RETVAL(EXCP_INVAL);
  769 +}
  770 +
  771 +/*** Floating-Point round & convert ***/
  772 +/* fctiw */
  773 +GEN_HANDLER(fctiw, 0x3F, 0x0E, 0xFF, 0x001F0000, PPC_FLOAT)
  774 +{
  775 + SET_RETVAL(EXCP_INVAL);
  776 +}
  777 +
  778 +/* fctiwz */
  779 +GEN_HANDLER(fctiwz, 0x3F, 0x0F, 0xFF, 0x001F0000, PPC_FLOAT)
  780 +{
  781 + SET_RETVAL(EXCP_INVAL);
  782 +}
  783 +
  784 +/* frsp */
  785 +GEN_HANDLER(frsp, 0x3F, 0x0C, 0xFF, 0x001F0000, PPC_FLOAT)
  786 +{
  787 + SET_RETVAL(EXCP_INVAL);
  788 +}
  789 +
  790 +/*** Floating-Point compare ***/
  791 +/* fcmpo */
  792 +GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
  793 +{
  794 + SET_RETVAL(EXCP_INVAL);
  795 +}
  796 +
  797 +/* fcmpu */
  798 +GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
  799 +{
  800 + SET_RETVAL(EXCP_INVAL);
  801 +}
  802 +
  803 +/*** Floating-Point status & ctrl register ***/
  804 +/* mcrfs */
  805 +GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
  806 +{
  807 + SET_RETVAL(EXCP_INVAL);
  808 +}
  809 +
  810 +/* mffs */
  811 +GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
  812 +{
  813 + gen_op_load_fpscr(rD(ctx->opcode));
  814 + if (Rc(ctx->opcode)) {
  815 + /* Update CR1 */
  816 + }
  817 + SET_RETVAL(0);
  818 +}
  819 +
  820 +/* mtfsb0 */
  821 +GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
  822 +{
  823 + SET_RETVAL(EXCP_INVAL);
  824 +}
  825 +
  826 +/* mtfsb1 */
  827 +GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
  828 +{
  829 + SET_RETVAL(EXCP_INVAL);
  830 +}
  831 +
  832 +/* mtfsf */
  833 +GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
  834 +{
  835 + gen_op_store_fpscr(FM(ctx->opcode), rB(ctx->opcode));
  836 + if (Rc(ctx->opcode)) {
  837 + /* Update CR1 */
  838 + }
  839 + SET_RETVAL(0);
  840 +}
  841 +
  842 +/* mtfsfi */
  843 +GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
  844 +{
  845 + SET_RETVAL(EXCP_INVAL);
  846 +}
  847 +
  848 +/*** Integer load ***/
  849 +#define GEN_ILDZ(width, opc) \
  850 +GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
  851 +{ \
  852 + uint32_t simm = SIMM(ctx->opcode); \
  853 + if (rA(ctx->opcode) == 0) { \
  854 + gen_op_l##width##_z(simm); \
  855 + } else { \
  856 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  857 + gen_op_l##width (simm); \
  858 + } \
  859 + gen_op_store_T1_gpr(rD(ctx->opcode)); \
  860 + SET_RETVAL(0); \
  861 +}
  862 +
  863 +#define GEN_ILDZU(width, opc) \
  864 +GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
  865 +{ \
  866 + if (rA(ctx->opcode) == 0 || \
  867 + rA(ctx->opcode) == rD(ctx->opcode)) \
  868 + SET_RETVAL(EXCP_INVAL); \
  869 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  870 + gen_op_l##width(SIMM(ctx->opcode)); \
  871 + gen_op_store_T1_gpr(rD(ctx->opcode)); \
  872 + gen_op_store_T0_gpr(rA(ctx->opcode)); \
  873 + SET_RETVAL(0); \
  874 +}
  875 +
  876 +#define GEN_ILDZUX(width, opc) \
  877 +GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
  878 +{ \
  879 + if (rA(ctx->opcode) == 0 || \
  880 + rA(ctx->opcode) == rD(ctx->opcode)) \
  881 + SET_RETVAL(EXCP_INVAL); \
  882 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  883 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  884 + gen_op_l##width##x(); \
  885 + gen_op_store_T1_gpr(rD(ctx->opcode)); \
  886 + gen_op_store_T0_gpr(rA(ctx->opcode)); \
  887 + SET_RETVAL(0); \
  888 +}
  889 +
  890 +#define GEN_ILDZX(width, opc2, opc3) \
  891 +GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
  892 +{ \
  893 + if (rA(ctx->opcode) == 0) { \
  894 + gen_op_load_gpr_T0(rB(ctx->opcode)); \
  895 + gen_op_l##width##x_z(); \
  896 + } else { \
  897 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  898 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  899 + gen_op_l##width##x(); \
  900 + } \
  901 + gen_op_store_T1_gpr(rD(ctx->opcode)); \
  902 + SET_RETVAL(0); \
  903 +}
  904 +
  905 +#define GEN_ILD(width, op) \
  906 +GEN_ILDZ(width, op | 0x20) \
  907 +GEN_ILDZU(width, op | 0x21) \
  908 +GEN_ILDZUX(width, op | 0x01) \
  909 +GEN_ILDZX(width, 0x17, op | 0x00)
  910 +
  911 +/* lbz lbzu lbzux lbzx */
  912 +GEN_ILD(bz, 0x02);
  913 +/* lha lhau lhaux lhax */
  914 +GEN_ILD(ha, 0x0A);
  915 +/* lhz lhzu lhzux lhzx */
  916 +GEN_ILD(hz, 0x08);
  917 +/* lwz lwzu lwzux lwzx */
  918 +GEN_ILD(wz, 0x00);
  919 +
  920 +/*** Integer store ***/
  921 +#define GEN_IST(width, opc) \
  922 +GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
  923 +{ \
  924 + uint32_t simm = SIMM(ctx->opcode); \
  925 + if (rA(ctx->opcode) == 0) { \
  926 + gen_op_load_gpr_T0(rS(ctx->opcode)); \
  927 + gen_op_st##width##_z(simm); \
  928 + } else { \
  929 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  930 + gen_op_load_gpr_T1(rS(ctx->opcode)); \
  931 + gen_op_st##width(simm); \
  932 + } \
  933 + SET_RETVAL(0); \
  934 +}
  935 +
  936 +#define GEN_ISTU(width, opc) \
  937 +GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
  938 +{ \
  939 + if (rA(ctx->opcode) == 0) \
  940 + SET_RETVAL(EXCP_INVAL); \
  941 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  942 + gen_op_load_gpr_T1(rS(ctx->opcode)); \
  943 + gen_op_st##width(SIMM(ctx->opcode)); \
  944 + gen_op_store_T0_gpr(rA(ctx->opcode)); \
  945 + SET_RETVAL(0); \
  946 +}
  947 +
  948 +#define GEN_ISTUX(width, opc) \
  949 +GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
  950 +{ \
  951 + if (rA(ctx->opcode) == 0) \
  952 + SET_RETVAL(EXCP_INVAL); \
  953 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  954 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  955 + gen_op_load_gpr_T2(rS(ctx->opcode)); \
  956 + gen_op_st##width##x(); \
  957 + gen_op_store_T0_gpr(rA(ctx->opcode)); \
  958 + SET_RETVAL(0); \
  959 +}
  960 +
  961 +#define GEN_ISTX(width, opc2, opc3) \
  962 +GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
  963 +{ \
  964 + if (rA(ctx->opcode) == 0) { \
  965 + gen_op_load_gpr_T0(rB(ctx->opcode)); \
  966 + gen_op_load_gpr_T1(rS(ctx->opcode)); \
  967 + gen_op_st##width##x_z(); \
  968 + } else { \
  969 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  970 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  971 + gen_op_load_gpr_T2(rS(ctx->opcode)); \
  972 + gen_op_st##width##x(); \
  973 + } \
  974 + SET_RETVAL(0); \
  975 +}
  976 +
  977 +#define GEN_ISTO(width, opc) \
  978 +GEN_IST(width, opc | 0x20) \
  979 +GEN_ISTU(width, opc | 0x21) \
  980 +GEN_ISTUX(width, opc | 0x01) \
  981 +GEN_ISTX(width, 0x17, opc | 0x00)
  982 +
  983 +/* stb stbu stbux stbx */
  984 +GEN_ISTO(b, 0x06);
  985 +/* sth sthu sthux sthx */
  986 +GEN_ISTO(h, 0x0C);
  987 +/* stw stwu stwux stwx */
  988 +GEN_ISTO(w, 0x04);
  989 +
  990 +/*** Integer load and store with byte reverse ***/
  991 +/* lhbrx */
  992 +GEN_ILDZX(hbr, 0x16, 0x18);
  993 +/* lwbrx */
  994 +GEN_ILDZX(wbr, 0x16, 0x10);
  995 +/* sthbrx */
  996 +GEN_ISTX(hbr, 0x16, 0x1C);
  997 +/* stwbrx */
  998 +GEN_ISTX(wbr, 0x16, 0x14);
  999 +
  1000 +/*** Integer load and store multiple ***/
  1001 +/* lmw */
  1002 +GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  1003 +{
  1004 + if (rA(ctx->opcode) == 0) {
  1005 + gen_op_set_T0(0);
  1006 + } else {
  1007 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1008 + }
  1009 + gen_op_lmw(rD(ctx->opcode), SIMM(ctx->opcode));
  1010 + SET_RETVAL(0);
  1011 +}
  1012 +
  1013 +/* stmw */
  1014 +GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
  1015 +{
  1016 + if (rA(ctx->opcode) == 0) {
  1017 + gen_op_set_T0(0);
  1018 + } else {
  1019 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1020 + }
  1021 + gen_op_stmw(rS(ctx->opcode), SIMM(ctx->opcode));
  1022 + SET_RETVAL(0);
  1023 +}
  1024 +
  1025 +/*** Integer load and store strings ***/
  1026 +/* lswi */
  1027 +GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
  1028 +{
  1029 + int nb = NB(ctx->opcode);
  1030 + int start = rD(ctx->opcode);
  1031 + int nr;
  1032 +
  1033 + if (nb == 0)
  1034 + nb = 32;
  1035 + nr = nb / 4;
  1036 + if ((start + nr) > 32) {
  1037 + /* handle wrap around r0 */
  1038 + if (rA(ctx->opcode) == 0) {
  1039 + gen_op_set_T0(0);
  1040 + } else {
  1041 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1042 + }
  1043 + gen_op_lswi(start, 4 * (32 - start));
  1044 + nb -= 4 * (32 - start);
  1045 + start = 0;
  1046 + }
  1047 + if (rA(ctx->opcode) == 0) {
  1048 + gen_op_set_T0(0);
  1049 + } else {
  1050 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1051 + }
  1052 + gen_op_lswi(start, nb);
  1053 + SET_RETVAL(0);
  1054 +}
  1055 +
  1056 +/* lswx */
  1057 +GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
  1058 +{
  1059 + gen_op_load_xer_bc();
  1060 + gen_op_load_gpr_T1(rB(ctx->opcode));
  1061 + if (rA(ctx->opcode) == 0) {
  1062 + gen_op_set_T2(0);
  1063 + } else {
  1064 + gen_op_load_gpr_T2(rA(ctx->opcode));
  1065 + }
  1066 + gen_op_lswx(rD(ctx->opcode));
  1067 + SET_RETVAL(0);
  1068 +}
  1069 +
  1070 +/* stswi */
  1071 +GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
  1072 +{
  1073 + int nb = NB(ctx->opcode);
  1074 + int start = rS(ctx->opcode);
  1075 + int nr;
  1076 +
  1077 + if (nb == 0)
  1078 + nb = 32;
  1079 + nr = nb / 4;
  1080 + if ((start + nr) > 32) {
  1081 + /* handle wrap around r0 */
  1082 + if (rA(ctx->opcode) == 0) {
  1083 + gen_op_set_T0(0);
  1084 + } else {
  1085 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1086 + }
  1087 + gen_op_stswi(start, 4 * (32 - start));
  1088 + nb -= 4 * (32 - start);
  1089 + start = 0;
  1090 + }
  1091 + if (rA(ctx->opcode) == 0) {
  1092 + gen_op_set_T0(0);
  1093 + } else {
  1094 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1095 + }
  1096 + gen_op_stswi(start, nb);
  1097 + SET_RETVAL(0);
  1098 +}
  1099 +
  1100 +/* stswx */
  1101 +GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
  1102 +{
  1103 + gen_op_load_xer_bc();
  1104 + gen_op_load_gpr_T1(rB(ctx->opcode));
  1105 + if (rA(ctx->opcode) == 0) {
  1106 + gen_op_set_T2(0);
  1107 + } else {
  1108 + gen_op_load_gpr_T2(rA(ctx->opcode));
  1109 + }
  1110 + gen_op_stswx(rS(ctx->opcode));
  1111 + SET_RETVAL(0);
  1112 +}
  1113 +
  1114 +/*** Memory synchronisation ***/
  1115 +/* eieio */
  1116 +GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM)
  1117 +{
  1118 + /* Do a branch to next instruction */
  1119 + gen_op_b((uint32_t)ctx->nip);
  1120 + SET_RETVAL(EXCP_BRANCH);
  1121 +}
  1122 +
  1123 +/* isync */
  1124 +GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM)
  1125 +{
  1126 + /* Do a branch to next instruction */
  1127 + gen_op_b((uint32_t)ctx->nip);
  1128 + SET_RETVAL(EXCP_BRANCH);
  1129 +}
  1130 +
  1131 +/* lwarx */
  1132 +GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_MEM)
  1133 +{
  1134 + reserve = 1;
  1135 + if (rA(ctx->opcode) == 0) {
  1136 + gen_op_load_gpr_T0(rB(ctx->opcode));
  1137 + gen_op_lwzx_z();
  1138 + gen_op_set_reservation();
  1139 + } else {
  1140 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1141 + gen_op_load_gpr_T1(rB(ctx->opcode));
  1142 + gen_op_lwzx();
  1143 + gen_op_set_reservation();
  1144 + }
  1145 + gen_op_store_T1_gpr(rD(ctx->opcode));
  1146 + SET_RETVAL(0);
  1147 +}
  1148 +
  1149 +/* stwcx. */
  1150 +GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_MEM)
  1151 +{
  1152 + if (reserve == 0) {
  1153 + gen_op_reset_Rc0();
  1154 + } else {
  1155 + if (rA(ctx->opcode) == 0) {
  1156 + gen_op_load_gpr_T0(rB(ctx->opcode));
  1157 + gen_op_load_gpr_T1(rS(ctx->opcode));
  1158 + gen_op_stwx_z();
  1159 + } else {
  1160 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1161 + gen_op_load_gpr_T1(rB(ctx->opcode));
  1162 + gen_op_load_gpr_T2(rS(ctx->opcode));
  1163 + gen_op_stwx();
  1164 + }
  1165 + gen_op_set_Rc0_1();
  1166 + gen_op_reset_reservation();
  1167 + }
  1168 + SET_RETVAL(0);
  1169 +}
  1170 +
  1171 +/* sync */
  1172 +GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM)
  1173 +{
  1174 + /* Do a branch to next instruction */
  1175 + gen_op_b((uint32_t)ctx->nip);
  1176 + SET_RETVAL(EXCP_BRANCH);
  1177 +}
  1178 +
  1179 +/*** Floating-point load ***/
  1180 +#define GEN_LF(width, opc) \
  1181 +GEN_HANDLER(lf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
  1182 +{ \
  1183 + uint32_t simm = SIMM(ctx->opcode); \
  1184 + if (rA(ctx->opcode) == 0) { \
  1185 + gen_op_lf##width##_z(simm, rD(ctx->opcode)); \
  1186 + } else { \
  1187 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  1188 + gen_op_lf##width(simm, rD(ctx->opcode)); \
  1189 + } \
  1190 + SET_RETVAL(0); \
  1191 +}
  1192 +
  1193 +#define GEN_LFU(width, opc) \
  1194 +GEN_HANDLER(lf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
  1195 +{ \
  1196 + if (rA(ctx->opcode) == 0 || \
  1197 + rA(ctx->opcode) == rD(ctx->opcode)) \
  1198 + SET_RETVAL(EXCP_INVAL); \
  1199 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  1200 + gen_op_lf##width(SIMM(ctx->opcode), rD(ctx->opcode)); \
  1201 + gen_op_store_T0_gpr(rA(ctx->opcode)); \
  1202 + SET_RETVAL(0); \
  1203 +}
  1204 +
  1205 +#define GEN_LFUX(width, opc) \
  1206 +GEN_HANDLER(lf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
  1207 +{ \
  1208 + if (rA(ctx->opcode) == 0 || \
  1209 + rA(ctx->opcode) == rD(ctx->opcode)) \
  1210 + SET_RETVAL(EXCP_INVAL); \
  1211 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  1212 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  1213 + gen_op_lf##width##x(rD(ctx->opcode)); \
  1214 + gen_op_store_T0_gpr(rA(ctx->opcode)); \
  1215 + SET_RETVAL(0); \
  1216 +}
  1217 +
  1218 +#define GEN_LFX(width, opc) \
  1219 +GEN_HANDLER(lf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
  1220 +{ \
  1221 + if (rA(ctx->opcode) == 0) { \
  1222 + gen_op_load_gpr_T0(rB(ctx->opcode)); \
  1223 + gen_op_lf##width##x_z(rD(ctx->opcode)); \
  1224 + } else { \
  1225 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  1226 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  1227 + gen_op_lf##width##x(rD(ctx->opcode)); \
  1228 + } \
  1229 + SET_RETVAL(0); \
  1230 +}
  1231 +
  1232 +#define GEN_LDF(width, opc) \
  1233 +GEN_LF(width, opc | 0x20) \
  1234 +GEN_LFU(width, opc | 0x21) \
  1235 +GEN_LFUX(width, opc | 0x01) \
  1236 +GEN_LFX(width, opc | 0x00)
  1237 +
  1238 +/* lfd lfdu lfdux lfdx */
  1239 +GEN_LDF(d, 0x12);
  1240 +/* lfs lfsu lfsux lfsx */
  1241 +#define gen_op_lfs_z(a, b)
  1242 +#define gen_op_lfs(a, b)
  1243 +#define gen_op_lfsx_z(a)
  1244 +#define gen_op_lfsx(a)
  1245 +GEN_LDF(s, 0x10);
  1246 +
  1247 +/*** Floating-point store ***/
  1248 +#define GEN_STF(width, opc) \
  1249 +GEN_HANDLER(stf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
  1250 +{ \
  1251 + uint32_t simm = SIMM(ctx->opcode); \
  1252 + if (rA(ctx->opcode) == 0) { \
  1253 + gen_op_stf##width##_z(simm, rS(ctx->opcode)); \
  1254 + } else { \
  1255 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  1256 + gen_op_stf##width(simm, rS(ctx->opcode)); \
  1257 + } \
  1258 + SET_RETVAL(0); \
  1259 +}
  1260 +
  1261 +#define GEN_STFU(width, opc) \
  1262 +GEN_HANDLER(stf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
  1263 +{ \
  1264 + if (rA(ctx->opcode) == 0) \
  1265 + SET_RETVAL(EXCP_INVAL); \
  1266 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  1267 + gen_op_stf##width(SIMM(ctx->opcode), rS(ctx->opcode)); \
  1268 + gen_op_store_T0_gpr(rA(ctx->opcode)); \
  1269 + SET_RETVAL(0); \
  1270 +}
  1271 +
  1272 +#define GEN_STFUX(width, opc) \
  1273 +GEN_HANDLER(stf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
  1274 +{ \
  1275 + if (rA(ctx->opcode) == 0) \
  1276 + SET_RETVAL(EXCP_INVAL); \
  1277 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  1278 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  1279 + gen_op_stf##width##x(rS(ctx->opcode)); \
  1280 + gen_op_store_T0_gpr(rA(ctx->opcode)); \
  1281 + SET_RETVAL(0); \
  1282 +}
  1283 +
  1284 +#define GEN_STFX(width, opc) \
  1285 +GEN_HANDLER(stf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
  1286 +{ \
  1287 + if (rA(ctx->opcode) == 0) { \
  1288 + gen_op_load_gpr_T0(rB(ctx->opcode)); \
  1289 + gen_op_stf##width##x_z(rS(ctx->opcode)); \
  1290 + } else { \
  1291 + gen_op_load_gpr_T0(rA(ctx->opcode)); \
  1292 + gen_op_load_gpr_T1(rB(ctx->opcode)); \
  1293 + gen_op_stf##width##x(rS(ctx->opcode)); \
  1294 + } \
  1295 + SET_RETVAL(0); \
  1296 +}
  1297 +
  1298 +#define GEN_STOF(width, opc) \
  1299 +GEN_STF(width, opc | 0x20) \
  1300 +GEN_STFU(width, opc | 0x21) \
  1301 +GEN_STFUX(width, opc | 0x01) \
  1302 +GEN_STFX(width, opc | 0x00)
  1303 +
  1304 +/* stfd stfdu stfdux stfdx */
  1305 +GEN_STOF(d, 0x16);
  1306 +/* stfs stfsu stfsux stfsx */
  1307 +#define gen_op_stfs_z(a, b)
  1308 +#define gen_op_stfs(a, b)
  1309 +#define gen_op_stfsx_z(a)
  1310 +#define gen_op_stfsx(a)
  1311 +GEN_STOF(s, 0x14);
  1312 +
  1313 +/* Optional: */
  1314 +/* stfiwx */
  1315 +GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
  1316 +{
  1317 + SET_RETVAL(EXCP_INVAL);
  1318 +}
  1319 +
  1320 +/*** Floating-point move ***/
  1321 +/* fabs */
  1322 +GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT)
  1323 +{
  1324 + SET_RETVAL(EXCP_INVAL);
  1325 +}
  1326 +
  1327 +/* fmr */
  1328 +GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
  1329 +{
  1330 + SET_RETVAL(EXCP_INVAL);
  1331 +}
  1332 +
  1333 +/* fnabs */
  1334 +GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT)
  1335 +{
  1336 + SET_RETVAL(EXCP_INVAL);
  1337 +}
  1338 +
  1339 +/* fneg */
  1340 +GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT)
  1341 +{
  1342 + SET_RETVAL(EXCP_INVAL);
  1343 +}
  1344 +
  1345 +/*** Branch ***/
  1346 +#define GEN_BCOND(name, opc1, opc2, opc3, prologue, \
  1347 + bl_ctr, b_ctr, bl_ctrz, b_ctrz, b, \
  1348 + bl_ctr_true, b_ctr_true, bl_ctrz_true, b_ctrz_true, bl_true, b_true, \
  1349 + bl_ctr_false, b_ctr_false, bl_ctrz_false, b_ctrz_false, bl_false, b_false) \
  1350 +GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
  1351 +{ \
  1352 + __attribute__ ((unused)) uint32_t target; \
  1353 + uint32_t bo = BO(ctx->opcode); \
  1354 + uint32_t bi = BI(ctx->opcode); \
  1355 + uint32_t mask; \
  1356 + prologue; \
  1357 + if ((bo & 0x4) == 0) \
  1358 + gen_op_dec_ctr(); \
  1359 + if (bo & 0x10) { \
  1360 + /* No CR condition */ \
  1361 + switch (bo & 0x6) { \
  1362 + case 0: \
  1363 + if (LK(ctx->opcode)) { \
  1364 + bl_ctr; \
  1365 + } else { \
  1366 + b_ctr; \
  1367 + } \
  1368 + break; \
  1369 + case 2: \
  1370 + if (LK(ctx->opcode)) { \
  1371 + bl_ctrz; \
  1372 + } else { \
  1373 + b_ctrz; \
  1374 + } \
  1375 + break; \
  1376 + case 4: \
  1377 + case 6: \
  1378 + b; \
  1379 + if (LK(ctx->opcode)) \
  1380 + gen_op_load_lr((uint32_t)ctx->nip); \
  1381 + break; \
  1382 + default: \
  1383 + printf("ERROR: %s: unhandled ba case (%d)\n", __func__, bo); \
  1384 + SET_RETVAL(EXCP_INVAL); \
  1385 + break; \
  1386 + } \
  1387 + } else { \
  1388 + mask = 1 << (3 - (bi & 0x03)); \
  1389 + gen_op_load_crf_T0(bi >> 2); \
  1390 + if (bo & 0x8) { \
  1391 + switch (bo & 0x6) { \
  1392 + case 0: \
  1393 + if (LK(ctx->opcode)) { \
  1394 + bl_ctr_true; \
  1395 + } else { \
  1396 + b_ctr_true; \
  1397 + } \
  1398 + break; \
  1399 + case 2: \
  1400 + if (LK(ctx->opcode)) { \
  1401 + bl_ctrz_true; \
  1402 + } else { \
  1403 + b_ctrz_true; \
  1404 + } \
  1405 + break; \
  1406 + case 4: \
  1407 + case 6: \
  1408 + if (LK(ctx->opcode)) { \
  1409 + bl_true; \
  1410 + } else { \
  1411 + b_true; \
  1412 + } \
  1413 + break; \
  1414 + default: \
  1415 + printf("ERROR: %s: unhandled b case (%d)\n", __func__, bo); \
  1416 + SET_RETVAL(EXCP_INVAL); \
  1417 + break; \
  1418 + } \
  1419 + } else { \
  1420 + switch (bo & 0x6) { \
  1421 + case 0: \
  1422 + if (LK(ctx->opcode)) { \
  1423 + bl_ctr_false; \
  1424 + } else { \
  1425 + b_ctr_false; \
  1426 + } \
  1427 + break; \
  1428 + case 2: \
  1429 + if (LK(ctx->opcode)) { \
  1430 + bl_ctrz_false; \
  1431 + } else { \
  1432 + b_ctrz_false; \
  1433 + } \
  1434 + break; \
  1435 + case 4: \
  1436 + case 6: \
  1437 + if (LK(ctx->opcode)) { \
  1438 + bl_false; \
  1439 + } else { \
  1440 + b_false; \
  1441 + } \
  1442 + break; \
  1443 + default: \
  1444 + printf("ERROR: %s: unhandled bn case (%d)\n", __func__, bo); \
  1445 + SET_RETVAL(EXCP_INVAL); \
  1446 + break; \
  1447 + } \
  1448 + } \
  1449 + } \
  1450 + SET_RETVAL(EXCP_BRANCH); \
  1451 +}
  1452 +
  1453 +/* b ba bl bla */
  1454 +GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
  1455 +{
  1456 + uint32_t li = s_ext24(LI(ctx->opcode)), target;
  1457 +
  1458 + if (AA(ctx->opcode) == 0)
  1459 + target = (uint32_t)ctx->nip + li - 4;
  1460 + else
  1461 + target = s_ext24(LI(ctx->opcode));
  1462 + gen_op_b(target);
  1463 + if (LK(ctx->opcode))
  1464 + gen_op_load_lr((uint32_t)ctx->nip);
  1465 + SET_RETVAL(EXCP_BRANCH);
  1466 +}
  1467 +
  1468 +/* bc bca bcl bcla */
  1469 +GEN_BCOND(bc, 0x10, 0xFF, 0xFF,
  1470 + do {
  1471 + uint32_t li = s_ext16(BD(ctx->opcode));
  1472 + if (AA(ctx->opcode) == 0) {
  1473 + target = (uint32_t)ctx->nip + li - 4;
  1474 + } else {
  1475 + target = li;
  1476 + }
  1477 + } while (0),
  1478 + gen_op_bl_ctr((uint32_t)ctx->nip, target),
  1479 + gen_op_b_ctr((uint32_t)ctx->nip, target),
  1480 + gen_op_bl_ctrz((uint32_t)ctx->nip, target),
  1481 + gen_op_b_ctrz((uint32_t)ctx->nip, target),
  1482 + gen_op_b(target),
  1483 + gen_op_bl_ctr_true((uint32_t)ctx->nip, target, mask),
  1484 + gen_op_b_ctr_true((uint32_t)ctx->nip, target, mask),
  1485 + gen_op_bl_ctrz_true((uint32_t)ctx->nip, target, mask),
  1486 + gen_op_b_ctrz_true((uint32_t)ctx->nip, target, mask),
  1487 + gen_op_bl_true((uint32_t)ctx->nip, target, mask),
  1488 + gen_op_b_true((uint32_t)ctx->nip, target, mask),
  1489 + gen_op_bl_ctr_false((uint32_t)ctx->nip, target, mask),
  1490 + gen_op_b_ctr_false((uint32_t)ctx->nip, target, mask),
  1491 + gen_op_bl_ctrz_false((uint32_t)ctx->nip, target, mask),
  1492 + gen_op_b_ctrz_false((uint32_t)ctx->nip, target, mask),
  1493 + gen_op_bl_false((uint32_t)ctx->nip, target, mask),
  1494 + gen_op_b_false((uint32_t)ctx->nip, target, mask));
  1495 +
  1496 +/* bcctr bcctrl */
  1497 +GEN_BCOND(bcctr, 0x13, 0x10, 0x10, do { } while (0),
  1498 + gen_op_bctrl_ctr((uint32_t)ctx->nip),
  1499 + gen_op_bctr_ctr((uint32_t)ctx->nip),
  1500 + gen_op_bctrl_ctrz((uint32_t)ctx->nip),
  1501 + gen_op_bctr_ctrz((uint32_t)ctx->nip),
  1502 + gen_op_bctr(),
  1503 + gen_op_bctrl_ctr_true((uint32_t)ctx->nip, mask),
  1504 + gen_op_bctr_ctr_true((uint32_t)ctx->nip, mask),
  1505 + gen_op_bctrl_ctrz_true((uint32_t)ctx->nip, mask),
  1506 + gen_op_bctr_ctrz_true((uint32_t)ctx->nip, mask),
  1507 + gen_op_bctrl_true((uint32_t)ctx->nip, mask),
  1508 + gen_op_bctr_true((uint32_t)ctx->nip, mask),
  1509 + gen_op_bctrl_ctr_false((uint32_t)ctx->nip, mask),
  1510 + gen_op_bctr_ctr_false((uint32_t)ctx->nip, mask),
  1511 + gen_op_bctrl_ctrz_false((uint32_t)ctx->nip, mask),
  1512 + gen_op_bctr_ctrz_false((uint32_t)ctx->nip, mask),
  1513 + gen_op_bctrl_false((uint32_t)ctx->nip, mask),
  1514 + gen_op_bctr_false((uint32_t)ctx->nip, mask))
  1515 +
  1516 +/* bclr bclrl */
  1517 +GEN_BCOND(bclr, 0x13, 0x10, 0x00, do { } while (0),
  1518 + gen_op_blrl_ctr((uint32_t)ctx->nip),
  1519 + gen_op_blr_ctr((uint32_t)ctx->nip),
  1520 + gen_op_blrl_ctrz((uint32_t)ctx->nip),
  1521 + gen_op_blr_ctrz((uint32_t)ctx->nip),
  1522 + gen_op_blr(),
  1523 + gen_op_blrl_ctr_true((uint32_t)ctx->nip, mask),
  1524 + gen_op_blr_ctr_true((uint32_t)ctx->nip, mask),
  1525 + gen_op_blrl_ctrz_true((uint32_t)ctx->nip, mask),
  1526 + gen_op_blr_ctrz_true((uint32_t)ctx->nip, mask),
  1527 + gen_op_blrl_true((uint32_t)ctx->nip, mask),
  1528 + gen_op_blr_true((uint32_t)ctx->nip, mask),
  1529 + gen_op_blrl_ctr_false((uint32_t)ctx->nip, mask),
  1530 + gen_op_blr_ctr_false((uint32_t)ctx->nip, mask),
  1531 + gen_op_blrl_ctrz_false((uint32_t)ctx->nip, mask),
  1532 + gen_op_blr_ctrz_false((uint32_t)ctx->nip, mask),
  1533 + gen_op_blrl_false((uint32_t)ctx->nip, mask),
  1534 + gen_op_blr_false((uint32_t)ctx->nip, mask))
  1535 +
  1536 +/*** Condition register logical ***/
  1537 +#define GEN_CRLOGIC(op, opc) \
  1538 +GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
  1539 +{ \
  1540 + gen_op_load_crf_T0(crbA(ctx->opcode) >> 2); \
  1541 + gen_op_getbit_T0(3 - (crbA(ctx->opcode) & 0x03)); \
  1542 + gen_op_load_crf_T1(crbB(ctx->opcode) >> 2); \
  1543 + gen_op_getbit_T1(3 - (crbB(ctx->opcode) & 0x03)); \
  1544 + gen_op_##op(); \
  1545 + gen_op_load_crf_T1(crbD(ctx->opcode) >> 2); \
  1546 + gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))), \
  1547 + 3 - (crbD(ctx->opcode) & 0x03)); \
  1548 + gen_op_store_T1_crf(crbD(ctx->opcode) >> 2); \
  1549 + SET_RETVAL(0); \
  1550 +}
  1551 +
  1552 +/* crand */
  1553 +GEN_CRLOGIC(and, 0x08)
  1554 +/* crandc */
  1555 +GEN_CRLOGIC(andc, 0x04)
  1556 +/* creqv */
  1557 +GEN_CRLOGIC(eqv, 0x09)
  1558 +/* crnand */
  1559 +GEN_CRLOGIC(nand, 0x07)
  1560 +/* crnor */
  1561 +GEN_CRLOGIC(nor, 0x01)
  1562 +/* cror */
  1563 +GEN_CRLOGIC(or, 0x0E)
  1564 +/* crorc */
  1565 +GEN_CRLOGIC(orc, 0x0D)
  1566 +/* crxor */
  1567 +GEN_CRLOGIC(xor, 0x06)
  1568 +/* mcrf */
  1569 +GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
  1570 +{
  1571 + gen_op_load_crf_T0(crfS(ctx->opcode));
  1572 + gen_op_store_T0_crf(crfD(ctx->opcode));
  1573 + SET_RETVAL(0);
  1574 +}
  1575 +
  1576 +/*** System linkage ***/
  1577 +/* rfi (supervisor only) */
  1578 +GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
  1579 +{
  1580 + SET_RETVAL(EXCP_INVAL);
  1581 +}
  1582 +
  1583 +/* sc */
  1584 +GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
  1585 +{
  1586 + gen_op_b((uint32_t)ctx->nip);
  1587 + SET_RETVAL(EXCP_SYSCALL);
  1588 +}
  1589 +
  1590 +/*** Trap ***/
  1591 +/* tw */
  1592 +GEN_HANDLER(tw, 0x1F, 0x04, 0xFF, 0x00000001, PPC_FLOW)
  1593 +{
  1594 + SET_RETVAL(EXCP_INVAL);
  1595 +}
  1596 +
  1597 +/* twi */
  1598 +GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
  1599 +{
  1600 + SET_RETVAL(EXCP_INVAL);
  1601 +}
  1602 +
  1603 +/*** Processor control ***/
  1604 +static inline int check_spr_access (int spr, int rw, int supervisor)
  1605 +{
  1606 + uint32_t rights = spr_access[spr >> 1] >> (4 * (spr & 1));
  1607 +
  1608 + rights = rights >> (2 * supervisor);
  1609 + rights = rights >> rw;
  1610 +
  1611 + return rights & 1;
  1612 +}
  1613 +
  1614 +/* mcrxr */
  1615 +GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
  1616 +{
  1617 + gen_op_load_xer_cr();
  1618 + gen_op_store_T0_crf(crfD(ctx->opcode));
  1619 + gen_op_clear_xer_cr();
  1620 + SET_RETVAL(0);
  1621 +}
  1622 +
  1623 +/* mfcr */
  1624 +GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
  1625 +{
  1626 + gen_op_load_cr();
  1627 + gen_op_store_T0_gpr(rD(ctx->opcode));
  1628 + SET_RETVAL(0);
  1629 +}
  1630 +
  1631 +/* mfmsr */
  1632 +GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
  1633 +{
  1634 + if (!ctx->supervisor)
  1635 + SET_RETVAL(EXCP_PRIV);
  1636 + gen_op_load_msr();
  1637 + gen_op_store_T0_gpr(rD(ctx->opcode));
  1638 + SET_RETVAL(0);
  1639 +}
  1640 +
  1641 +/* mfspr */
  1642 +GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
  1643 +{
  1644 + uint32_t sprn = SPR(ctx->opcode);
  1645 +
  1646 + if (check_spr_access(sprn, 0, ctx->supervisor) == 0)
  1647 + SET_RETVAL(EXCP_PRIV);
  1648 + /* XXX: make this more generic */
  1649 + switch (sprn) {
  1650 + case SPR_ENCODE(1):
  1651 + if (loglevel > 0) {
  1652 + fprintf(logfile, "LOAD XER at %p\n", ctx->nip - 1);
  1653 + }
  1654 + gen_op_load_xer();
  1655 + break;
  1656 + case SPR_ENCODE(268):
  1657 + /* We need to update the time base before reading it */
  1658 + gen_op_update_tb(ctx->tb_offset);
  1659 + ctx->tb_offset = 0;
  1660 + break;
  1661 + case SPR_ENCODE(269):
  1662 + gen_op_update_tb(ctx->tb_offset);
  1663 + ctx->tb_offset = 0;
  1664 + break;
  1665 + default:
  1666 + gen_op_load_spr(sprn);
  1667 + break;
  1668 + }
  1669 + gen_op_store_T0_gpr(rD(ctx->opcode)); //
  1670 + SET_RETVAL(0);
  1671 +}
  1672 +
  1673 +/* mftb */
  1674 +GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC)
  1675 +{
  1676 + uint32_t sprn = SPR(ctx->opcode);
  1677 +
  1678 + if (check_spr_access(sprn, 0, ctx->supervisor) == 0)
  1679 + SET_RETVAL(EXCP_PRIV);
  1680 + switch (sprn) {
  1681 + case SPR_ENCODE(268):
  1682 + /* We need to update the time base before reading it */
  1683 + gen_op_update_tb(ctx->tb_offset);
  1684 + ctx->tb_offset = 0;
  1685 + break;
  1686 + case SPR_ENCODE(269):
  1687 + gen_op_update_tb(ctx->tb_offset);
  1688 + ctx->tb_offset = 0;
  1689 + break;
  1690 + default:
  1691 + SET_RETVAL(EXCP_INVAL);
  1692 + break;
  1693 + }
  1694 + SET_RETVAL(0);
  1695 +}
  1696 +
  1697 +/* mtcrf */
  1698 +GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00100801, PPC_MISC)
  1699 +{
  1700 + gen_op_load_gpr_T0(rS(ctx->opcode));
  1701 + gen_op_store_cr(CRM(ctx->opcode));
  1702 + SET_RETVAL(0);
  1703 +}
  1704 +
  1705 +/* mtmsr */
  1706 +GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
  1707 +{
  1708 + if (!ctx->supervisor)
  1709 + SET_RETVAL(EXCP_PRIV);
  1710 + gen_op_load_gpr_T0(rS(ctx->opcode));
  1711 + gen_op_store_msr();
  1712 + /* Must stop the translation as machine state (may have) changed */
  1713 + SET_RETVAL(EXCP_MTMSR);
  1714 +}
  1715 +
  1716 +/* mtspr */
  1717 +GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
  1718 +{
  1719 + uint32_t sprn = SPR(ctx->opcode);
  1720 +
  1721 + if (check_spr_access(sprn, 1, ctx->supervisor) == 0)
  1722 + SET_RETVAL(EXCP_PRIV);
  1723 + gen_op_load_gpr_T0(rS(ctx->opcode));
  1724 + if (sprn == SPR_ENCODE(1)) {
  1725 + gen_op_store_xer();
  1726 + } else {
  1727 + gen_op_store_spr(sprn);
  1728 + }
  1729 + SET_RETVAL(0);
  1730 +}
  1731 +
  1732 +/*** Cache management ***/
  1733 +/* For now, all those will be implemented as nop:
  1734 + * this is valid, regarding the PowerPC specs...
  1735 + */
  1736 +/* dcbf */
  1737 +GEN_HANDLER(dcbf, 0x1F, 0x16, 0x17, 0x03E00001, PPC_MEM)
  1738 +{
  1739 + SET_RETVAL(0);
  1740 +}
  1741 +
  1742 +/* dcbi (Supervisor only) */
  1743 +GEN_HANDLER(dcbi, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_MEM)
  1744 +{
  1745 + SET_RETVAL(0);
  1746 +}
  1747 +
  1748 +/* dcdst */
  1749 +GEN_HANDLER(dcbst, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_MEM)
  1750 +{
  1751 + SET_RETVAL(0);
  1752 +}
  1753 +
  1754 +/* dcbt */
  1755 +GEN_HANDLER(dcbt, 0x1F, 0x16, 0x01, 0x03E00001, PPC_MEM)
  1756 +{
  1757 + SET_RETVAL(0);
  1758 +}
  1759 +
  1760 +/* dcbtst */
  1761 +GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x02, 0x03E00001, PPC_MEM)
  1762 +{
  1763 + SET_RETVAL(0);
  1764 +}
  1765 +
  1766 +/* dcbz */
  1767 +GEN_HANDLER(dcbz, 0x1F, 0x16, 0x08, 0x03E00001, PPC_MEM)
  1768 +{
  1769 + SET_RETVAL(0);
  1770 +}
  1771 +
  1772 +/* icbi */
  1773 +GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_MEM)
  1774 +{
  1775 + SET_RETVAL(0);
  1776 +}
  1777 +
  1778 +/* Optional: */
  1779 +/* dcba */
  1780 +GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_MEM)
  1781 +{
  1782 + SET_RETVAL(0);
  1783 +}
  1784 +
  1785 +/*** Segment register manipulation ***/
  1786 +/* Supervisor only: */
  1787 +/* mfsr */
  1788 +GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
  1789 +{
  1790 + SET_RETVAL(EXCP_INVAL);
  1791 +}
  1792 +
  1793 +/* mfsrin */
  1794 +GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x0010F001, PPC_SEGMENT)
  1795 +{
  1796 + SET_RETVAL(EXCP_INVAL);
  1797 +}
  1798 +
  1799 +/* mtsr */
  1800 +GEN_HANDLER(mtsr, 0x1F, 0x12, 0x02, 0x0010F801, PPC_SEGMENT)
  1801 +{
  1802 + SET_RETVAL(EXCP_INVAL);
  1803 +}
  1804 +
  1805 +/* mtsrin */
  1806 +GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x0010F001, PPC_SEGMENT)
  1807 +{
  1808 + SET_RETVAL(EXCP_INVAL);
  1809 +}
  1810 +
  1811 +/*** Lookaside buffer management ***/
  1812 +/* Optional & supervisor only: */
  1813 +/* tlbia */
  1814 +GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM)
  1815 +{
  1816 + SET_RETVAL(EXCP_INVAL);
  1817 +}
  1818 +
  1819 +/* tlbie */
  1820 +GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF8001, PPC_MEM)
  1821 +{
  1822 + SET_RETVAL(EXCP_INVAL);
  1823 +}
  1824 +
  1825 +/* tlbsync */
  1826 +GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFFC01, PPC_MEM)
  1827 +{
  1828 + SET_RETVAL(EXCP_INVAL);
  1829 +}
  1830 +
  1831 +/*** External control ***/
  1832 +/* Optional: */
  1833 +/* eciwx */
  1834 +GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
  1835 +{
  1836 + SET_RETVAL(EXCP_INVAL);
  1837 +}
  1838 +
  1839 +/* ecowx */
  1840 +GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
  1841 +{
  1842 + SET_RETVAL(EXCP_INVAL);
  1843 +}
  1844 +
  1845 +/* End opcode list */
  1846 +GEN_OPCODE_MARK(end);
  1847 +
  1848 +/*****************************************************************************/
  1849 +
  1850 +#include <string.h>
  1851 +extern FILE *stderr;
  1852 +void free (void *p);
  1853 +int fflush (FILE *f);
  1854 +
  1855 +/* Main ppc opcodes table:
  1856 + * at init, all opcodes are invalids
  1857 + */
  1858 +static opc_handler_t *ppc_opcodes[0x40];
  1859 +
  1860 +/* Opcode types */
  1861 +enum {
  1862 + PPC_DIRECT = 0, /* Opcode routine */
  1863 + PPC_INDIRECT = 1, /* Indirect opcode table */
  1864 +};
  1865 +
  1866 +static inline int is_indirect_opcode (void *handler)
  1867 +{
  1868 + return ((unsigned long)handler & 0x03) == PPC_INDIRECT;
  1869 +}
  1870 +
  1871 +static inline opc_handler_t **ind_table(void *handler)
  1872 +{
  1873 + return (opc_handler_t **)((unsigned long)handler & ~3);
  1874 +}
  1875 +
  1876 +/* Opcodes tables creation */
  1877 +static void fill_new_table (opc_handler_t **table, int len)
  1878 +{
  1879 + int i;
  1880 +
  1881 + for (i = 0; i < len; i++)
  1882 + table[i] = &invalid_handler;
  1883 +}
  1884 +
  1885 +static int create_new_table (opc_handler_t **table, unsigned char idx)
  1886 +{
  1887 + opc_handler_t **tmp;
  1888 +
  1889 + tmp = malloc(0x20 * sizeof(opc_handler_t));
  1890 + if (tmp == NULL)
  1891 + return -1;
  1892 + fill_new_table(tmp, 0x20);
  1893 + table[idx] = (opc_handler_t *)((unsigned long)tmp | PPC_INDIRECT);
  1894 +
  1895 + return 0;
  1896 +}
  1897 +
  1898 +static int insert_in_table (opc_handler_t **table, unsigned char idx,
  1899 + opc_handler_t *handler)
  1900 +{
  1901 + if (table[idx] != &invalid_handler)
  1902 + return -1;
  1903 + table[idx] = handler;
  1904 +
  1905 + return 0;
  1906 +}
  1907 +
  1908 +static int register_direct_insn (unsigned char idx, opc_handler_t *handler)
  1909 +{
  1910 + if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
  1911 + fprintf(stderr, "*** ERROR: opcode %02x already assigned in main "
  1912 + "opcode table\n", idx);
  1913 + return -1;
  1914 + }
  1915 +
  1916 + return 0;
  1917 +}
  1918 +
  1919 +static int register_ind_in_table (opc_handler_t **table,
  1920 + unsigned char idx1, unsigned char idx2,
  1921 + opc_handler_t *handler)
  1922 +{
  1923 + if (table[idx1] == &invalid_handler) {
  1924 + if (create_new_table(table, idx1) < 0) {
  1925 + fprintf(stderr, "*** ERROR: unable to create indirect table "
  1926 + "idx=%02x\n", idx1);
  1927 + return -1;
  1928 + }
  1929 + } else {
  1930 + if (!is_indirect_opcode(table[idx1])) {
  1931 + fprintf(stderr, "*** ERROR: idx %02x already assigned to a direct "
  1932 + "opcode\n", idx1);
  1933 + return -1;
  1934 + }
  1935 + }
  1936 + if (handler != NULL &&
  1937 + insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
  1938 + fprintf(stderr, "*** ERROR: opcode %02x already assigned in "
  1939 + "opcode table %02x\n", idx2, idx1);
  1940 + return -1;
  1941 + }
  1942 +
  1943 + return 0;
  1944 +}
  1945 +
  1946 +static int register_ind_insn (unsigned char idx1, unsigned char idx2,
  1947 + opc_handler_t *handler)
  1948 +{
  1949 + int ret;
  1950 +
  1951 + ret = register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
  1952 +
  1953 + return ret;
  1954 +}
  1955 +
  1956 +static int register_dblind_insn (unsigned char idx1, unsigned char idx2,
  1957 + unsigned char idx3, opc_handler_t *handler)
  1958 +{
  1959 + if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
  1960 + fprintf(stderr, "*** ERROR: unable to join indirect table idx "
  1961 + "[%02x-%02x]\n", idx1, idx2);
  1962 + return -1;
  1963 + }
  1964 + if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
  1965 + handler) < 0) {
  1966 + fprintf(stderr, "*** ERROR: unable to insert opcode "
  1967 + "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
  1968 + return -1;
  1969 + }
  1970 +
  1971 + return 0;
  1972 +}
  1973 +
  1974 +static int register_insn (opcode_t *insn)
  1975 +{
  1976 + if (insn->opc2 != 0xFF) {
  1977 + if (insn->opc3 != 0xFF) {
  1978 + if (register_dblind_insn(insn->opc1, insn->opc2, insn->opc3,
  1979 + &insn->handler) < 0)
  1980 + return -1;
  1981 + } else {
  1982 + if (register_ind_insn(insn->opc1, insn->opc2, &insn->handler) < 0)
  1983 + return -1;
  1984 + }
  1985 + } else {
  1986 + if (register_direct_insn(insn->opc1, &insn->handler) < 0)
  1987 + return -1;
  1988 + }
  1989 +
  1990 + return 0;
  1991 +}
  1992 +
  1993 +static int test_opcode_table (opc_handler_t **table, int len)
  1994 +{
  1995 + int i, count, tmp;
  1996 +
  1997 + for (i = 0, count = 0; i < len; i++) {
  1998 + /* Consistency fixup */
  1999 + if (table[i] == NULL)
  2000 + table[i] = &invalid_handler;
  2001 + if (table[i] != &invalid_handler) {
  2002 + if (is_indirect_opcode(table[i])) {
  2003 + tmp = test_opcode_table(ind_table(table[i]), 0x20);
  2004 + if (tmp == 0) {
  2005 + free(table[i]);
  2006 + table[i] = &invalid_handler;
  2007 + } else {
  2008 + count++;
  2009 + }
  2010 + } else {
  2011 + count++;
  2012 + }
  2013 + }
  2014 + }
  2015 +
  2016 + return count;
  2017 +}
  2018 +
  2019 +static void fix_opcode_tables (void)
  2020 +{
  2021 + if (test_opcode_table(ppc_opcodes, 0x40) == 0)
  2022 + fprintf(stderr, "*** WARNING: no opcode defined !\n");
  2023 +}
  2024 +
  2025 +#define SPR_RIGHTS(rw, priv) ((2 * (priv)) + (rw))
  2026 +#define SPR_UR SPR_RIGHTS(0, 0)
  2027 +#define SPR_UW SPR_RIGHTS(1, 0)
  2028 +#define SPR_SR SPR_RIGHTS(0, 1)
  2029 +#define SPR_SW SPR_RIGHTS(1, 1)
  2030 +
  2031 +#define spr_set_rights(spr, rights) \
  2032 +do { \
  2033 + spr_access[(spr) >> 1] |= ((rights) << (4 * ((spr) & 1))); \
  2034 +} while (0)
  2035 +
  2036 +static void init_spr_rights (void)
  2037 +{
  2038 + /* XER (SPR 1) */
  2039 + spr_set_rights(SPR_ENCODE(1), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
  2040 + /* LR (SPR 8) */
  2041 + spr_set_rights(SPR_ENCODE(8), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
  2042 + /* CTR (SPR 9) */
  2043 + spr_set_rights(SPR_ENCODE(9), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
  2044 + /* TBL (SPR 268) */
  2045 + spr_set_rights(SPR_ENCODE(268), SPR_UR | SPR_SR);
  2046 + /* TBU (SPR 269) */
  2047 + spr_set_rights(SPR_ENCODE(269), SPR_UR | SPR_SR);
  2048 + /* DSISR (SPR 18) */
  2049 + spr_set_rights(SPR_ENCODE(18), SPR_SR | SPR_SW);
  2050 + /* DAR (SPR 19) */
  2051 + spr_set_rights(SPR_ENCODE(19), SPR_SR | SPR_SW);
  2052 + /* DEC (SPR 22) */
  2053 + spr_set_rights(SPR_ENCODE(22), SPR_SR | SPR_SW);
  2054 + /* SDR1 (SPR 25) */
  2055 + spr_set_rights(SPR_ENCODE(25), SPR_SR | SPR_SW);
  2056 + /* SPRG0 (SPR 272) */
  2057 + spr_set_rights(SPR_ENCODE(272), SPR_SR | SPR_SW);
  2058 + /* SPRG1 (SPR 273) */
  2059 + spr_set_rights(SPR_ENCODE(273), SPR_SR | SPR_SW);
  2060 + /* SPRG2 (SPR 274) */
  2061 + spr_set_rights(SPR_ENCODE(274), SPR_SR | SPR_SW);
  2062 + /* SPRG3 (SPR 275) */
  2063 + spr_set_rights(SPR_ENCODE(275), SPR_SR | SPR_SW);
  2064 + /* ASR (SPR 280) */
  2065 + spr_set_rights(SPR_ENCODE(281), SPR_SR | SPR_SW);
  2066 + /* EAR (SPR 282) */
  2067 + spr_set_rights(SPR_ENCODE(282), SPR_SR | SPR_SW);
  2068 + /* IBAT0U (SPR 528) */
  2069 + spr_set_rights(SPR_ENCODE(528), SPR_SR | SPR_SW);
  2070 + /* IBAT0L (SPR 529) */
  2071 + spr_set_rights(SPR_ENCODE(529), SPR_SR | SPR_SW);
  2072 + /* IBAT1U (SPR 530) */
  2073 + spr_set_rights(SPR_ENCODE(530), SPR_SR | SPR_SW);
  2074 + /* IBAT1L (SPR 531) */
  2075 + spr_set_rights(SPR_ENCODE(531), SPR_SR | SPR_SW);
  2076 + /* IBAT2U (SPR 532) */
  2077 + spr_set_rights(SPR_ENCODE(532), SPR_SR | SPR_SW);
  2078 + /* IBAT2L (SPR 533) */
  2079 + spr_set_rights(SPR_ENCODE(533), SPR_SR | SPR_SW);
  2080 + /* IBAT3U (SPR 534) */
  2081 + spr_set_rights(SPR_ENCODE(534), SPR_SR | SPR_SW);
  2082 + /* IBAT3L (SPR 535) */
  2083 + spr_set_rights(SPR_ENCODE(535), SPR_SR | SPR_SW);
  2084 + /* DBAT0U (SPR 536) */
  2085 + spr_set_rights(SPR_ENCODE(536), SPR_SR | SPR_SW);
  2086 + /* DBAT0L (SPR 537) */
  2087 + spr_set_rights(SPR_ENCODE(537), SPR_SR | SPR_SW);
  2088 + /* DBAT1U (SPR 538) */
  2089 + spr_set_rights(SPR_ENCODE(538), SPR_SR | SPR_SW);
  2090 + /* DBAT1L (SPR 539) */
  2091 + spr_set_rights(SPR_ENCODE(539), SPR_SR | SPR_SW);
  2092 + /* DBAT2U (SPR 540) */
  2093 + spr_set_rights(SPR_ENCODE(540), SPR_SR | SPR_SW);
  2094 + /* DBAT2L (SPR 541) */
  2095 + spr_set_rights(SPR_ENCODE(541), SPR_SR | SPR_SW);
  2096 + /* DBAT3U (SPR 542) */
  2097 + spr_set_rights(SPR_ENCODE(542), SPR_SR | SPR_SW);
  2098 + /* DBAT3L (SPR 543) */
  2099 + spr_set_rights(SPR_ENCODE(543), SPR_SR | SPR_SW);
  2100 + /* DABR (SPR 1013) */
  2101 + spr_set_rights(SPR_ENCODE(1013), SPR_SR | SPR_SW);
  2102 + /* FPECR (SPR 1022) */
  2103 + spr_set_rights(SPR_ENCODE(1022), SPR_SR | SPR_SW);
  2104 + /* PIR (SPR 1023) */
  2105 + spr_set_rights(SPR_ENCODE(1023), SPR_SR | SPR_SW);
  2106 + /* PVR (SPR 287) */
  2107 + spr_set_rights(SPR_ENCODE(287), SPR_SR);
  2108 + /* TBL (SPR 284) */
  2109 + spr_set_rights(SPR_ENCODE(284), SPR_SW);
  2110 + /* TBU (SPR 285) */
  2111 + spr_set_rights(SPR_ENCODE(285), SPR_SW);
  2112 +}
  2113 +
  2114 +/* PPC "main stream" common instructions */
  2115 +#define PPC_COMMON (PPC_INTEGER | PPC_FLOAT | PPC_FLOW | PPC_MEM | \
  2116 + PPC_MISC | PPC_EXTERN | PPC_SEGMENT)
  2117 +
  2118 +typedef struct ppc_proc_t {
  2119 + int flags;
  2120 + void *specific;
  2121 +} ppc_proc_t;
  2122 +
  2123 +typedef struct ppc_def_t {
  2124 + unsigned long pvr;
  2125 + unsigned long pvr_mask;
  2126 + ppc_proc_t *proc;
  2127 +} ppc_def_t;
  2128 +
  2129 +static ppc_proc_t ppc_proc_common = {
  2130 + .flags = PPC_COMMON,
  2131 + .specific = NULL,
  2132 +};
  2133 +
  2134 +static ppc_def_t ppc_defs[] =
  2135 +{
  2136 + /* Fallback */
  2137 + {
  2138 + .pvr = 0x00000000,
  2139 + .pvr_mask = 0x00000000,
  2140 + .proc = &ppc_proc_common,
  2141 + },
  2142 +};
  2143 +
  2144 +static int create_ppc_proc (unsigned long pvr)
  2145 +{
  2146 + opcode_t *opc;
  2147 + int i, flags;
  2148 +
  2149 + fill_new_table(ppc_opcodes, 0x40);
  2150 + for (i = 0; ; i++) {
  2151 + if ((ppc_defs[i].pvr & ppc_defs[i].pvr_mask) ==
  2152 + (pvr & ppc_defs[i].pvr_mask)) {
  2153 + flags = ppc_defs[i].proc->flags;
  2154 + break;
  2155 + }
  2156 + }
  2157 +
  2158 + for (opc = &opc_start + 1; opc != &opc_end; opc++) {
  2159 + if ((opc->type & flags) != 0)
  2160 + if (register_insn(opc) < 0) {
  2161 + fprintf(stderr, "*** ERROR initializing PPC instruction "
  2162 + "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
  2163 + opc->opc3);
  2164 + return -1;
  2165 + }
  2166 + }
  2167 + fix_opcode_tables();
  2168 +
  2169 + return 0;
  2170 +}
  2171 +
  2172 +/*****************************************************************************/
  2173 +uint32_t do_load_xer (void);
  2174 +
  2175 +void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
  2176 +{
  2177 + int i;
  2178 +
  2179 + if (loglevel > 0) {
  2180 + fprintf(logfile, "nip=0x%08x LR=0x%08x CTR=0x%08x XER=0x%08x\n",
  2181 + env->nip, env->LR, env->CTR, do_load_xer());
  2182 + for (i = 0; i < 32; i++) {
  2183 + if ((i & 7) == 0)
  2184 + fprintf(logfile, "GPR%02d:", i);
  2185 + fprintf(logfile, " %08x", env->gpr[i]);
  2186 + if ((i & 7) == 7)
  2187 + fprintf(logfile, "\n");
  2188 + }
  2189 + fprintf(logfile, "CR: 0x");
  2190 + for (i = 0; i < 8; i++)
  2191 + fprintf(logfile, "%01x", env->crf[i]);
  2192 + fprintf(logfile, " [");
  2193 + for (i = 0; i < 8; i++) {
  2194 + char a = '-';
  2195 +
  2196 + if (env->crf[i] & 0x08)
  2197 + a = 'L';
  2198 + else if (env->crf[i] & 0x04)
  2199 + a = 'G';
  2200 + else if (env->crf[i] & 0x02)
  2201 + a = 'E';
  2202 + fprintf(logfile, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
  2203 + }
  2204 + fprintf(logfile, " ] ");
  2205 + fprintf(logfile, "TB: 0x%08x %08x\n", env->spr[SPR_ENCODE(269)],
  2206 + env->spr[SPR_ENCODE(268)]);
  2207 + for (i = 0; i < 16; i++) {
  2208 + if ((i & 3) == 0)
  2209 + fprintf(logfile, "FPR%02d:", i);
  2210 + fprintf(logfile, " %016llx", env->fpr[i]);
  2211 + if ((i & 3) == 3)
  2212 + fprintf(logfile, "\n");
  2213 + }
  2214 + fflush(logfile);
  2215 + }
  2216 +}
  2217 +
  2218 +CPUPPCState *cpu_ppc_init(void)
  2219 +{
  2220 + CPUPPCState *env;
  2221 +
  2222 + cpu_exec_init();
  2223 +
  2224 + env = malloc(sizeof(CPUPPCState));
  2225 + if (!env)
  2226 + return NULL;
  2227 + memset(env, 0, sizeof(CPUPPCState));
  2228 + env->PVR = 0;
  2229 + if (create_ppc_proc(0) < 0)
  2230 + return NULL;
  2231 + init_spr_rights();
  2232 +
  2233 + return env;
  2234 +}
  2235 +
  2236 +void cpu_ppc_close(CPUPPCState *env)
  2237 +{
  2238 + /* Should also remove all opcode tables... */
  2239 + free(env);
  2240 +}
  2241 +
  2242 +int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
  2243 + int search_pc)
  2244 +{
  2245 + DisasContext ctx;
  2246 + opc_handler_t **table, *handler;
  2247 + uint32_t pc_start;
  2248 + uint16_t *gen_opc_end;
  2249 + int j, lj = -1;
  2250 + int ret = 0;
  2251 +
  2252 + pc_start = tb->pc;
  2253 + gen_opc_ptr = gen_opc_buf;
  2254 + gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
  2255 + gen_opparam_ptr = gen_opparam_buf;
  2256 + ctx.nip = (uint32_t *)pc_start;
  2257 + ctx.tb_offset = 0;
  2258 + ctx.supervisor = msr_ip;
  2259 + ctx.tb = tb;
  2260 + ctx.exception = 0;
  2261 +
  2262 + while (ret == 0 && gen_opc_ptr < gen_opc_end) {
  2263 + if (search_pc) {
  2264 + if (loglevel > 0)
  2265 + fprintf(logfile, "Search PC...\n");
  2266 + j = gen_opc_ptr - gen_opc_buf;
  2267 + if (lj < j) {
  2268 + lj++;
  2269 + while (lj < j)
  2270 + gen_opc_instr_start[lj++] = 0;
  2271 + gen_opc_pc[lj] = (uint32_t)ctx.nip;
  2272 + gen_opc_instr_start[lj] = 1;
  2273 + }
  2274 + }
  2275 + ctx.opcode = __be32_to_cpu(*ctx.nip);
  2276 +#ifdef DEBUG_DISAS
  2277 + if (loglevel > 0) {
  2278 + fprintf(logfile, "----------------\n");
  2279 + fprintf(logfile, "%p: translate opcode %08x\n",
  2280 + ctx.nip, ctx.opcode);
  2281 + }
  2282 +#endif
  2283 + ctx.nip++;
  2284 + table = ppc_opcodes;
  2285 + handler = table[opc1(ctx.opcode)];
  2286 + if (is_indirect_opcode(handler)) {
  2287 + table = ind_table(handler);
  2288 + handler = table[opc2(ctx.opcode)];
  2289 + if (is_indirect_opcode(handler)) {
  2290 + table = ind_table(handler);
  2291 + handler = table[opc3(ctx.opcode)];
  2292 + }
  2293 + }
  2294 + /* Is opcode *REALLY* valid ? */
  2295 + if ((ctx.opcode & handler->inval) != 0) {
  2296 + if (loglevel > 0) {
  2297 + if (handler->handler == &gen_invalid) {
  2298 + fprintf(logfile, "invalid/unsupported opcode: "
  2299 + "%02x -%02x - %02x (%08x)\n", opc1(ctx.opcode),
  2300 + opc2(ctx.opcode), opc3(ctx.opcode), ctx.opcode);
  2301 + } else {
  2302 + fprintf(logfile, "invalid bits: %08x for opcode: "
  2303 + "%02x -%02x - %02x (%p)\n",
  2304 + ctx.opcode & handler->inval, opc1(ctx.opcode),
  2305 + opc2(ctx.opcode), opc3(ctx.opcode),
  2306 + handler->handler);
  2307 + }
  2308 + }
  2309 + ret = GET_RETVAL(gen_invalid, ctx.opcode);
  2310 + } else {
  2311 + ret = GET_RETVAL(*(handler->handler), ctx.opcode);
  2312 + }
  2313 + ctx.tb_offset++;
  2314 +#if defined (DO_SINGLE_STEP)
  2315 + break;
  2316 +#endif
  2317 + }
  2318 +#if defined (DO_STEP_FLUSH)
  2319 + tb_flush();
  2320 +#endif
  2321 + /* We need to update the time base */
  2322 + if (!search_pc)
  2323 + gen_op_update_tb(ctx.tb_offset);
  2324 + /* If we are in step-by-step mode, do a branch to the next instruction
  2325 + * so the nip will be up-to-date
  2326 + */
  2327 +#if defined (DO_SINGLE_STEP)
  2328 + if (ret == 0) {
  2329 + gen_op_b((uint32_t)ctx.nip);
  2330 + ret = EXCP_BRANCH;
  2331 + }
  2332 +#endif
  2333 + /* If the exeption isn't a PPC one,
  2334 + * generate it now.
  2335 + */
  2336 + if (ret != EXCP_BRANCH) {
  2337 + gen_op_set_T0(0);
  2338 + if ((ret & 0x2000) == 0)
  2339 + gen_op_raise_exception(ret);
  2340 + }
  2341 + /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump
  2342 + * do bad business and then qemu crashes !
  2343 + */
  2344 + gen_op_set_T0(0);
  2345 + /* Generate the return instruction */
  2346 + gen_op_exit_tb();
  2347 + *gen_opc_ptr = INDEX_op_end;
  2348 + if (!search_pc)
  2349 + tb->size = (uint32_t)ctx.nip - pc_start;
  2350 + else
  2351 + tb->size = 0;
  2352 +// *gen_opc_ptr = INDEX_op_end;
  2353 +#ifdef DEBUG_DISAS
  2354 + if (loglevel > 0) {
  2355 + fprintf(logfile, "IN: %s\n", lookup_symbol((void *)pc_start));
  2356 + disas(logfile, (void *)pc_start, (uint32_t)ctx.nip - pc_start, 0, 0);
  2357 + fprintf(logfile, "\n");
  2358 +
  2359 + fprintf(logfile, "OP:\n");
  2360 + dump_ops(gen_opc_buf, gen_opparam_buf);
  2361 + fprintf(logfile, "\n");
  2362 + }
  2363 +#endif
  2364 +
  2365 + return 0;
  2366 +}
  2367 +
  2368 +int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb)
  2369 +{
  2370 + return gen_intermediate_code_internal(env, tb, 0);
  2371 +}
  2372 +
  2373 +int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb)
  2374 +{
  2375 + return gen_intermediate_code_internal(env, tb, 1);
  2376 +}
... ...