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 | 140 | stl(ptr, u.i); |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | + | |
| 143 | 144 | #if defined(__arm__) && !defined(WORDS_BIGENDIAN) |
| 144 | 145 | |
| 145 | 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 | 318 | int cpu_breakpoint_remove(CPUState *env, uint32_t pc); |
| 318 | 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 | 332 | /* gdb stub API */ |
| 321 | 333 | extern int gdbstub_fd; |
| 322 | 334 | CPUState *cpu_gdbstub_get_env(void *opaque); | ... | ... |
cpu-arm.h
| ... | ... | @@ -20,12 +20,10 @@ |
| 20 | 20 | #ifndef CPU_ARM_H |
| 21 | 21 | #define CPU_ARM_H |
| 22 | 22 | |
| 23 | -#include "config.h" | |
| 24 | -#include <setjmp.h> | |
| 23 | +#include "cpu-defs.h" | |
| 25 | 24 | |
| 26 | 25 | #define EXCP_UDEF 1 /* undefined instruction */ |
| 27 | 26 | #define EXCP_SWI 2 /* software interrupt */ |
| 28 | -#define EXCP_INTERRUPT 256 /* async interruption */ | |
| 29 | 27 | |
| 30 | 28 | typedef struct CPUARMState { |
| 31 | 29 | uint32_t regs[16]; | ... | ... |
cpu-i386.h
| ... | ... | @@ -20,8 +20,7 @@ |
| 20 | 20 | #ifndef CPU_I386_H |
| 21 | 21 | #define CPU_I386_H |
| 22 | 22 | |
| 23 | -#include "config.h" | |
| 24 | -#include <setjmp.h> | |
| 23 | +#include "cpu-defs.h" | |
| 25 | 24 | |
| 26 | 25 | #define R_EAX 0 |
| 27 | 26 | #define R_ECX 1 |
| ... | ... | @@ -153,12 +152,6 @@ |
| 153 | 152 | #define EXCP11_ALGN 17 |
| 154 | 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 | 155 | enum { |
| 163 | 156 | CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ |
| 164 | 157 | CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */ |
| ... | ... | @@ -257,7 +250,8 @@ typedef struct CPUX86State { |
| 257 | 250 | SegmentCache gdt; /* only base and limit are used */ |
| 258 | 251 | SegmentCache idt; /* only base and limit are used */ |
| 259 | 252 | int cpl; /* current cpl */ |
| 260 | - | |
| 253 | + int soft_mmu; /* TRUE if soft mmu is being used */ | |
| 254 | + | |
| 261 | 255 | /* sysenter registers */ |
| 262 | 256 | uint32_t sysenter_cs; |
| 263 | 257 | uint32_t sysenter_esp; |
| ... | ... | @@ -275,10 +269,16 @@ typedef struct CPUX86State { |
| 275 | 269 | int interrupt_request; |
| 276 | 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 | 278 | uint32_t breakpoints[MAX_BREAKPOINTS]; |
| 279 | 279 | int nb_breakpoints; |
| 280 | 280 | int singlestep_enabled; |
| 281 | - | |
| 281 | + | |
| 282 | 282 | /* user data */ |
| 283 | 283 | void *opaque; |
| 284 | 284 | } CPUX86State; | ... | ... |
exec-i386.h
| ... | ... | @@ -138,6 +138,7 @@ void cpu_x86_update_cr0(CPUX86State *env); |
| 138 | 138 | void cpu_x86_update_cr3(CPUX86State *env); |
| 139 | 139 | void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr); |
| 140 | 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 | 142 | void __hidden cpu_lock(void); |
| 142 | 143 | void __hidden cpu_unlock(void); |
| 143 | 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 | 365 | env->eflags = (env->eflags & ~update_mask) | |
| 365 | 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 | 68 | #define L2_SIZE (1 << L2_BITS) |
| 69 | 69 | |
| 70 | 70 | static void tb_invalidate_page(unsigned long address); |
| 71 | +static void io_mem_init(void); | |
| 71 | 72 | |
| 72 | 73 | unsigned long real_host_page_size; |
| 73 | 74 | unsigned long host_page_bits; |
| ... | ... | @@ -76,6 +77,12 @@ unsigned long host_page_mask; |
| 76 | 77 | |
| 77 | 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 | 86 | static void page_init(void) |
| 80 | 87 | { |
| 81 | 88 | /* NOTE: we can always suppose that host_page_size >= |
| ... | ... | @@ -201,6 +208,7 @@ void cpu_exec_init(void) |
| 201 | 208 | if (!code_gen_ptr) { |
| 202 | 209 | code_gen_ptr = code_gen_buffer; |
| 203 | 210 | page_init(); |
| 211 | + io_mem_init(); | |
| 204 | 212 | } |
| 205 | 213 | } |
| 206 | 214 | |
| ... | ... | @@ -744,3 +752,133 @@ void page_unmap(void) |
| 744 | 752 | tb_flush(); |
| 745 | 753 | } |
| 746 | 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 | 21 | /* allow to see translation results - the slowdown should be negligible, so we leave it */ |
| 22 | 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 | 35 | /* is_jmp field values */ |
| 25 | 36 | #define DISAS_NEXT 0 /* next instruction can be analyzed */ |
| 26 | 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 | 55 | |
| 45 | 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 | 70 | #endif |
| 57 | 71 | |
| ... | ... | @@ -68,6 +82,8 @@ int cpu_restore_state(struct TranslationBlock *tb, |
| 68 | 82 | void cpu_exec_init(void); |
| 69 | 83 | int page_unprotect(unsigned long address); |
| 70 | 84 | void page_unmap(void); |
| 85 | +void tlb_flush_page(CPUState *env, uint32_t addr); | |
| 86 | +void tlb_flush(CPUState *env); | |
| 71 | 87 | |
| 72 | 88 | #define CODE_GEN_MAX_SIZE 65536 |
| 73 | 89 | #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ |
| ... | ... | @@ -230,6 +246,17 @@ dummy_label ## n:\ |
| 230 | 246 | |
| 231 | 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 | 260 | #ifdef __powerpc__ |
| 234 | 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 | 781 | int new_cs, new_eip; |
| 782 | 782 | uint32_t esp, esp_mask; |
| 783 | 783 | uint8_t *ssp; |
| 784 | - | |
| 784 | + | |
| 785 | 785 | new_cs = T0; |
| 786 | 786 | new_eip = T1; |
| 787 | 787 | esp = env->regs[R_ESP]; |
| ... | ... | @@ -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 | 376 | |
| 377 | 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 | 388 | /* used for bit operations */ |
| 445 | 389 | |
| ... | ... | @@ -635,6 +579,38 @@ void OPPROTO op_movswl_DX_AX(void) |
| 635 | 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 | 614 | /* push/pop */ |
| 639 | 615 | |
| 640 | 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 | 2 | void OPPROTO glue(glue(op_repz_scas, SUFFIX), STRING_SUFFIX)(void) |
| 93 | 3 | { |
| 94 | 4 | int v1, v2, inc; |
| ... | ... | @@ -133,18 +43,6 @@ void OPPROTO glue(glue(op_repnz_scas, SUFFIX), STRING_SUFFIX)(void) |
| 133 | 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 | 46 | void OPPROTO glue(glue(op_repz_cmps, SUFFIX), STRING_SUFFIX)(void) |
| 149 | 47 | { |
| 150 | 48 | int v1, v2, inc; |
| ... | ... | @@ -187,54 +85,6 @@ void OPPROTO glue(glue(op_repnz_cmps, SUFFIX), STRING_SUFFIX)(void) |
| 187 | 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 | 88 | #undef STRING_SUFFIX |
| 239 | 89 | #undef SI_ADDR |
| 240 | 90 | #undef DI_ADDR | ... | ... |
ops_template.h
| ... | ... | @@ -547,6 +547,31 @@ void OPPROTO op_update_bt_cc(void) |
| 547 | 547 | #define DEC_CX() ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff) |
| 548 | 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 | 575 | /* port I/O */ |
| 551 | 576 | |
| 552 | 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 | 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 | 597 | #undef DATA_BITS |
| 563 | 598 | #undef SHIFT_MASK |
| 564 | 599 | #undef SIGN_MASK | ... | ... |