Annotation of qemu/translate-all.c, revision 1.1.1.4

1.1       root        1: /*
                      2:  *  Host code generation
1.1.1.4 ! root        3:  *
1.1       root        4:  *  Copyright (c) 2003 Fabrice Bellard
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, write to the Free Software
                     18:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     19:  */
                     20: #include <stdarg.h>
                     21: #include <stdlib.h>
                     22: #include <stdio.h>
                     23: #include <string.h>
                     24: #include <inttypes.h>
                     25: 
                     26: #include "config.h"
                     27: 
                     28: #define NO_CPU_IO_DEFS
                     29: #include "cpu.h"
                     30: #include "exec-all.h"
                     31: #include "disas.h"
                     32: 
                     33: extern int dyngen_code(uint8_t *gen_code_buf,
                     34:                        uint16_t *label_offsets, uint16_t *jmp_offsets,
                     35:                        const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels);
                     36: 
                     37: enum {
                     38: #define DEF(s, n, copy_size) INDEX_op_ ## s,
                     39: #include "opc.h"
                     40: #undef DEF
                     41:     NB_OPS,
                     42: };
                     43: 
                     44: uint16_t gen_opc_buf[OPC_BUF_SIZE];
                     45: uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
                     46: long gen_labels[OPC_BUF_SIZE];
                     47: int nb_gen_labels;
                     48: 
                     49: target_ulong gen_opc_pc[OPC_BUF_SIZE];
                     50: uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
                     51: #if defined(TARGET_I386)
                     52: uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
                     53: #elif defined(TARGET_SPARC)
                     54: target_ulong gen_opc_npc[OPC_BUF_SIZE];
                     55: target_ulong gen_opc_jump_pc[2];
1.1.1.4 ! root       56: #elif defined(TARGET_MIPS) || defined(TARGET_SH4)
1.1.1.2   root       57: uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1.1       root       58: #endif
                     59: 
                     60: int code_copy_enabled = 1;
                     61: 
                     62: #ifdef DEBUG_DISAS
                     63: static const char *op_str[] = {
                     64: #define DEF(s, n, copy_size) #s,
                     65: #include "opc.h"
                     66: #undef DEF
                     67: };
                     68: 
                     69: static uint8_t op_nb_args[] = {
                     70: #define DEF(s, n, copy_size) n,
                     71: #include "opc.h"
                     72: #undef DEF
                     73: };
                     74: 
                     75: static const unsigned short opc_copy_size[] = {
                     76: #define DEF(s, n, copy_size) copy_size,
                     77: #include "opc.h"
                     78: #undef DEF
                     79: };
                     80: 
                     81: void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
                     82: {
                     83:     const uint16_t *opc_ptr;
                     84:     const uint32_t *opparam_ptr;
                     85:     int c, n, i;
                     86: 
                     87:     opc_ptr = opc_buf;
                     88:     opparam_ptr = opparam_buf;
                     89:     for(;;) {
                     90:         c = *opc_ptr++;
                     91:         n = op_nb_args[c];
1.1.1.4 ! root       92:         fprintf(logfile, "0x%04x: %s",
1.1       root       93:                 (int)(opc_ptr - opc_buf - 1), op_str[c]);
                     94:         for(i = 0; i < n; i++) {
                     95:             fprintf(logfile, " 0x%x", opparam_ptr[i]);
                     96:         }
                     97:         fprintf(logfile, "\n");
                     98:         if (c == INDEX_op_end)
                     99:             break;
                    100:         opparam_ptr += n;
                    101:     }
                    102: }
                    103: 
                    104: #endif
                    105: 
                    106: /* compute label info */
                    107: static void dyngen_labels(long *gen_labels, int nb_gen_labels,
                    108:                           uint8_t *gen_code_buf, const uint16_t *opc_buf)
                    109: {
                    110:     uint8_t *gen_code_ptr;
                    111:     int c, i;
                    112:     unsigned long gen_code_addr[OPC_BUF_SIZE];
1.1.1.4 ! root      113: 
1.1       root      114:     if (nb_gen_labels == 0)
                    115:         return;
                    116:     /* compute the address of each op code */
1.1.1.4 ! root      117: 
1.1       root      118:     gen_code_ptr = gen_code_buf;
                    119:     i = 0;
                    120:     for(;;) {
                    121:         c = opc_buf[i];
                    122:         gen_code_addr[i] =(unsigned long)gen_code_ptr;
                    123:         if (c == INDEX_op_end)
                    124:             break;
                    125:         gen_code_ptr += opc_copy_size[c];
                    126:         i++;
                    127:     }
1.1.1.4 ! root      128: 
1.1       root      129:     /* compute the address of each label */
                    130:     for(i = 0; i < nb_gen_labels; i++) {
                    131:         gen_labels[i] = gen_code_addr[gen_labels[i]];
                    132:     }
                    133: }
                    134: 
