Revision ec6338ba

b/Makefile.target
302 302

  
303 303
ifeq ($(TARGET_ARCH), i386)
304 304
LIBOBJS+=helper.o helper2.o
305
ifeq ($(ARCH), i386)
306
LIBOBJS+=translate-copy.o
307
endif
308 305
endif
309 306

  
310 307
ifeq ($(TARGET_ARCH), x86_64)
b/cpu-exec.c
612 612
#if USE_KQEMU
613 613
                        (env->kqemu_enabled != 2) &&
614 614
#endif
615
                        tb->page_addr[1] == -1
616
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
617
                    && (tb->cflags & CF_CODE_COPY) ==
618
                    (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
619
#endif
620
                    ) {
615
                        tb->page_addr[1] == -1) {
621 616
                    spin_lock(&tb_lock);
622 617
                    tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
623
#if defined(USE_CODE_COPY)
624
                    /* propagates the FP use info */
625
                    ((TranslationBlock *)(T0 & ~3))->cflags |=
626
                        (tb->cflags & CF_FP_USED);
627
#endif
628 618
                    spin_unlock(&tb_lock);
629 619
                }
630 620
                }
......
648 638
                              : /* no outputs */
649 639
                              : "r" (gen_func)
650 640
                              : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
651
#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
652
{
653
    if (!(tb->cflags & CF_CODE_COPY)) {
654
        if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
655
            save_native_fp_state(env);
656
        }
657
        gen_func();
658
    } else {
659
        if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
660
            restore_native_fp_state(env);
661
        }
662
        /* we work with native eflags */
663
        CC_SRC = cc_table[CC_OP].compute_all();
664
        CC_OP = CC_OP_EFLAGS;
665
        asm(".globl exec_loop\n"
666
            "\n"
667
            "debug1:\n"
668
            "    pushl %%ebp\n"
669
            "    fs movl %10, %9\n"
670
            "    fs movl %11, %%eax\n"
671
            "    andl $0x400, %%eax\n"
672
            "    fs orl %8, %%eax\n"
673
            "    pushl %%eax\n"
674
            "    popf\n"
675
            "    fs movl %%esp, %12\n"
676
            "    fs movl %0, %%eax\n"
677
            "    fs movl %1, %%ecx\n"
678
            "    fs movl %2, %%edx\n"
679
            "    fs movl %3, %%ebx\n"
680
            "    fs movl %4, %%esp\n"
681
            "    fs movl %5, %%ebp\n"
682
            "    fs movl %6, %%esi\n"
683
            "    fs movl %7, %%edi\n"
684
            "    fs jmp *%9\n"
685
            "exec_loop:\n"
686
            "    fs movl %%esp, %4\n"
687
            "    fs movl %12, %%esp\n"
688
            "    fs movl %%eax, %0\n"
689
            "    fs movl %%ecx, %1\n"
690
            "    fs movl %%edx, %2\n"
691
            "    fs movl %%ebx, %3\n"
692
            "    fs movl %%ebp, %5\n"
693
            "    fs movl %%esi, %6\n"
694
            "    fs movl %%edi, %7\n"
695
            "    pushf\n"
696
            "    popl %%eax\n"
697
            "    movl %%eax, %%ecx\n"
698
            "    andl $0x400, %%ecx\n"
699
            "    shrl $9, %%ecx\n"
700
            "    andl $0x8d5, %%eax\n"
701
            "    fs movl %%eax, %8\n"
702
            "    movl $1, %%eax\n"
703
            "    subl %%ecx, %%eax\n"
704
            "    fs movl %%eax, %11\n"
705
            "    fs movl %9, %%ebx\n" /* get T0 value */
706
            "    popl %%ebp\n"
707
            :
708
            : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
709
            "m" (*(uint8_t *)offsetof(CPUState, regs[1])),
710
            "m" (*(uint8_t *)offsetof(CPUState, regs[2])),
711
            "m" (*(uint8_t *)offsetof(CPUState, regs[3])),
712
            "m" (*(uint8_t *)offsetof(CPUState, regs[4])),
713
            "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
714
            "m" (*(uint8_t *)offsetof(CPUState, regs[6])),
715
            "m" (*(uint8_t *)offsetof(CPUState, regs[7])),
716
            "m" (*(uint8_t *)offsetof(CPUState, cc_src)),
717
            "m" (*(uint8_t *)offsetof(CPUState, tmp0)),
718
            "a" (gen_func),
719
            "m" (*(uint8_t *)offsetof(CPUState, df)),
720
            "m" (*(uint8_t *)offsetof(CPUState, saved_esp))
721
            : "%ecx", "%edx"
722
            );
723
    }
724
}
725 641
#elif defined(__ia64)
726 642
		struct fptr {
727 643
			void *ip;
......
759 675

  
760 676

  
761 677
#if defined(TARGET_I386)
762
#if defined(USE_CODE_COPY)
763
    if (env->native_fp_regs) {
764
        save_native_fp_state(env);
765
    }
766
#endif
767 678
    /* restore flags in standard format */
768 679
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
769 680
#elif defined(TARGET_ARM)
......
1275 1186
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1276 1187
#endif
1277 1188

  
1278
#if defined(USE_CODE_COPY)
1279
static void cpu_send_trap(unsigned long pc, int trap,
1280
                          struct ucontext *uc)
1281
{
1282
    TranslationBlock *tb;
1283

  
1284
    if (cpu_single_env)
1285
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1286
    /* now we have a real cpu fault */
1287
    tb = tb_find_pc(pc);
1288
    if (tb) {
1289
        /* the PC is inside the translated code. It means that we have
1290
           a virtual CPU fault */
1291
        cpu_restore_state(tb, env, pc, uc);
1292
    }
1293
    sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
1294
    raise_exception_err(trap, env->error_code);
1295
}
1296
#endif
1297

  
1298 1189
int cpu_signal_handler(int host_signum, void *pinfo,
1299 1190
                       void *puc)
1300 1191
{
......
1311 1202
#endif
1312 1203
    pc = EIP_sig(uc);
1313 1204
    trapno = TRAP_sig(uc);
1314
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
1315
    if (trapno == 0x00 || trapno == 0x05) {
1316
        /* send division by zero or bound exception */
1317
        cpu_send_trap(pc, trapno, uc);
1318
        return 1;
1319
    } else
1320
#endif
1321
        return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1322
                                 trapno == 0xe ?
1323
                                 (ERROR_sig(uc) >> 1) & 1 : 0,
1324
                                 &uc->uc_sigmask, puc);
1205
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1206
                             trapno == 0xe ?
1207
                             (ERROR_sig(uc) >> 1) & 1 : 0,
1208
                             &uc->uc_sigmask, puc);
1325 1209
}
1326 1210

  
1327 1211
#elif defined(__x86_64__)
b/darwin-user/main.c
757 757
           "-s size      set the stack size in bytes (default=%ld)\n"
758 758
           "\n"
759 759
           "debug options:\n"
760
#ifdef USE_CODE_COPY
761
           "-no-code-copy   disable code copy acceleration\n"
762
#endif
763 760
           "-d options   activate log (logfile='%s')\n"
764 761
           "-g wait for gdb on port 1234\n"
765 762
           "-p pagesize  set the host page size to 'pagesize'\n",
......
845 842
        if (!strcmp(r, "g")) {
846 843
            use_gdbstub = 1;
847 844
        } else
848
#ifdef USE_CODE_COPY
849
        if (!strcmp(r, "no-code-copy")) {
850
            code_copy_enabled = 0;
851
        } else
852
#endif
853 845
        {
854 846
            usage();
855 847
        }
b/darwin-user/signal.c
198 198

  
199 199
    /* the CPU emulator uses some host signals to detect exceptions,
200 200
       we we forward to it some signals */
