Commit 33417e7025afa5ea1c38c3c2b2ea53d975b5648b
1 parent
4021dab0
soft mmu support - Memory I/O API - synthetize string instructions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@354 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
10 changed files
with
351 additions
and
234 deletions
cpu-all.h
| @@ -140,6 +140,7 @@ static inline void stfl(void *ptr, float v) | @@ -140,6 +140,7 @@ static inline void stfl(void *ptr, float v) | ||
| 140 | stl(ptr, u.i); | 140 | stl(ptr, u.i); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | + | ||
| 143 | #if defined(__arm__) && !defined(WORDS_BIGENDIAN) | 144 | #if defined(__arm__) && !defined(WORDS_BIGENDIAN) |
| 144 | 145 | ||
| 145 | /* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */ | 146 | /* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */ |
| @@ -317,6 +318,17 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc); | @@ -317,6 +318,17 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc); | ||
| 317 | int cpu_breakpoint_remove(CPUState *env, uint32_t pc); | 318 | int cpu_breakpoint_remove(CPUState *env, uint32_t pc); |
| 318 | void cpu_single_step(CPUState *env, int enabled); | 319 | void cpu_single_step(CPUState *env, int enabled); |
| 319 | 320 | ||
| 321 | +/* memory API */ | ||
| 322 | + | ||
| 323 | +typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value); | ||
| 324 | +typedef uint32_t CPUReadMemoryFunc(uint32_t addr); | ||
| 325 | + | ||
| 326 | +void cpu_register_physical_memory(unsigned long start_addr, unsigned long size, | ||
| 327 | + long phys_offset); | ||
| 328 | +int cpu_register_io_memory(int io_index, | ||
| 329 | + CPUReadMemoryFunc **mem_read, | ||
| 330 | + CPUWriteMemoryFunc **mem_write); | ||
| 331 | + | ||
| 320 | /* gdb stub API */ | 332 | /* gdb stub API */ |
| 321 | extern int gdbstub_fd; | 333 | extern int gdbstub_fd; |
| 322 | CPUState *cpu_gdbstub_get_env(void *opaque); | 334 | CPUState *cpu_gdbstub_get_env(void *opaque); |
cpu-arm.h
| @@ -20,12 +20,10 @@ | @@ -20,12 +20,10 @@ | ||
| 20 | #ifndef CPU_ARM_H | 20 | #ifndef CPU_ARM_H |
| 21 | #define CPU_ARM_H | 21 | #define CPU_ARM_H |
| 22 | 22 | ||
| 23 | -#include "config.h" | ||
| 24 | -#include <setjmp.h> | 23 | +#include "cpu-defs.h" |
| 25 | 24 | ||
| 26 | #define EXCP_UDEF 1 /* undefined instruction */ | 25 | #define EXCP_UDEF 1 /* undefined instruction */ |
| 27 | #define EXCP_SWI 2 /* software interrupt */ | 26 | #define EXCP_SWI 2 /* software interrupt */ |
| 28 | -#define EXCP_INTERRUPT 256 /* async interruption */ | ||
| 29 | 27 | ||
| 30 | typedef struct CPUARMState { | 28 | typedef struct CPUARMState { |
| 31 | uint32_t regs[16]; | 29 | uint32_t regs[16]; |
cpu-i386.h
| @@ -20,8 +20,7 @@ | @@ -20,8 +20,7 @@ | ||
| 20 | #ifndef CPU_I386_H | 20 | #ifndef CPU_I386_H |
| 21 | #define CPU_I386_H | 21 | #define CPU_I386_H |
| 22 | 22 | ||
| 23 | -#include "config.h" | ||
| 24 | -#include <setjmp.h> | 23 | +#include "cpu-defs.h" |
| 25 | 24 | ||
| 26 | #define R_EAX 0 | 25 | #define R_EAX 0 |
| 27 | #define R_ECX 1 | 26 | #define R_ECX 1 |
| @@ -153,12 +152,6 @@ | @@ -153,12 +152,6 @@ | ||
| 153 | #define EXCP11_ALGN 17 | 152 | #define EXCP11_ALGN 17 |
| 154 | #define EXCP12_MCHK 18 | 153 | #define EXCP12_MCHK 18 |
| 155 | 154 | ||
| 156 | -#define EXCP_INTERRUPT 256 /* async interruption */ | ||
| 157 | -#define EXCP_HLT 257 /* hlt instruction reached */ | ||
| 158 | -#define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */ | ||
| 159 | - | ||
| 160 | -#define MAX_BREAKPOINTS 32 | ||
| 161 | - | ||
| 162 | enum { | 155 | enum { |
| 163 | CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ | 156 | CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ |
| 164 | CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */ | 157 | CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */ |
| @@ -257,7 +250,8 @@ typedef struct CPUX86State { | @@ -257,7 +250,8 @@ typedef struct CPUX86State { | ||
| 257 | SegmentCache gdt; /* only base and limit are used */ | 250 | SegmentCache gdt; /* only base and limit are used */ |
| 258 | SegmentCache idt; /* only base and limit are used */ | 251 | SegmentCache idt; /* only base and limit are used */ |
| 259 | int cpl; /* current cpl */ | 252 | int cpl; /* current cpl */ |
| 260 | - | 253 | + int soft_mmu; /* TRUE if soft mmu is being used */ |
| 254 | + | ||
| 261 | /* sysenter registers */ | 255 | /* sysenter registers */ |
| 262 | uint32_t sysenter_cs; | 256 | uint32_t sysenter_cs; |
| 263 | uint32_t sysenter_esp; | 257 | uint32_t sysenter_esp; |
| @@ -275,10 +269,16 @@ typedef struct CPUX86State { | @@ -275,10 +269,16 @@ typedef struct CPUX86State { | ||
| 275 | int interrupt_request; | 269 | int interrupt_request; |
| 276 | int user_mode_only; /* user mode only simulation */ | 270 | int user_mode_only; /* user mode only simulation */ |
| 277 | 271 | ||
| 272 | + /* soft mmu support */ | ||
| 273 | + /* 0 = kernel, 1 = user */ | ||
| 274 | + CPUTLBEntry tlb_read[2][CPU_TLB_SIZE]; | ||
| 275 | + CPUTLBEntry tlb_write[2][CPU_TLB_SIZE]; | ||
| 276 | + | ||
| 277 | + /* ice debug support */ | ||
| 278 | uint32_t breakpoints[MAX_BREAKPOINTS]; | 278 | uint32_t breakpoints[MAX_BREAKPOINTS]; |
| 279 | int nb_breakpoints; | 279 | int nb_breakpoints; |
| 280 | int singlestep_enabled; | 280 | int singlestep_enabled; |
| 281 | - | 281 | + |
| 282 | /* user data */ | 282 | /* user data */ |
| 283 | void *opaque; | 283 | void *opaque; |
| 284 | } CPUX86State; | 284 | } CPUX86State; |
exec-i386.h
| @@ -138,6 +138,7 @@ void cpu_x86_update_cr0(CPUX86State *env); | @@ -138,6 +138,7 @@ void cpu_x86_update_cr0(CPUX86State *env); | ||
| 138 | void cpu_x86_update_cr3(CPUX86State *env); | 138 | void cpu_x86_update_cr3(CPUX86State *env); |
| 139 | void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr); | 139 | void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr); |
| 140 | int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write); | 140 | int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write); |
| 141 | +void tlb_fill(unsigned long addr, int is_write, void *retaddr); | ||
| 141 | void __hidden cpu_lock(void); | 142 | void __hidden cpu_lock(void); |
| 142 | void __hidden cpu_unlock(void); | 143 | void __hidden cpu_unlock(void); |
| 143 | void do_interrupt(int intno, int is_int, int error_code, | 144 | void do_interrupt(int intno, int is_int, int error_code, |
| @@ -364,3 +365,52 @@ static inline void load_eflags(int eflags, int update_mask) | @@ -364,3 +365,52 @@ static inline void load_eflags(int eflags, int update_mask) | ||
| 364 | env->eflags = (env->eflags & ~update_mask) | | 365 | env->eflags = (env->eflags & ~update_mask) | |
| 365 | (eflags & update_mask); | 366 | (eflags & update_mask); |
| 366 | } | 367 | } |
| 368 | + | ||
| 369 | +/* memory access macros */ | ||
| 370 | + | ||
| 371 | +#define ldul ldl | ||
| 372 | +#define lduq ldq | ||
| 373 | +#define ldul_user ldl_user | ||
| 374 | +#define ldul_kernel ldl_kernel | ||
| 375 | + | ||
| 376 | +#define ldub_raw ldub | ||
| 377 | +#define ldsb_raw ldsb | ||
| 378 | +#define lduw_raw lduw | ||
| 379 | +#define ldsw_raw ldsw | ||
| 380 | +#define ldl_raw ldl | ||
| 381 | +#define ldq_raw ldq | ||
| 382 | + | ||
| 383 | +#define stb_raw stb | ||
| 384 | +#define stw_raw stw | ||
| 385 | +#define stl_raw stl | ||
| 386 | +#define stq_raw stq | ||
| 387 | + | ||
| 388 | +#define MEMUSER 0 | ||
| 389 | +#define DATA_SIZE 1 | ||
| 390 | +#include "softmmu_header.h" | ||
| 391 | + | ||
| 392 | +#define DATA_SIZE 2 | ||
| 393 | +#include "softmmu_header.h" | ||
| 394 | + | ||
| 395 | +#define DATA_SIZE 4 | ||
| 396 | +#include "softmmu_header.h" | ||
| 397 | + | ||
| 398 | +#define DATA_SIZE 8 | ||
| 399 | +#include "softmmu_header.h" | ||
| 400 | + | ||
| 401 | +#undef MEMUSER | ||
| 402 | +#define MEMUSER 1 | ||
| 403 | +#define DATA_SIZE 1 | ||
| 404 | +#include "softmmu_header.h" | ||
| 405 | + | ||
| 406 | +#define DATA_SIZE 2 | ||
| 407 | +#include "softmmu_header.h" | ||
| 408 | + | ||
| 409 | +#define DATA_SIZE 4 | ||
| 410 | +#include "softmmu_header.h" | ||
| 411 | + | ||
| 412 | +#define DATA_SIZE 8 | ||
| 413 | +#include "softmmu_header.h" | ||
| 414 | + | ||
| 415 | +#undef MEMUSER | ||
| 416 | + |
exec.c
| @@ -68,6 +68,7 @@ typedef struct PageDesc { | @@ -68,6 +68,7 @@ typedef struct PageDesc { | ||
| 68 | #define L2_SIZE (1 << L2_BITS) | 68 | #define L2_SIZE (1 << L2_BITS) |
| 69 | 69 | ||
| 70 | static void tb_invalidate_page(unsigned long address); | 70 | static void tb_invalidate_page(unsigned long address); |
| 71 | +static void io_mem_init(void); | ||
| 71 | 72 | ||
| 72 | unsigned long real_host_page_size; | 73 | unsigned long real_host_page_size; |
| 73 | unsigned long host_page_bits; | 74 | unsigned long host_page_bits; |
| @@ -76,6 +77,12 @@ unsigned long host_page_mask; | @@ -76,6 +77,12 @@ unsigned long host_page_mask; | ||
| 76 | 77 | ||
| 77 | static PageDesc *l1_map[L1_SIZE]; | 78 | static PageDesc *l1_map[L1_SIZE]; |
| 78 | 79 | ||
| 80 | +/* io memory support */ | ||
| 81 | +static unsigned long *l1_physmap[L1_SIZE]; | ||
| 82 | +CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; | ||
| 83 | +CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; | ||
| 84 | +static int io_mem_nb; | ||
| 85 | + | ||
| 79 | static void page_init(void) | 86 | static void page_init(void) |
| 80 | { | 87 | { |
| 81 | /* NOTE: we can always suppose that host_page_size >= | 88 | /* NOTE: we can always suppose that host_page_size >= |
| @@ -201,6 +208,7 @@ void cpu_exec_init(void) | @@ -201,6 +208,7 @@ void cpu_exec_init(void) | ||
| 201 | if (!code_gen_ptr) { | 208 | if (!code_gen_ptr) { |
| 202 | code_gen_ptr = code_gen_buffer; | 209 | code_gen_ptr = code_gen_buffer; |
| 203 | page_init(); | 210 | page_init(); |
| 211 | + io_mem_init(); | ||
| 204 | } | 212 | } |
| 205 | } | 213 | } |
| 206 | 214 | ||
| @@ -744,3 +752,133 @@ void page_unmap(void) | @@ -744,3 +752,133 @@ void page_unmap(void) | ||
| 744 | tb_flush(); | 752 | tb_flush(); |
| 745 | } | 753 | } |
| 746 | #endif | 754 | #endif |
| 755 | + | ||
| 756 | +void tlb_flush(CPUState *env) | ||
| 757 | +{ | ||
| 758 | +#if defined(TARGET_I386) | ||
| 759 | + int i; | ||
| 760 | + for(i = 0; i < CPU_TLB_SIZE; i++) { | ||
| 761 | + env->tlb_read[0][i].address = -1; | ||
| 762 | + env->tlb_write[0][i].address = -1; | ||
| 763 | + env->tlb_read[1][i].address = -1; | ||
| 764 | + env->tlb_write[1][i].address = -1; | ||
| 765 | + } | ||
| 766 | +#endif | ||
| 767 | +} | ||
| 768 | + | ||
| 769 | +void tlb_flush_page(CPUState *env, uint32_t addr) | ||
| 770 | +{ | ||
| 771 | +#if defined(TARGET_I386) | ||
| 772 | + int i; | ||
| 773 | + | ||
| 774 | + i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); | ||
| 775 | + env->tlb_read[0][i].address = -1; | ||
| 776 | + env->tlb_write[0][i].address = -1; | ||
| 777 | + env->tlb_read[1][i].address = -1; | ||
| 778 | + env->tlb_write[1][i].address = -1; | ||
| 779 | +#endif | ||
| 780 | +} | ||
| 781 | + | ||
| 782 | +static inline unsigned long *physpage_find_alloc(unsigned int page) | ||
| 783 | +{ | ||
| 784 | + unsigned long **lp, *p; | ||
| 785 | + unsigned int index, i; | ||
| 786 | + | ||
| 787 | + index = page >> TARGET_PAGE_BITS; | ||
| 788 | + lp = &l1_physmap[index >> L2_BITS]; | ||
| 789 | + p = *lp; | ||
| 790 | + if (!p) { | ||
| 791 | + /* allocate if not found */ | ||
| 792 | + p = malloc(sizeof(unsigned long) * L2_SIZE); | ||
| 793 | + for(i = 0; i < L2_SIZE; i++) | ||
| 794 | + p[i] = IO_MEM_UNASSIGNED; | ||
| 795 | + *lp = p; | ||
| 796 | + } | ||
| 797 | + return p + (index & (L2_SIZE - 1)); | ||
| 798 | +} | ||
| 799 | + | ||
| 800 | +/* return NULL if no page defined (unused memory) */ | ||
| 801 | +unsigned long physpage_find(unsigned long page) | ||
| 802 | +{ | ||
| 803 | + unsigned long *p; | ||
| 804 | + unsigned int index; | ||
| 805 | + index = page >> TARGET_PAGE_BITS; | ||
| 806 | + p = l1_physmap[index >> L2_BITS]; | ||
| 807 | + if (!p) | ||
| 808 | + return IO_MEM_UNASSIGNED; | ||
| 809 | + return p[index & (L2_SIZE - 1)]; | ||
| 810 | +} | ||
| 811 | + | ||
| 812 | +/* register physical memory. 'size' must be a multiple of the target | ||
| 813 | + page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an | ||
| 814 | + io memory page */ | ||
| 815 | +void cpu_register_physical_memory(unsigned long start_addr, unsigned long size, | ||
| 816 | + long phys_offset) | ||
| 817 | +{ | ||
| 818 | + unsigned long addr, end_addr; | ||
| 819 | + unsigned long *p; | ||
| 820 | + | ||
| 821 | + end_addr = start_addr + size; | ||
| 822 | + for(addr = start_addr; addr < end_addr; addr += TARGET_PAGE_SIZE) { | ||
| 823 | + p = physpage_find_alloc(addr); | ||
| 824 | + *p = phys_offset; | ||
| 825 | + if ((phys_offset & ~TARGET_PAGE_MASK) == 0) | ||
| 826 | + phys_offset += TARGET_PAGE_SIZE; | ||
| 827 | + } | ||
| 828 | +} | ||
| 829 | + | ||
| 830 | +static uint32_t unassigned_mem_readb(uint32_t addr) | ||
| 831 | +{ | ||
| 832 | + return 0; | ||
| 833 | +} | ||
| 834 | + | ||
| 835 | +static void unassigned_mem_writeb(uint32_t addr, uint32_t val) | ||
| 836 | +{ | ||
| 837 | +} | ||
| 838 | + | ||
| 839 | +static CPUReadMemoryFunc *unassigned_mem_read[3] = { | ||
| 840 | + unassigned_mem_readb, | ||
| 841 | + unassigned_mem_readb, | ||
| 842 | + unassigned_mem_readb, | ||
| 843 | +}; | ||
| 844 | + | ||
| 845 | +static CPUWriteMemoryFunc *unassigned_mem_write[3] = { | ||
| 846 | + unassigned_mem_writeb, | ||
| 847 | + unassigned_mem_writeb, | ||
| 848 | + unassigned_mem_writeb, | ||
| 849 | +}; | ||
| 850 | + | ||
| 851 | + | ||
| 852 | +static void io_mem_init(void) | ||
| 853 | +{ | ||
| 854 | + io_mem_nb = 1; | ||
| 855 | + cpu_register_io_memory(0, unassigned_mem_read, unassigned_mem_write); | ||
| 856 | +} | ||
| 857 | + | ||
| 858 | +/* mem_read and mem_write are arrays of functions containing the | ||
| 859 | + function to access byte (index 0), word (index 1) and dword (index | ||
| 860 | + 2). All functions must be supplied. If io_index is non zero, the | ||
| 861 | + corresponding io zone is modified. If it is zero, a new io zone is | ||
| 862 | + allocated. The return value can be used with | ||
| 863 | + cpu_register_physical_memory(). (-1) is returned if error. */ | ||
| 864 | +int cpu_register_io_memory(int io_index, | ||
| 865 | + CPUReadMemoryFunc **mem_read, | ||
| 866 | + CPUWriteMemoryFunc **mem_write) | ||
| 867 | +{ | ||
| 868 | + int i; | ||
| 869 | + | ||
| 870 | + if (io_index <= 0) { | ||
| 871 | + if (io_index >= IO_MEM_NB_ENTRIES) | ||
| 872 | + return -1; | ||
| 873 | + io_index = io_mem_nb++; | ||
| 874 | + } else { | ||
| 875 | + if (io_index >= IO_MEM_NB_ENTRIES) | ||
| 876 | + return -1; | ||
| 877 | + } | ||
| 878 | + | ||
| 879 | + for(i = 0;i < 3; i++) { | ||
| 880 | + io_mem_read[io_index][i] = mem_read[i]; | ||
| 881 | + io_mem_write[io_index][i] = mem_write[i]; | ||
| 882 | + } | ||
| 883 | + return io_index << IO_MEM_SHIFT; | ||
| 884 | +} |
exec.h
| @@ -21,6 +21,17 @@ | @@ -21,6 +21,17 @@ | ||
| 21 | /* allow to see translation results - the slowdown should be negligible, so we leave it */ | 21 | /* allow to see translation results - the slowdown should be negligible, so we leave it */ |
| 22 | #define DEBUG_DISAS | 22 | #define DEBUG_DISAS |
| 23 | 23 | ||
| 24 | +#ifndef glue | ||
| 25 | +#define xglue(x, y) x ## y | ||
| 26 | +#define glue(x, y) xglue(x, y) | ||
| 27 | +#define stringify(s) tostring(s) | ||
| 28 | +#define tostring(s) #s | ||
| 29 | +#endif | ||
| 30 | + | ||
| 31 | +#if GCC_MAJOR < 3 | ||
| 32 | +#define __builtin_expect(x, n) (x) | ||
| 33 | +#endif | ||
| 34 | + | ||
| 24 | /* is_jmp field values */ | 35 | /* is_jmp field values */ |
| 25 | #define DISAS_NEXT 0 /* next instruction can be analyzed */ | 36 | #define DISAS_NEXT 0 /* next instruction can be analyzed */ |
| 26 | #define DISAS_JUMP 1 /* only pc was modified dynamically */ | 37 | #define DISAS_JUMP 1 /* only pc was modified dynamically */ |
| @@ -44,14 +55,17 @@ extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; | @@ -44,14 +55,17 @@ extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; | ||
| 44 | 55 | ||
| 45 | #if defined(TARGET_I386) | 56 | #if defined(TARGET_I386) |
| 46 | 57 | ||
| 47 | -#define GEN_FLAG_CODE32_SHIFT 0 | ||
| 48 | -#define GEN_FLAG_ADDSEG_SHIFT 1 | ||
| 49 | -#define GEN_FLAG_SS32_SHIFT 2 | ||
| 50 | -#define GEN_FLAG_VM_SHIFT 3 | ||
| 51 | -#define GEN_FLAG_ST_SHIFT 4 | ||
| 52 | -#define GEN_FLAG_TF_SHIFT 8 /* same position as eflags */ | ||
| 53 | -#define GEN_FLAG_CPL_SHIFT 9 | ||
| 54 | -#define GEN_FLAG_IOPL_SHIFT 12 /* same position as eflags */ | 58 | +#define GEN_FLAG_CODE32_SHIFT 0 |
| 59 | +#define GEN_FLAG_ADDSEG_SHIFT 1 | ||
| 60 | +#define GEN_FLAG_SS32_SHIFT 2 | ||
| 61 | +#define GEN_FLAG_VM_SHIFT 3 | ||
| 62 | +#define GEN_FLAG_ST_SHIFT 4 | ||
| 63 | +#define GEN_FLAG_TF_SHIFT 8 /* same position as eflags */ | ||
| 64 | +#define GEN_FLAG_CPL_SHIFT 9 | ||
| 65 | +#define GEN_FLAG_SOFT_MMU_SHIFT 11 | ||
| 66 | +#define GEN_FLAG_IOPL_SHIFT 12 /* same position as eflags */ | ||
| 67 | + | ||
| 68 | +void optimize_flags_init(void); | ||
| 55 | 69 | ||
| 56 | #endif | 70 | #endif |
| 57 | 71 | ||
| @@ -68,6 +82,8 @@ int cpu_restore_state(struct TranslationBlock *tb, | @@ -68,6 +82,8 @@ int cpu_restore_state(struct TranslationBlock *tb, | ||
| 68 | void cpu_exec_init(void); | 82 | void cpu_exec_init(void); |
| 69 | int page_unprotect(unsigned long address); | 83 | int page_unprotect(unsigned long address); |
| 70 | void page_unmap(void); | 84 | void page_unmap(void); |
| 85 | +void tlb_flush_page(CPUState *env, uint32_t addr); | ||
| 86 | +void tlb_flush(CPUState *env); | ||
| 71 | 87 | ||
| 72 | #define CODE_GEN_MAX_SIZE 65536 | 88 | #define CODE_GEN_MAX_SIZE 65536 |
| 73 | #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ | 89 | #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ |
| @@ -230,6 +246,17 @@ dummy_label ## n:\ | @@ -230,6 +246,17 @@ dummy_label ## n:\ | ||
| 230 | 246 | ||
| 231 | #endif | 247 | #endif |
| 232 | 248 | ||
| 249 | +/* physical memory access */ | ||
| 250 | +#define IO_MEM_NB_ENTRIES 256 | ||
| 251 | +#define TLB_INVALID_MASK (1 << 3) | ||
| 252 | +#define IO_MEM_SHIFT 4 | ||
| 253 | +#define IO_MEM_UNASSIGNED (1 << IO_MEM_SHIFT) | ||
| 254 | + | ||
| 255 | +unsigned long physpage_find(unsigned long page); | ||
| 256 | + | ||
| 257 | +extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; | ||
| 258 | +extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; | ||
| 259 | + | ||
| 233 | #ifdef __powerpc__ | 260 | #ifdef __powerpc__ |
| 234 | static inline int testandset (int *p) | 261 | static inline int testandset (int *p) |
| 235 | { | 262 | { |
helper-i386.c
| @@ -781,7 +781,7 @@ void helper_lcall_real_T0_T1(int shift, int next_eip) | @@ -781,7 +781,7 @@ void helper_lcall_real_T0_T1(int shift, int next_eip) | ||
| 781 | int new_cs, new_eip; | 781 | int new_cs, new_eip; |
| 782 | uint32_t esp, esp_mask; | 782 | uint32_t esp, esp_mask; |
| 783 | uint8_t *ssp; | 783 | uint8_t *ssp; |
| 784 | - | 784 | + |
| 785 | new_cs = T0; | 785 | new_cs = T0; |
| 786 | new_eip = T1; | 786 | new_eip = T1; |
| 787 | esp = env->regs[R_ESP]; | 787 | esp = env->regs[R_ESP]; |
| @@ -1741,3 +1741,34 @@ void helper_frstor(uint8_t *ptr, int data32) | @@ -1741,3 +1741,34 @@ void helper_frstor(uint8_t *ptr, int data32) | ||
| 1741 | } | 1741 | } |
| 1742 | } | 1742 | } |
| 1743 | 1743 | ||
| 1744 | +#define SHIFT 0 | ||
| 1745 | +#include "softmmu_template.h" | ||
| 1746 | + | ||
| 1747 | +#define SHIFT 1 | ||
| 1748 | +#include "softmmu_template.h" | ||
| 1749 | + | ||
| 1750 | +#define SHIFT 2 | ||
| 1751 | +#include "softmmu_template.h" | ||
| 1752 | + | ||
| 1753 | +#define SHIFT 3 | ||
| 1754 | +#include "softmmu_template.h" | ||
| 1755 | + | ||
| 1756 | +/* try to fill the TLB and return an exception if error */ | ||
| 1757 | +void tlb_fill(unsigned long addr, int is_write, void *retaddr) | ||
| 1758 | +{ | ||
| 1759 | + TranslationBlock *tb; | ||
| 1760 | + int ret; | ||
| 1761 | + unsigned long pc; | ||
| 1762 | + ret = cpu_x86_handle_mmu_fault(env, addr, is_write); | ||
| 1763 | + if (ret) { | ||
| 1764 | + /* now we have a real cpu fault */ | ||
| 1765 | + pc = (unsigned long)retaddr; | ||
| 1766 | + tb = tb_find_pc(pc); | ||
| 1767 | + if (tb) { | ||
| 1768 | + /* the PC is inside the translated code. It means that we have | ||
| 1769 | + a virtual CPU fault */ | ||
| 1770 | + cpu_restore_state(tb, env, pc); | ||
| 1771 | + } | ||
| 1772 | + raise_exception_err(EXCP0E_PAGE, env->error_code); | ||
| 1773 | + } | ||
| 1774 | +} |
op-i386.c
| @@ -376,70 +376,14 @@ void OPPROTO op_andl_A0_ffff(void) | @@ -376,70 +376,14 @@ void OPPROTO op_andl_A0_ffff(void) | ||
| 376 | 376 | ||
| 377 | /* memory access */ | 377 | /* memory access */ |
| 378 | 378 | ||
| 379 | -void OPPROTO op_ldub_T0_A0(void) | ||
| 380 | -{ | ||
| 381 | - T0 = ldub((uint8_t *)A0); | ||
| 382 | -} | ||
| 383 | - | ||
| 384 | -void OPPROTO op_ldsb_T0_A0(void) | ||
| 385 | -{ | ||
| 386 | - T0 = ldsb((int8_t *)A0); | ||
| 387 | -} | ||
| 388 | - | ||
| 389 | -void OPPROTO op_lduw_T0_A0(void) | ||
| 390 | -{ | ||
| 391 | - T0 = lduw((uint8_t *)A0); | ||
| 392 | -} | ||
| 393 | - | ||
| 394 | -void OPPROTO op_ldsw_T0_A0(void) | ||
| 395 | -{ | ||
| 396 | - T0 = ldsw((int8_t *)A0); | ||
| 397 | -} | ||
| 398 | - | ||
| 399 | -void OPPROTO op_ldl_T0_A0(void) | ||
| 400 | -{ | ||
| 401 | - T0 = ldl((uint8_t *)A0); | ||
| 402 | -} | 379 | +#define MEMSUFFIX |
| 380 | +#include "ops_mem.h" | ||
| 403 | 381 | ||
| 404 | -void OPPROTO op_ldub_T1_A0(void) | ||
| 405 | -{ | ||
| 406 | - T1 = ldub((uint8_t *)A0); | ||
| 407 | -} | ||
| 408 | - | ||
| 409 | -void OPPROTO op_ldsb_T1_A0(void) | ||
| 410 | -{ | ||
| 411 | - T1 = ldsb((int8_t *)A0); | ||
| 412 | -} | ||
| 413 | - | ||
| 414 | -void OPPROTO op_lduw_T1_A0(void) | ||
| 415 | -{ | ||
| 416 | - T1 = lduw((uint8_t *)A0); | ||
| 417 | -} | 382 | +#define MEMSUFFIX _user |
| 383 | +#include "ops_mem.h" | ||
| 418 | 384 | ||
| 419 | -void OPPROTO op_ldsw_T1_A0(void) | ||
| 420 | -{ | ||
| 421 | - T1 = ldsw((int8_t *)A0); | ||
| 422 | -} | ||
| 423 | - | ||
| 424 | -void OPPROTO op_ldl_T1_A0(void) | ||
| 425 | -{ | ||
| 426 | - T1 = ldl((uint8_t *)A0); | ||
| 427 | -} | ||
| 428 | - | ||
| 429 | -void OPPROTO op_stb_T0_A0(void) | ||
| 430 | -{ | ||
| 431 | - stb((uint8_t *)A0, T0); | ||
| 432 | -} | ||
| 433 | - | ||
| 434 | -void OPPROTO op_stw_T0_A0(void) | ||
| 435 | -{ | ||
| 436 | - stw((uint8_t *)A0, T0); | ||
| 437 | -} | ||
| 438 | - | ||
| 439 | -void OPPROTO op_stl_T0_A0(void) | ||
| 440 | -{ | ||
| 441 | - stl((uint8_t *)A0, T0); | ||
| 442 | -} | 385 | +#define MEMSUFFIX _kernel |
| 386 | +#include "ops_mem.h" | ||
| 443 | 387 | ||
| 444 | /* used for bit operations */ | 388 | /* used for bit operations */ |
| 445 | 389 | ||
| @@ -635,6 +579,38 @@ void OPPROTO op_movswl_DX_AX(void) | @@ -635,6 +579,38 @@ void OPPROTO op_movswl_DX_AX(void) | ||
| 635 | EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff); | 579 | EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff); |
| 636 | } | 580 | } |
| 637 | 581 | ||
| 582 | +/* string ops helpers */ | ||
| 583 | + | ||
| 584 | +void OPPROTO op_addl_ESI_T0(void) | ||
| 585 | +{ | ||
| 586 | + ESI += T0; | ||
| 587 | +} | ||
| 588 | + | ||
| 589 | +void OPPROTO op_addw_ESI_T0(void) | ||
| 590 | +{ | ||
| 591 | + ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff); | ||
| 592 | +} | ||
| 593 | + | ||
| 594 | +void OPPROTO op_addl_EDI_T0(void) | ||
| 595 | +{ | ||
| 596 | + EDI += T0; | ||
| 597 | +} | ||
| 598 | + | ||
| 599 | +void OPPROTO op_addw_EDI_T0(void) | ||
| 600 | +{ | ||
| 601 | + EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff); | ||
| 602 | +} | ||
| 603 | + | ||
| 604 | +void OPPROTO op_decl_ECX(void) | ||
| 605 | +{ | ||
| 606 | + ECX--; | ||
| 607 | +} | ||
| 608 | + | ||
| 609 | +void OPPROTO op_decw_ECX(void) | ||
| 610 | +{ | ||
| 611 | + ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff); | ||
| 612 | +} | ||
| 613 | + | ||
| 638 | /* push/pop */ | 614 | /* push/pop */ |
| 639 | 615 | ||
| 640 | void op_pushl_T0(void) | 616 | void op_pushl_T0(void) |
op_string.h
| 1 | 1 | ||
| 2 | -void OPPROTO glue(glue(op_movs, SUFFIX), STRING_SUFFIX)(void) | ||
| 3 | -{ | ||
| 4 | - int v, inc; | ||
| 5 | - v = glue(ldu, SUFFIX)(SI_ADDR); | ||
| 6 | - glue(st, SUFFIX)(DI_ADDR, v); | ||
| 7 | - inc = (DF << SHIFT); | ||
| 8 | - INC_SI(); | ||
| 9 | - INC_DI(); | ||
| 10 | -} | ||
| 11 | - | ||
| 12 | -void OPPROTO glue(glue(op_rep_movs, SUFFIX), STRING_SUFFIX)(void) | ||
| 13 | -{ | ||
| 14 | - int v, inc; | ||
| 15 | - inc = (DF << SHIFT); | ||
| 16 | - while (CX != 0) { | ||
| 17 | - v = glue(ldu, SUFFIX)(SI_ADDR); | ||
| 18 | - glue(st, SUFFIX)(DI_ADDR, v); | ||
| 19 | - INC_SI(); | ||
| 20 | - INC_DI(); | ||
| 21 | - DEC_CX(); | ||
| 22 | - } | ||
| 23 | - FORCE_RET(); | ||
| 24 | -} | ||
| 25 | - | ||
| 26 | -void OPPROTO glue(glue(op_stos, SUFFIX), STRING_SUFFIX)(void) | ||
| 27 | -{ | ||
| 28 | - int inc; | ||
| 29 | - glue(st, SUFFIX)(DI_ADDR, EAX); | ||
| 30 | - inc = (DF << SHIFT); | ||
| 31 | - INC_DI(); | ||
| 32 | -} | ||
| 33 | - | ||
| 34 | -void OPPROTO glue(glue(op_rep_stos, SUFFIX), STRING_SUFFIX)(void) | ||
| 35 | -{ | ||
| 36 | - int inc; | ||
| 37 | - inc = (DF << SHIFT); | ||
| 38 | - while (CX != 0) { | ||
| 39 | - glue(st, SUFFIX)(DI_ADDR, EAX); | ||
| 40 | - INC_DI(); | ||
| 41 | - DEC_CX(); | ||
| 42 | - } | ||
| 43 | - FORCE_RET(); | ||
| 44 | -} | ||
| 45 | - | ||
| 46 | -void OPPROTO glue(glue(op_lods, SUFFIX), STRING_SUFFIX)(void) | ||
| 47 | -{ | ||
| 48 | - int v, inc; | ||
| 49 | - v = glue(ldu, SUFFIX)(SI_ADDR); | ||
| 50 | -#if SHIFT == 0 | ||
| 51 | - EAX = (EAX & ~0xff) | v; | ||
| 52 | -#elif SHIFT == 1 | ||
| 53 | - EAX = (EAX & ~0xffff) | v; | ||
| 54 | -#else | ||
| 55 | - EAX = v; | ||
| 56 | -#endif | ||
| 57 | - inc = (DF << SHIFT); | ||
| 58 | - INC_SI(); | ||
| 59 | -} | ||
| 60 | - | ||
| 61 | -/* don't know if it is used */ | ||
| 62 | -void OPPROTO glue(glue(op_rep_lods, SUFFIX), STRING_SUFFIX)(void) | ||
| 63 | -{ | ||
| 64 | - int v, inc; | ||
| 65 | - inc = (DF << SHIFT); | ||
| 66 | - while (CX != 0) { | ||
| 67 | - v = glue(ldu, SUFFIX)(SI_ADDR); | ||
| 68 | -#if SHIFT == 0 | ||
| 69 | - EAX = (EAX & ~0xff) | v; | ||
| 70 | -#elif SHIFT == 1 | ||
| 71 | - EAX = (EAX & ~0xffff) | v; | ||
| 72 | -#else | ||
| 73 | - EAX = v; | ||
| 74 | -#endif | ||
| 75 | - INC_SI(); | ||
| 76 | - DEC_CX(); | ||
| 77 | - } | ||
| 78 | - FORCE_RET(); | ||
| 79 | -} | ||
| 80 | - | ||
| 81 | -void OPPROTO glue(glue(op_scas, SUFFIX), STRING_SUFFIX)(void) | ||
| 82 | -{ | ||
| 83 | - int v, inc; | ||
| 84 | - | ||
| 85 | - v = glue(ldu, SUFFIX)(DI_ADDR); | ||
| 86 | - inc = (DF << SHIFT); | ||
| 87 | - INC_DI(); | ||
| 88 | - CC_SRC = v; | ||
| 89 | - CC_DST = EAX - v; | ||
| 90 | -} | ||
| 91 | - | ||
| 92 | void OPPROTO glue(glue(op_repz_scas, SUFFIX), STRING_SUFFIX)(void) | 2 | void OPPROTO glue(glue(op_repz_scas, SUFFIX), STRING_SUFFIX)(void) |
| 93 | { | 3 | { |
| 94 | int v1, v2, inc; | 4 | int v1, v2, inc; |
| @@ -133,18 +43,6 @@ void OPPROTO glue(glue(op_repnz_scas, SUFFIX), STRING_SUFFIX)(void) | @@ -133,18 +43,6 @@ void OPPROTO glue(glue(op_repnz_scas, SUFFIX), STRING_SUFFIX)(void) | ||
| 133 | FORCE_RET(); | 43 | FORCE_RET(); |
| 134 | } | 44 | } |
| 135 | 45 | ||
| 136 | -void OPPROTO glue(glue(op_cmps, SUFFIX), STRING_SUFFIX)(void) | ||
| 137 | -{ | ||
| 138 | - int v1, v2, inc; | ||
| 139 | - v1 = glue(ldu, SUFFIX)(SI_ADDR); | ||
| 140 | - v2 = glue(ldu, SUFFIX)(DI_ADDR); | ||
| 141 | - inc = (DF << SHIFT); | ||
| 142 | - INC_SI(); | ||
| 143 | - INC_DI(); | ||
| 144 | - CC_SRC = v2; | ||
| 145 | - CC_DST = v1 - v2; | ||
| 146 | -} | ||
| 147 | - | ||
| 148 | void OPPROTO glue(glue(op_repz_cmps, SUFFIX), STRING_SUFFIX)(void) | 46 | void OPPROTO glue(glue(op_repz_cmps, SUFFIX), STRING_SUFFIX)(void) |
| 149 | { | 47 | { |
| 150 | int v1, v2, inc; | 48 | int v1, v2, inc; |
| @@ -187,54 +85,6 @@ void OPPROTO glue(glue(op_repnz_cmps, SUFFIX), STRING_SUFFIX)(void) | @@ -187,54 +85,6 @@ void OPPROTO glue(glue(op_repnz_cmps, SUFFIX), STRING_SUFFIX)(void) | ||
| 187 | FORCE_RET(); | 85 | FORCE_RET(); |
| 188 | } | 86 | } |
| 189 | 87 | ||
| 190 | -void OPPROTO glue(glue(op_outs, SUFFIX), STRING_SUFFIX)(void) | ||
| 191 | -{ | ||
| 192 | - int v, dx, inc; | ||
| 193 | - dx = EDX & 0xffff; | ||
| 194 | - v = glue(ldu, SUFFIX)(SI_ADDR); | ||
| 195 | - glue(cpu_x86_out, SUFFIX)(env, dx, v); | ||
| 196 | - inc = (DF << SHIFT); | ||
| 197 | - INC_SI(); | ||
| 198 | -} | ||
| 199 | - | ||
| 200 | -void OPPROTO glue(glue(op_rep_outs, SUFFIX), STRING_SUFFIX)(void) | ||
| 201 | -{ | ||
| 202 | - int v, dx, inc; | ||
| 203 | - inc = (DF << SHIFT); | ||
| 204 | - dx = EDX & 0xffff; | ||
| 205 | - while (CX != 0) { | ||
| 206 | - v = glue(ldu, SUFFIX)(SI_ADDR); | ||
| 207 | - glue(cpu_x86_out, SUFFIX)(env, dx, v); | ||
| 208 | - INC_SI(); | ||
| 209 | - DEC_CX(); | ||
| 210 | - } | ||
| 211 | - FORCE_RET(); | ||
| 212 | -} | ||
| 213 | - | ||
| 214 | -void OPPROTO glue(glue(op_ins, SUFFIX), STRING_SUFFIX)(void) | ||
| 215 | -{ | ||
| 216 | - int v, dx, inc; | ||
| 217 | - dx = EDX & 0xffff; | ||
| 218 | - v = glue(cpu_x86_in, SUFFIX)(env, dx); | ||
| 219 | - glue(st, SUFFIX)(DI_ADDR, v); | ||
| 220 | - inc = (DF << SHIFT); | ||
| 221 | - INC_DI(); | ||
| 222 | -} | ||
| 223 | - | ||
| 224 | -void OPPROTO glue(glue(op_rep_ins, SUFFIX), STRING_SUFFIX)(void) | ||
| 225 | -{ | ||
| 226 | - int v, dx, inc; | ||
| 227 | - inc = (DF << SHIFT); | ||
| 228 | - dx = EDX & 0xffff; | ||
| 229 | - while (CX != 0) { | ||
| 230 | - v = glue(cpu_x86_in, SUFFIX)(env, dx); | ||
| 231 | - glue(st, SUFFIX)(DI_ADDR, v); | ||
| 232 | - INC_DI(); | ||
| 233 | - DEC_CX(); | ||
| 234 | - } | ||
| 235 | - FORCE_RET(); | ||
| 236 | -} | ||
| 237 | - | ||
| 238 | #undef STRING_SUFFIX | 88 | #undef STRING_SUFFIX |
| 239 | #undef SI_ADDR | 89 | #undef SI_ADDR |
| 240 | #undef DI_ADDR | 90 | #undef DI_ADDR |
ops_template.h
| @@ -547,6 +547,31 @@ void OPPROTO op_update_bt_cc(void) | @@ -547,6 +547,31 @@ void OPPROTO op_update_bt_cc(void) | ||
| 547 | #define DEC_CX() ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff) | 547 | #define DEC_CX() ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff) |
| 548 | #include "op_string.h" | 548 | #include "op_string.h" |
| 549 | 549 | ||
| 550 | +void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void) | ||
| 551 | +{ | ||
| 552 | + T0 = DF << SHIFT; | ||
| 553 | +} | ||
| 554 | + | ||
| 555 | +void OPPROTO glue(op_string_jz_sub, SUFFIX)(void) | ||
| 556 | +{ | ||
| 557 | + if ((DATA_TYPE)CC_DST == 0) | ||
| 558 | + JUMP_TB(PARAM1, 1, PARAM2); | ||
| 559 | +} | ||
| 560 | + | ||
| 561 | +void OPPROTO glue(op_string_jnz_sub, SUFFIX)(void) | ||
| 562 | +{ | ||
| 563 | + if ((DATA_TYPE)CC_DST != 0) | ||
| 564 | + JUMP_TB(PARAM1, 1, PARAM2); | ||
| 565 | +} | ||
| 566 | + | ||
| 567 | +#if DATA_BITS >= 16 | ||
| 568 | +void OPPROTO glue(op_jz_ecx, SUFFIX)(void) | ||
| 569 | +{ | ||
| 570 | + if ((DATA_TYPE)ECX == 0) | ||
| 571 | + JUMP_TB(PARAM1, 1, PARAM2); | ||
| 572 | +} | ||
| 573 | +#endif | ||
| 574 | + | ||
| 550 | /* port I/O */ | 575 | /* port I/O */ |
| 551 | 576 | ||
| 552 | void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void) | 577 | void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void) |
| @@ -559,6 +584,16 @@ void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void) | @@ -559,6 +584,16 @@ void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void) | ||
| 559 | T1 = glue(cpu_x86_in, SUFFIX)(env, T0 & 0xffff); | 584 | T1 = glue(cpu_x86_in, SUFFIX)(env, T0 & 0xffff); |
| 560 | } | 585 | } |
| 561 | 586 | ||
| 587 | +void OPPROTO glue(glue(op_in, SUFFIX), _DX_T0)(void) | ||
| 588 | +{ | ||
| 589 | + T0 = glue(cpu_x86_in, SUFFIX)(env, EDX & 0xffff); | ||
| 590 | +} | ||
| 591 | + | ||
| 592 | +void OPPROTO glue(glue(op_out, SUFFIX), _DX_T0)(void) | ||
| 593 | +{ | ||
| 594 | + glue(cpu_x86_out, SUFFIX)(env, EDX & 0xffff, T0); | ||
| 595 | +} | ||
| 596 | + | ||
| 562 | #undef DATA_BITS | 597 | #undef DATA_BITS |
| 563 | #undef SHIFT_MASK | 598 | #undef SHIFT_MASK |
| 564 | #undef SIGN_MASK | 599 | #undef SIGN_MASK |