1.1.1.4 ! root      135: unsigned long code_gen_max_block_size(void)
        !           136: {
        !           137:     static unsigned long max;
        !           138: 
        !           139:     if (max == 0) {
        !           140: #define DEF(s, n, copy_size) max = copy_size > max? copy_size : max;
        !           141: #include "opc.h"
        !           142: #undef DEF
        !           143:         max *= OPC_MAX_SIZE;
        !           144:     }
        !           145: 
        !           146:     return max;
        !           147: }
        !           148: 
1.1       root      149: /* return non zero if the very first instruction is invalid so that
1.1.1.4 ! root      150:    the virtual CPU can trigger an exception.
1.1       root      151: 
                    152:    '*gen_code_size_ptr' contains the size of the generated code (host
                    153:    code).
                    154: */
1.1.1.4 ! root      155: int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
1.1       root      156: {
                    157:     uint8_t *gen_code_buf;
                    158:     int gen_code_size;
                    159: 
1.1.1.4 ! root      160:     if (gen_intermediate_code(env, tb) < 0)
        !           161:         return -1;
        !           162:     
        !           163:     /* generate machine code */
        !           164:     tb->tb_next_offset[0] = 0xffff;
        !           165:     tb->tb_next_offset[1] = 0xffff;
        !           166:     gen_code_buf = tb->tc_ptr;
1.1       root      167: #ifdef USE_DIRECT_JUMP
1.1.1.4 ! root      168:     /* the following two entries are optional (only used for string ops) */
        !           169:     tb->tb_jmp_offset[2] = 0xffff;
        !           170:     tb->tb_jmp_offset[3] = 0xffff;
1.1       root      171: #endif
1.1.1.4 ! root      172:     dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf);
        !           173:     
        !           174:     gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
1.1       root      175: #ifdef USE_DIRECT_JUMP
1.1.1.4 ! root      176:                                 tb->tb_jmp_offset,
1.1       root      177: #else
1.1.1.4 ! root      178:                                 NULL,
1.1       root      179: #endif
1.1.1.4 ! root      180:                                 gen_opc_buf, gen_opparam_buf, gen_labels);
1.1       root      181:     *gen_code_size_ptr = gen_code_size;
                    182: #ifdef DEBUG_DISAS
                    183:     if (loglevel & CPU_LOG_TB_OUT_ASM) {
                    184:         fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
                    185:         disas(logfile, tb->tc_ptr, *gen_code_size_ptr);
                    186:         fprintf(logfile, "\n");
                    187:         fflush(logfile);
                    188:     }
                    189: #endif
                    190:     return 0;
                    191: }
                    192: 
1.1.1.4 ! root      193: /* The cpu state corresponding to 'searched_pc' is restored.
1.1       root      194:  */
1.1.1.4 ! root      195: int cpu_restore_state(TranslationBlock *tb,
1.1       root      196:                       CPUState *env, unsigned long searched_pc,
                    197:                       void *puc)
                    198: {
                    199:     int j, c;
                    200:     unsigned long tc_ptr;
                    201:     uint16_t *opc_ptr;
                    202: 
                    203:     if (gen_intermediate_code_pc(env, tb) < 0)
                    204:         return -1;
1.1.1.4 ! root      205: 
1.1       root      206:     /* find opc index corresponding to search_pc */
                    207:     tc_ptr = (unsigned long)tb->tc_ptr;
                    208:     if (searched_pc < tc_ptr)
                    209:         return -1;
                    210:     j = 0;
                    211:     opc_ptr = gen_opc_buf;
                    212:     for(;;) {
                    213:         c = *opc_ptr;
                    214:         if (c == INDEX_op_end)
                    215:             return -1;
                    216:         tc_ptr += opc_copy_size[c];
                    217:         if (searched_pc < tc_ptr)
                    218:             break;
                    219:         opc_ptr++;
                    220:     }
                    221:     j = opc_ptr - gen_opc_buf;
                    222:     /* now find start of instruction before */
                    223:     while (gen_opc_instr_start[j] == 0)
                    224:         j--;
                    225: #if defined(TARGET_I386)
                    226:     {
                    227:         int cc_op;
                    228: #ifdef DEBUG_DISAS
                    229:         if (loglevel & CPU_LOG_TB_OP) {
                    230:             int i;
                    231:             fprintf(logfile, "RESTORE:\n");
                    232:             for(i=0;i<=j; i++) {
                    233:                 if (gen_opc_instr_start[i]) {
                    234:                     fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
                    235:                 }
                    236:             }
1.1.1.4 ! root      237:             fprintf(logfile, "spc=0x%08lx j=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
        !           238:                     searched_pc, j, gen_opc_pc[j] - tb->cs_base,
1.1       root      239:                     (uint32_t)tb->cs_base);
                    240:         }
                    241: #endif
                    242:         env->eip = gen_opc_pc[j] - tb->cs_base;
                    243:         cc_op = gen_opc_cc_op[j];
                    244:         if (cc_op != CC_OP_DYNAMIC)
                    245:             env->cc_op = cc_op;
                    246:     }
                    247: #elif defined(TARGET_ARM)
                    248:     env->regs[15] = gen_opc_pc[j];
                    249: #elif defined(TARGET_SPARC)
                    250:     {
                    251:         target_ulong npc;
                    252:         env->pc = gen_opc_pc[j];
                    253:         npc = gen_opc_npc[j];
                    254:         if (npc == 1) {
                    255:             /* dynamic NPC: already stored */
                    256:         } else if (npc == 2) {
1.1.1.4 ! root      257:             target_ulong t2 = (target_ulong)(unsigned long)puc;
1.1       root      258:             /* jump PC: use T2 and the jump targets of the translation */
1.1.1.4 ! root      259:             if (t2)
1.1       root      260:                 env->npc = gen_opc_jump_pc[0];
                    261:             else
                    262:                 env->npc = gen_opc_jump_pc[1];
                    263:         } else {
                    264:             env->npc = npc;
                    265:         }
                    266:     }
                    267: #elif defined(TARGET_PPC)
                    268:     {
                    269:         int type;
                    270:         /* for PPC, we need to look at the micro operation to get the
                    271:            access type */
                    272:         env->nip = gen_opc_pc[j];
                    273:         switch(c) {
                    274: #if defined(CONFIG_USER_ONLY)
                    275: #define CASE3(op)\
                    276:         case INDEX_op_ ## op ## _raw
                    277: #else
                    278: #define CASE3(op)\
                    279:         case INDEX_op_ ## op ## _user:\
1.1.1.4 ! root      280:         case INDEX_op_ ## op ## _kernel:\
        !           281:         case INDEX_op_ ## op ## _hypv
1.1       root      282: #endif
1.1.1.4 ! root      283: 
1.1       root      284:         CASE3(stfd):
                    285:         CASE3(stfs):
                    286:         CASE3(lfd):
                    287:         CASE3(lfs):
                    288:             type = ACCESS_FLOAT;
                    289:             break;
                    290:         CASE3(lwarx):
                    291:             type = ACCESS_RES;
                    292:             break;
                    293:         CASE3(stwcx):
                    294:             type = ACCESS_RES;
                    295:             break;
                    296:         CASE3(eciwx):
                    297:         CASE3(ecowx):
                    298:             type = ACCESS_EXT;
                    299:             break;
                    300:         default:
                    301:             type = ACCESS_INT;
                    302:             break;
                    303:         }
                    304:         env->access_type = type;
                    305:     }
1.1.1.3   root      306: #elif defined(TARGET_M68K)
                    307:     env->pc = gen_opc_pc[j];
1.1       root      308: #elif defined(TARGET_MIPS)
1.1.1.4 ! root      309:     env->PC[env->current_tc] = gen_opc_pc[j];
1.1.1.2   root      310:     env->hflags &= ~MIPS_HFLAG_BMASK;
                    311:     env->hflags |= gen_opc_hflags[j];
1.1.1.4 ! root      312: #elif defined(TARGET_ALPHA)
        !           313:     env->pc = gen_opc_pc[j];
        !           314: #elif defined(TARGET_SH4)
        !           315:     env->pc = gen_opc_pc[j];
        !           316:     env->flags = gen_opc_hflags[j];
1.1       root      317: #endif
                    318:     return 0;
                    319: }

unix.superglobalmegacorp.com