mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
new directory structure
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@385 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
196ad10903
commit
2c0262afa7
19 changed files with 13306 additions and 0 deletions
28
linux-user/arm/syscall.h
Normal file
28
linux-user/arm/syscall.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
|
||||
/* this struct defines the way the registers are stored on the
|
||||
stack during a system call. */
|
||||
|
||||
struct target_pt_regs {
|
||||
target_long uregs[18];
|
||||
};
|
||||
|
||||
#define ARM_cpsr uregs[16]
|
||||
#define ARM_pc uregs[15]
|
||||
#define ARM_lr uregs[14]
|
||||
#define ARM_sp uregs[13]
|
||||
#define ARM_ip uregs[12]
|
||||
#define ARM_fp uregs[11]
|
||||
#define ARM_r10 uregs[10]
|
||||
#define ARM_r9 uregs[9]
|
||||
#define ARM_r8 uregs[8]
|
||||
#define ARM_r7 uregs[7]
|
||||
#define ARM_r6 uregs[6]
|
||||
#define ARM_r5 uregs[5]
|
||||
#define ARM_r4 uregs[4]
|
||||
#define ARM_r3 uregs[3]
|
||||
#define ARM_r2 uregs[2]
|
||||
#define ARM_r1 uregs[1]
|
||||
#define ARM_r0 uregs[0]
|
||||
#define ARM_ORIG_r0 uregs[17]
|
||||
|
||||
#define ARM_SYSCALL_BASE 0x900000
|
261
linux-user/arm/syscall_nr.h
Normal file
261
linux-user/arm/syscall_nr.h
Normal file
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* This file contains the system call numbers.
|
||||
*/
|
||||
|
||||
#define TARGET_NR_restart_syscall ( 0)
|
||||
#define TARGET_NR_exit ( 1)
|
||||
#define TARGET_NR_fork ( 2)
|
||||
#define TARGET_NR_read ( 3)
|
||||
#define TARGET_NR_write ( 4)
|
||||
#define TARGET_NR_open ( 5)
|
||||
#define TARGET_NR_close ( 6)
|
||||
#define TARGET_NR_waitpid ( 7) /* removed */
|
||||
#define TARGET_NR_creat ( 8)
|
||||
#define TARGET_NR_link ( 9)
|
||||
#define TARGET_NR_unlink ( 10)
|
||||
#define TARGET_NR_execve ( 11)
|
||||
#define TARGET_NR_chdir ( 12)
|
||||
#define TARGET_NR_time ( 13)
|
||||
#define TARGET_NR_mknod ( 14)
|
||||
#define TARGET_NR_chmod ( 15)
|
||||
#define TARGET_NR_lchown ( 16)
|
||||
#define TARGET_NR_break ( 17) /* removed */
|
||||
/* 18 was sys_stat */
|
||||
#define TARGET_NR_lseek ( 19)
|
||||
#define TARGET_NR_getpid ( 20)
|
||||
#define TARGET_NR_mount ( 21)
|
||||
#define TARGET_NR_umount ( 22)
|
||||
#define TARGET_NR_setuid ( 23)
|
||||
#define TARGET_NR_getuid ( 24)
|
||||
#define TARGET_NR_stime ( 25)
|
||||
#define TARGET_NR_ptrace ( 26)
|
||||
#define TARGET_NR_alarm ( 27)
|
||||
|
||||
#define TARGET_NR_pause ( 29)
|
||||
#define TARGET_NR_utime ( 30)
|
||||
#define TARGET_NR_stty ( 31) /* removed */
|
||||
#define TARGET_NR_gtty ( 32) /* removed */
|
||||
#define TARGET_NR_access ( 33)
|
||||
#define TARGET_NR_nice ( 34)
|
||||
#define TARGET_NR_ftime ( 35) /* removed */
|
||||
#define TARGET_NR_sync ( 36)
|
||||
#define TARGET_NR_kill ( 37)
|
||||
#define TARGET_NR_rename ( 38)
|
||||
#define TARGET_NR_mkdir ( 39)
|
||||
#define TARGET_NR_rmdir ( 40)
|
||||
#define TARGET_NR_dup ( 41)
|
||||
#define TARGET_NR_pipe ( 42)
|
||||
#define TARGET_NR_times ( 43)
|
||||
#define TARGET_NR_prof ( 44) /* removed */
|
||||
#define TARGET_NR_brk ( 45)
|
||||
#define TARGET_NR_setgid ( 46)
|
||||
#define TARGET_NR_getgid ( 47)
|
||||
#define TARGET_NR_signal ( 48) /* removed */
|
||||
#define TARGET_NR_geteuid ( 49)
|
||||
#define TARGET_NR_getegid ( 50)
|
||||
#define TARGET_NR_acct ( 51)
|
||||
#define TARGET_NR_umount2 ( 52)
|
||||
#define TARGET_NR_lock ( 53) /* removed */
|
||||
#define TARGET_NR_ioctl ( 54)
|
||||
#define TARGET_NR_fcntl ( 55)
|
||||
#define TARGET_NR_mpx ( 56) /* removed */
|
||||
#define TARGET_NR_setpgid ( 57)
|
||||
#define TARGET_NR_ulimit ( 58) /* removed */
|
||||
/* 59 was sys_olduname */
|
||||
#define TARGET_NR_umask ( 60)
|
||||
#define TARGET_NR_chroot ( 61)
|
||||
#define TARGET_NR_ustat ( 62)
|
||||
#define TARGET_NR_dup2 ( 63)
|
||||
#define TARGET_NR_getppid ( 64)
|
||||
#define TARGET_NR_getpgrp ( 65)
|
||||
#define TARGET_NR_setsid ( 66)
|
||||
#define TARGET_NR_sigaction ( 67)
|
||||
#define TARGET_NR_sgetmask ( 68) /* removed */
|
||||
#define TARGET_NR_ssetmask ( 69) /* removed */
|
||||
#define TARGET_NR_setreuid ( 70)
|
||||
#define TARGET_NR_setregid ( 71)
|
||||
#define TARGET_NR_sigsuspend ( 72)
|
||||
#define TARGET_NR_sigpending ( 73)
|
||||
#define TARGET_NR_sethostname ( 74)
|
||||
#define TARGET_NR_setrlimit ( 75)
|
||||
#define TARGET_NR_getrlimit ( 76) /* Back compat 2GB limited rlimit */
|
||||
#define TARGET_NR_getrusage ( 77)
|
||||
#define TARGET_NR_gettimeofday ( 78)
|
||||
#define TARGET_NR_settimeofday ( 79)
|
||||
#define TARGET_NR_getgroups ( 80)
|
||||
#define TARGET_NR_setgroups ( 81)
|
||||
#define TARGET_NR_select ( 82)
|
||||
#define TARGET_NR_symlink ( 83)
|
||||
/* 84 was sys_lstat */
|
||||
#define TARGET_NR_readlink ( 85)
|
||||
#define TARGET_NR_uselib ( 86)
|
||||
#define TARGET_NR_swapon ( 87)
|
||||
#define TARGET_NR_reboot ( 88)
|
||||
#define TARGET_NR_readdir ( 89)
|
||||
#define TARGET_NR_mmap ( 90)
|
||||
#define TARGET_NR_munmap ( 91)
|
||||
#define TARGET_NR_truncate ( 92)
|
||||
#define TARGET_NR_ftruncate ( 93)
|
||||
#define TARGET_NR_fchmod ( 94)
|
||||
#define TARGET_NR_fchown ( 95)
|
||||
#define TARGET_NR_getpriority ( 96)
|
||||
#define TARGET_NR_setpriority ( 97)
|
||||
#define TARGET_NR_profil ( 98) /* removed */
|
||||
#define TARGET_NR_statfs ( 99)
|
||||
#define TARGET_NR_fstatfs (100)
|
||||
#define TARGET_NR_ioperm (101)
|
||||
#define TARGET_NR_socketcall (102)
|
||||
#define TARGET_NR_syslog (103)
|
||||
#define TARGET_NR_setitimer (104)
|
||||
#define TARGET_NR_getitimer (105)
|
||||
#define TARGET_NR_stat (106)
|
||||
#define TARGET_NR_lstat (107)
|
||||
#define TARGET_NR_fstat (108)
|
||||
/* 109 was sys_uname */
|
||||
/* 110 was sys_iopl */
|
||||
#define TARGET_NR_vhangup (111)
|
||||
#define TARGET_NR_idle (112)
|
||||
#define TARGET_NR_syscall (113) /* syscall to call a syscall! */
|
||||
#define TARGET_NR_wait4 (114)
|
||||
#define TARGET_NR_swapoff (115)
|
||||
#define TARGET_NR_sysinfo (116)
|
||||
#define TARGET_NR_ipc (117)
|
||||
#define TARGET_NR_fsync (118)
|
||||
#define TARGET_NR_sigreturn (119)
|
||||
#define TARGET_NR_clone (120)
|
||||
#define TARGET_NR_setdomainname (121)
|
||||
#define TARGET_NR_uname (122)
|
||||
#define TARGET_NR_modify_ldt (123)
|
||||
#define TARGET_NR_adjtimex (124)
|
||||
#define TARGET_NR_mprotect (125)
|
||||
#define TARGET_NR_sigprocmask (126)
|
||||
#define TARGET_NR_create_module (127) /* removed */
|
||||
#define TARGET_NR_init_module (128)
|
||||
#define TARGET_NR_delete_module (129)
|
||||
#define TARGET_NR_get_kernel_syms (130) /* removed */
|
||||
#define TARGET_NR_quotactl (131)
|
||||
#define TARGET_NR_getpgid (132)
|
||||
#define TARGET_NR_fchdir (133)
|
||||
#define TARGET_NR_bdflush (134)
|
||||
#define TARGET_NR_sysfs (135)
|
||||
#define TARGET_NR_personality (136)
|
||||
#define TARGET_NR_afs_syscall (137) /* Syscall for Andrew File System */
|
||||
#define TARGET_NR_setfsuid (138)
|
||||
#define TARGET_NR_setfsgid (139)
|
||||
#define TARGET_NR__llseek (140)
|
||||
#define TARGET_NR_getdents (141)
|
||||
#define TARGET_NR__newselect (142)
|
||||
#define TARGET_NR_flock (143)
|
||||
#define TARGET_NR_msync (144)
|
||||
#define TARGET_NR_readv (145)
|
||||
#define TARGET_NR_writev (146)
|
||||
#define TARGET_NR_getsid (147)
|
||||
#define TARGET_NR_fdatasync (148)
|
||||
#define TARGET_NR__sysctl (149)
|
||||
#define TARGET_NR_mlock (150)
|
||||
#define TARGET_NR_munlock (151)
|
||||
#define TARGET_NR_mlockall (152)
|
||||
#define TARGET_NR_munlockall (153)
|
||||
#define TARGET_NR_sched_setparam (154)
|
||||
#define TARGET_NR_sched_getparam (155)
|
||||
#define TARGET_NR_sched_setscheduler (156)
|
||||
#define TARGET_NR_sched_getscheduler (157)
|
||||
#define TARGET_NR_sched_yield (158)
|
||||
#define TARGET_NR_sched_get_priority_max (159)
|
||||
#define TARGET_NR_sched_get_priority_min (160)
|
||||
#define TARGET_NR_sched_rr_get_interval (161)
|
||||
#define TARGET_NR_nanosleep (162)
|
||||
#define TARGET_NR_mremap (163)
|
||||
#define TARGET_NR_setresuid (164)
|
||||
#define TARGET_NR_getresuid (165)
|
||||
#define TARGET_NR_vm86 (166) /* removed */
|
||||
#define TARGET_NR_query_module (167) /* removed */
|
||||
#define TARGET_NR_poll (168)
|
||||
#define TARGET_NR_nfsservctl (169)
|
||||
#define TARGET_NR_setresgid (170)
|
||||
#define TARGET_NR_getresgid (171)
|
||||
#define TARGET_NR_prctl (172)
|
||||
#define TARGET_NR_rt_sigreturn (173)
|
||||
#define TARGET_NR_rt_sigaction (174)
|
||||
#define TARGET_NR_rt_sigprocmask (175)
|
||||
#define TARGET_NR_rt_sigpending (176)
|
||||
#define TARGET_NR_rt_sigtimedwait (177)
|
||||
#define TARGET_NR_rt_sigqueueinfo (178)
|
||||
#define TARGET_NR_rt_sigsuspend (179)
|
||||
#define TARGET_NR_pread (180)
|
||||
#define TARGET_NR_pwrite (181)
|
||||
#define TARGET_NR_chown (182)
|
||||
#define TARGET_NR_getcwd (183)
|
||||
#define TARGET_NR_capget (184)
|
||||
#define TARGET_NR_capset (185)
|
||||
#define TARGET_NR_sigaltstack (186)
|
||||
#define TARGET_NR_sendfile (187)
|
||||
/* 188 reserved */
|
||||
/* 189 reserved */
|
||||
#define TARGET_NR_vfork (190)
|
||||
#define TARGET_NR_ugetrlimit (191) /* SuS compliant getrlimit */
|
||||
#define TARGET_NR_mmap2 (192)
|
||||
#define TARGET_NR_truncate64 (193)
|
||||
#define TARGET_NR_ftruncate64 (194)
|
||||
#define TARGET_NR_stat64 (195)
|
||||
#define TARGET_NR_lstat64 (196)
|
||||
#define TARGET_NR_fstat64 (197)
|
||||
#define TARGET_NR_lchown32 (198)
|
||||
#define TARGET_NR_getuid32 (199)
|
||||
#define TARGET_NR_getgid32 (200)
|
||||
#define TARGET_NR_geteuid32 (201)
|
||||
#define TARGET_NR_getegid32 (202)
|
||||
#define TARGET_NR_setreuid32 (203)
|
||||
#define TARGET_NR_setregid32 (204)
|
||||
#define TARGET_NR_getgroups32 (205)
|
||||
#define TARGET_NR_setgroups32 (206)
|
||||
#define TARGET_NR_fchown32 (207)
|
||||
#define TARGET_NR_setresuid32 (208)
|
||||
#define TARGET_NR_getresuid32 (209)
|
||||
#define TARGET_NR_setresgid32 (210)
|
||||
#define TARGET_NR_getresgid32 (211)
|
||||
#define TARGET_NR_chown32 (212)
|
||||
#define TARGET_NR_setuid32 (213)
|
||||
#define TARGET_NR_setgid32 (214)
|
||||
#define TARGET_NR_setfsuid32 (215)
|
||||
#define TARGET_NR_setfsgid32 (216)
|
||||
#define TARGET_NR_getdents64 (217)
|
||||
#define TARGET_NR_pivot_root (218)
|
||||
#define TARGET_NR_mincore (219)
|
||||
#define TARGET_NR_madvise (220)
|
||||
#define TARGET_NR_fcntl64 (221)
|
||||
/* 222 for tux */
|
||||
/* 223 is unused */
|
||||
#define TARGET_NR_gettid (224)
|
||||
#define TARGET_NR_readahead (225)
|
||||
#define TARGET_NR_setxattr (226)
|
||||
#define TARGET_NR_lsetxattr (227)
|
||||
#define TARGET_NR_fsetxattr (228)
|
||||
#define TARGET_NR_getxattr (229)
|
||||
#define TARGET_NR_lgetxattr (230)
|
||||
#define TARGET_NR_fgetxattr (231)
|
||||
#define TARGET_NR_listxattr (232)
|
||||
#define TARGET_NR_llistxattr (233)
|
||||
#define TARGET_NR_flistxattr (234)
|
||||
#define TARGET_NR_removexattr (235)
|
||||
#define TARGET_NR_lremovexattr (236)
|
||||
#define TARGET_NR_fremovexattr (237)
|
||||
#define TARGET_NR_tkill (238)
|
||||
#define TARGET_NR_sendfile64 (239)
|
||||
#define TARGET_NR_futex (240)
|
||||
#define TARGET_NR_sched_setaffinity (241)
|
||||
#define TARGET_NR_sched_getaffinity (242)
|
||||
#define TARGET_NR_io_setup (243)
|
||||
#define TARGET_NR_io_destroy (244)
|
||||
#define TARGET_NR_io_getevents (245)
|
||||
#define TARGET_NR_io_submit (246)
|
||||
#define TARGET_NR_io_cancel (247)
|
||||
#define TARGET_NR_exit_group (248)
|
||||
#define TARGET_NR_lookup_dcookie (249)
|
||||
#define TARGET_NR_epoll_create (250)
|
||||
#define TARGET_NR_epoll_ctl (251)
|
||||
#define TARGET_NR_epoll_wait (252)
|
||||
#define TARGET_NR_remap_file_pages (253)
|
||||
/* 254 for set_thread_area */
|
||||
/* 255 for get_thread_area */
|
||||
/* 256 for set_tid_address */
|
220
linux-user/i386/syscall.h
Normal file
220
linux-user/i386/syscall.h
Normal file
|
@ -0,0 +1,220 @@
|
|||
/* default linux values for the selectors */
|
||||
#define __USER_CS (0x23)
|
||||
#define __USER_DS (0x2B)
|
||||
|
||||
struct target_pt_regs {
|
||||
long ebx;
|
||||
long ecx;
|
||||
long edx;
|
||||
long esi;
|
||||
long edi;
|
||||
long ebp;
|
||||
long eax;
|
||||
int xds;
|
||||
int xes;
|
||||
long orig_eax;
|
||||
long eip;
|
||||
int xcs;
|
||||
long eflags;
|
||||
long esp;
|
||||
int xss;
|
||||
};
|
||||
|
||||
/* ioctls */
|
||||
|
||||
#define TARGET_LDT_ENTRIES 8192
|
||||
#define TARGET_LDT_ENTRY_SIZE 8
|
||||
|
||||
#define TARGET_GDT_ENTRY_TLS_ENTRIES 3
|
||||
#define TARGET_GDT_ENTRY_TLS_MIN 6
|
||||
#define TARGET_GDT_ENTRY_TLS_MAX (TARGET_GDT_ENTRY_TLS_MIN + TARGET_GDT_ENTRY_TLS_ENTRIES - 1)
|
||||
|
||||
struct target_modify_ldt_ldt_s {
|
||||
unsigned int entry_number;
|
||||
target_ulong base_addr;
|
||||
unsigned int limit;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
/* vm86 defines */
|
||||
|
||||
#define TARGET_BIOSSEG 0x0f000
|
||||
|
||||
#define TARGET_CPU_086 0
|
||||
#define TARGET_CPU_186 1
|
||||
#define TARGET_CPU_286 2
|
||||
#define TARGET_CPU_386 3
|
||||
#define TARGET_CPU_486 4
|
||||
#define TARGET_CPU_586 5
|
||||
|
||||
#define TARGET_VM86_SIGNAL 0 /* return due to signal */
|
||||
#define TARGET_VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */
|
||||
#define TARGET_VM86_INTx 2 /* int3/int x instruction (ARG = x) */
|
||||
#define TARGET_VM86_STI 3 /* sti/popf/iret instruction enabled virtual interrupts */
|
||||
|
||||
/*
|
||||
* Additional return values when invoking new vm86()
|
||||
*/
|
||||
#define TARGET_VM86_PICRETURN 4 /* return due to pending PIC request */
|
||||
#define TARGET_VM86_TRAP 6 /* return due to DOS-debugger request */
|
||||
|
||||
/*
|
||||
* function codes when invoking new vm86()
|
||||
*/
|
||||
#define TARGET_VM86_PLUS_INSTALL_CHECK 0
|
||||
#define TARGET_VM86_ENTER 1
|
||||
#define TARGET_VM86_ENTER_NO_BYPASS 2
|
||||
#define TARGET_VM86_REQUEST_IRQ 3
|
||||
#define TARGET_VM86_FREE_IRQ 4
|
||||
#define TARGET_VM86_GET_IRQ_BITS 5
|
||||
#define TARGET_VM86_GET_AND_RESET_IRQ 6
|
||||
|
||||
/*
|
||||
* This is the stack-layout seen by the user space program when we have
|
||||
* done a translation of "SAVE_ALL" from vm86 mode. The real kernel layout
|
||||
* is 'kernel_vm86_regs' (see below).
|
||||
*/
|
||||
|
||||
struct target_vm86_regs {
|
||||
/*
|
||||
* normal regs, with special meaning for the segment descriptors..
|
||||
*/
|
||||
target_long ebx;
|
||||
target_long ecx;
|
||||
target_long edx;
|
||||
target_long esi;
|
||||
target_long edi;
|
||||
target_long ebp;
|
||||
target_long eax;
|
||||
target_long __null_ds;
|
||||
target_long __null_es;
|
||||
target_long __null_fs;
|
||||
target_long __null_gs;
|
||||
target_long orig_eax;
|
||||
target_long eip;
|
||||
unsigned short cs, __csh;
|
||||
target_long eflags;
|
||||
target_long esp;
|
||||
unsigned short ss, __ssh;
|
||||
/*
|
||||
* these are specific to v86 mode:
|
||||
*/
|
||||
unsigned short es, __esh;
|
||||
unsigned short ds, __dsh;
|
||||
unsigned short fs, __fsh;
|
||||
unsigned short gs, __gsh;
|
||||
};
|
||||
|
||||
struct target_revectored_struct {
|
||||
target_ulong __map[8]; /* 256 bits */
|
||||
};
|
||||
|
||||
struct target_vm86_struct {
|
||||
struct target_vm86_regs regs;
|
||||
target_ulong flags;
|
||||
target_ulong screen_bitmap;
|
||||
target_ulong cpu_type;
|
||||
struct target_revectored_struct int_revectored;
|
||||
struct target_revectored_struct int21_revectored;
|
||||
};
|
||||
|
||||
/*
|
||||
* flags masks
|
||||
*/
|
||||
#define TARGET_VM86_SCREEN_BITMAP 0x0001
|
||||
|
||||
struct target_vm86plus_info_struct {
|
||||
target_ulong flags;
|
||||
#define TARGET_force_return_for_pic (1 << 0)
|
||||
#define TARGET_vm86dbg_active (1 << 1) /* for debugger */
|
||||
#define TARGET_vm86dbg_TFpendig (1 << 2) /* for debugger */
|
||||
#define TARGET_is_vm86pus (1 << 31) /* for vm86 internal use */
|
||||
unsigned char vm86dbg_intxxtab[32]; /* for debugger */
|
||||
};
|
||||
|
||||
struct target_vm86plus_struct {
|
||||
struct target_vm86_regs regs;
|
||||
target_ulong flags;
|
||||
target_ulong screen_bitmap;
|
||||
target_ulong cpu_type;
|
||||
struct target_revectored_struct int_revectored;
|
||||
struct target_revectored_struct int21_revectored;
|
||||
struct target_vm86plus_info_struct vm86plus;
|
||||
};
|
||||
|
||||
/* ipcs */
|
||||
|
||||
#define TARGET_SEMOP 1
|
||||
#define TARGET_SEMGET 2
|
||||
#define TARGET_SEMCTL 3
|
||||
#define TARGET_MSGSND 11
|
||||
#define TARGET_MSGRCV 12
|
||||
#define TARGET_MSGGET 13
|
||||
#define TARGET_MSGCTL 14
|
||||
#define TARGET_SHMAT 21
|
||||
#define TARGET_SHMDT 22
|
||||
#define TARGET_SHMGET 23
|
||||
#define TARGET_SHMCTL 24
|
||||
|
||||
struct target_msgbuf {
|
||||
int mtype;
|
||||
char mtext[1];
|
||||
};
|
||||
|
||||
struct target_ipc_kludge {
|
||||
unsigned int msgp; /* Really (struct msgbuf *) */
|
||||
int msgtyp;
|
||||
};
|
||||
|
||||
struct target_ipc_perm {
|
||||
int key;
|
||||
unsigned short uid;
|
||||
unsigned short gid;
|
||||
unsigned short cuid;
|
||||
unsigned short cgid;
|
||||
unsigned short mode;
|
||||
unsigned short seq;
|
||||
};
|
||||
|
||||
struct target_msqid_ds {
|
||||
struct target_ipc_perm msg_perm;
|
||||
unsigned int msg_first; /* really struct target_msg* */
|
||||
unsigned int msg_last; /* really struct target_msg* */
|
||||
unsigned int msg_stime; /* really target_time_t */
|
||||
unsigned int msg_rtime; /* really target_time_t */
|
||||
unsigned int msg_ctime; /* really target_time_t */
|
||||
unsigned int wwait; /* really struct wait_queue* */
|
||||
unsigned int rwait; /* really struct wait_queue* */
|
||||
unsigned short msg_cbytes;
|
||||
unsigned short msg_qnum;
|
||||
unsigned short msg_qbytes;
|
||||
unsigned short msg_lspid;
|
||||
unsigned short msg_lrpid;
|
||||
};
|
||||
|
||||
struct target_shmid_ds {
|
||||
struct target_ipc_perm shm_perm;
|
||||
int shm_segsz;
|
||||
unsigned int shm_atime; /* really target_time_t */
|
||||
unsigned int shm_dtime; /* really target_time_t */
|
||||
unsigned int shm_ctime; /* really target_time_t */
|
||||
unsigned short shm_cpid;
|
||||
unsigned short shm_lpid;
|
||||
short shm_nattch;
|
||||
unsigned short shm_npages;
|
||||
unsigned long *shm_pages;
|
||||
void *attaches; /* really struct shm_desc * */
|
||||
};
|
||||
|
||||
#define TARGET_IPC_RMID 0
|
||||
#define TARGET_IPC_SET 1
|
||||
#define TARGET_IPC_STAT 2
|
||||
|
||||
union target_semun {
|
||||
int val;
|
||||
unsigned int buf; /* really struct semid_ds * */
|
||||
unsigned int array; /* really unsigned short * */
|
||||
unsigned int __buf; /* really struct seminfo * */
|
||||
unsigned int __pad; /* really void* */
|
||||
};
|
||||
|
273
linux-user/i386/syscall_nr.h
Normal file
273
linux-user/i386/syscall_nr.h
Normal file
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* This file contains the system call numbers.
|
||||
*/
|
||||
|
||||
#define TARGET_NR_restart_syscall 0
|
||||
#define TARGET_NR_exit 1
|
||||
#define TARGET_NR_fork 2
|
||||
#define TARGET_NR_read 3
|
||||
#define TARGET_NR_write 4
|
||||
#define TARGET_NR_open 5
|
||||
#define TARGET_NR_close 6
|
||||
#define TARGET_NR_waitpid 7
|
||||
#define TARGET_NR_creat 8
|
||||
#define TARGET_NR_link 9
|
||||
#define TARGET_NR_unlink 10
|
||||
#define TARGET_NR_execve 11
|
||||
#define TARGET_NR_chdir 12
|
||||
#define TARGET_NR_time 13
|
||||
#define TARGET_NR_mknod 14
|
||||
#define TARGET_NR_chmod 15
|
||||
#define TARGET_NR_lchown 16
|
||||
#define TARGET_NR_break 17
|
||||
#define TARGET_NR_oldstat 18
|
||||
#define TARGET_NR_lseek 19
|
||||
#define TARGET_NR_getpid 20
|
||||
#define TARGET_NR_mount 21
|
||||
#define TARGET_NR_umount 22
|
||||
#define TARGET_NR_setuid 23
|
||||
#define TARGET_NR_getuid 24
|
||||
#define TARGET_NR_stime 25
|
||||
#define TARGET_NR_ptrace 26
|
||||
#define TARGET_NR_alarm 27
|
||||
#define TARGET_NR_oldfstat 28
|
||||
#define TARGET_NR_pause 29
|
||||
#define TARGET_NR_utime 30
|
||||
#define TARGET_NR_stty 31
|
||||
#define TARGET_NR_gtty 32
|
||||
#define TARGET_NR_access 33
|
||||
#define TARGET_NR_nice 34
|
||||
#define TARGET_NR_ftime 35
|
||||
#define TARGET_NR_sync 36
|
||||
#define TARGET_NR_kill 37
|
||||
#define TARGET_NR_rename 38
|
||||
#define TARGET_NR_mkdir 39
|
||||
#define TARGET_NR_rmdir 40
|
||||
#define TARGET_NR_dup 41
|
||||
#define TARGET_NR_pipe 42
|
||||
#define TARGET_NR_times 43
|
||||
#define TARGET_NR_prof 44
|
||||
#define TARGET_NR_brk 45
|
||||
#define TARGET_NR_setgid 46
|
||||
#define TARGET_NR_getgid 47
|
||||
#define TARGET_NR_signal 48
|
||||
#define TARGET_NR_geteuid 49
|
||||
#define TARGET_NR_getegid 50
|
||||
#define TARGET_NR_acct 51
|
||||
#define TARGET_NR_umount2 52
|
||||
#define TARGET_NR_lock 53
|
||||
#define TARGET_NR_ioctl 54
|
||||
#define TARGET_NR_fcntl 55
|
||||
#define TARGET_NR_mpx 56
|
||||
#define TARGET_NR_setpgid 57
|
||||
#define TARGET_NR_ulimit 58
|
||||
#define TARGET_NR_oldolduname 59
|
||||
#define TARGET_NR_umask 60
|
||||
#define TARGET_NR_chroot 61
|
||||
#define TARGET_NR_ustat 62
|
||||
#define TARGET_NR_dup2 63
|
||||
#define TARGET_NR_getppid 64
|
||||
#define TARGET_NR_getpgrp 65
|
||||
#define TARGET_NR_setsid 66
|
||||
#define TARGET_NR_sigaction 67
|
||||
#define TARGET_NR_sgetmask 68
|
||||
#define TARGET_NR_ssetmask 69
|
||||
#define TARGET_NR_setreuid 70
|
||||
#define TARGET_NR_setregid 71
|
||||
#define TARGET_NR_sigsuspend 72
|
||||
#define TARGET_NR_sigpending 73
|
||||
#define TARGET_NR_sethostname 74
|
||||
#define TARGET_NR_setrlimit 75
|
||||
#define TARGET_NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
|
||||
#define TARGET_NR_getrusage 77
|
||||
#define TARGET_NR_gettimeofday 78
|
||||
#define TARGET_NR_settimeofday 79
|
||||
#define TARGET_NR_getgroups 80
|
||||
#define TARGET_NR_setgroups 81
|
||||
#define TARGET_NR_select 82
|
||||
#define TARGET_NR_symlink 83
|
||||
#define TARGET_NR_oldlstat 84
|
||||
#define TARGET_NR_readlink 85
|
||||
#define TARGET_NR_uselib 86
|
||||
#define TARGET_NR_swapon 87
|
||||
#define TARGET_NR_reboot 88
|
||||
#define TARGET_NR_readdir 89
|
||||
#define TARGET_NR_mmap 90
|
||||
#define TARGET_NR_munmap 91
|
||||
#define TARGET_NR_truncate 92
|
||||
#define TARGET_NR_ftruncate 93
|
||||
#define TARGET_NR_fchmod 94
|
||||
#define TARGET_NR_fchown 95
|
||||
#define TARGET_NR_getpriority 96
|
||||
#define TARGET_NR_setpriority 97
|
||||
#define TARGET_NR_profil 98
|
||||
#define TARGET_NR_statfs 99
|
||||
#define TARGET_NR_fstatfs 100
|
||||
#define TARGET_NR_ioperm 101
|
||||
#define TARGET_NR_socketcall 102
|
||||
#define TARGET_NR_syslog 103
|
||||
#define TARGET_NR_setitimer 104
|
||||
#define TARGET_NR_getitimer 105
|
||||
#define TARGET_NR_stat 106
|
||||
#define TARGET_NR_lstat 107
|
||||
#define TARGET_NR_fstat 108
|
||||
#define TARGET_NR_olduname 109
|
||||
#define TARGET_NR_iopl 110
|
||||
#define TARGET_NR_vhangup 111
|
||||
#define TARGET_NR_idle 112
|
||||
#define TARGET_NR_vm86old 113
|
||||
#define TARGET_NR_wait4 114
|
||||
#define TARGET_NR_swapoff 115
|
||||
#define TARGET_NR_sysinfo 116
|
||||
#define TARGET_NR_ipc 117
|
||||
#define TARGET_NR_fsync 118
|
||||
#define TARGET_NR_sigreturn 119
|
||||
#define TARGET_NR_clone 120
|
||||
#define TARGET_NR_setdomainname 121
|
||||
#define TARGET_NR_uname 122
|
||||
#define TARGET_NR_modify_ldt 123
|
||||
#define TARGET_NR_adjtimex 124
|
||||
#define TARGET_NR_mprotect 125
|
||||
#define TARGET_NR_sigprocmask 126
|
||||
#define TARGET_NR_create_module 127
|
||||
#define TARGET_NR_init_module 128
|
||||
#define TARGET_NR_delete_module 129
|
||||
#define TARGET_NR_get_kernel_syms 130
|
||||
#define TARGET_NR_quotactl 131
|
||||
#define TARGET_NR_getpgid 132
|
||||
#define TARGET_NR_fchdir 133
|
||||
#define TARGET_NR_bdflush 134
|
||||
#define TARGET_NR_sysfs 135
|
||||
#define TARGET_NR_personality 136
|
||||
#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */
|
||||
#define TARGET_NR_setfsuid 138
|
||||
#define TARGET_NR_setfsgid 139
|
||||
#define TARGET_NR__llseek 140
|
||||
#define TARGET_NR_getdents 141
|
||||
#define TARGET_NR__newselect 142
|
||||
#define TARGET_NR_flock 143
|
||||
#define TARGET_NR_msync 144
|
||||
#define TARGET_NR_readv 145
|
||||
#define TARGET_NR_writev 146
|
||||
#define TARGET_NR_getsid 147
|
||||
#define TARGET_NR_fdatasync 148
|
||||
#define TARGET_NR__sysctl 149
|
||||
#define TARGET_NR_mlock 150
|
||||
#define TARGET_NR_munlock 151
|
||||
#define TARGET_NR_mlockall 152
|
||||
#define TARGET_NR_munlockall 153
|
||||
#define TARGET_NR_sched_setparam 154
|
||||
#define TARGET_NR_sched_getparam 155
|
||||
#define TARGET_NR_sched_setscheduler 156
|
||||
#define TARGET_NR_sched_getscheduler 157
|
||||
#define TARGET_NR_sched_yield 158
|
||||
#define TARGET_NR_sched_get_priority_max 159
|
||||
#define TARGET_NR_sched_get_priority_min 160
|
||||
#define TARGET_NR_sched_rr_get_interval 161
|
||||
#define TARGET_NR_nanosleep 162
|
||||
#define TARGET_NR_mremap 163
|
||||
#define TARGET_NR_setresuid 164
|
||||
#define TARGET_NR_getresuid 165
|
||||
#define TARGET_NR_vm86 166
|
||||
#define TARGET_NR_query_module 167
|
||||
#define TARGET_NR_poll 168
|
||||
#define TARGET_NR_nfsservctl 169
|
||||
#define TARGET_NR_setresgid 170
|
||||
#define TARGET_NR_getresgid 171
|
||||
#define TARGET_NR_prctl 172
|
||||
#define TARGET_NR_rt_sigreturn 173
|
||||
#define TARGET_NR_rt_sigaction 174
|
||||
#define TARGET_NR_rt_sigprocmask 175
|
||||
#define TARGET_NR_rt_sigpending 176
|
||||
#define TARGET_NR_rt_sigtimedwait 177
|
||||
#define TARGET_NR_rt_sigqueueinfo 178
|
||||
#define TARGET_NR_rt_sigsuspend 179
|
||||
#define TARGET_NR_pread 180
|
||||
#define TARGET_NR_pwrite 181
|
||||
#define TARGET_NR_chown 182
|
||||
#define TARGET_NR_getcwd 183
|
||||
#define TARGET_NR_capget 184
|
||||
#define TARGET_NR_capset 185
|
||||
#define TARGET_NR_sigaltstack 186
|
||||
#define TARGET_NR_sendfile 187
|
||||
#define TARGET_NR_getpmsg 188 /* some people actually want streams */
|
||||
#define TARGET_NR_putpmsg 189 /* some people actually want streams */
|
||||
#define TARGET_NR_vfork 190
|
||||
#define TARGET_NR_ugetrlimit 191 /* SuS compliant getrlimit */
|
||||
#define TARGET_NR_mmap2 192
|
||||
#define TARGET_NR_truncate64 193
|
||||
#define TARGET_NR_ftruncate64 194
|
||||
#define TARGET_NR_stat64 195
|
||||
#define TARGET_NR_lstat64 196
|
||||
#define TARGET_NR_fstat64 197
|
||||
#define TARGET_NR_lchown32 198
|
||||
#define TARGET_NR_getuid32 199
|
||||
#define TARGET_NR_getgid32 200
|
||||
#define TARGET_NR_geteuid32 201
|
||||
#define TARGET_NR_getegid32 202
|
||||
#define TARGET_NR_setreuid32 203
|
||||
#define TARGET_NR_setregid32 204
|
||||
#define TARGET_NR_getgroups32 205
|
||||
#define TARGET_NR_setgroups32 206
|
||||
#define TARGET_NR_fchown32 207
|
||||
#define TARGET_NR_setresuid32 208
|
||||
#define TARGET_NR_getresuid32 209
|
||||
#define TARGET_NR_setresgid32 210
|
||||
#define TARGET_NR_getresgid32 211
|
||||
#define TARGET_NR_chown32 212
|
||||
#define TARGET_NR_setuid32 213
|
||||
#define TARGET_NR_setgid32 214
|
||||
#define TARGET_NR_setfsuid32 215
|
||||
#define TARGET_NR_setfsgid32 216
|
||||
#define TARGET_NR_pivot_root 217
|
||||
#define TARGET_NR_mincore 218
|
||||
#define TARGET_NR_madvise 219
|
||||
#define TARGET_NR_madvise1 219 /* delete when C lib stub is removed */
|
||||
#define TARGET_NR_getdents64 220
|
||||
#define TARGET_NR_fcntl64 221
|
||||
/* 223 is unused */
|
||||
#define TARGET_NR_gettid 224
|
||||
#define TARGET_NR_readahead 225
|
||||
#define TARGET_NR_setxattr 226
|
||||
#define TARGET_NR_lsetxattr 227
|
||||
#define TARGET_NR_fsetxattr 228
|
||||
#define TARGET_NR_getxattr 229
|
||||
#define TARGET_NR_lgetxattr 230
|
||||
#define TARGET_NR_fgetxattr 231
|
||||
#define TARGET_NR_listxattr 232
|
||||
#define TARGET_NR_llistxattr 233
|
||||
#define TARGET_NR_flistxattr 234
|
||||
#define TARGET_NR_removexattr 235
|
||||
#define TARGET_NR_lremovexattr 236
|
||||
#define TARGET_NR_fremovexattr 237
|
||||
#define TARGET_NR_tkill 238
|
||||
#define TARGET_NR_sendfile64 239
|
||||
#define TARGET_NR_futex 240
|
||||
#define TARGET_NR_sched_setaffinity 241
|
||||
#define TARGET_NR_sched_getaffinity 242
|
||||
#define TARGET_NR_set_thread_area 243
|
||||
#define TARGET_NR_get_thread_area 244
|
||||
#define TARGET_NR_io_setup 245
|
||||
#define TARGET_NR_io_destroy 246
|
||||
#define TARGET_NR_io_getevents 247
|
||||
#define TARGET_NR_io_submit 248
|
||||
#define TARGET_NR_io_cancel 249
|
||||
#define TARGET_NR_fadvise64 250
|
||||
|
||||
#define TARGET_NR_exit_group 252
|
||||
#define TARGET_NR_lookup_dcookie 253
|
||||
#define TARGET_NR_epoll_create 254
|
||||
#define TARGET_NR_epoll_ctl 255
|
||||
#define TARGET_NR_epoll_wait 256
|
||||
#define TARGET_NR_remap_file_pages 257
|
||||
#define TARGET_NR_set_tid_address 258
|
||||
#define TARGET_NR_timer_create 259
|
||||
#define TARGET_NR_timer_settime (TARGET_NR_timer_create+1)
|
||||
#define TARGET_NR_timer_gettime (TARGET_NR_timer_create+2)
|
||||
#define TARGET_NR_timer_getoverrun (TARGET_NR_timer_create+3)
|
||||
#define TARGET_NR_timer_delete (TARGET_NR_timer_create+4)
|
||||
#define TARGET_NR_clock_settime (TARGET_NR_timer_create+5)
|
||||
#define TARGET_NR_clock_gettime (TARGET_NR_timer_create+6)
|
||||
#define TARGET_NR_clock_getres (TARGET_NR_timer_create+7)
|
||||
#define TARGET_NR_clock_nanosleep (TARGET_NR_timer_create+8)
|
||||
|
63
target-arm/cpu.h
Normal file
63
target-arm/cpu.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* ARM virtual CPU header
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef CPU_ARM_H
|
||||
#define CPU_ARM_H
|
||||
|
||||
#include "cpu-defs.h"
|
||||
|
||||
#define EXCP_UDEF 1 /* undefined instruction */
|
||||
#define EXCP_SWI 2 /* software interrupt */
|
||||
|
||||
typedef struct CPUARMState {
|
||||
uint32_t regs[16];
|
||||
uint32_t cpsr;
|
||||
|
||||
/* cpsr flag cache for faster execution */
|
||||
uint32_t CF; /* 0 or 1 */
|
||||
uint32_t VF; /* V is the bit 31. All other bits are undefined */
|
||||
uint32_t NZF; /* N is bit 31. Z is computed from NZF */
|
||||
|
||||
/* exception/interrupt handling */
|
||||
jmp_buf jmp_env;
|
||||
int exception_index;
|
||||
int interrupt_request;
|
||||
struct TranslationBlock *current_tb;
|
||||
int user_mode_only;
|
||||
|
||||
/* user data */
|
||||
void *opaque;
|
||||
} CPUARMState;
|
||||
|
||||
CPUARMState *cpu_arm_init(void);
|
||||
int cpu_arm_exec(CPUARMState *s);
|
||||
void cpu_arm_close(CPUARMState *s);
|
||||
/* you can call this signal handler from your SIGBUS and SIGSEGV
|
||||
signal handlers to inform the virtual CPU of exceptions. non zero
|
||||
is returned if the signal was handled by the virtual CPU. */
|
||||
struct siginfo;
|
||||
int cpu_arm_signal_handler(int host_signum, struct siginfo *info,
|
||||
void *puc);
|
||||
|
||||
void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags);
|
||||
|
||||
#define TARGET_PAGE_BITS 12
|
||||
#include "cpu-all.h"
|
||||
|
||||
#endif
|
40
target-arm/exec.h
Normal file
40
target-arm/exec.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* ARM execution defines
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "dyngen-exec.h"
|
||||
|
||||
register struct CPUARMState *env asm(AREG0);
|
||||
register uint32_t T0 asm(AREG1);
|
||||
register uint32_t T1 asm(AREG2);
|
||||
register uint32_t T2 asm(AREG3);
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec-all.h"
|
||||
|
||||
void cpu_lock(void);
|
||||
void cpu_unlock(void);
|
||||
void cpu_loop_exit(void);
|
||||
|
||||
static inline int compute_cpsr(void)
|
||||
{
|
||||
int ZF;
|
||||
ZF = (env->NZF == 0);
|
||||
return env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) |
|
||||
(env->CF << 29) | ((env->VF & 0x80000000) >> 3);
|
||||
}
|
673
target-arm/op.c
Normal file
673
target-arm/op.c
Normal file
|
@ -0,0 +1,673 @@
|
|||
/*
|
||||
* ARM micro operations
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "exec.h"
|
||||
|
||||
#define REGNAME r0
|
||||
#define REG (env->regs[0])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r1
|
||||
#define REG (env->regs[1])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r2
|
||||
#define REG (env->regs[2])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r3
|
||||
#define REG (env->regs[3])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r4
|
||||
#define REG (env->regs[4])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r5
|
||||
#define REG (env->regs[5])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r6
|
||||
#define REG (env->regs[6])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r7
|
||||
#define REG (env->regs[7])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r8
|
||||
#define REG (env->regs[8])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r9
|
||||
#define REG (env->regs[9])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r10
|
||||
#define REG (env->regs[10])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r11
|
||||
#define REG (env->regs[11])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r12
|
||||
#define REG (env->regs[12])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r13
|
||||
#define REG (env->regs[13])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r14
|
||||
#define REG (env->regs[14])
|
||||
#include "op_template.h"
|
||||
|
||||
#define REGNAME r15
|
||||
#define REG (env->regs[15])
|
||||
#include "op_template.h"
|
||||
|
||||
void OPPROTO op_movl_T0_0(void)
|
||||
{
|
||||
T0 = 0;
|
||||
}
|
||||
|
||||
void OPPROTO op_movl_T0_im(void)
|
||||
{
|
||||
T0 = PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_movl_T1_im(void)
|
||||
{
|
||||
T1 = PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_movl_T2_im(void)
|
||||
{
|
||||
T2 = PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_addl_T1_im(void)
|
||||
{
|
||||
T1 += PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_addl_T1_T2(void)
|
||||
{
|
||||
T1 += T2;
|
||||
}
|
||||
|
||||
void OPPROTO op_subl_T1_T2(void)
|
||||
{
|
||||
T1 -= T2;
|
||||
}
|
||||
|
||||
void OPPROTO op_addl_T0_T1(void)
|
||||
{
|
||||
T0 += T1;
|
||||
}
|
||||
|
||||
void OPPROTO op_addl_T0_T1_cc(void)
|
||||
{
|
||||
unsigned int src1;
|
||||
src1 = T0;
|
||||
T0 += T1;
|
||||
env->NZF = T0;
|
||||
env->CF = T0 < src1;
|
||||
env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
|
||||
}
|
||||
|
||||
void OPPROTO op_adcl_T0_T1(void)
|
||||
{
|
||||
T0 += T1 + env->CF;
|
||||
}
|
||||
|
||||
void OPPROTO op_adcl_T0_T1_cc(void)
|
||||
{
|
||||
unsigned int src1;
|
||||
src1 = T0;
|
||||
if (!env->CF) {
|
||||
T0 += T1;
|
||||
env->CF = T0 < src1;
|
||||
} else {
|
||||
T0 += T1 + 1;
|
||||
env->CF = T0 <= src1;
|
||||
}
|
||||
env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
|
||||
env->NZF = T0;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
#define OPSUB(sub, sbc, res, T0, T1) \
|
||||
\
|
||||
void OPPROTO op_ ## sub ## l_T0_T1(void) \
|
||||
{ \
|
||||
res = T0 - T1; \
|
||||
} \
|
||||
\
|
||||
void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \
|
||||
{ \
|
||||
unsigned int src1; \
|
||||
src1 = T0; \
|
||||
T0 -= T1; \
|
||||
env->NZF = T0; \
|
||||
env->CF = src1 >= T1; \
|
||||
env->VF = (src1 ^ T1) & (src1 ^ T0); \
|
||||
res = T0; \
|
||||
} \
|
||||
\
|
||||
void OPPROTO op_ ## sbc ## l_T0_T1(void) \
|
||||
{ \
|
||||
res = T0 - T1 + env->CF - 1; \
|
||||
} \
|
||||
\
|
||||
void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \
|
||||
{ \
|
||||
unsigned int src1; \
|
||||
src1 = T0; \
|
||||
if (!env->CF) { \
|
||||
T0 = T0 - T1 - 1; \
|
||||
env->CF = src1 >= T1; \
|
||||
} else { \
|
||||
T0 = T0 - T1; \
|
||||
env->CF = src1 > T1; \
|
||||
} \
|
||||
env->VF = (src1 ^ T1) & (src1 ^ T0); \
|
||||
env->NZF = T0; \
|
||||
res = T0; \
|
||||
FORCE_RET(); \
|
||||
}
|
||||
|
||||
OPSUB(sub, sbc, T0, T0, T1)
|
||||
|
||||
OPSUB(rsb, rsc, T0, T1, T0)
|
||||
|
||||
void OPPROTO op_andl_T0_T1(void)
|
||||
{
|
||||
T0 &= T1;
|
||||
}
|
||||
|
||||
void OPPROTO op_xorl_T0_T1(void)
|
||||
{
|
||||
T0 ^= T1;
|
||||
}
|
||||
|
||||
void OPPROTO op_orl_T0_T1(void)
|
||||
{
|
||||
T0 |= T1;
|
||||
}
|
||||
|
||||
void OPPROTO op_bicl_T0_T1(void)
|
||||
{
|
||||
T0 &= ~T1;
|
||||
}
|
||||
|
||||
void OPPROTO op_notl_T1(void)
|
||||
{
|
||||
T1 = ~T1;
|
||||
}
|
||||
|
||||
void OPPROTO op_logic_T0_cc(void)
|
||||
{
|
||||
env->NZF = T0;
|
||||
}
|
||||
|
||||
void OPPROTO op_logic_T1_cc(void)
|
||||
{
|
||||
env->NZF = T1;
|
||||
}
|
||||
|
||||
#define EIP (env->regs[15])
|
||||
|
||||
void OPPROTO op_test_eq(void)
|
||||
{
|
||||
if (env->NZF == 0)
|
||||
JUMP_TB(op_test_eq, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_ne(void)
|
||||
{
|
||||
if (env->NZF != 0)
|
||||
JUMP_TB(op_test_ne, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_cs(void)
|
||||
{
|
||||
if (env->CF != 0)
|
||||
JUMP_TB(op_test_cs, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_cc(void)
|
||||
{
|
||||
if (env->CF == 0)
|
||||
JUMP_TB(op_test_cc, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_mi(void)
|
||||
{
|
||||
if ((env->NZF & 0x80000000) != 0)
|
||||
JUMP_TB(op_test_mi, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_pl(void)
|
||||
{
|
||||
if ((env->NZF & 0x80000000) == 0)
|
||||
JUMP_TB(op_test_pl, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_vs(void)
|
||||
{
|
||||
if ((env->VF & 0x80000000) != 0)
|
||||
JUMP_TB(op_test_vs, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_vc(void)
|
||||
{
|
||||
if ((env->VF & 0x80000000) == 0)
|
||||
JUMP_TB(op_test_vc, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_hi(void)
|
||||
{
|
||||
if (env->CF != 0 && env->NZF != 0)
|
||||
JUMP_TB(op_test_hi, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_ls(void)
|
||||
{
|
||||
if (env->CF == 0 || env->NZF == 0)
|
||||
JUMP_TB(op_test_ls, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_ge(void)
|
||||
{
|
||||
if (((env->VF ^ env->NZF) & 0x80000000) == 0)
|
||||
JUMP_TB(op_test_ge, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_lt(void)
|
||||
{
|
||||
if (((env->VF ^ env->NZF) & 0x80000000) != 0)
|
||||
JUMP_TB(op_test_lt, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_gt(void)
|
||||
{
|
||||
if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0)
|
||||
JUMP_TB(op_test_gt, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_test_le(void)
|
||||
{
|
||||
if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0)
|
||||
JUMP_TB(op_test_le, PARAM1, 0, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_jmp(void)
|
||||
{
|
||||
JUMP_TB(op_jmp, PARAM1, 1, PARAM2);
|
||||
}
|
||||
|
||||
void OPPROTO op_exit_tb(void)
|
||||
{
|
||||
EXIT_TB();
|
||||
}
|
||||
|
||||
void OPPROTO op_movl_T0_psr(void)
|
||||
{
|
||||
T0 = compute_cpsr();
|
||||
}
|
||||
|
||||
/* NOTE: N = 1 and Z = 1 cannot be stored currently */
|
||||
void OPPROTO op_movl_psr_T0(void)
|
||||
{
|
||||
unsigned int psr;
|
||||
psr = T0;
|
||||
env->CF = (psr >> 29) & 1;
|
||||
env->NZF = (psr & 0xc0000000) ^ 0x40000000;
|
||||
env->VF = (psr << 3) & 0x80000000;
|
||||
/* for user mode we do not update other state info */
|
||||
}
|
||||
|
||||
void OPPROTO op_mul_T0_T1(void)
|
||||
{
|
||||
T0 = T0 * T1;
|
||||
}
|
||||
|
||||
/* 64 bit unsigned mul */
|
||||
void OPPROTO op_mull_T0_T1(void)
|
||||
{
|
||||
uint64_t res;
|
||||
res = T0 * T1;
|
||||
T1 = res >> 32;
|
||||
T0 = res;
|
||||
}
|
||||
|
||||
/* 64 bit signed mul */
|
||||
void OPPROTO op_imull_T0_T1(void)
|
||||
{
|
||||
uint64_t res;
|
||||
res = (int32_t)T0 * (int32_t)T1;
|
||||
T1 = res >> 32;
|
||||
T0 = res;
|
||||
}
|
||||
|
||||
void OPPROTO op_addq_T0_T1(void)
|
||||
{
|
||||
uint64_t res;
|
||||
res = ((uint64_t)T1 << 32) | T0;
|
||||
res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
|
||||
T1 = res >> 32;
|
||||
T0 = res;
|
||||
}
|
||||
|
||||
void OPPROTO op_logicq_cc(void)
|
||||
{
|
||||
env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
|
||||
}
|
||||
|
||||
/* memory access */
|
||||
|
||||
void OPPROTO op_ldub_T0_T1(void)
|
||||
{
|
||||
T0 = ldub((void *)T1);
|
||||
}
|
||||
|
||||
void OPPROTO op_ldsb_T0_T1(void)
|
||||
{
|
||||
T0 = ldsb((void *)T1);
|
||||
}
|
||||
|
||||
void OPPROTO op_lduw_T0_T1(void)
|
||||
{
|
||||
T0 = lduw((void *)T1);
|
||||
}
|
||||
|
||||
void OPPROTO op_ldsw_T0_T1(void)
|
||||
{
|
||||
T0 = ldsw((void *)T1);
|
||||
}
|
||||
|
||||
void OPPROTO op_ldl_T0_T1(void)
|
||||
{
|
||||
T0 = ldl((void *)T1);
|
||||
}
|
||||
|
||||
void OPPROTO op_stb_T0_T1(void)
|
||||
{
|
||||
stb((void *)T1, T0);
|
||||
}
|
||||
|
||||
void OPPROTO op_stw_T0_T1(void)
|
||||
{
|
||||
stw((void *)T1, T0);
|
||||
}
|
||||
|
||||
void OPPROTO op_stl_T0_T1(void)
|
||||
{
|
||||
stl((void *)T1, T0);
|
||||
}
|
||||
|
||||
void OPPROTO op_swpb_T0_T1(void)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
cpu_lock();
|
||||
tmp = ldub((void *)T1);
|
||||
stb((void *)T1, T0);
|
||||
T0 = tmp;
|
||||
cpu_unlock();
|
||||
}
|
||||
|
||||
void OPPROTO op_swpl_T0_T1(void)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
cpu_lock();
|
||||
tmp = ldl((void *)T1);
|
||||
stl((void *)T1, T0);
|
||||
T0 = tmp;
|
||||
cpu_unlock();
|
||||
}
|
||||
|
||||
/* shifts */
|
||||
|
||||
/* T1 based */
|
||||
void OPPROTO op_shll_T1_im(void)
|
||||
{
|
||||
T1 = T1 << PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_shrl_T1_im(void)
|
||||
{
|
||||
T1 = (uint32_t)T1 >> PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_sarl_T1_im(void)
|
||||
{
|
||||
T1 = (int32_t)T1 >> PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_rorl_T1_im(void)
|
||||
{
|
||||
int shift;
|
||||
shift = PARAM1;
|
||||
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
|
||||
}
|
||||
|
||||
/* T1 based, set C flag */
|
||||
void OPPROTO op_shll_T1_im_cc(void)
|
||||
{
|
||||
env->CF = (T1 >> (32 - PARAM1)) & 1;
|
||||
T1 = T1 << PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_shrl_T1_im_cc(void)
|
||||
{
|
||||
env->CF = (T1 >> (PARAM1 - 1)) & 1;
|
||||
T1 = (uint32_t)T1 >> PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_sarl_T1_im_cc(void)
|
||||
{
|
||||
env->CF = (T1 >> (PARAM1 - 1)) & 1;
|
||||
T1 = (int32_t)T1 >> PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_rorl_T1_im_cc(void)
|
||||
{
|
||||
int shift;
|
||||
shift = PARAM1;
|
||||
env->CF = (T1 >> (shift - 1)) & 1;
|
||||
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
|
||||
}
|
||||
|
||||
/* T2 based */
|
||||
void OPPROTO op_shll_T2_im(void)
|
||||
{
|
||||
T2 = T2 << PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_shrl_T2_im(void)
|
||||
{
|
||||
T2 = (uint32_t)T2 >> PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_sarl_T2_im(void)
|
||||
{
|
||||
T2 = (int32_t)T2 >> PARAM1;
|
||||
}
|
||||
|
||||
void OPPROTO op_rorl_T2_im(void)
|
||||
{
|
||||
int shift;
|
||||
shift = PARAM1;
|
||||
T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
|
||||
}
|
||||
|
||||
/* T1 based, use T0 as shift count */
|
||||
|
||||
void OPPROTO op_shll_T1_T0(void)
|
||||
{
|
||||
int shift;
|
||||
shift = T0 & 0xff;
|
||||
if (shift >= 32)
|
||||
T1 = 0;
|
||||
else
|
||||
T1 = T1 << shift;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_shrl_T1_T0(void)
|
||||
{
|
||||
int shift;
|
||||
shift = T0 & 0xff;
|
||||
if (shift >= 32)
|
||||
T1 = 0;
|
||||
else
|
||||
T1 = (uint32_t)T1 >> shift;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_sarl_T1_T0(void)
|
||||
{
|
||||
int shift;
|
||||
shift = T0 & 0xff;
|
||||
if (shift >= 32)
|
||||
shift = 31;
|
||||
T1 = (int32_t)T1 >> shift;
|
||||
}
|
||||
|
||||
void OPPROTO op_rorl_T1_T0(void)
|
||||
{
|
||||
int shift;
|
||||
shift = T0 & 0x1f;
|
||||
if (shift) {
|
||||
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
/* T1 based, use T0 as shift count and compute CF */
|
||||
|
||||
void OPPROTO op_shll_T1_T0_cc(void)
|
||||
{
|
||||
int shift;
|
||||
shift = T0 & 0xff;
|
||||
if (shift >= 32) {
|
||||
if (shift == 32)
|
||||
env->CF = T1 & 1;
|
||||
else
|
||||
env->CF = 0;
|
||||
T1 = 0;
|
||||
} else if (shift != 0) {
|
||||
env->CF = (T1 >> (32 - shift)) & 1;
|
||||
T1 = T1 << shift;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_shrl_T1_T0_cc(void)
|
||||
{
|
||||
int shift;
|
||||
shift = T0 & 0xff;
|
||||
if (shift >= 32) {
|
||||
if (shift == 32)
|
||||
env->CF = (T1 >> 31) & 1;
|
||||
else
|
||||
env->CF = 0;
|
||||
T1 = 0;
|
||||
} else if (shift != 0) {
|
||||
env->CF = (T1 >> (shift - 1)) & 1;
|
||||
T1 = (uint32_t)T1 >> shift;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_sarl_T1_T0_cc(void)
|
||||
{
|
||||
int shift;
|
||||
shift = T0 & 0xff;
|
||||
if (shift >= 32) {
|
||||
env->CF = (T1 >> 31) & 1;
|
||||
T1 = (int32_t)T1 >> 31;
|
||||
} else {
|
||||
env->CF = (T1 >> (shift - 1)) & 1;
|
||||
T1 = (int32_t)T1 >> shift;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_rorl_T1_T0_cc(void)
|
||||
{
|
||||
int shift1, shift;
|
||||
shift1 = T0 & 0xff;
|
||||
shift = shift1 & 0x1f;
|
||||
if (shift == 0) {
|
||||
if (shift1 != 0)
|
||||
env->CF = (T1 >> 31) & 1;
|
||||
} else {
|
||||
env->CF = (T1 >> (shift - 1)) & 1;
|
||||
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
/* exceptions */
|
||||
|
||||
void OPPROTO op_swi(void)
|
||||
{
|
||||
env->exception_index = EXCP_SWI;
|
||||
cpu_loop_exit();
|
||||
}
|
||||
|
||||
void OPPROTO op_undef_insn(void)
|
||||
{
|
||||
env->exception_index = EXCP_UDEF;
|
||||
cpu_loop_exit();
|
||||
}
|
||||
|
||||
/* thread support */
|
||||
|
||||
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
void cpu_lock(void)
|
||||
{
|
||||
spin_lock(&global_cpu_lock);
|
||||
}
|
||||
|
||||
void cpu_unlock(void)
|
||||
{
|
||||
spin_unlock(&global_cpu_lock);
|
||||
}
|
||||
|
48
target-arm/op_template.h
Normal file
48
target-arm/op_template.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* ARM micro operations (templates for various register related
|
||||
* operations)
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
void OPPROTO glue(op_movl_T0_, REGNAME)(void)
|
||||
{
|
||||
T0 = REG;
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_movl_T1_, REGNAME)(void)
|
||||
{
|
||||
T1 = REG;
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_movl_T2_, REGNAME)(void)
|
||||
{
|
||||
T2 = REG;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_movl_, REGNAME), _T0)(void)
|
||||
{
|
||||
REG = T0;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_movl_, REGNAME), _T1)(void)
|
||||
{
|
||||
REG = T1;
|
||||
}
|
||||
|
||||
#undef REG
|
||||
#undef REGNAME
|
903
target-arm/translate.c
Normal file
903
target-arm/translate.c
Normal file
|
@ -0,0 +1,903 @@
|
|||
/*
|
||||
* ARM translation
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec-all.h"
|
||||
#include "disas.h"
|
||||
|
||||
/* internal defines */
|
||||
typedef struct DisasContext {
|
||||
uint8_t *pc;
|
||||
int is_jmp;
|
||||
struct TranslationBlock *tb;
|
||||
} DisasContext;
|
||||
|
||||
#define DISAS_JUMP_NEXT 4
|
||||
|
||||
/* XXX: move that elsewhere */
|
||||
static uint16_t *gen_opc_ptr;
|
||||
static uint32_t *gen_opparam_ptr;
|
||||
extern FILE *logfile;
|
||||
extern int loglevel;
|
||||
|
||||
enum {
|
||||
#define DEF(s, n, copy_size) INDEX_op_ ## s,
|
||||
#include "opc.h"
|
||||
#undef DEF
|
||||
NB_OPS,
|
||||
};
|
||||
|
||||
#include "gen-op.h"
|
||||
|
||||
typedef void (GenOpFunc)(void);
|
||||
typedef void (GenOpFunc1)(long);
|
||||
typedef void (GenOpFunc2)(long, long);
|
||||
typedef void (GenOpFunc3)(long, long, long);
|
||||
|
||||
static GenOpFunc2 *gen_test_cc[14] = {
|
||||
gen_op_test_eq,
|
||||
gen_op_test_ne,
|
||||
gen_op_test_cs,
|
||||
gen_op_test_cc,
|
||||
gen_op_test_mi,
|
||||
gen_op_test_pl,
|
||||
gen_op_test_vs,
|
||||
gen_op_test_vc,
|
||||
gen_op_test_hi,
|
||||
gen_op_test_ls,
|
||||
gen_op_test_ge,
|
||||
gen_op_test_lt,
|
||||
gen_op_test_gt,
|
||||
gen_op_test_le,
|
||||
};
|
||||
|
||||
const uint8_t table_logic_cc[16] = {
|
||||
1, /* and */
|
||||
1, /* xor */
|
||||
0, /* sub */
|
||||
0, /* rsb */
|
||||
0, /* add */
|
||||
0, /* adc */
|
||||
0, /* sbc */
|
||||
0, /* rsc */
|
||||
1, /* andl */
|
||||
1, /* xorl */
|
||||
0, /* cmp */
|
||||
0, /* cmn */
|
||||
1, /* orr */
|
||||
1, /* mov */
|
||||
1, /* bic */
|
||||
1, /* mvn */
|
||||
};
|
||||
|
||||
static GenOpFunc1 *gen_shift_T1_im[4] = {
|
||||
gen_op_shll_T1_im,
|
||||
gen_op_shrl_T1_im,
|
||||
gen_op_sarl_T1_im,
|
||||
gen_op_rorl_T1_im,
|
||||
};
|
||||
|
||||
static GenOpFunc1 *gen_shift_T2_im[4] = {
|
||||
gen_op_shll_T2_im,
|
||||
gen_op_shrl_T2_im,
|
||||
gen_op_sarl_T2_im,
|
||||
gen_op_rorl_T2_im,
|
||||
};
|
||||
|
||||
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
|
||||
gen_op_shll_T1_im_cc,
|
||||
gen_op_shrl_T1_im_cc,
|
||||
gen_op_sarl_T1_im_cc,
|
||||
gen_op_rorl_T1_im_cc,
|
||||
};
|
||||
|
||||
static GenOpFunc *gen_shift_T1_T0[4] = {
|
||||
gen_op_shll_T1_T0,
|
||||
gen_op_shrl_T1_T0,
|
||||
gen_op_sarl_T1_T0,
|
||||
gen_op_rorl_T1_T0,
|
||||
};
|
||||
|
||||
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
|
||||
gen_op_shll_T1_T0_cc,
|
||||
gen_op_shrl_T1_T0_cc,
|
||||
gen_op_sarl_T1_T0_cc,
|
||||
gen_op_rorl_T1_T0_cc,
|
||||
};
|
||||
|
||||
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
|
||||
{
|
||||
gen_op_movl_T0_r0,
|
||||
gen_op_movl_T0_r1,
|
||||
gen_op_movl_T0_r2,
|
||||
gen_op_movl_T0_r3,
|
||||
gen_op_movl_T0_r4,
|
||||
gen_op_movl_T0_r5,
|
||||
gen_op_movl_T0_r6,
|
||||
gen_op_movl_T0_r7,
|
||||
gen_op_movl_T0_r8,
|
||||
gen_op_movl_T0_r9,
|
||||
gen_op_movl_T0_r10,
|
||||
gen_op_movl_T0_r11,
|
||||
gen_op_movl_T0_r12,
|
||||
gen_op_movl_T0_r13,
|
||||
gen_op_movl_T0_r14,
|
||||
gen_op_movl_T0_r15,
|
||||
},
|
||||
{
|
||||
gen_op_movl_T1_r0,
|
||||
gen_op_movl_T1_r1,
|
||||
gen_op_movl_T1_r2,
|
||||
gen_op_movl_T1_r3,
|
||||
gen_op_movl_T1_r4,
|
||||
gen_op_movl_T1_r5,
|
||||
gen_op_movl_T1_r6,
|
||||
gen_op_movl_T1_r7,
|
||||
gen_op_movl_T1_r8,
|
||||
gen_op_movl_T1_r9,
|
||||
gen_op_movl_T1_r10,
|
||||
gen_op_movl_T1_r11,
|
||||
gen_op_movl_T1_r12,
|
||||
gen_op_movl_T1_r13,
|
||||
gen_op_movl_T1_r14,
|
||||
gen_op_movl_T1_r15,
|
||||
},
|
||||
{
|
||||
gen_op_movl_T2_r0,
|
||||
gen_op_movl_T2_r1,
|
||||
gen_op_movl_T2_r2,
|
||||
gen_op_movl_T2_r3,
|
||||
gen_op_movl_T2_r4,
|
||||
gen_op_movl_T2_r5,
|
||||
gen_op_movl_T2_r6,
|
||||
gen_op_movl_T2_r7,
|
||||
gen_op_movl_T2_r8,
|
||||
gen_op_movl_T2_r9,
|
||||
gen_op_movl_T2_r10,
|
||||
gen_op_movl_T2_r11,
|
||||
gen_op_movl_T2_r12,
|
||||
gen_op_movl_T2_r13,
|
||||
gen_op_movl_T2_r14,
|
||||
gen_op_movl_T2_r15,
|
||||
},
|
||||
};
|
||||
|
||||
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
|
||||
{
|
||||
gen_op_movl_r0_T0,
|
||||
gen_op_movl_r1_T0,
|
||||
gen_op_movl_r2_T0,
|
||||
gen_op_movl_r3_T0,
|
||||
gen_op_movl_r4_T0,
|
||||
gen_op_movl_r5_T0,
|
||||
gen_op_movl_r6_T0,
|
||||
gen_op_movl_r7_T0,
|
||||
gen_op_movl_r8_T0,
|
||||
gen_op_movl_r9_T0,
|
||||
gen_op_movl_r10_T0,
|
||||
gen_op_movl_r11_T0,
|
||||
gen_op_movl_r12_T0,
|
||||
gen_op_movl_r13_T0,
|
||||
gen_op_movl_r14_T0,
|
||||
gen_op_movl_r15_T0,
|
||||
},
|
||||
{
|
||||
gen_op_movl_r0_T1,
|
||||
gen_op_movl_r1_T1,
|
||||
gen_op_movl_r2_T1,
|
||||
gen_op_movl_r3_T1,
|
||||
gen_op_movl_r4_T1,
|
||||
gen_op_movl_r5_T1,
|
||||
gen_op_movl_r6_T1,
|
||||
gen_op_movl_r7_T1,
|
||||
gen_op_movl_r8_T1,
|
||||
gen_op_movl_r9_T1,
|
||||
gen_op_movl_r10_T1,
|
||||
gen_op_movl_r11_T1,
|
||||
gen_op_movl_r12_T1,
|
||||
gen_op_movl_r13_T1,
|
||||
gen_op_movl_r14_T1,
|
||||
gen_op_movl_r15_T1,
|
||||
},
|
||||
};
|
||||
|
||||
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
|
||||
gen_op_movl_T0_im,
|
||||
gen_op_movl_T1_im,
|
||||
gen_op_movl_T2_im,
|
||||
};
|
||||
|
||||
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (reg == 15) {
|
||||
/* normaly, since we updated PC, we need only to add 4 */
|
||||
val = (long)s->pc + 4;
|
||||
gen_op_movl_TN_im[t](val);
|
||||
} else {
|
||||
gen_op_movl_TN_reg[t][reg]();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
|
||||
{
|
||||
gen_movl_TN_reg(s, reg, 0);
|
||||
}
|
||||
|
||||
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
|
||||
{
|
||||
gen_movl_TN_reg(s, reg, 1);
|
||||
}
|
||||
|
||||
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
|
||||
{
|
||||
gen_movl_TN_reg(s, reg, 2);
|
||||
}
|
||||
|
||||
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
|
||||
{
|
||||
gen_op_movl_reg_TN[t][reg]();
|
||||
if (reg == 15) {
|
||||
s->is_jmp = DISAS_JUMP;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
|
||||
{
|
||||
gen_movl_reg_TN(s, reg, 0);
|
||||
}
|
||||
|
||||
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
|
||||
{
|
||||
gen_movl_reg_TN(s, reg, 1);
|
||||
}
|
||||
|
||||
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
|
||||
{
|
||||
int val, rm, shift;
|
||||
|
||||
if (!(insn & (1 << 25))) {
|
||||
/* immediate */
|
||||
val = insn & 0xfff;
|
||||
if (!(insn & (1 << 23)))
|
||||
val = -val;
|
||||
gen_op_addl_T1_im(val);
|
||||
} else {
|
||||
/* shift/register */
|
||||
rm = (insn) & 0xf;
|
||||
shift = (insn >> 7) & 0x1f;
|
||||
gen_movl_T2_reg(s, rm);
|
||||
if (shift != 0) {
|
||||
gen_shift_T2_im[(insn >> 5) & 3](shift);
|
||||
}
|
||||
if (!(insn & (1 << 23)))
|
||||
gen_op_subl_T1_T2();
|
||||
else
|
||||
gen_op_addl_T1_T2();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
|
||||
{
|
||||
int val, rm;
|
||||
|
||||
if (insn & (1 << 22)) {
|
||||
/* immediate */
|
||||
val = (insn & 0xf) | ((insn >> 4) & 0xf0);
|
||||
if (!(insn & (1 << 23)))
|
||||
val = -val;
|
||||
gen_op_addl_T1_im(val);
|
||||
} else {
|
||||
/* register */
|
||||
rm = (insn) & 0xf;
|
||||
gen_movl_T2_reg(s, rm);
|
||||
if (!(insn & (1 << 23)))
|
||||
gen_op_subl_T1_T2();
|
||||
else
|
||||
gen_op_addl_T1_T2();
|
||||
}
|
||||
}
|
||||
|
||||
static void disas_arm_insn(DisasContext *s)
|
||||
{
|
||||
unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
|
||||
|
||||
insn = ldl(s->pc);
|
||||
s->pc += 4;
|
||||
|
||||
cond = insn >> 28;
|
||||
if (cond == 0xf)
|
||||
goto illegal_op;
|
||||
if (cond != 0xe) {
|
||||
/* if not always execute, we generate a conditional jump to
|
||||
next instruction */
|
||||
gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
|
||||
s->is_jmp = DISAS_JUMP_NEXT;
|
||||
}
|
||||
if (((insn & 0x0e000000) == 0 &&
|
||||
(insn & 0x00000090) != 0x90) ||
|
||||
((insn & 0x0e000000) == (1 << 25))) {
|
||||
int set_cc, logic_cc, shiftop;
|
||||
|
||||
op1 = (insn >> 21) & 0xf;
|
||||
set_cc = (insn >> 20) & 1;
|
||||
logic_cc = table_logic_cc[op1] & set_cc;
|
||||
|
||||
/* data processing instruction */
|
||||
if (insn & (1 << 25)) {
|
||||
/* immediate operand */
|
||||
val = insn & 0xff;
|
||||
shift = ((insn >> 8) & 0xf) * 2;
|
||||
if (shift)
|
||||
val = (val >> shift) | (val << (32 - shift));
|
||||
gen_op_movl_T1_im(val);
|
||||
/* XXX: is CF modified ? */
|
||||
} else {
|
||||
/* register */
|
||||
rm = (insn) & 0xf;
|
||||
gen_movl_T1_reg(s, rm);
|
||||
shiftop = (insn >> 5) & 3;
|
||||
if (!(insn & (1 << 4))) {
|
||||
shift = (insn >> 7) & 0x1f;
|
||||
if (shift != 0) {
|
||||
if (logic_cc) {
|
||||
gen_shift_T1_im_cc[shiftop](shift);
|
||||
} else {
|
||||
gen_shift_T1_im[shiftop](shift);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rs = (insn >> 8) & 0xf;
|
||||
gen_movl_T0_reg(s, rs);
|
||||
if (logic_cc) {
|
||||
gen_shift_T1_T0_cc[shiftop]();
|
||||
} else {
|
||||
gen_shift_T1_T0[shiftop]();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (op1 != 0x0f && op1 != 0x0d) {
|
||||
rn = (insn >> 16) & 0xf;
|
||||
gen_movl_T0_reg(s, rn);
|
||||
}
|
||||
rd = (insn >> 12) & 0xf;
|
||||
switch(op1) {
|
||||
case 0x00:
|
||||
gen_op_andl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T0_cc();
|
||||
break;
|
||||
case 0x01:
|
||||
gen_op_xorl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T0_cc();
|
||||
break;
|
||||
case 0x02:
|
||||
if (set_cc)
|
||||
gen_op_subl_T0_T1_cc();
|
||||
else
|
||||
gen_op_subl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
break;
|
||||
case 0x03:
|
||||
if (set_cc)
|
||||
gen_op_rsbl_T0_T1_cc();
|
||||
else
|
||||
gen_op_rsbl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
break;
|
||||
case 0x04:
|
||||
if (set_cc)
|
||||
gen_op_addl_T0_T1_cc();
|
||||
else
|
||||
gen_op_addl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
break;
|
||||
case 0x05:
|
||||
if (set_cc)
|
||||
gen_op_adcl_T0_T1_cc();
|
||||
else
|
||||
gen_op_adcl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
break;
|
||||
case 0x06:
|
||||
if (set_cc)
|
||||
gen_op_sbcl_T0_T1_cc();
|
||||
else
|
||||
gen_op_sbcl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
break;
|
||||
case 0x07:
|
||||
if (set_cc)
|
||||
gen_op_rscl_T0_T1_cc();
|
||||
else
|
||||
gen_op_rscl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
break;
|
||||
case 0x08:
|
||||
if (set_cc) {
|
||||
gen_op_andl_T0_T1();
|
||||
gen_op_logic_T0_cc();
|
||||
}
|
||||
break;
|
||||
case 0x09:
|
||||
if (set_cc) {
|
||||
gen_op_xorl_T0_T1();
|
||||
gen_op_logic_T0_cc();
|
||||
}
|
||||
break;
|
||||
case 0x0a:
|
||||
if (set_cc) {
|
||||
gen_op_subl_T0_T1_cc();
|
||||
}
|
||||
break;
|
||||
case 0x0b:
|
||||
if (set_cc) {
|
||||
gen_op_addl_T0_T1_cc();
|
||||
}
|
||||
break;
|
||||
case 0x0c:
|
||||
gen_op_orl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T0_cc();
|
||||
break;
|
||||
case 0x0d:
|
||||
gen_movl_reg_T1(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T1_cc();
|
||||
break;
|
||||
case 0x0e:
|
||||
gen_op_bicl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T0_cc();
|
||||
break;
|
||||
default:
|
||||
case 0x0f:
|
||||
gen_op_notl_T1();
|
||||
gen_movl_reg_T1(s, rd);
|
||||
if (logic_cc)
|
||||
gen_op_logic_T1_cc();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* other instructions */
|
||||
op1 = (insn >> 24) & 0xf;
|
||||
switch(op1) {
|
||||
case 0x0:
|
||||
case 0x1:
|
||||
sh = (insn >> 5) & 3;
|
||||
if (sh == 0) {
|
||||
if (op1 == 0x0) {
|
||||
rd = (insn >> 16) & 0xf;
|
||||
rn = (insn >> 12) & 0xf;
|
||||
rs = (insn >> 8) & 0xf;
|
||||
rm = (insn) & 0xf;
|
||||
if (!(insn & (1 << 23))) {
|
||||
/* 32 bit mul */
|
||||
gen_movl_T0_reg(s, rs);
|
||||
gen_movl_T1_reg(s, rm);
|
||||
gen_op_mul_T0_T1();
|
||||
if (insn & (1 << 21)) {
|
||||
gen_movl_T1_reg(s, rn);
|
||||
gen_op_addl_T0_T1();
|
||||
}
|
||||
if (insn & (1 << 20))
|
||||
gen_op_logic_T0_cc();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
} else {
|
||||
/* 64 bit mul */
|
||||
gen_movl_T0_reg(s, rs);
|
||||
gen_movl_T1_reg(s, rm);
|
||||
if (insn & (1 << 22))
|
||||
gen_op_mull_T0_T1();
|
||||
else
|
||||
gen_op_imull_T0_T1();
|
||||
if (insn & (1 << 21))
|
||||
gen_op_addq_T0_T1(rn, rd);
|
||||
if (insn & (1 << 20))
|
||||
gen_op_logicq_cc();
|
||||
gen_movl_reg_T0(s, rn);
|
||||
gen_movl_reg_T1(s, rd);
|
||||
}
|
||||
} else {
|
||||
/* SWP instruction */
|
||||
rn = (insn >> 16) & 0xf;
|
||||
rd = (insn >> 12) & 0xf;
|
||||
rm = (insn) & 0xf;
|
||||
|
||||
gen_movl_T0_reg(s, rm);
|
||||
gen_movl_T1_reg(s, rn);
|
||||
if (insn & (1 << 22)) {
|
||||
gen_op_swpb_T0_T1();
|
||||
} else {
|
||||
gen_op_swpl_T0_T1();
|
||||
}
|
||||
gen_movl_reg_T0(s, rd);
|
||||
}
|
||||
} else {
|
||||
/* load/store half word */
|
||||
rn = (insn >> 16) & 0xf;
|
||||
rd = (insn >> 12) & 0xf;
|
||||
gen_movl_T1_reg(s, rn);
|
||||
if (insn & (1 << 25))
|
||||
gen_add_datah_offset(s, insn);
|
||||
if (insn & (1 << 20)) {
|
||||
/* load */
|
||||
switch(sh) {
|
||||
case 1:
|
||||
gen_op_lduw_T0_T1();
|
||||
break;
|
||||
case 2:
|
||||
gen_op_ldsb_T0_T1();
|
||||
break;
|
||||
default:
|
||||
case 3:
|
||||
gen_op_ldsw_T0_T1();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* store */
|
||||
gen_op_stw_T0_T1();
|
||||
}
|
||||
if (!(insn & (1 << 24))) {
|
||||
gen_add_datah_offset(s, insn);
|
||||
gen_movl_reg_T1(s, rn);
|
||||
} else if (insn & (1 << 21)) {
|
||||
gen_movl_reg_T1(s, rn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x4:
|
||||
case 0x5:
|
||||
case 0x6:
|
||||
case 0x7:
|
||||
/* load/store byte/word */
|
||||
rn = (insn >> 16) & 0xf;
|
||||
rd = (insn >> 12) & 0xf;
|
||||
gen_movl_T1_reg(s, rn);
|
||||
if (insn & (1 << 24))
|
||||
gen_add_data_offset(s, insn);
|
||||
if (insn & (1 << 20)) {
|
||||
/* load */
|
||||
if (insn & (1 << 22))
|
||||
gen_op_ldub_T0_T1();
|
||||
else
|
||||
gen_op_ldl_T0_T1();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
} else {
|
||||
/* store */
|
||||
gen_movl_T0_reg(s, rd);
|
||||
if (insn & (1 << 22))
|
||||
gen_op_stb_T0_T1();
|
||||
else
|
||||
gen_op_stl_T0_T1();
|
||||
}
|
||||
if (!(insn & (1 << 24))) {
|
||||
gen_add_data_offset(s, insn);
|
||||
gen_movl_reg_T1(s, rn);
|
||||
} else if (insn & (1 << 21))
|
||||
gen_movl_reg_T1(s, rn); {
|
||||
}
|
||||
break;
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
{
|
||||
int j, n;
|
||||
/* load/store multiple words */
|
||||
/* XXX: store correct base if write back */
|
||||
if (insn & (1 << 22))
|
||||
goto illegal_op; /* only usable in supervisor mode */
|
||||
rn = (insn >> 16) & 0xf;
|
||||
gen_movl_T1_reg(s, rn);
|
||||
|
||||
/* compute total size */
|
||||
n = 0;
|
||||
for(i=0;i<16;i++) {
|
||||
if (insn & (1 << i))
|
||||
n++;
|
||||
}
|
||||
/* XXX: test invalid n == 0 case ? */
|
||||
if (insn & (1 << 23)) {
|
||||
if (insn & (1 << 24)) {
|
||||
/* pre increment */
|
||||
gen_op_addl_T1_im(4);
|
||||
} else {
|
||||
/* post increment */
|
||||
}
|
||||
} else {
|
||||
if (insn & (1 << 24)) {
|
||||
/* pre decrement */
|
||||
gen_op_addl_T1_im(-(n * 4));
|
||||
} else {
|
||||
/* post decrement */
|
||||
if (n != 1)
|
||||
gen_op_addl_T1_im(-((n - 1) * 4));
|
||||
}
|
||||
}
|
||||
j = 0;
|
||||
for(i=0;i<16;i++) {
|
||||
if (insn & (1 << i)) {
|
||||
if (insn & (1 << 20)) {
|
||||
/* load */
|
||||
gen_op_ldl_T0_T1();
|
||||
gen_movl_reg_T0(s, i);
|
||||
} else {
|
||||
/* store */
|
||||
if (i == 15) {
|
||||
/* special case: r15 = PC + 12 */
|
||||
val = (long)s->pc + 8;
|
||||
gen_op_movl_TN_im[0](val);
|
||||
} else {
|
||||
gen_movl_T0_reg(s, i);
|
||||
}
|
||||
gen_op_stl_T0_T1();
|
||||
}
|
||||
j++;
|
||||
/* no need to add after the last transfer */
|
||||
if (j != n)
|
||||
gen_op_addl_T1_im(4);
|
||||
}
|
||||
}
|
||||
if (insn & (1 << 21)) {
|
||||
/* write back */
|
||||
if (insn & (1 << 23)) {
|
||||
if (insn & (1 << 24)) {
|
||||
/* pre increment */
|
||||
} else {
|
||||
/* post increment */
|
||||
gen_op_addl_T1_im(4);
|
||||
}
|
||||
} else {
|
||||
if (insn & (1 << 24)) {
|
||||
/* pre decrement */
|
||||
if (n != 1)
|
||||
gen_op_addl_T1_im(-((n - 1) * 4));
|
||||
} else {
|
||||
/* post decrement */
|
||||
gen_op_addl_T1_im(-(n * 4));
|
||||
}
|
||||
}
|
||||
gen_movl_reg_T1(s, rn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xa:
|
||||
case 0xb:
|
||||
{
|
||||
int offset;
|
||||
|
||||
/* branch (and link) */
|
||||
val = (int)s->pc;
|
||||
if (insn & (1 << 24)) {
|
||||
gen_op_movl_T0_im(val);
|
||||
gen_op_movl_reg_TN[0][14]();
|
||||
}
|
||||
offset = (((int)insn << 8) >> 8);
|
||||
val += (offset << 2) + 4;
|
||||
gen_op_jmp((long)s->tb, val);
|
||||
s->is_jmp = DISAS_TB_JUMP;
|
||||
}
|
||||
break;
|
||||
case 0xf:
|
||||
/* swi */
|
||||
gen_op_movl_T0_im((long)s->pc);
|
||||
gen_op_movl_reg_TN[0][15]();
|
||||
gen_op_swi();
|
||||
s->is_jmp = DISAS_JUMP;
|
||||
break;
|
||||
case 0xc:
|
||||
case 0xd:
|
||||
rd = (insn >> 12) & 0x7;
|
||||
rn = (insn >> 16) & 0xf;
|
||||
gen_movl_T1_reg(s, rn);
|
||||
val = (insn) & 0xff;
|
||||
if (!(insn & (1 << 23)))
|
||||
val = -val;
|
||||
switch((insn >> 8) & 0xf) {
|
||||
case 0x1:
|
||||
/* load/store */
|
||||
if ((insn & (1 << 24)))
|
||||
gen_op_addl_T1_im(val);
|
||||
/* XXX: do it */
|
||||
if (!(insn & (1 << 24)))
|
||||
gen_op_addl_T1_im(val);
|
||||
if (insn & (1 << 21))
|
||||
gen_movl_reg_T1(s, rn);
|
||||
break;
|
||||
case 0x2:
|
||||
{
|
||||
int n, i;
|
||||
/* load store multiple */
|
||||
if ((insn & (1 << 24)))
|
||||
gen_op_addl_T1_im(val);
|
||||
switch(insn & 0x00408000) {
|
||||
case 0x00008000: n = 1; break;
|
||||
case 0x00400000: n = 2; break;
|
||||
case 0x00408000: n = 3; break;
|
||||
default: n = 4; break;
|
||||
}
|
||||
for(i = 0;i < n; i++) {
|
||||
/* XXX: do it */
|
||||
}
|
||||
if (!(insn & (1 << 24)))
|
||||
gen_op_addl_T1_im(val);
|
||||
if (insn & (1 << 21))
|
||||
gen_movl_reg_T1(s, rn);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto illegal_op;
|
||||
}
|
||||
break;
|
||||
case 0x0e:
|
||||
/* float ops */
|
||||
/* XXX: do it */
|
||||
switch((insn >> 20) & 0xf) {
|
||||
case 0x2: /* wfs */
|
||||
break;
|
||||
case 0x3: /* rfs */
|
||||
break;
|
||||
case 0x4: /* wfc */
|
||||
break;
|
||||
case 0x5: /* rfc */
|
||||
break;
|
||||
default:
|
||||
goto illegal_op;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
illegal_op:
|
||||
gen_op_movl_T0_im((long)s->pc - 4);
|
||||
gen_op_movl_reg_TN[0][15]();
|
||||
gen_op_undef_insn();
|
||||
s->is_jmp = DISAS_JUMP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
|
||||
basic block 'tb'. If search_pc is TRUE, also generate PC
|
||||
information for each intermediate instruction. */
|
||||
static inline int gen_intermediate_code_internal(CPUState *env,
|
||||
TranslationBlock *tb,
|
||||
int search_pc)
|
||||
{
|
||||
DisasContext dc1, *dc = &dc1;
|
||||
uint16_t *gen_opc_end;
|
||||
int j, lj;
|
||||
uint8_t *pc_start;
|
||||
|
||||
/* generate intermediate code */
|
||||
pc_start = (uint8_t *)tb->pc;
|
||||
|
||||
dc->tb = tb;
|
||||
|
||||
gen_opc_ptr = gen_opc_buf;
|
||||
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
|
||||
gen_opparam_ptr = gen_opparam_buf;
|
||||
|
||||
dc->is_jmp = DISAS_NEXT;
|
||||
dc->pc = pc_start;
|
||||
lj = -1;
|
||||
do {
|
||||
if (search_pc) {
|
||||
j = gen_opc_ptr - gen_opc_buf;
|
||||
if (lj < j) {
|
||||
lj++;
|
||||
while (lj < j)
|
||||
gen_opc_instr_start[lj++] = 0;
|
||||
}
|
||||
gen_opc_pc[lj] = (uint32_t)dc->pc;
|
||||
gen_opc_instr_start[lj] = 1;
|
||||
}
|
||||
disas_arm_insn(dc);
|
||||
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
|
||||
(dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
|
||||
switch(dc->is_jmp) {
|
||||
case DISAS_JUMP_NEXT:
|
||||
case DISAS_NEXT:
|
||||
gen_op_jmp((long)dc->tb, (long)dc->pc);
|
||||
break;
|
||||
default:
|
||||
case DISAS_JUMP:
|
||||
/* indicate that the hash table must be used to find the next TB */
|
||||
gen_op_movl_T0_0();
|
||||
gen_op_exit_tb();
|
||||
break;
|
||||
case DISAS_TB_JUMP:
|
||||
/* nothing more to generate */
|
||||
break;
|
||||
}
|
||||
*gen_opc_ptr = INDEX_op_end;
|
||||
|
||||
#ifdef DEBUG_DISAS
|
||||
if (loglevel) {
|
||||
fprintf(logfile, "----------------\n");
|
||||
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
|
||||
disas(logfile, pc_start, dc->pc - pc_start, 0, 0);
|
||||
fprintf(logfile, "\n");
|
||||
|
||||
fprintf(logfile, "OP:\n");
|
||||
dump_ops(gen_opc_buf, gen_opparam_buf);
|
||||
fprintf(logfile, "\n");
|
||||
}
|
||||
#endif
|
||||
if (!search_pc)
|
||||
tb->size = dc->pc - pc_start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
|
||||
{
|
||||
return gen_intermediate_code_internal(env, tb, 0);
|
||||
}
|
||||
|
||||
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
|
||||
{
|
||||
return gen_intermediate_code_internal(env, tb, 1);
|
||||
}
|
||||
|
||||
CPUARMState *cpu_arm_init(void)
|
||||
{
|
||||
CPUARMState *env;
|
||||
|
||||
cpu_exec_init();
|
||||
|
||||
env = malloc(sizeof(CPUARMState));
|
||||
if (!env)
|
||||
return NULL;
|
||||
memset(env, 0, sizeof(CPUARMState));
|
||||
return env;
|
||||
}
|
||||
|
||||
void cpu_arm_close(CPUARMState *env)
|
||||
{
|
||||
free(env);
|
||||
}
|
||||
|
||||
void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0;i<16;i++) {
|
||||
fprintf(f, "R%02d=%08x", i, env->regs[i]);
|
||||
if ((i % 4) == 3)
|
||||
fprintf(f, "\n");
|
||||
else
|
||||
fprintf(f, " ");
|
||||
}
|
||||
fprintf(f, "PSR=%08x %c%c%c%c\n",
|
||||
env->cpsr,
|
||||
env->cpsr & (1 << 31) ? 'N' : '-',
|
||||
env->cpsr & (1 << 30) ? 'Z' : '-',
|
||||
env->cpsr & (1 << 29) ? 'C' : '-',
|
||||
env->cpsr & (1 << 28) ? 'V' : '-');
|
||||
}
|
401
target-i386/cpu.h
Normal file
401
target-i386/cpu.h
Normal file
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
* i386 virtual CPU header
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef CPU_I386_H
|
||||
#define CPU_I386_H
|
||||
|
||||
#include "cpu-defs.h"
|
||||
|
||||
#define R_EAX 0
|
||||
#define R_ECX 1
|
||||
#define R_EDX 2
|
||||
#define R_EBX 3
|
||||
#define R_ESP 4
|
||||
#define R_EBP 5
|
||||
#define R_ESI 6
|
||||
#define R_EDI 7
|
||||
|
||||
#define R_AL 0
|
||||
#define R_CL 1
|
||||
#define R_DL 2
|
||||
#define R_BL 3
|
||||
#define R_AH 4
|
||||
#define R_CH 5
|
||||
#define R_DH 6
|
||||
#define R_BH 7
|
||||
|
||||
#define R_ES 0
|
||||
#define R_CS 1
|
||||
#define R_SS 2
|
||||
#define R_DS 3
|
||||
#define R_FS 4
|
||||
#define R_GS 5
|
||||
|
||||
/* segment descriptor fields */
|
||||
#define DESC_G_MASK (1 << 23)
|
||||
#define DESC_B_SHIFT 22
|
||||
#define DESC_B_MASK (1 << DESC_B_SHIFT)
|
||||
#define DESC_AVL_MASK (1 << 20)
|
||||
#define DESC_P_MASK (1 << 15)
|
||||
#define DESC_DPL_SHIFT 13
|
||||
#define DESC_S_MASK (1 << 12)
|
||||
#define DESC_TYPE_SHIFT 8
|
||||
#define DESC_A_MASK (1 << 8)
|
||||
|
||||
#define DESC_CS_MASK (1 << 11)
|
||||
#define DESC_C_MASK (1 << 10)
|
||||
#define DESC_R_MASK (1 << 9)
|
||||
|
||||
#define DESC_E_MASK (1 << 10)
|
||||
#define DESC_W_MASK (1 << 9)
|
||||
|
||||
/* eflags masks */
|
||||
#define CC_C 0x0001
|
||||
#define CC_P 0x0004
|
||||
#define CC_A 0x0010
|
||||
#define CC_Z 0x0040
|
||||
#define CC_S 0x0080
|
||||
#define CC_O 0x0800
|
||||
|
||||
#define TF_SHIFT 8
|
||||
#define IOPL_SHIFT 12
|
||||
#define VM_SHIFT 17
|
||||
|
||||
#define TF_MASK 0x00000100
|
||||
#define IF_MASK 0x00000200
|
||||
#define DF_MASK 0x00000400
|
||||
#define IOPL_MASK 0x00003000
|
||||
#define NT_MASK 0x00004000
|
||||
#define RF_MASK 0x00010000
|
||||
#define VM_MASK 0x00020000
|
||||
#define AC_MASK 0x00040000
|
||||
#define VIF_MASK 0x00080000
|
||||
#define VIP_MASK 0x00100000
|
||||
#define ID_MASK 0x00200000
|
||||
|
||||
/* hidden flags - used internally by qemu to represent additionnal cpu
|
||||
states. Only the CPL and INHIBIT_IRQ are not redundant. We avoid
|
||||
using the IOPL_MASK, TF_MASK and VM_MASK bit position to ease oring
|
||||
with eflags. */
|
||||
/* current cpl */
|
||||
#define HF_CPL_SHIFT 0
|
||||
/* true if soft mmu is being used */
|
||||
#define HF_SOFTMMU_SHIFT 2
|
||||
/* true if hardware interrupts must be disabled for next instruction */
|
||||
#define HF_INHIBIT_IRQ_SHIFT 3
|
||||
/* 16 or 32 segments */
|
||||
#define HF_CS32_SHIFT 4
|
||||
#define HF_SS32_SHIFT 5
|
||||
/* zero base for DS, ES and SS */
|
||||
#define HF_ADDSEG_SHIFT 6
|
||||
|
||||
#define HF_CPL_MASK (3 << HF_CPL_SHIFT)
|
||||
#define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT)
|
||||
#define HF_INHIBIT_IRQ_MASK (1 << HF_INHIBIT_IRQ_SHIFT)
|
||||
#define HF_CS32_MASK (1 << HF_CS32_SHIFT)
|
||||
#define HF_SS32_MASK (1 << HF_SS32_SHIFT)
|
||||
#define HF_ADDSEG_MASK (1 << HF_ADDSEG_SHIFT)
|
||||
|
||||
#define CR0_PE_MASK (1 << 0)
|
||||
#define CR0_TS_MASK (1 << 3)
|
||||
#define CR0_WP_MASK (1 << 16)
|
||||
#define CR0_AM_MASK (1 << 18)
|
||||
#define CR0_PG_MASK (1 << 31)
|
||||
|
||||
#define CR4_VME_MASK (1 << 0)
|
||||
#define CR4_PVI_MASK (1 << 1)
|
||||
#define CR4_TSD_MASK (1 << 2)
|
||||
#define CR4_DE_MASK (1 << 3)
|
||||
#define CR4_PSE_MASK (1 << 4)
|
||||
|
||||
#define PG_PRESENT_BIT 0
|
||||
#define PG_RW_BIT 1
|
||||
#define PG_USER_BIT 2
|
||||
#define PG_PWT_BIT 3
|
||||
#define PG_PCD_BIT 4
|
||||
#define PG_ACCESSED_BIT 5
|
||||
#define PG_DIRTY_BIT 6
|
||||
#define PG_PSE_BIT 7
|
||||
#define PG_GLOBAL_BIT 8
|
||||
|
||||
#define PG_PRESENT_MASK (1 << PG_PRESENT_BIT)
|
||||
#define PG_RW_MASK (1 << PG_RW_BIT)
|
||||
#define PG_USER_MASK (1 << PG_USER_BIT)
|
||||
#define PG_PWT_MASK (1 << PG_PWT_BIT)
|
||||
#define PG_PCD_MASK (1 << PG_PCD_BIT)
|
||||
#define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT)
|
||||
#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT)
|
||||
#define PG_PSE_MASK (1 << PG_PSE_BIT)
|
||||
#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT)
|
||||
|
||||
#define PG_ERROR_W_BIT 1
|
||||
|
||||
#define PG_ERROR_P_MASK 0x01
|
||||
#define PG_ERROR_W_MASK (1 << PG_ERROR_W_BIT)
|
||||
#define PG_ERROR_U_MASK 0x04
|
||||
#define PG_ERROR_RSVD_MASK 0x08
|
||||
|
||||
#define MSR_IA32_APICBASE 0x1b
|
||||
#define MSR_IA32_APICBASE_BSP (1<<8)
|
||||
#define MSR_IA32_APICBASE_ENABLE (1<<11)
|
||||
#define MSR_IA32_APICBASE_BASE (0xfffff<<12)
|
||||
|
||||
#define MSR_IA32_SYSENTER_CS 0x174
|
||||
#define MSR_IA32_SYSENTER_ESP 0x175
|
||||
#define MSR_IA32_SYSENTER_EIP 0x176
|
||||
|
||||
#define EXCP00_DIVZ 0
|
||||
#define EXCP01_SSTP 1
|
||||
#define EXCP02_NMI 2
|
||||
#define EXCP03_INT3 3
|
||||
#define EXCP04_INTO 4
|
||||
#define EXCP05_BOUND 5
|
||||
#define EXCP06_ILLOP 6
|
||||
#define EXCP07_PREX 7
|
||||
#define EXCP08_DBLE 8
|
||||
#define EXCP09_XERR 9
|
||||
#define EXCP0A_TSS 10
|
||||
#define EXCP0B_NOSEG 11
|
||||
#define EXCP0C_STACK 12
|
||||
#define EXCP0D_GPF 13
|
||||
#define EXCP0E_PAGE 14
|
||||
#define EXCP10_COPR 16
|
||||
#define EXCP11_ALGN 17
|
||||
#define EXCP12_MCHK 18
|
||||
|
||||
enum {
|
||||
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
|
||||
CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
|
||||
CC_OP_MUL, /* modify all flags, C, O = (CC_SRC != 0) */
|
||||
|
||||
CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_ADDW,
|
||||
CC_OP_ADDL,
|
||||
|
||||
CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_ADCW,
|
||||
CC_OP_ADCL,
|
||||
|
||||
CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_SUBW,
|
||||
CC_OP_SUBL,
|
||||
|
||||
CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
||||
CC_OP_SBBW,
|
||||
CC_OP_SBBL,
|
||||
|
||||
CC_OP_LOGICB, /* modify all flags, CC_DST = res */
|
||||
CC_OP_LOGICW,
|
||||
CC_OP_LOGICL,
|
||||
|
||||
CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */
|
||||
CC_OP_INCW,
|
||||
CC_OP_INCL,
|
||||
|
||||
CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C */
|
||||
CC_OP_DECW,
|
||||
CC_OP_DECL,
|
||||
|
||||
CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
|
||||
CC_OP_SHLW,
|
||||
CC_OP_SHLL,
|
||||
|
||||
CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
|
||||
CC_OP_SARW,
|
||||
CC_OP_SARL,
|
||||
|
||||
CC_OP_NB,
|
||||
};
|
||||
|
||||
#ifdef __i386__
|
||||
#define USE_X86LDOUBLE
|
||||
#endif
|
||||
|
||||
#ifdef USE_X86LDOUBLE
|
||||
typedef long double CPU86_LDouble;
|
||||
#else
|
||||
typedef double CPU86_LDouble;
|
||||
#endif
|
||||
|
||||
typedef struct SegmentCache {
|
||||
uint32_t selector;
|
||||
uint8_t *base;
|
||||
uint32_t limit;
|
||||
uint32_t flags;
|
||||
} SegmentCache;
|
||||
|
||||
typedef struct CPUX86State {
|
||||
/* standard registers */
|
||||
uint32_t regs[8];
|
||||
uint32_t eip;
|
||||
uint32_t eflags; /* eflags register. During CPU emulation, CC
|
||||
flags and DF are set to zero because they are
|
||||
stored elsewhere */
|
||||
|
||||
/* emulator internal eflags handling */
|
||||
uint32_t cc_src;
|
||||
uint32_t cc_dst;
|
||||
uint32_t cc_op;
|
||||
int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
|
||||
uint32_t hflags; /* hidden flags, see HF_xxx constants */
|
||||
|
||||
/* FPU state */
|
||||
unsigned int fpstt; /* top of stack index */
|
||||
unsigned int fpus;
|
||||
unsigned int fpuc;
|
||||
uint8_t fptags[8]; /* 0 = valid, 1 = empty */
|
||||
CPU86_LDouble fpregs[8];
|
||||
|
||||
/* emulator internal variables */
|
||||
CPU86_LDouble ft0;
|
||||
union {
|
||||
float f;
|
||||
double d;
|
||||
int i32;
|
||||
int64_t i64;
|
||||
} fp_convert;
|
||||
|
||||
/* segments */
|
||||
SegmentCache segs[6]; /* selector values */
|
||||
SegmentCache ldt;
|
||||
SegmentCache tr;
|
||||
SegmentCache gdt; /* only base and limit are used */
|
||||
SegmentCache idt; /* only base and limit are used */
|
||||
|
||||
/* sysenter registers */
|
||||
uint32_t sysenter_cs;
|
||||
uint32_t sysenter_esp;
|
||||
uint32_t sysenter_eip;
|
||||
|
||||
/* exception/interrupt handling */
|
||||
jmp_buf jmp_env;
|
||||
int exception_index;
|
||||
int error_code;
|
||||
int exception_is_int;
|
||||
int exception_next_eip;
|
||||
struct TranslationBlock *current_tb; /* currently executing TB */
|
||||
uint32_t cr[5]; /* NOTE: cr1 is unused */
|
||||
uint32_t dr[8]; /* debug registers */
|
||||
int interrupt_request;
|
||||
int user_mode_only; /* user mode only simulation */
|
||||
|
||||
/* soft mmu support */
|
||||
/* 0 = kernel, 1 = user */
|
||||
CPUTLBEntry tlb_read[2][CPU_TLB_SIZE];
|
||||
CPUTLBEntry tlb_write[2][CPU_TLB_SIZE];
|
||||
|
||||
/* ice debug support */
|
||||
uint32_t breakpoints[MAX_BREAKPOINTS];
|
||||
int nb_breakpoints;
|
||||
int singlestep_enabled;
|
||||
|
||||
/* user data */
|
||||
void *opaque;
|
||||
} CPUX86State;
|
||||
|
||||
#ifndef IN_OP_I386
|
||||
void cpu_x86_outb(CPUX86State *env, int addr, int val);
|
||||
void cpu_x86_outw(CPUX86State *env, int addr, int val);
|
||||
void cpu_x86_outl(CPUX86State *env, int addr, int val);
|
||||
int cpu_x86_inb(CPUX86State *env, int addr);
|
||||
int cpu_x86_inw(CPUX86State *env, int addr);
|
||||
int cpu_x86_inl(CPUX86State *env, int addr);
|
||||
#endif
|
||||
|
||||
CPUX86State *cpu_x86_init(void);
|
||||
int cpu_x86_exec(CPUX86State *s);
|
||||
void cpu_x86_close(CPUX86State *s);
|
||||
int cpu_x86_get_pic_interrupt(CPUX86State *s);
|
||||
|
||||
/* this function must always be used to load data in the segment
|
||||
cache: it synchronizes the hflags with the segment cache values */
|
||||
static inline void cpu_x86_load_seg_cache(CPUX86State *env,
|
||||
int seg_reg, unsigned int selector,
|
||||
uint8_t *base, unsigned int limit,
|
||||
unsigned int flags)
|
||||
{
|
||||
SegmentCache *sc;
|
||||
unsigned int new_hflags;
|
||||
|
||||
sc = &env->segs[seg_reg];
|
||||
sc->selector = selector;
|
||||
sc->base = base;
|
||||
sc->limit = limit;
|
||||
sc->flags = flags;
|
||||
|
||||
/* update the hidden flags */
|
||||
new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
|
||||
>> (DESC_B_SHIFT - HF_CS32_SHIFT);
|
||||
new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)
|
||||
>> (DESC_B_SHIFT - HF_SS32_SHIFT);
|
||||
if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
|
||||
/* XXX: try to avoid this test. The problem comes from the
|
||||
fact that is real mode or vm86 mode we only modify the
|
||||
'base' and 'selector' fields of the segment cache to go
|
||||
faster. A solution may be to force addseg to one in
|
||||
translate-i386.c. */
|
||||
new_hflags |= HF_ADDSEG_MASK;
|
||||
} else {
|
||||
new_hflags |= (((unsigned long)env->segs[R_DS].base |
|
||||
(unsigned long)env->segs[R_ES].base |
|
||||
(unsigned long)env->segs[R_SS].base) != 0) <<
|
||||
HF_ADDSEG_SHIFT;
|
||||
}
|
||||
env->hflags = (env->hflags &
|
||||
~(HF_CS32_MASK | HF_SS32_MASK | HF_ADDSEG_MASK)) | new_hflags;
|
||||
}
|
||||
|
||||
/* wrapper, just in case memory mappings must be changed */
|
||||
static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl)
|
||||
{
|
||||
#if HF_CPL_MASK == 3
|
||||
s->hflags = (s->hflags & ~HF_CPL_MASK) | cpl;
|
||||
#else
|
||||
#error HF_CPL_MASK is hardcoded
|
||||
#endif
|
||||
}
|
||||
|
||||
/* the following helpers are only usable in user mode simulation as
|
||||
they can trigger unexpected exceptions */
|
||||
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
|
||||
void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32);
|
||||
void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32);
|
||||
|
||||
/* you can call this signal handler from your SIGBUS and SIGSEGV
|
||||
signal handlers to inform the virtual CPU of exceptions. non zero
|
||||
is returned if the signal was handled by the virtual CPU. */
|
||||
struct siginfo;
|
||||
int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
|
||||
void *puc);
|
||||
|
||||
/* MMU defines */
|
||||
void cpu_x86_init_mmu(CPUX86State *env);
|
||||
extern int phys_ram_size;
|
||||
extern int phys_ram_fd;
|
||||
extern uint8_t *phys_ram_base;
|
||||
|
||||
/* used to debug */
|
||||
#define X86_DUMP_FPU 0x0001 /* dump FPU state too */
|
||||
#define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
|
||||
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags);
|
||||
|
||||
#define TARGET_PAGE_BITS 12
|
||||
#include "cpu-all.h"
|
||||
|
||||
#endif /* CPU_I386_H */
|
416
target-i386/exec.h
Normal file
416
target-i386/exec.h
Normal file
|
@ -0,0 +1,416 @@
|
|||
/*
|
||||
* i386 execution defines
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "dyngen-exec.h"
|
||||
|
||||
/* at least 4 register variables are defines */
|
||||
register struct CPUX86State *env asm(AREG0);
|
||||
register uint32_t T0 asm(AREG1);
|
||||
register uint32_t T1 asm(AREG2);
|
||||
register uint32_t T2 asm(AREG3);
|
||||
|
||||
#define A0 T2
|
||||
|
||||
/* if more registers are available, we define some registers too */
|
||||
#ifdef AREG4
|
||||
register uint32_t EAX asm(AREG4);
|
||||
#define reg_EAX
|
||||
#endif
|
||||
|
||||
#ifdef AREG5
|
||||
register uint32_t ESP asm(AREG5);
|
||||
#define reg_ESP
|
||||
#endif
|
||||
|
||||
#ifdef AREG6
|
||||
register uint32_t EBP asm(AREG6);
|
||||
#define reg_EBP
|
||||
#endif
|
||||
|
||||
#ifdef AREG7
|
||||
register uint32_t ECX asm(AREG7);
|
||||
#define reg_ECX
|
||||
#endif
|
||||
|
||||
#ifdef AREG8
|
||||
register uint32_t EDX asm(AREG8);
|
||||
#define reg_EDX
|
||||
#endif
|
||||
|
||||
#ifdef AREG9
|
||||
register uint32_t EBX asm(AREG9);
|
||||
#define reg_EBX
|
||||
#endif
|
||||
|
||||
#ifdef AREG10
|
||||
register uint32_t ESI asm(AREG10);
|
||||
#define reg_ESI
|
||||
#endif
|
||||
|
||||
#ifdef AREG11
|
||||
register uint32_t EDI asm(AREG11);
|
||||
#define reg_EDI
|
||||
#endif
|
||||
|
||||
extern FILE *logfile;
|
||||
extern int loglevel;
|
||||
|
||||
#ifndef reg_EAX
|
||||
#define EAX (env->regs[R_EAX])
|
||||
#endif
|
||||
#ifndef reg_ECX
|
||||
#define ECX (env->regs[R_ECX])
|
||||
#endif
|
||||
#ifndef reg_EDX
|
||||
#define EDX (env->regs[R_EDX])
|
||||
#endif
|
||||
#ifndef reg_EBX
|
||||
#define EBX (env->regs[R_EBX])
|
||||
#endif
|
||||
#ifndef reg_ESP
|
||||
#define ESP (env->regs[R_ESP])
|
||||
#endif
|
||||
#ifndef reg_EBP
|
||||
#define EBP (env->regs[R_EBP])
|
||||
#endif
|
||||
#ifndef reg_ESI
|
||||
#define ESI (env->regs[R_ESI])
|
||||
#endif
|
||||
#ifndef reg_EDI
|
||||
#define EDI (env->regs[R_EDI])
|
||||
#endif
|
||||
#define EIP (env->eip)
|
||||
#define DF (env->df)
|
||||
|
||||
#define CC_SRC (env->cc_src)
|
||||
#define CC_DST (env->cc_dst)
|
||||
#define CC_OP (env->cc_op)
|
||||
|
||||
/* float macros */
|
||||
#define FT0 (env->ft0)
|
||||
#define ST0 (env->fpregs[env->fpstt])
|
||||
#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7])
|
||||
#define ST1 ST(1)
|
||||
|
||||
#ifdef USE_FP_CONVERT
|
||||
#define FP_CONVERT (env->fp_convert)
|
||||
#endif
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec-all.h"
|
||||
|
||||
typedef struct CCTable {
|
||||
int (*compute_all)(void); /* return all the flags */
|
||||
int (*compute_c)(void); /* return the C flag */
|
||||
} CCTable;
|
||||
|
||||
extern CCTable cc_table[];
|
||||
|
||||
void load_seg(int seg_reg, int selector, unsigned cur_eip);
|
||||
void helper_ljmp_protected_T0_T1(void);
|
||||
void helper_lcall_real_T0_T1(int shift, int next_eip);
|
||||
void helper_lcall_protected_T0_T1(int shift, int next_eip);
|
||||
void helper_iret_real(int shift);
|
||||
void helper_iret_protected(int shift);
|
||||
void helper_lret_protected(int shift, int addend);
|
||||
void helper_lldt_T0(void);
|
||||
void helper_ltr_T0(void);
|
||||
void helper_movl_crN_T0(int reg);
|
||||
void helper_movl_drN_T0(int reg);
|
||||
void helper_invlpg(unsigned int addr);
|
||||
void cpu_x86_update_cr0(CPUX86State *env);
|
||||
void cpu_x86_update_cr3(CPUX86State *env);
|
||||
void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr);
|
||||
int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write);
|
||||
void tlb_fill(unsigned long addr, int is_write, void *retaddr);
|
||||
void __hidden cpu_lock(void);
|
||||
void __hidden cpu_unlock(void);
|
||||
void do_interrupt(int intno, int is_int, int error_code,
|
||||
unsigned int next_eip, int is_hw);
|
||||
void do_interrupt_user(int intno, int is_int, int error_code,
|
||||
unsigned int next_eip);
|
||||
void raise_interrupt(int intno, int is_int, int error_code,
|
||||
unsigned int next_eip);
|
||||
void raise_exception_err(int exception_index, int error_code);
|
||||
void raise_exception(int exception_index);
|
||||
void __hidden cpu_loop_exit(void);
|
||||
void helper_fsave(uint8_t *ptr, int data32);
|
||||
void helper_frstor(uint8_t *ptr, int data32);
|
||||
|
||||
void OPPROTO op_movl_eflags_T0(void);
|
||||
void OPPROTO op_movl_T0_eflags(void);
|
||||
void raise_interrupt(int intno, int is_int, int error_code,
|
||||
unsigned int next_eip);
|
||||
void raise_exception_err(int exception_index, int error_code);
|
||||
void raise_exception(int exception_index);
|
||||
void helper_divl_EAX_T0(uint32_t eip);
|
||||
void helper_idivl_EAX_T0(uint32_t eip);
|
||||
void helper_cmpxchg8b(void);
|
||||
void helper_cpuid(void);
|
||||
void helper_rdtsc(void);
|
||||
void helper_rdmsr(void);
|
||||
void helper_wrmsr(void);
|
||||
void helper_lsl(void);
|
||||
void helper_lar(void);
|
||||
|
||||
#ifdef USE_X86LDOUBLE
|
||||
/* use long double functions */
|
||||
#define lrint lrintl
|
||||
#define llrint llrintl
|
||||
#define fabs fabsl
|
||||
#define sin sinl
|
||||
#define cos cosl
|
||||
#define sqrt sqrtl
|
||||
#define pow powl
|
||||
#define log logl
|
||||
#define tan tanl
|
||||
#define atan2 atan2l
|
||||
#define floor floorl
|
||||
#define ceil ceill
|
||||
#define rint rintl
|
||||
#endif
|
||||
|
||||
extern int lrint(CPU86_LDouble x);
|
||||
extern int64_t llrint(CPU86_LDouble x);
|
||||
extern CPU86_LDouble fabs(CPU86_LDouble x);
|
||||
extern CPU86_LDouble sin(CPU86_LDouble x);
|
||||
extern CPU86_LDouble cos(CPU86_LDouble x);
|
||||
extern CPU86_LDouble sqrt(CPU86_LDouble x);
|
||||
extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);
|
||||
extern CPU86_LDouble log(CPU86_LDouble x);
|
||||
extern CPU86_LDouble tan(CPU86_LDouble x);
|
||||
extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
|
||||
extern CPU86_LDouble floor(CPU86_LDouble x);
|
||||
extern CPU86_LDouble ceil(CPU86_LDouble x);
|
||||
extern CPU86_LDouble rint(CPU86_LDouble x);
|
||||
|
||||
#define RC_MASK 0xc00
|
||||
#define RC_NEAR 0x000
|
||||
#define RC_DOWN 0x400
|
||||
#define RC_UP 0x800
|
||||
#define RC_CHOP 0xc00
|
||||
|
||||
#define MAXTAN 9223372036854775808.0
|
||||
|
||||
#ifdef __arm__
|
||||
/* we have no way to do correct rounding - a FPU emulator is needed */
|
||||
#define FE_DOWNWARD FE_TONEAREST
|
||||
#define FE_UPWARD FE_TONEAREST
|
||||
#define FE_TOWARDZERO FE_TONEAREST
|
||||
#endif
|
||||
|
||||
#ifdef USE_X86LDOUBLE
|
||||
|
||||
/* only for x86 */
|
||||
typedef union {
|
||||
long double d;
|
||||
struct {
|
||||
unsigned long long lower;
|
||||
unsigned short upper;
|
||||
} l;
|
||||
} CPU86_LDoubleU;
|
||||
|
||||
/* the following deal with x86 long double-precision numbers */
|
||||
#define MAXEXPD 0x7fff
|
||||
#define EXPBIAS 16383
|
||||
#define EXPD(fp) (fp.l.upper & 0x7fff)
|
||||
#define SIGND(fp) ((fp.l.upper) & 0x8000)
|
||||
#define MANTD(fp) (fp.l.lower)
|
||||
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
|
||||
|
||||
#else
|
||||
|
||||
/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
|
||||
typedef union {
|
||||
double d;
|
||||
#if !defined(WORDS_BIGENDIAN) && !defined(__arm__)
|
||||
struct {
|
||||
uint32_t lower;
|
||||
int32_t upper;
|
||||
} l;
|
||||
#else
|
||||
struct {
|
||||
int32_t upper;
|
||||
uint32_t lower;
|
||||
} l;
|
||||
#endif
|
||||
#ifndef __arm__
|
||||
int64_t ll;
|
||||
#endif
|
||||
} CPU86_LDoubleU;
|
||||
|
||||
/* the following deal with IEEE double-precision numbers */
|
||||
#define MAXEXPD 0x7ff
|
||||
#define EXPBIAS 1023
|
||||
#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
|
||||
#define SIGND(fp) ((fp.l.upper) & 0x80000000)
|
||||
#ifdef __arm__
|
||||
#define MANTD(fp) (fp.l.lower | ((uint64_t)(fp.l.upper & ((1 << 20) - 1)) << 32))
|
||||
#else
|
||||
#define MANTD(fp) (fp.ll & ((1LL << 52) - 1))
|
||||
#endif
|
||||
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
|
||||
#endif
|
||||
|
||||
static inline void fpush(void)
|
||||
{
|
||||
env->fpstt = (env->fpstt - 1) & 7;
|
||||
env->fptags[env->fpstt] = 0; /* validate stack entry */
|
||||
}
|
||||
|
||||
static inline void fpop(void)
|
||||
{
|
||||
env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
|
||||
env->fpstt = (env->fpstt + 1) & 7;
|
||||
}
|
||||
|
||||
#ifndef USE_X86LDOUBLE
|
||||
static inline CPU86_LDouble helper_fldt(uint8_t *ptr)
|
||||
{
|
||||
CPU86_LDoubleU temp;
|
||||
int upper, e;
|
||||
uint64_t ll;
|
||||
|
||||
/* mantissa */
|
||||
upper = lduw(ptr + 8);
|
||||
/* XXX: handle overflow ? */
|
||||
e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
|
||||
e |= (upper >> 4) & 0x800; /* sign */
|
||||
ll = (ldq(ptr) >> 11) & ((1LL << 52) - 1);
|
||||
#ifdef __arm__
|
||||
temp.l.upper = (e << 20) | (ll >> 32);
|
||||
temp.l.lower = ll;
|
||||
#else
|
||||
temp.ll = ll | ((uint64_t)e << 52);
|
||||
#endif
|
||||
return temp.d;
|
||||
}
|
||||
|
||||
static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr)
|
||||
{
|
||||
CPU86_LDoubleU temp;
|
||||
int e;
|
||||
|
||||
temp.d = f;
|
||||
/* mantissa */
|
||||
stq(ptr, (MANTD(temp) << 11) | (1LL << 63));
|
||||
/* exponent + sign */
|
||||
e = EXPD(temp) - EXPBIAS + 16383;
|
||||
e |= SIGND(temp) >> 16;
|
||||
stw(ptr + 8, e);
|
||||
}
|
||||
#endif
|
||||
|
||||
const CPU86_LDouble f15rk[7];
|
||||
|
||||
void helper_fldt_ST0_A0(void);
|
||||
void helper_fstt_ST0_A0(void);
|
||||
void helper_fbld_ST0_A0(void);
|
||||
void helper_fbst_ST0_A0(void);
|
||||
void helper_f2xm1(void);
|
||||
void helper_fyl2x(void);
|
||||
void helper_fptan(void);
|
||||
void helper_fpatan(void);
|
||||
void helper_fxtract(void);
|
||||
void helper_fprem1(void);
|
||||
void helper_fprem(void);
|
||||
void helper_fyl2xp1(void);
|
||||
void helper_fsqrt(void);
|
||||
void helper_fsincos(void);
|
||||
void helper_frndint(void);
|
||||
void helper_fscale(void);
|
||||
void helper_fsin(void);
|
||||
void helper_fcos(void);
|
||||
void helper_fxam_ST0(void);
|
||||
void helper_fstenv(uint8_t *ptr, int data32);
|
||||
void helper_fldenv(uint8_t *ptr, int data32);
|
||||
void helper_fsave(uint8_t *ptr, int data32);
|
||||
void helper_frstor(uint8_t *ptr, int data32);
|
||||
|
||||
const uint8_t parity_table[256];
|
||||
const uint8_t rclw_table[32];
|
||||
const uint8_t rclb_table[32];
|
||||
|
||||
static inline uint32_t compute_eflags(void)
|
||||
{
|
||||
return env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
|
||||
}
|
||||
|
||||
#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK)
|
||||
|
||||
#define FL_UPDATE_CPL0_MASK (TF_MASK | IF_MASK | IOPL_MASK | NT_MASK | \
|
||||
RF_MASK | AC_MASK | ID_MASK)
|
||||
|
||||
/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
|
||||
static inline void load_eflags(int eflags, int update_mask)
|
||||
{
|
||||
CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
|
||||
DF = 1 - (2 * ((eflags >> 10) & 1));
|
||||
env->eflags = (env->eflags & ~update_mask) |
|
||||
(eflags & update_mask);
|
||||
}
|
||||
|
||||
/* memory access macros */
|
||||
|
||||
#define ldul ldl
|
||||
#define lduq ldq
|
||||
#define ldul_user ldl_user
|
||||
#define ldul_kernel ldl_kernel
|
||||
|
||||
#define ldub_raw ldub
|
||||
#define ldsb_raw ldsb
|
||||
#define lduw_raw lduw
|
||||
#define ldsw_raw ldsw
|
||||
#define ldl_raw ldl
|
||||
#define ldq_raw ldq
|
||||
|
||||
#define stb_raw stb
|
||||
#define stw_raw stw
|
||||
#define stl_raw stl
|
||||
#define stq_raw stq
|
||||
|
||||
#define MEMUSER 0
|
||||
#define DATA_SIZE 1
|
||||
#include "softmmu_header.h"
|
||||
|
||||
#define DATA_SIZE 2
|
||||
#include "softmmu_header.h"
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#include "softmmu_header.h"
|
||||
|
||||
#define DATA_SIZE 8
|
||||
#include "softmmu_header.h"
|
||||
|
||||
#undef MEMUSER
|
||||
#define MEMUSER 1
|
||||
#define DATA_SIZE 1
|
||||
#include "softmmu_header.h"
|
||||
|
||||
#define DATA_SIZE 2
|
||||
#include "softmmu_header.h"
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#include "softmmu_header.h"
|
||||
|
||||
#define DATA_SIZE 8
|
||||
#include "softmmu_header.h"
|
||||
|
||||
#undef MEMUSER
|
||||
|
1803
target-i386/helper.c
Normal file
1803
target-i386/helper.c
Normal file
File diff suppressed because it is too large
Load diff
390
target-i386/helper2.c
Normal file
390
target-i386/helper2.c
Normal file
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
* i386 helpers (without register variable usage)
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec-all.h"
|
||||
|
||||
//#define DEBUG_MMU
|
||||
|
||||
CPUX86State *cpu_x86_init(void)
|
||||
{
|
||||
CPUX86State *env;
|
||||
int i;
|
||||
static int inited;
|
||||
|
||||
cpu_exec_init();
|
||||
|
||||
env = malloc(sizeof(CPUX86State));
|
||||
if (!env)
|
||||
return NULL;
|
||||
memset(env, 0, sizeof(CPUX86State));
|
||||
/* basic FPU init */
|
||||
for(i = 0;i < 8; i++)
|
||||
env->fptags[i] = 1;
|
||||
env->fpuc = 0x37f;
|
||||
/* flags setup : we activate the IRQs by default as in user mode */
|
||||
env->eflags = 0x2 | IF_MASK;
|
||||
|
||||
tlb_flush(env);
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
env->hflags |= HF_SOFTMMU_MASK;
|
||||
#endif
|
||||
/* init various static tables */
|
||||
if (!inited) {
|
||||
inited = 1;
|
||||
optimize_flags_init();
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
void cpu_x86_close(CPUX86State *env)
|
||||
{
|
||||
free(env);
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
/* x86 debug */
|
||||
|
||||
static const char *cc_op_str[] = {
|
||||
"DYNAMIC",
|
||||
"EFLAGS",
|
||||
"MUL",
|
||||
"ADDB",
|
||||
"ADDW",
|
||||
"ADDL",
|
||||
"ADCB",
|
||||
"ADCW",
|
||||
"ADCL",
|
||||
"SUBB",
|
||||
"SUBW",
|
||||
"SUBL",
|
||||
"SBBB",
|
||||
"SBBW",
|
||||
"SBBL",
|
||||
"LOGICB",
|
||||
"LOGICW",
|
||||
"LOGICL",
|
||||
"INCB",
|
||||
"INCW",
|
||||
"INCL",
|
||||
"DECB",
|
||||
"DECW",
|
||||
"DECL",
|
||||
"SHLB",
|
||||
"SHLW",
|
||||
"SHLL",
|
||||
"SARB",
|
||||
"SARW",
|
||||
"SARL",
|
||||
};
|
||||
|
||||
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
|
||||
{
|
||||
int eflags;
|
||||
char cc_op_name[32];
|
||||
|
||||
eflags = env->eflags;
|
||||
fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
|
||||
"ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
|
||||
"EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
|
||||
env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
|
||||
env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
|
||||
env->eip, eflags,
|
||||
eflags & DF_MASK ? 'D' : '-',
|
||||
eflags & CC_O ? 'O' : '-',
|
||||
eflags & CC_S ? 'S' : '-',
|
||||
eflags & CC_Z ? 'Z' : '-',
|
||||
eflags & CC_A ? 'A' : '-',
|
||||
eflags & CC_P ? 'P' : '-',
|
||||
eflags & CC_C ? 'C' : '-');
|
||||
fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
|
||||
env->segs[R_CS].selector,
|
||||
env->segs[R_SS].selector,
|
||||
env->segs[R_DS].selector,
|
||||
env->segs[R_ES].selector,
|
||||
env->segs[R_FS].selector,
|
||||
env->segs[R_GS].selector);
|
||||
if (flags & X86_DUMP_CCOP) {
|
||||
if ((unsigned)env->cc_op < CC_OP_NB)
|
||||
strcpy(cc_op_name, cc_op_str[env->cc_op]);
|
||||
else
|
||||
snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
|
||||
fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
|
||||
env->cc_src, env->cc_dst, cc_op_name);
|
||||
}
|
||||
if (flags & X86_DUMP_FPU) {
|
||||
fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
|
||||
(double)env->fpregs[0],
|
||||
(double)env->fpregs[1],
|
||||
(double)env->fpregs[2],
|
||||
(double)env->fpregs[3]);
|
||||
fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
|
||||
(double)env->fpregs[4],
|
||||
(double)env->fpregs[5],
|
||||
(double)env->fpregs[7],
|
||||
(double)env->fpregs[8]);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
/* x86 mmu */
|
||||
/* XXX: add PGE support */
|
||||
|
||||
/* called when cr3 or PG bit are modified */
|
||||
static int last_pg_state = -1;
|
||||
static int last_pe_state = 0;
|
||||
int phys_ram_size;
|
||||
int phys_ram_fd;
|
||||
uint8_t *phys_ram_base;
|
||||
|
||||
void cpu_x86_update_cr0(CPUX86State *env)
|
||||
{
|
||||
int pg_state, pe_state;
|
||||
|
||||
#ifdef DEBUG_MMU
|
||||
printf("CR0 update: CR0=0x%08x\n", env->cr[0]);
|
||||
#endif
|
||||
pg_state = env->cr[0] & CR0_PG_MASK;
|
||||
if (pg_state != last_pg_state) {
|
||||
page_unmap();
|
||||
tlb_flush(env);
|
||||
last_pg_state = pg_state;
|
||||
}
|
||||
pe_state = env->cr[0] & CR0_PE_MASK;
|
||||
if (last_pe_state != pe_state) {
|
||||
tb_flush();
|
||||
last_pe_state = pe_state;
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_x86_update_cr3(CPUX86State *env)
|
||||
{
|
||||
if (env->cr[0] & CR0_PG_MASK) {
|
||||
#if defined(DEBUG_MMU)
|
||||
printf("CR3 update: CR3=%08x\n", env->cr[3]);
|
||||
#endif
|
||||
page_unmap();
|
||||
tlb_flush(env);
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_x86_init_mmu(CPUX86State *env)
|
||||
{
|
||||
last_pg_state = -1;
|
||||
cpu_x86_update_cr0(env);
|
||||
}
|
||||
|
||||
/* XXX: also flush 4MB pages */
|
||||
void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
|
||||
{
|
||||
int flags;
|
||||
unsigned long virt_addr;
|
||||
|
||||
tlb_flush_page(env, addr);
|
||||
|
||||
flags = page_get_flags(addr);
|
||||
if (flags & PAGE_VALID) {
|
||||
virt_addr = addr & ~0xfff;
|
||||
munmap((void *)virt_addr, 4096);
|
||||
page_set_flags(virt_addr, virt_addr + 4096, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* return value:
|
||||
-1 = cannot handle fault
|
||||
0 = nothing more to do
|
||||
1 = generate PF fault
|
||||
2 = soft MMU activation required for this block
|
||||
*/
|
||||
int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
|
||||
{
|
||||
uint8_t *pde_ptr, *pte_ptr;
|
||||
uint32_t pde, pte, virt_addr;
|
||||
int cpl, error_code, is_dirty, is_user, prot, page_size, ret;
|
||||
unsigned long pd;
|
||||
|
||||
cpl = env->hflags & HF_CPL_MASK;
|
||||
is_user = (cpl == 3);
|
||||
|
||||
#ifdef DEBUG_MMU
|
||||
printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n",
|
||||
addr, is_write, is_user, env->eip);
|
||||
#endif
|
||||
|
||||
if (env->user_mode_only) {
|
||||
/* user mode only emulation */
|
||||
error_code = 0;
|
||||
goto do_fault;
|
||||
}
|
||||
|
||||
if (!(env->cr[0] & CR0_PG_MASK)) {
|
||||
pte = addr;
|
||||
virt_addr = addr & ~0xfff;
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
page_size = 4096;
|
||||
goto do_mapping;
|
||||
}
|
||||
|
||||
/* page directory entry */
|
||||
pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3));
|
||||
pde = ldl(pde_ptr);
|
||||
if (!(pde & PG_PRESENT_MASK)) {
|
||||
error_code = 0;
|
||||
goto do_fault;
|
||||
}
|
||||
if (is_user) {
|
||||
if (!(pde & PG_USER_MASK))
|
||||
goto do_fault_protect;
|
||||
if (is_write && !(pde & PG_RW_MASK))
|
||||
goto do_fault_protect;
|
||||
} else {
|
||||
if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&
|
||||
is_write && !(pde & PG_RW_MASK))
|
||||
goto do_fault_protect;
|
||||
}
|
||||
/* if PSE bit is set, then we use a 4MB page */
|
||||
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
|
||||
is_dirty = is_write && !(pde & PG_DIRTY_MASK);
|
||||
if (!(pde & PG_ACCESSED_MASK)) {
|
||||
pde |= PG_ACCESSED_MASK;
|
||||
if (is_dirty)
|
||||
pde |= PG_DIRTY_MASK;
|
||||
stl(pde_ptr, pde);
|
||||
}
|
||||
|
||||
pte = pde & ~0x003ff000; /* align to 4MB */
|
||||
page_size = 4096 * 1024;
|
||||
virt_addr = addr & ~0x003fffff;
|
||||
} else {
|
||||
if (!(pde & PG_ACCESSED_MASK)) {
|
||||
pde |= PG_ACCESSED_MASK;
|
||||
stl(pde_ptr, pde);
|
||||
}
|
||||
|
||||
/* page directory entry */
|
||||
pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc));
|
||||
pte = ldl(pte_ptr);
|
||||
if (!(pte & PG_PRESENT_MASK)) {
|
||||
error_code = 0;
|
||||
goto do_fault;
|
||||
}
|
||||
if (is_user) {
|
||||
if (!(pte & PG_USER_MASK))
|
||||
goto do_fault_protect;
|
||||
if (is_write && !(pte & PG_RW_MASK))
|
||||
goto do_fault_protect;
|
||||
} else {
|
||||
if ((env->cr[0] & CR0_WP_MASK) && (pte & PG_USER_MASK) &&
|
||||
is_write && !(pte & PG_RW_MASK))
|
||||
goto do_fault_protect;
|
||||
}
|
||||
is_dirty = is_write && !(pte & PG_DIRTY_MASK);
|
||||
if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
|
||||
pte |= PG_ACCESSED_MASK;
|
||||
if (is_dirty)
|
||||
pte |= PG_DIRTY_MASK;
|
||||
stl(pte_ptr, pte);
|
||||
}
|
||||
page_size = 4096;
|
||||
virt_addr = addr & ~0xfff;
|
||||
}
|
||||
/* the page can be put in the TLB */
|
||||
prot = PROT_READ;
|
||||
if (is_user) {
|
||||
if (pte & PG_RW_MASK)
|
||||
prot |= PROT_WRITE;
|
||||
} else {
|
||||
if (!(env->cr[0] & CR0_WP_MASK) || !(pte & PG_USER_MASK) ||
|
||||
(pte & PG_RW_MASK))
|
||||
prot |= PROT_WRITE;
|
||||
}
|
||||
|
||||
do_mapping:
|
||||
if (env->hflags & HF_SOFTMMU_MASK) {
|
||||
unsigned long paddr, vaddr, address, addend, page_offset;
|
||||
int index;
|
||||
|
||||
/* software MMU case. Even if 4MB pages, we map only one 4KB
|
||||
page in the cache to avoid filling it too fast */
|
||||
page_offset = (addr & ~0xfff) & (page_size - 1);
|
||||
paddr = (pte & ~0xfff) + page_offset;
|
||||
vaddr = virt_addr + page_offset;
|
||||
index = (addr >> 12) & (CPU_TLB_SIZE - 1);
|
||||
pd = physpage_find(paddr);
|
||||
if (pd & 0xfff) {
|
||||
/* IO memory case */
|
||||
address = vaddr | pd;
|
||||
addend = paddr;
|
||||
} else {
|
||||
/* standard memory */
|
||||
address = vaddr;
|
||||
addend = (unsigned long)phys_ram_base + pd;
|
||||
}
|
||||
addend -= vaddr;
|
||||
env->tlb_read[is_user][index].address = address;
|
||||
env->tlb_read[is_user][index].addend = addend;
|
||||
if (prot & PROT_WRITE) {
|
||||
env->tlb_write[is_user][index].address = address;
|
||||
env->tlb_write[is_user][index].addend = addend;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
/* XXX: incorrect for 4MB pages */
|
||||
pd = physpage_find(pte & ~0xfff);
|
||||
if ((pd & 0xfff) != 0) {
|
||||
/* IO access: no mapping is done as it will be handled by the
|
||||
soft MMU */
|
||||
if (!(env->hflags & HF_SOFTMMU_MASK))
|
||||
ret = 2;
|
||||
} else {
|
||||
void *map_addr;
|
||||
map_addr = mmap((void *)virt_addr, page_size, prot,
|
||||
MAP_SHARED | MAP_FIXED, phys_ram_fd, pd);
|
||||
if (map_addr == MAP_FAILED) {
|
||||
fprintf(stderr,
|
||||
"mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
|
||||
pte & ~0xfff, virt_addr);
|
||||
exit(1);
|
||||
}
|
||||
#ifdef DEBUG_MMU
|
||||
printf("mmaping 0x%08x to virt 0x%08x pse=%d\n",
|
||||
pte & ~0xfff, virt_addr, (page_size != 4096));
|
||||
#endif
|
||||
page_set_flags(virt_addr, virt_addr + page_size,
|
||||
PAGE_VALID | PAGE_EXEC | prot);
|
||||
}
|
||||
return ret;
|
||||
do_fault_protect:
|
||||
error_code = PG_ERROR_P_MASK;
|
||||
do_fault:
|
||||
env->cr[2] = addr;
|
||||
env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;
|
||||
if (is_user)
|
||||
env->error_code |= PG_ERROR_U_MASK;
|
||||
return 1;
|
||||
}
|
2054
target-i386/op.c
Normal file
2054
target-i386/op.c
Normal file
File diff suppressed because it is too large
Load diff
134
target-i386/opreg_template.h
Normal file
134
target-i386/opreg_template.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* i386 micro operations (templates for various register related
|
||||
* operations)
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
void OPPROTO glue(op_movl_A0,REGNAME)(void)
|
||||
{
|
||||
A0 = REG;
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_addl_A0,REGNAME)(void)
|
||||
{
|
||||
A0 += REG;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_addl_A0,REGNAME),_s1)(void)
|
||||
{
|
||||
A0 += REG << 1;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_addl_A0,REGNAME),_s2)(void)
|
||||
{
|
||||
A0 += REG << 2;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_addl_A0,REGNAME),_s3)(void)
|
||||
{
|
||||
A0 += REG << 3;
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_movl_T0,REGNAME)(void)
|
||||
{
|
||||
T0 = REG;
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_movl_T1,REGNAME)(void)
|
||||
{
|
||||
T1 = REG;
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_movh_T0,REGNAME)(void)
|
||||
{
|
||||
T0 = REG >> 8;
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_movh_T1,REGNAME)(void)
|
||||
{
|
||||
T1 = REG >> 8;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_movl,REGNAME),_T0)(void)
|
||||
{
|
||||
REG = T0;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_movl,REGNAME),_T1)(void)
|
||||
{
|
||||
REG = T1;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_movl,REGNAME),_A0)(void)
|
||||
{
|
||||
REG = A0;
|
||||
}
|
||||
|
||||
/* mov T1 to REG if T0 is true */
|
||||
void OPPROTO glue(glue(op_cmovw,REGNAME),_T1_T0)(void)
|
||||
{
|
||||
if (T0)
|
||||
REG = (REG & 0xffff0000) | (T1 & 0xffff);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_cmovl,REGNAME),_T1_T0)(void)
|
||||
{
|
||||
if (T0)
|
||||
REG = T1;
|
||||
}
|
||||
|
||||
/* NOTE: T0 high order bits are ignored */
|
||||
void OPPROTO glue(glue(op_movw,REGNAME),_T0)(void)
|
||||
{
|
||||
REG = (REG & 0xffff0000) | (T0 & 0xffff);
|
||||
}
|
||||
|
||||
/* NOTE: T0 high order bits are ignored */
|
||||
void OPPROTO glue(glue(op_movw,REGNAME),_T1)(void)
|
||||
{
|
||||
REG = (REG & 0xffff0000) | (T1 & 0xffff);
|
||||
}
|
||||
|
||||
/* NOTE: A0 high order bits are ignored */
|
||||
void OPPROTO glue(glue(op_movw,REGNAME),_A0)(void)
|
||||
{
|
||||
REG = (REG & 0xffff0000) | (A0 & 0xffff);
|
||||
}
|
||||
|
||||
/* NOTE: T0 high order bits are ignored */
|
||||
void OPPROTO glue(glue(op_movb,REGNAME),_T0)(void)
|
||||
{
|
||||
REG = (REG & 0xffffff00) | (T0 & 0xff);
|
||||
}
|
||||
|
||||
/* NOTE: T0 high order bits are ignored */
|
||||
void OPPROTO glue(glue(op_movh,REGNAME),_T0)(void)
|
||||
{
|
||||
REG = (REG & 0xffff00ff) | ((T0 & 0xff) << 8);
|
||||
}
|
||||
|
||||
/* NOTE: T1 high order bits are ignored */
|
||||
void OPPROTO glue(glue(op_movb,REGNAME),_T1)(void)
|
||||
{
|
||||
REG = (REG & 0xffffff00) | (T1 & 0xff);
|
||||
}
|
||||
|
||||
/* NOTE: T1 high order bits are ignored */
|
||||
void OPPROTO glue(glue(op_movh,REGNAME),_T1)(void)
|
||||
{
|
||||
REG = (REG & 0xffff00ff) | ((T1 & 0xff) << 8);
|
||||
}
|
66
target-i386/ops_mem.h
Normal file
66
target-i386/ops_mem.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
void OPPROTO glue(glue(op_ldub, MEMSUFFIX), _T0_A0)(void)
|
||||
{
|
||||
T0 = glue(ldub, MEMSUFFIX)((uint8_t *)A0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_ldsb, MEMSUFFIX), _T0_A0)(void)
|
||||
{
|
||||
T0 = glue(ldsb, MEMSUFFIX)((int8_t *)A0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_lduw, MEMSUFFIX), _T0_A0)(void)
|
||||
{
|
||||
T0 = glue(lduw, MEMSUFFIX)((uint8_t *)A0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_ldsw, MEMSUFFIX), _T0_A0)(void)
|
||||
{
|
||||
T0 = glue(ldsw, MEMSUFFIX)((int8_t *)A0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_ldl, MEMSUFFIX), _T0_A0)(void)
|
||||
{
|
||||
T0 = glue(ldl, MEMSUFFIX)((uint8_t *)A0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_ldub, MEMSUFFIX), _T1_A0)(void)
|
||||
{
|
||||
T1 = glue(ldub, MEMSUFFIX)((uint8_t *)A0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_ldsb, MEMSUFFIX), _T1_A0)(void)
|
||||
{
|
||||
T1 = glue(ldsb, MEMSUFFIX)((int8_t *)A0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_lduw, MEMSUFFIX), _T1_A0)(void)
|
||||
{
|
||||
T1 = glue(lduw, MEMSUFFIX)((uint8_t *)A0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_ldsw, MEMSUFFIX), _T1_A0)(void)
|
||||
{
|
||||
T1 = glue(ldsw, MEMSUFFIX)((int8_t *)A0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_ldl, MEMSUFFIX), _T1_A0)(void)
|
||||
{
|
||||
T1 = glue(ldl, MEMSUFFIX)((uint8_t *)A0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_stb, MEMSUFFIX), _T0_A0)(void)
|
||||
{
|
||||
glue(stb, MEMSUFFIX)((uint8_t *)A0, T0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_stw, MEMSUFFIX), _T0_A0)(void)
|
||||
{
|
||||
glue(stw, MEMSUFFIX)((uint8_t *)A0, T0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_stl, MEMSUFFIX), _T0_A0)(void)
|
||||
{
|
||||
glue(stl, MEMSUFFIX)((uint8_t *)A0, T0);
|
||||
}
|
||||
|
||||
#undef MEMSUFFIX
|
617
target-i386/ops_template.h
Normal file
617
target-i386/ops_template.h
Normal file
|
@ -0,0 +1,617 @@
|
|||
/*
|
||||
* i386 micro operations (included several times to generate
|
||||
* different operand sizes)
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#define DATA_BITS (1 << (3 + SHIFT))
|
||||
#define SHIFT_MASK (DATA_BITS - 1)
|
||||
#define SIGN_MASK (1 << (DATA_BITS - 1))
|
||||
|
||||
#if DATA_BITS == 8
|
||||
#define SUFFIX b
|
||||
#define DATA_TYPE uint8_t
|
||||
#define DATA_STYPE int8_t
|
||||
#define DATA_MASK 0xff
|
||||
#elif DATA_BITS == 16
|
||||
#define SUFFIX w
|
||||
#define DATA_TYPE uint16_t
|
||||
#define DATA_STYPE int16_t
|
||||
#define DATA_MASK 0xffff
|
||||
#elif DATA_BITS == 32
|
||||
#define SUFFIX l
|
||||
#define DATA_TYPE uint32_t
|
||||
#define DATA_STYPE int32_t
|
||||
#define DATA_MASK 0xffffffff
|
||||
#else
|
||||
#error unhandled operand size
|
||||
#endif
|
||||
|
||||
/* dynamic flags computation */
|
||||
|
||||
static int glue(compute_all_add, SUFFIX)(void)
|
||||
{
|
||||
int cf, pf, af, zf, sf, of;
|
||||
int src1, src2;
|
||||
src1 = CC_SRC;
|
||||
src2 = CC_DST - CC_SRC;
|
||||
cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
|
||||
pf = parity_table[(uint8_t)CC_DST];
|
||||
af = (CC_DST ^ src1 ^ src2) & 0x10;
|
||||
zf = ((DATA_TYPE)CC_DST == 0) << 6;
|
||||
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
|
||||
of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
|
||||
return cf | pf | af | zf | sf | of;
|
||||
}
|
||||
|
||||
static int glue(compute_c_add, SUFFIX)(void)
|
||||
{
|
||||
int src1, cf;
|
||||
src1 = CC_SRC;
|
||||
cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
|
||||
return cf;
|
||||
}
|
||||
|
||||
static int glue(compute_all_adc, SUFFIX)(void)
|
||||
{
|
||||
int cf, pf, af, zf, sf, of;
|
||||
int src1, src2;
|
||||
src1 = CC_SRC;
|
||||
src2 = CC_DST - CC_SRC - 1;
|
||||
cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
|
||||
pf = parity_table[(uint8_t)CC_DST];
|
||||
af = (CC_DST ^ src1 ^ src2) & 0x10;
|
||||
zf = ((DATA_TYPE)CC_DST == 0) << 6;
|
||||
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
|
||||
of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
|
||||
return cf | pf | af | zf | sf | of;
|
||||
}
|
||||
|
||||
static int glue(compute_c_adc, SUFFIX)(void)
|
||||
{
|
||||
int src1, cf;
|
||||
src1 = CC_SRC;
|
||||
cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
|
||||
return cf;
|
||||
}
|
||||
|
||||
static int glue(compute_all_sub, SUFFIX)(void)
|
||||
{
|
||||
int cf, pf, af, zf, sf, of;
|
||||
int src1, src2;
|
||||
src1 = CC_DST + CC_SRC;
|
||||
src2 = CC_SRC;
|
||||
cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
|
||||
pf = parity_table[(uint8_t)CC_DST];
|
||||
af = (CC_DST ^ src1 ^ src2) & 0x10;
|
||||
zf = ((DATA_TYPE)CC_DST == 0) << 6;
|
||||
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
|
||||
of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
|
||||
return cf | pf | af | zf | sf | of;
|
||||
}
|
||||
|
||||
static int glue(compute_c_sub, SUFFIX)(void)
|
||||
{
|
||||
int src1, src2, cf;
|
||||
src1 = CC_DST + CC_SRC;
|
||||
src2 = CC_SRC;
|
||||
cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
|
||||
return cf;
|
||||
}
|
||||
|
||||
static int glue(compute_all_sbb, SUFFIX)(void)
|
||||
{
|
||||
int cf, pf, af, zf, sf, of;
|
||||
int src1, src2;
|
||||
src1 = CC_DST + CC_SRC + 1;
|
||||
src2 = CC_SRC;
|
||||
cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
|
||||
pf = parity_table[(uint8_t)CC_DST];
|
||||
af = (CC_DST ^ src1 ^ src2) & 0x10;
|
||||
zf = ((DATA_TYPE)CC_DST == 0) << 6;
|
||||
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
|
||||
of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
|
||||
return cf | pf | af | zf | sf | of;
|
||||
}
|
||||
|
||||
static int glue(compute_c_sbb, SUFFIX)(void)
|
||||
{
|
||||
int src1, src2, cf;
|
||||
src1 = CC_DST + CC_SRC + 1;
|
||||
src2 = CC_SRC;
|
||||
cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
|
||||
return cf;
|
||||
}
|
||||
|
||||
static int glue(compute_all_logic, SUFFIX)(void)
|
||||
{
|
||||
int cf, pf, af, zf, sf, of;
|
||||
cf = 0;
|
||||
pf = parity_table[(uint8_t)CC_DST];
|
||||
af = 0;
|
||||
zf = ((DATA_TYPE)CC_DST == 0) << 6;
|
||||
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
|
||||
of = 0;
|
||||
return cf | pf | af | zf | sf | of;
|
||||
}
|
||||
|
||||
static int glue(compute_c_logic, SUFFIX)(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int glue(compute_all_inc, SUFFIX)(void)
|
||||
{
|
||||
int cf, pf, af, zf, sf, of;
|
||||
int src1, src2;
|
||||
src1 = CC_DST - 1;
|
||||
src2 = 1;
|
||||
cf = CC_SRC;
|
||||
pf = parity_table[(uint8_t)CC_DST];
|
||||
af = (CC_DST ^ src1 ^ src2) & 0x10;
|
||||
zf = ((DATA_TYPE)CC_DST == 0) << 6;
|
||||
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
|
||||
of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
|
||||
return cf | pf | af | zf | sf | of;
|
||||
}
|
||||
|
||||
#if DATA_BITS == 32
|
||||
static int glue(compute_c_inc, SUFFIX)(void)
|
||||
{
|
||||
return CC_SRC;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int glue(compute_all_dec, SUFFIX)(void)
|
||||
{
|
||||
int cf, pf, af, zf, sf, of;
|
||||
int src1, src2;
|
||||
src1 = CC_DST + 1;
|
||||
src2 = 1;
|
||||
cf = CC_SRC;
|
||||
pf = parity_table[(uint8_t)CC_DST];
|
||||
af = (CC_DST ^ src1 ^ src2) & 0x10;
|
||||
zf = ((DATA_TYPE)CC_DST == 0) << 6;
|
||||
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
|
||||
of = ((CC_DST & DATA_MASK) == ((uint32_t)SIGN_MASK - 1)) << 11;
|
||||
return cf | pf | af | zf | sf | of;
|
||||
}
|
||||
|
||||
static int glue(compute_all_shl, SUFFIX)(void)
|
||||
{
|
||||
int cf, pf, af, zf, sf, of;
|
||||
cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
|
||||
pf = parity_table[(uint8_t)CC_DST];
|
||||
af = 0; /* undefined */
|
||||
zf = ((DATA_TYPE)CC_DST == 0) << 6;
|
||||
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
|
||||
/* of is defined if shift count == 1 */
|
||||
of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
|
||||
return cf | pf | af | zf | sf | of;
|
||||
}
|
||||
|
||||
static int glue(compute_c_shl, SUFFIX)(void)
|
||||
{
|
||||
return (CC_SRC >> (DATA_BITS - 1)) & CC_C;
|
||||
}
|
||||
|
||||
#if DATA_BITS == 32
|
||||
static int glue(compute_c_sar, SUFFIX)(void)
|
||||
{
|
||||
return CC_SRC & 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int glue(compute_all_sar, SUFFIX)(void)
|
||||
{
|
||||
int cf, pf, af, zf, sf, of;
|
||||
cf = CC_SRC & 1;
|
||||
pf = parity_table[(uint8_t)CC_DST];
|
||||
af = 0; /* undefined */
|
||||
zf = ((DATA_TYPE)CC_DST == 0) << 6;
|
||||
sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
|
||||
/* of is defined if shift count == 1 */
|
||||
of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
|
||||
return cf | pf | af | zf | sf | of;
|
||||
}
|
||||
|
||||
/* various optimized jumps cases */
|
||||
|
||||
void OPPROTO glue(op_jb_sub, SUFFIX)(void)
|
||||
{
|
||||
int src1, src2;
|
||||
src1 = CC_DST + CC_SRC;
|
||||
src2 = CC_SRC;
|
||||
|
||||
if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
|
||||
JUMP_TB(glue(op_jb_sub, SUFFIX), PARAM1, 0, PARAM2);
|
||||
else
|
||||
JUMP_TB(glue(op_jb_sub, SUFFIX), PARAM1, 1, PARAM3);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_jz_sub, SUFFIX)(void)
|
||||
{
|
||||
if ((DATA_TYPE)CC_DST == 0)
|
||||
JUMP_TB(glue(op_jz_sub, SUFFIX), PARAM1, 0, PARAM2);
|
||||
else
|
||||
JUMP_TB(glue(op_jz_sub, SUFFIX), PARAM1, 1, PARAM3);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
|
||||
{
|
||||
int src1, src2;
|
||||
src1 = CC_DST + CC_SRC;
|
||||
src2 = CC_SRC;
|
||||
|
||||
if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
|
||||
JUMP_TB(glue(op_jbe_sub, SUFFIX), PARAM1, 0, PARAM2);
|
||||
else
|
||||
JUMP_TB(glue(op_jbe_sub, SUFFIX), PARAM1, 1, PARAM3);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_js_sub, SUFFIX)(void)
|
||||
{
|
||||
if (CC_DST & SIGN_MASK)
|
||||
JUMP_TB(glue(op_js_sub, SUFFIX), PARAM1, 0, PARAM2);
|
||||
else
|
||||
JUMP_TB(glue(op_js_sub, SUFFIX), PARAM1, 1, PARAM3);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_jl_sub, SUFFIX)(void)
|
||||
{
|
||||
int src1, src2;
|
||||
src1 = CC_DST + CC_SRC;
|
||||
src2 = CC_SRC;
|
||||
|
||||
if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
|
||||
JUMP_TB(glue(op_jl_sub, SUFFIX), PARAM1, 0, PARAM2);
|
||||
else
|
||||
JUMP_TB(glue(op_jl_sub, SUFFIX), PARAM1, 1, PARAM3);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_jle_sub, SUFFIX)(void)
|
||||
{
|
||||
int src1, src2;
|
||||
src1 = CC_DST + CC_SRC;
|
||||
src2 = CC_SRC;
|
||||
|
||||
if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
|
||||
JUMP_TB(glue(op_jle_sub, SUFFIX), PARAM1, 0, PARAM2);
|
||||
else
|
||||
JUMP_TB(glue(op_jle_sub, SUFFIX), PARAM1, 1, PARAM3);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
/* oldies */
|
||||
|
||||
#if DATA_BITS >= 16
|
||||
|
||||
void OPPROTO glue(op_loopnz, SUFFIX)(void)
|
||||
{
|
||||
unsigned int tmp;
|
||||
int eflags;
|
||||
eflags = cc_table[CC_OP].compute_all();
|
||||
tmp = (ECX - 1) & DATA_MASK;
|
||||
ECX = (ECX & ~DATA_MASK) | tmp;
|
||||
if (tmp != 0 && !(eflags & CC_Z))
|
||||
EIP = PARAM1;
|
||||
else
|
||||
EIP = PARAM2;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_loopz, SUFFIX)(void)
|
||||
{
|
||||
unsigned int tmp;
|
||||
int eflags;
|
||||
eflags = cc_table[CC_OP].compute_all();
|
||||
tmp = (ECX - 1) & DATA_MASK;
|
||||
ECX = (ECX & ~DATA_MASK) | tmp;
|
||||
if (tmp != 0 && (eflags & CC_Z))
|
||||
EIP = PARAM1;
|
||||
else
|
||||
EIP = PARAM2;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_loop, SUFFIX)(void)
|
||||
{
|
||||
unsigned int tmp;
|
||||
tmp = (ECX - 1) & DATA_MASK;
|
||||
ECX = (ECX & ~DATA_MASK) | tmp;
|
||||
if (tmp != 0)
|
||||
EIP = PARAM1;
|
||||
else
|
||||
EIP = PARAM2;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_jecxz, SUFFIX)(void)
|
||||
{
|
||||
if ((DATA_TYPE)ECX == 0)
|
||||
EIP = PARAM1;
|
||||
else
|
||||
EIP = PARAM2;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* various optimized set cases */
|
||||
|
||||
void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
|
||||
{
|
||||
int src1, src2;
|
||||
src1 = CC_DST + CC_SRC;
|
||||
src2 = CC_SRC;
|
||||
|
||||
T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
|
||||
{
|
||||
T0 = ((DATA_TYPE)CC_DST == 0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
|
||||
{
|
||||
int src1, src2;
|
||||
src1 = CC_DST + CC_SRC;
|
||||
src2 = CC_SRC;
|
||||
|
||||
T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
|
||||
{
|
||||
T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
|
||||
{
|
||||
int src1, src2;
|
||||
src1 = CC_DST + CC_SRC;
|
||||
src2 = CC_SRC;
|
||||
|
||||
T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
|
||||
{
|
||||
int src1, src2;
|
||||
src1 = CC_DST + CC_SRC;
|
||||
src2 = CC_SRC;
|
||||
|
||||
T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
|
||||
}
|
||||
|
||||
/* shifts */
|
||||
|
||||
void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void)
|
||||
{
|
||||
int count;
|
||||
count = T1 & 0x1f;
|
||||
T0 = T0 << count;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void)
|
||||
{
|
||||
int count;
|
||||
count = T1 & 0x1f;
|
||||
T0 &= DATA_MASK;
|
||||
T0 = T0 >> count;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void)
|
||||
{
|
||||
int count, src;
|
||||
count = T1 & 0x1f;
|
||||
src = (DATA_STYPE)T0;
|
||||
T0 = src >> count;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
#undef MEM_WRITE
|
||||
#include "ops_template_mem.h"
|
||||
|
||||
#define MEM_WRITE
|
||||
#include "ops_template_mem.h"
|
||||
|
||||
/* bit operations */
|
||||
#if DATA_BITS >= 16
|
||||
|
||||
void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int count;
|
||||
count = T1 & SHIFT_MASK;
|
||||
CC_SRC = T0 >> count;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int count;
|
||||
count = T1 & SHIFT_MASK;
|
||||
T1 = T0 >> count;
|
||||
T0 |= (1 << count);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int count;
|
||||
count = T1 & SHIFT_MASK;
|
||||
T1 = T0 >> count;
|
||||
T0 &= ~(1 << count);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int count;
|
||||
count = T1 & SHIFT_MASK;
|
||||
T1 = T0 >> count;
|
||||
T0 ^= (1 << count);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
|
||||
{
|
||||
int res, count;
|
||||
res = T0 & DATA_MASK;
|
||||
if (res != 0) {
|
||||
count = 0;
|
||||
while ((res & 1) == 0) {
|
||||
count++;
|
||||
res >>= 1;
|
||||
}
|
||||
T0 = count;
|
||||
CC_DST = 1; /* ZF = 1 */
|
||||
} else {
|
||||
CC_DST = 0; /* ZF = 1 */
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
|
||||
{
|
||||
int res, count;
|
||||
res = T0 & DATA_MASK;
|
||||
if (res != 0) {
|
||||
count = DATA_BITS - 1;
|
||||
while ((res & SIGN_MASK) == 0) {
|
||||
count--;
|
||||
res <<= 1;
|
||||
}
|
||||
T0 = count;
|
||||
CC_DST = 1; /* ZF = 1 */
|
||||
} else {
|
||||
CC_DST = 0; /* ZF = 1 */
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if DATA_BITS == 32
|
||||
void OPPROTO op_update_bt_cc(void)
|
||||
{
|
||||
CC_SRC = T1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* string operations */
|
||||
|
||||
void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void)
|
||||
{
|
||||
T0 = DF << SHIFT;
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_string_jz_sub, SUFFIX)(void)
|
||||
{
|
||||
if ((DATA_TYPE)CC_DST == 0)
|
||||
JUMP_TB2(glue(op_string_jz_sub, SUFFIX), PARAM1, 1);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_string_jnz_sub, SUFFIX)(void)
|
||||
{
|
||||
if ((DATA_TYPE)CC_DST != 0)
|
||||
JUMP_TB2(glue(op_string_jnz_sub, SUFFIX), PARAM1, 1);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_string_jz_sub, SUFFIX), _im)(void)
|
||||
{
|
||||
if ((DATA_TYPE)CC_DST == 0) {
|
||||
EIP = PARAM1;
|
||||
if (env->eflags & TF_MASK) {
|
||||
raise_exception(EXCP01_SSTP);
|
||||
}
|
||||
T0 = 0;
|
||||
EXIT_TB();
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_string_jnz_sub, SUFFIX), _im)(void)
|
||||
{
|
||||
if ((DATA_TYPE)CC_DST != 0) {
|
||||
EIP = PARAM1;
|
||||
if (env->eflags & TF_MASK) {
|
||||
raise_exception(EXCP01_SSTP);
|
||||
}
|
||||
T0 = 0;
|
||||
EXIT_TB();
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
#if DATA_BITS >= 16
|
||||
void OPPROTO glue(op_jz_ecx, SUFFIX)(void)
|
||||
{
|
||||
if ((DATA_TYPE)ECX == 0)
|
||||
JUMP_TB(glue(op_jz_ecx, SUFFIX), PARAM1, 1, PARAM2);
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_jz_ecx, SUFFIX), _im)(void)
|
||||
{
|
||||
if ((DATA_TYPE)ECX == 0) {
|
||||
EIP = PARAM1;
|
||||
if (env->eflags & TF_MASK) {
|
||||
raise_exception(EXCP01_SSTP);
|
||||
}
|
||||
T0 = 0;
|
||||
EXIT_TB();
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* port I/O */
|
||||
|
||||
void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
|
||||
{
|
||||
glue(cpu_x86_out, SUFFIX)(env, T0 & 0xffff, T1 & DATA_MASK);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
|
||||
{
|
||||
T1 = glue(cpu_x86_in, SUFFIX)(env, T0 & 0xffff);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_in, SUFFIX), _DX_T0)(void)
|
||||
{
|
||||
T0 = glue(cpu_x86_in, SUFFIX)(env, EDX & 0xffff);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_out, SUFFIX), _DX_T0)(void)
|
||||
{
|
||||
glue(cpu_x86_out, SUFFIX)(env, EDX & 0xffff, T0);
|
||||
}
|
||||
|
||||
#undef DATA_BITS
|
||||
#undef SHIFT_MASK
|
||||
#undef SIGN_MASK
|
||||
#undef DATA_TYPE
|
||||
#undef DATA_STYPE
|
||||
#undef DATA_MASK
|
||||
#undef SUFFIX
|
429
target-i386/ops_template_mem.h
Normal file
429
target-i386/ops_template_mem.h
Normal file
|
@ -0,0 +1,429 @@
|
|||
/*
|
||||
* i386 micro operations (included several times to generate
|
||||
* different operand sizes)
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifdef MEM_WRITE
|
||||
|
||||
#if DATA_BITS == 8
|
||||
#define MEM_SUFFIX b_mem
|
||||
#elif DATA_BITS == 16
|
||||
#define MEM_SUFFIX w_mem
|
||||
#elif DATA_BITS == 32
|
||||
#define MEM_SUFFIX l_mem
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define MEM_SUFFIX SUFFIX
|
||||
|
||||
#endif
|
||||
|
||||
void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int count, src;
|
||||
count = T1 & SHIFT_MASK;
|
||||
if (count) {
|
||||
src = T0;
|
||||
T0 &= DATA_MASK;
|
||||
T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#else
|
||||
/* gcc 3.2 workaround. This is really a bug in gcc. */
|
||||
asm volatile("" : : "r" (T0));
|
||||
#endif
|
||||
CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) |
|
||||
(lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
|
||||
(T0 & CC_C);
|
||||
CC_OP = CC_OP_EFLAGS;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int count, src;
|
||||
count = T1 & SHIFT_MASK;
|
||||
if (count) {
|
||||
src = T0;
|
||||
T0 &= DATA_MASK;
|
||||
T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#else
|
||||
/* gcc 3.2 workaround. This is really a bug in gcc. */
|
||||
asm volatile("" : : "r" (T0));
|
||||
#endif
|
||||
CC_SRC = (cc_table[CC_OP].compute_all() & ~(CC_O | CC_C)) |
|
||||
(lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
|
||||
((T0 >> (DATA_BITS - 1)) & CC_C);
|
||||
CC_OP = CC_OP_EFLAGS;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1)(void)
|
||||
{
|
||||
int count;
|
||||
count = T1 & SHIFT_MASK;
|
||||
if (count) {
|
||||
T0 &= DATA_MASK;
|
||||
T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1)(void)
|
||||
{
|
||||
int count;
|
||||
count = T1 & SHIFT_MASK;
|
||||
if (count) {
|
||||
T0 &= DATA_MASK;
|
||||
T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_rcl, MEM_SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int count, res, eflags;
|
||||
unsigned int src;
|
||||
|
||||
count = T1 & 0x1f;
|
||||
#if DATA_BITS == 16
|
||||
count = rclw_table[count];
|
||||
#elif DATA_BITS == 8
|
||||
count = rclb_table[count];
|
||||
#endif
|
||||
if (count) {
|
||||
eflags = cc_table[CC_OP].compute_all();
|
||||
T0 &= DATA_MASK;
|
||||
src = T0;
|
||||
res = (T0 << count) | ((eflags & CC_C) << (count - 1));
|
||||
if (count > 1)
|
||||
res |= T0 >> (DATA_BITS + 1 - count);
|
||||
T0 = res;
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = (eflags & ~(CC_C | CC_O)) |
|
||||
(lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
|
||||
((src >> (DATA_BITS - count)) & CC_C);
|
||||
CC_OP = CC_OP_EFLAGS;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_rcr, MEM_SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int count, res, eflags;
|
||||
unsigned int src;
|
||||
|
||||
count = T1 & 0x1f;
|
||||
#if DATA_BITS == 16
|
||||
count = rclw_table[count];
|
||||
#elif DATA_BITS == 8
|
||||
count = rclb_table[count];
|
||||
#endif
|
||||
if (count) {
|
||||
eflags = cc_table[CC_OP].compute_all();
|
||||
T0 &= DATA_MASK;
|
||||
src = T0;
|
||||
res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
|
||||
if (count > 1)
|
||||
res |= T0 << (DATA_BITS + 1 - count);
|
||||
T0 = res;
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = (eflags & ~(CC_C | CC_O)) |
|
||||
(lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
|
||||
((src >> (count - 1)) & CC_C);
|
||||
CC_OP = CC_OP_EFLAGS;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_shl, MEM_SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int count, src;
|
||||
count = T1 & 0x1f;
|
||||
if (count) {
|
||||
src = (DATA_TYPE)T0 << (count - 1);
|
||||
T0 = T0 << count;
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = src;
|
||||
CC_DST = T0;
|
||||
CC_OP = CC_OP_SHLB + SHIFT;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_shr, MEM_SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int count, src;
|
||||
count = T1 & 0x1f;
|
||||
if (count) {
|
||||
T0 &= DATA_MASK;
|
||||
src = T0 >> (count - 1);
|
||||
T0 = T0 >> count;
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = src;
|
||||
CC_DST = T0;
|
||||
CC_OP = CC_OP_SARB + SHIFT;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_sar, MEM_SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int count, src;
|
||||
count = T1 & 0x1f;
|
||||
if (count) {
|
||||
src = (DATA_STYPE)T0;
|
||||
T0 = src >> count;
|
||||
src = src >> (count - 1);
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = src;
|
||||
CC_DST = T0;
|
||||
CC_OP = CC_OP_SARB + SHIFT;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
#if DATA_BITS == 16
|
||||
/* XXX: overflow flag might be incorrect in some cases in shldw */
|
||||
void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
|
||||
{
|
||||
int count;
|
||||
unsigned int res, tmp;
|
||||
count = PARAM1;
|
||||
T1 &= 0xffff;
|
||||
res = T1 | (T0 << 16);
|
||||
tmp = res >> (32 - count);
|
||||
res <<= count;
|
||||
if (count > 16)
|
||||
res |= T1 << (count - 16);
|
||||
T0 = res >> 16;
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = tmp;
|
||||
CC_DST = T0;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
|
||||
{
|
||||
int count;
|
||||
unsigned int res, tmp;
|
||||
count = ECX & 0x1f;
|
||||
if (count) {
|
||||
T1 &= 0xffff;
|
||||
res = T1 | (T0 << 16);
|
||||
tmp = res >> (32 - count);
|
||||
res <<= count;
|
||||
if (count > 16)
|
||||
res |= T1 << (count - 16);
|
||||
T0 = res >> 16;
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = tmp;
|
||||
CC_DST = T0;
|
||||
CC_OP = CC_OP_SARB + SHIFT;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
|
||||
{
|
||||
int count;
|
||||
unsigned int res, tmp;
|
||||
|
||||
count = PARAM1;
|
||||
res = (T0 & 0xffff) | (T1 << 16);
|
||||
tmp = res >> (count - 1);
|
||||
res >>= count;
|
||||
if (count > 16)
|
||||
res |= T1 << (32 - count);
|
||||
T0 = res;
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = tmp;
|
||||
CC_DST = T0;
|
||||
}
|
||||
|
||||
|
||||
void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
|
||||
{
|
||||
int count;
|
||||
unsigned int res, tmp;
|
||||
|
||||
count = ECX & 0x1f;
|
||||
if (count) {
|
||||
res = (T0 & 0xffff) | (T1 << 16);
|
||||
tmp = res >> (count - 1);
|
||||
res >>= count;
|
||||
if (count > 16)
|
||||
res |= T1 << (32 - count);
|
||||
T0 = res;
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = tmp;
|
||||
CC_DST = T0;
|
||||
CC_OP = CC_OP_SARB + SHIFT;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DATA_BITS == 32
|
||||
void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void)
|
||||
{
|
||||
int count, tmp;
|
||||
count = PARAM1;
|
||||
T0 &= DATA_MASK;
|
||||
T1 &= DATA_MASK;
|
||||
tmp = T0 << (count - 1);
|
||||
T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = tmp;
|
||||
CC_DST = T0;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
|
||||
{
|
||||
int count, tmp;
|
||||
count = ECX & 0x1f;
|
||||
if (count) {
|
||||
T0 &= DATA_MASK;
|
||||
T1 &= DATA_MASK;
|
||||
tmp = T0 << (count - 1);
|
||||
T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = tmp;
|
||||
CC_DST = T0;
|
||||
CC_OP = CC_OP_SHLB + SHIFT;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void)
|
||||
{
|
||||
int count, tmp;
|
||||
count = PARAM1;
|
||||
T0 &= DATA_MASK;
|
||||
T1 &= DATA_MASK;
|
||||
tmp = T0 >> (count - 1);
|
||||
T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = tmp;
|
||||
CC_DST = T0;
|
||||
}
|
||||
|
||||
|
||||
void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void)
|
||||
{
|
||||
int count, tmp;
|
||||
count = ECX & 0x1f;
|
||||
if (count) {
|
||||
T0 &= DATA_MASK;
|
||||
T1 &= DATA_MASK;
|
||||
tmp = T0 >> (count - 1);
|
||||
T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = tmp;
|
||||
CC_DST = T0;
|
||||
CC_OP = CC_OP_SARB + SHIFT;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* carry add/sub (we only need to set CC_OP differently) */
|
||||
|
||||
void OPPROTO glue(glue(op_adc, MEM_SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int cf;
|
||||
cf = cc_table[CC_OP].compute_c();
|
||||
T0 = T0 + T1 + cf;
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = T1;
|
||||
CC_DST = T0;
|
||||
CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void)
|
||||
{
|
||||
int cf;
|
||||
cf = cc_table[CC_OP].compute_c();
|
||||
T0 = T0 - T1 - cf;
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = T1;
|
||||
CC_DST = T0;
|
||||
CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_cmpxchg, MEM_SUFFIX), _T0_T1_EAX_cc)(void)
|
||||
{
|
||||
unsigned int src, dst;
|
||||
|
||||
src = T0;
|
||||
dst = EAX - T0;
|
||||
if ((DATA_TYPE)dst == 0) {
|
||||
T0 = T1;
|
||||
} else {
|
||||
EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
|
||||
}
|
||||
#ifdef MEM_WRITE
|
||||
glue(st, SUFFIX)((uint8_t *)A0, T0);
|
||||
#endif
|
||||
CC_SRC = src;
|
||||
CC_DST = dst;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
#undef MEM_SUFFIX
|
||||
#undef MEM_WRITE
|
4487
target-i386/translate.c
Normal file
4487
target-i386/translate.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue