translate-all.c 6.5 KB
Newer Older
B
bellard 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 *  Host code generation
 * 
 *  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 "config.h"
B
bellard 已提交
27

B
bellard 已提交
28
#define NO_CPU_IO_DEFS
B
bellard 已提交
29 30
#include "cpu.h"
#include "exec-all.h"
B
bellard 已提交
31 32 33 34
#include "disas.h"

enum {
#define DEF(s, n, copy_size) INDEX_op_ ## s,
B
bellard 已提交
35
#include "opc.h"
B
bellard 已提交
36 37 38 39 40
#undef DEF
    NB_OPS,
};

#include "dyngen.h"
B
bellard 已提交
41
#include "op.h"
B
bellard 已提交
42 43 44 45 46

uint16_t gen_opc_buf[OPC_BUF_SIZE];
uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
uint32_t gen_opc_pc[OPC_BUF_SIZE];
uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
47 48 49
#if defined(TARGET_I386)
uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
#endif
B
bellard 已提交
50

B
bellard 已提交
51 52
int code_copy_enabled = 1;

B
bellard 已提交
53 54 55
#ifdef DEBUG_DISAS
static const char *op_str[] = {
#define DEF(s, n, copy_size) #s,
B
bellard 已提交
56
#include "opc.h"
B
bellard 已提交
57 58 59 60 61
#undef DEF
};

static uint8_t op_nb_args[] = {
#define DEF(s, n, copy_size) n,
B
bellard 已提交
62
#include "opc.h"
B
bellard 已提交
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
#undef DEF
};

void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
{
    const uint16_t *opc_ptr;
    const uint32_t *opparam_ptr;
    int c, n, i;

    opc_ptr = opc_buf;
    opparam_ptr = opparam_buf;
    for(;;) {
        c = *opc_ptr++;
        n = op_nb_args[c];
        fprintf(logfile, "0x%04x: %s", 
                (int)(opc_ptr - opc_buf - 1), op_str[c]);
        for(i = 0; i < n; i++) {
            fprintf(logfile, " 0x%x", opparam_ptr[i]);
        }
        fprintf(logfile, "\n");
        if (c == INDEX_op_end)
            break;
        opparam_ptr += n;
    }
}

#endif

/* return non zero if the very first instruction is invalid so that
   the virtual CPU can trigger an exception. 

   '*gen_code_size_ptr' contains the size of the generated code (host
   code).
*/
B
bellard 已提交
97
int cpu_gen_code(CPUState *env, TranslationBlock *tb,
B
bellard 已提交
98 99 100 101 102
                 int max_code_size, int *gen_code_size_ptr)
{
    uint8_t *gen_code_buf;
    int gen_code_size;

B
bellard 已提交
103 104 105 106 107 108 109 110 111
#ifdef USE_CODE_COPY
    if (code_copy_enabled &&
        cpu_gen_code_copy(env, tb, max_code_size, &gen_code_size) == 0) {
        /* nothing more to do */
    } else
#endif
    {
        if (gen_intermediate_code(env, tb) < 0)
            return -1;
B
bellard 已提交
112

B
bellard 已提交
113 114 115 116
        /* generate machine code */
        tb->tb_next_offset[0] = 0xffff;
        tb->tb_next_offset[1] = 0xffff;
        gen_code_buf = tb->tc_ptr;
117
#ifdef USE_DIRECT_JUMP
B
bellard 已提交
118 119 120
        /* the following two entries are optional (only used for string ops) */
        tb->tb_jmp_offset[2] = 0xffff;
        tb->tb_jmp_offset[3] = 0xffff;
121
#endif
B
bellard 已提交
122
        gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
B
bellard 已提交
123
#ifdef USE_DIRECT_JUMP
B
bellard 已提交
124
                                    tb->tb_jmp_offset,
B
bellard 已提交
125
#else
B
bellard 已提交
126
                                    NULL,
B
bellard 已提交
127
#endif
B
bellard 已提交
128 129
                                    gen_opc_buf, gen_opparam_buf);
    }
B
bellard 已提交
130 131
    *gen_code_size_ptr = gen_code_size;
#ifdef DEBUG_DISAS
132
    if (loglevel & CPU_LOG_TB_OUT_ASM) {
B
bellard 已提交
133
        fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
B
bellard 已提交
134
        disas(logfile, tb->tc_ptr, *gen_code_size_ptr, 1, 0);
B
bellard 已提交
135 136 137 138 139 140 141 142 143
        fprintf(logfile, "\n");
        fflush(logfile);
    }
#endif
    return 0;
}

static const unsigned short opc_copy_size[] = {
#define DEF(s, n, copy_size) copy_size,
B
bellard 已提交
144
#include "opc.h"
B
bellard 已提交
145 146 147
#undef DEF
};

148
/* The cpu state corresponding to 'searched_pc' is restored. 
B
bellard 已提交
149
 */
150
int cpu_restore_state(TranslationBlock *tb, 
B
bellard 已提交
151 152
                      CPUState *env, unsigned long searched_pc,
                      void *puc)
B
bellard 已提交
153 154 155 156 157
{
    int j, c;
    unsigned long tc_ptr;
    uint16_t *opc_ptr;

B
bellard 已提交
158 159 160 161 162
#ifdef USE_CODE_COPY
    if (tb->cflags & CF_CODE_COPY) {
        return cpu_restore_state_copy(tb, env, searched_pc, puc);
    }
#endif
B
bellard 已提交
163
    if (gen_intermediate_code_pc(env, tb) < 0)
B
bellard 已提交
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
        return -1;
    
    /* find opc index corresponding to search_pc */
    tc_ptr = (unsigned long)tb->tc_ptr;
    if (searched_pc < tc_ptr)
        return -1;
    j = 0;
    opc_ptr = gen_opc_buf;
    for(;;) {
        c = *opc_ptr;
        if (c == INDEX_op_end)
            return -1;
        tc_ptr += opc_copy_size[c];
        if (searched_pc < tc_ptr)
            break;
        opc_ptr++;
    }
    j = opc_ptr - gen_opc_buf;
    /* now find start of instruction before */
    while (gen_opc_instr_start[j] == 0)
        j--;
185 186 187
#if defined(TARGET_I386)
    {
        int cc_op;
188
#ifdef DEBUG_DISAS
189
        if (loglevel & CPU_LOG_TB_OP) {
190
            int i;
B
bellard 已提交
191
            fprintf(logfile, "RESTORE:\n");
192 193
            for(i=0;i<=j; i++) {
                if (gen_opc_instr_start[i]) {
B
bellard 已提交
194
                    fprintf(logfile, "0x%04x: 0x%08x\n", i, gen_opc_pc[i]);
195 196
                }
            }
B
bellard 已提交
197 198
            fprintf(logfile, "spc=0x%08lx j=0x%x eip=0x%lx cs_base=%lx\n", 
                    searched_pc, j, gen_opc_pc[j] - tb->cs_base, tb->cs_base);
199 200
        }
#endif
201 202 203 204 205 206 207
        env->eip = gen_opc_pc[j] - tb->cs_base;
        cc_op = gen_opc_cc_op[j];
        if (cc_op != CC_OP_DYNAMIC)
            env->cc_op = cc_op;
    }
#elif defined(TARGET_ARM)
    env->regs[15] = gen_opc_pc[j];
B
bellard 已提交
208
#elif defined(TARGET_SPARC)
B
bellard 已提交
209
    /* XXX: restore npc too */
B
bellard 已提交
210 211
    env->pc = gen_opc_pc[j];
#elif defined(TARGET_PPC)
B
bellard 已提交
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
    {
        int type;
        /* for PPC, we need to look at the micro operation to get the
           access type */
        env->nip = gen_opc_pc[j];
        switch(c) {
#if defined(CONFIG_USER_ONLY)
#define CASE3(op)\
        case INDEX_op_ ## op ## _raw
#else
#define CASE3(op)\
        case INDEX_op_ ## op ## _user:\
        case INDEX_op_ ## op ## _kernel
#endif
            
        CASE3(stfd):
        CASE3(stfs):
        CASE3(lfd):
        CASE3(lfs):
            type = ACCESS_FLOAT;
            break;
233 234 235
        CASE3(lwarx):
            type = ACCESS_RES;
            break;
B
bellard 已提交
236 237 238 239 240 241 242 243 244 245 246 247 248
        CASE3(stwcx):
            type = ACCESS_RES;
            break;
        CASE3(eciwx):
        CASE3(ecowx):
            type = ACCESS_EXT;
            break;
        default:
            type = ACCESS_INT;
            break;
        }
        env->access_type = type;
    }
249
#endif
B
bellard 已提交
250 251
    return 0;
}