201
    if (host_signum == SIGSEGV || host_signum == SIGBUS
202
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
203
        || host_signum == SIGFPE
204
#endif
205
        ) {
201
    if (host_signum == SIGSEGV || host_signum == SIGBUS) {
206 202
        if (cpu_signal_handler(host_signum, (void*)info, puc))
207 203
            return;
208 204
    }
b/exec.c
944 944
    tb->jmp_first = (TranslationBlock *)((long)tb | 2);
945 945
    tb->jmp_next[0] = NULL;
946 946
    tb->jmp_next[1] = NULL;
947
#ifdef USE_CODE_COPY
948
    tb->cflags &= ~CF_FP_USED;
949
    if (tb->cflags & CF_TB_FP_USED)
950
        tb->cflags |= CF_FP_USED;
951
#endif
952 947

  
953 948
    /* init original jump addresses */
954 949
    if (tb->tb_next_offset[0] != 0xffff)
b/linux-user/main.c
1855 1855
           "-drop-ld-preload  drop LD_PRELOAD for target process\n"
1856 1856
           "\n"
1857 1857
           "debug options:\n"
1858
#ifdef USE_CODE_COPY
1859
           "-no-code-copy   disable code copy acceleration\n"
1860
#endif
1861 1858
           "-d options   activate log (logfile=%s)\n"
1862 1859
           "-p pagesize  set the host page size to 'pagesize'\n",
1863 1860
           TARGET_ARCH,
......
1956 1953
        } else if (!strcmp(r, "drop-ld-preload")) {
1957 1954
            drop_ld_preload = 1;
1958 1955
        } else
1959
#ifdef USE_CODE_COPY
1960
        if (!strcmp(r, "no-code-copy")) {
1961
            code_copy_enabled = 0;
1962
        } else
1963
#endif
1964 1956
        {
1965 1957
            usage();
1966 1958
        }
b/linux-user/signal.c
415 415

  
416 416
    /* the CPU emulator uses some host signals to detect exceptions,
417 417
       we we forward to it some signals */
418
    if (host_signum == SIGSEGV || host_signum == SIGBUS
419
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
420
        || host_signum == SIGFPE
421
#endif
422
        ) {
418
    if (host_signum == SIGSEGV || host_signum == SIGBUS) {
423 419
        if (cpu_signal_handler(host_signum, info, puc))
424 420
            return;
425 421
    }
b/target-i386/cpu.h
46 46

  
47 47
#include "softfloat.h"
48 48

  
49
#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(__APPLE__)
50
#define USE_CODE_COPY
51
#endif
52

  
53 49
#define R_EAX 0
54 50
#define R_ECX 1
55 51
#define R_EDX 2
......
552 548

  
553 549
    uint64_t pat;
554 550

  
555
    /* temporary data for USE_CODE_COPY mode */
556
#ifdef USE_CODE_COPY
557
    uint32_t tmp0;
558
    uint32_t saved_esp;
559
    int native_fp_regs; /* if true, the FPU state is in the native CPU regs */
560
#endif
561

  
562 551
    /* exception/interrupt handling */
563 552
    jmp_buf jmp_env;
564 553
    int exception_index;
b/target-i386/helper2.c
31 31

  
32 32
//#define DEBUG_MMU
33 33

  
34
#ifdef USE_CODE_COPY
35
#include <unistd.h>
36
#include <asm/ldt.h>
37
#include <linux/unistd.h>
38
#include <linux/version.h>
39

  
40
int modify_ldt(int func, void *ptr, unsigned long bytecount)
41
{
42
	return syscall(__NR_modify_ldt, func, ptr, bytecount);
43
}
44

  
45
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
46
#define modify_ldt_ldt_s user_desc
47
#endif
48
#endif /* USE_CODE_COPY */
49

  
50 34
static struct x86_def_t *x86_cpu_def;
51 35
typedef struct x86_def_t x86_def_t;
52 36
static int cpu_x86_register (CPUX86State *env, const x86_def_t *def);
......
123 107
        inited = 1;
124 108
        optimize_flags_init();
125 109
    }
126
#ifdef USE_CODE_COPY
127
    /* testing code for code copy case */
128
    {
129
        struct modify_ldt_ldt_s ldt;
130

  
131
        ldt.entry_number = 1;
132
        ldt.base_addr = (unsigned long)env;
133
        ldt.limit = (sizeof(CPUState) + 0xfff) >> 12;
134
        ldt.seg_32bit = 1;
135
        ldt.contents = MODIFY_LDT_CONTENTS_DATA;
136
        ldt.read_exec_only = 0;
137
        ldt.limit_in_pages = 1;
138
        ldt.seg_not_present = 0;
139
        ldt.useable = 1;
140
        modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
141

  
142
        asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7));
143
    }
144
#endif
145 110
    cpu_x86_register(env, x86_cpu_def);
146 111
    cpu_reset(env);
147 112
#ifdef USE_KQEMU
......
1186 1151
    return paddr;
1187 1152
}
1188 1153
#endif /* !CONFIG_USER_ONLY */
1189

  
1190
#if defined(USE_CODE_COPY)
1191
struct fpstate {
1192
    uint16_t fpuc;
1193
    uint16_t dummy1;
1194
    uint16_t fpus;
1195
    uint16_t dummy2;
1196
    uint16_t fptag;
1197
    uint16_t dummy3;
1198

  
1199
    uint32_t fpip;
1200
    uint32_t fpcs;
1201
    uint32_t fpoo;
1202
    uint32_t fpos;
1203
    uint8_t fpregs1[8 * 10];
1204
};
1205

  
1206
void restore_native_fp_state(CPUState *env)
1207
{
1208
    int fptag, i, j;
1209
    struct fpstate fp1, *fp = &fp1;
1210

  
1211
    fp->fpuc = env->fpuc;
1212
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1213
    fptag = 0;
1214
    for (i=7; i>=0; i--) {
1215
	fptag <<= 2;
1216
	if (env->fptags[i]) {
1217
            fptag |= 3;
1218
        } else {
1219
            /* the FPU automatically computes it */
1220
        }
1221
    }
1222
    fp->fptag = fptag;
1223
    j = env->fpstt;
1224
    for(i = 0;i < 8; i++) {
1225
        memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
1226
        j = (j + 1) & 7;
1227
    }
1228
    asm volatile ("frstor %0" : "=m" (*fp));
1229
    env->native_fp_regs = 1;
1230
}
1231

  
1232
void save_native_fp_state(CPUState *env)
1233
{
1234
    int fptag, i, j;
1235
    uint16_t fpuc;
1236
    struct fpstate fp1, *fp = &fp1;
1237

  
1238
    asm volatile ("fsave %0" : : "m" (*fp));
1239
    env->fpuc = fp->fpuc;
1240
    env->fpstt = (fp->fpus >> 11) & 7;
1241
    env->fpus = fp->fpus & ~0x3800;
1242
    fptag = fp->fptag;
1243
    for(i = 0;i < 8; i++) {
1244
        env->fptags[i] = ((fptag & 3) == 3);
1245
        fptag >>= 2;
1246
    }
1247
    j = env->fpstt;
1248
    for(i = 0;i < 8; i++) {
1249
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
1250
        j = (j + 1) & 7;
1251
    }
1252
    /* we must restore the default rounding state */
1253
    /* XXX: we do not restore the exception state */
1254
    fpuc = 0x037f | (env->fpuc & (3 << 10));
1255
    asm volatile("fldcw %0" : : "m" (fpuc));
1256
    env->native_fp_regs = 0;
1257
}
1258
#endif
b/target-i386/translate.c
4888 4888
                goto illegal_op;
4889 4889
            }
4890 4890
        }
4891
#ifdef USE_CODE_COPY
4892
        s->tb->cflags |= CF_TB_FP_USED;
4893
#endif
4894 4891
        break;
4895 4892
        /************************/
4896 4893
        /* string ops */
b/tests/qruncom.c
193 193
        act.sa_sigaction = host_segv_handler;
194 194
        sigaction(SIGSEGV, &act, NULL);
195 195
        sigaction(SIGBUS, &act, NULL);
196
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
197
        sigaction(SIGFPE, &act, NULL);
198
#endif
199 196
    }
200 197

  
201 198
    //    cpu_set_log(CPU_LOG_TB_IN_ASM | CPU_LOG_TB_OUT_ASM | CPU_LOG_EXEC);
b/translate-all.c
144 144
    uint8_t *gen_code_buf;
145 145
    int gen_code_size;
146 146

  
147
#ifdef USE_CODE_COPY
148
    if (code_copy_enabled &&
149
        cpu_gen_code_copy(env, tb, max_code_size, &gen_code_size) == 0) {
150
        /* nothing more to do */
151
    } else
152
#endif
153
    {
154
        if (gen_intermediate_code(env, tb) < 0)
155
            return -1;
156

  
157
        /* generate machine code */
158
        tb->tb_next_offset[0] = 0xffff;
159
        tb->tb_next_offset[1] = 0xffff;
160
        gen_code_buf = tb->tc_ptr;
147
    if (gen_intermediate_code(env, tb) < 0)
148
        return -1;
149
    
150
    /* generate machine code */
151
    tb->tb_next_offset[0] = 0xffff;
152
    tb->tb_next_offset[1] = 0xffff;
153
    gen_code_buf = tb->tc_ptr;
161 154
#ifdef USE_DIRECT_JUMP
162
        /* the following two entries are optional (only used for string ops) */
163
        tb->tb_jmp_offset[2] = 0xffff;
164
        tb->tb_jmp_offset[3] = 0xffff;
155
    /* the following two entries are optional (only used for string ops) */
156
    tb->tb_jmp_offset[2] = 0xffff;
157
    tb->tb_jmp_offset[3] = 0xffff;
165 158
#endif
166
        dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf);
167

  
168
        gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
159
    dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf);
160
    
161
    gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
169 162
#ifdef USE_DIRECT_JUMP
170
                                    tb->tb_jmp_offset,
163
                                tb->tb_jmp_offset,
171 164
#else
172
                                    NULL,
165
                                NULL,
173 166
#endif
174
                                    gen_opc_buf, gen_opparam_buf, gen_labels);
175
    }
167
                                gen_opc_buf, gen_opparam_buf, gen_labels);
176 168
    *gen_code_size_ptr = gen_code_size;
177 169
#ifdef DEBUG_DISAS
178 170
    if (loglevel & CPU_LOG_TB_OUT_ASM) {
......
195 187
    unsigned long tc_ptr;
196 188
    uint16_t *opc_ptr;
197 189

  
198
#ifdef USE_CODE_COPY
199
    if (tb->cflags & CF_CODE_COPY) {
200
        return cpu_restore_state_copy(tb, env, searched_pc, puc);
201
    }
202
#endif
203 190
    if (gen_intermediate_code_pc(env, tb) < 0)
204 191
        return -1;
205 192

  
b/vl.c
1222 1222
    /* timer signal */
1223 1223
    sigfillset(&act.sa_mask);
1224 1224
    act.sa_flags = 0;
1225
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
1226
    act.sa_flags |= SA_ONSTACK;
1227
#endif
1228 1225
    act.sa_handler = host_alarm_handler;
1229 1226

  
1230 1227
    sigaction(SIGIO, &act, NULL);
......
1322 1319

  
1323 1320
    sigfillset(&act.sa_mask);
1324 1321
    act.sa_flags = 0;
1325
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
1326
    act.sa_flags |= SA_ONSTACK;
1327
#endif
1328 1322
    act.sa_handler = host_alarm_handler;
1329 1323

  
1330 1324
    sigaction(SIGALRM, &act, NULL);
......
1399 1393
    /* timer signal */
1400 1394
    sigfillset(&act.sa_mask);
1401 1395
    act.sa_flags = 0;
1402
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
1403
    act.sa_flags |= SA_ONSTACK;
1404
#endif
1405 1396
    act.sa_handler = host_alarm_handler;
1406 1397

  
1407 1398
    sigaction(SIGALRM, &act, NULL);
......
7093 7084
           "-kernel-kqemu   enable KQEMU full virtualization (default is user mode only)\n"
7094 7085
           "-no-kqemu       disable KQEMU kernel module usage\n"
7095 7086
#endif
7096
#ifdef USE_CODE_COPY
7097
           "-no-code-copy   disable code copy acceleration\n"
7098
#endif
7099 7087
#ifdef TARGET_I386
7100 7088
           "-std-vga        simulate a standard VGA card with VESA Bochs Extensions\n"
7101 7089
           "                (default is CL-GD5446 PCI VGA)\n"
......
7324 7312
    { NULL },
7325 7313
};
7326 7314

  
7327
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
7328

  
7329
/* this stack is only used during signal handling */
7330
#define SIGNAL_STACK_SIZE 32768
7331

  
7332
static uint8_t *signal_stack;
7333

  
7334
#endif
7335

  
7336 7315
/* password input */
7337 7316

  
7338 7317
int qemu_key_check(BlockDriverState *bs, const char *name)

Also available in: Unified diff