Annotation of qemu/target-lm32/helper.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  *  LatticeMico32 helper routines.
                      3:  *
                      4:  *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
                      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, see <http://www.gnu.org/licenses/>.
                     18:  */
                     19: 
                     20: #include <stdio.h>
                     21: #include <string.h>
                     22: #include <assert.h>
                     23: 
                     24: #include "config.h"
                     25: #include "cpu.h"
                     26: #include "host-utils.h"
                     27: 
                     28: int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
1.1.1.2 ! root       29:                               int mmu_idx)
1.1       root       30: {
                     31:     int prot;
                     32: 
                     33:     address &= TARGET_PAGE_MASK;
                     34:     prot = PAGE_BITS;
                     35:     if (env->flags & LM32_FLAG_IGNORE_MSB) {
                     36:         tlb_set_page(env, address, address & 0x7fffffff, prot, mmu_idx,
                     37:                 TARGET_PAGE_SIZE);
                     38:     } else {
                     39:         tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
                     40:     }
                     41: 
                     42:     return 0;
                     43: }
                     44: 
                     45: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
                     46: {
                     47:     return addr & TARGET_PAGE_MASK;
                     48: }
                     49: 
                     50: void do_interrupt(CPUState *env)
                     51: {
                     52:     qemu_log_mask(CPU_LOG_INT,
                     53:             "exception at pc=%x type=%x\n", env->pc, env->exception_index);
                     54: 
                     55:     switch (env->exception_index) {
                     56:     case EXCP_INSN_BUS_ERROR:
                     57:     case EXCP_DATA_BUS_ERROR:
                     58:     case EXCP_DIVIDE_BY_ZERO:
                     59:     case EXCP_IRQ:
                     60:     case EXCP_SYSTEMCALL:
                     61:         /* non-debug exceptions */
                     62:         env->regs[R_EA] = env->pc;
                     63:         env->ie |= (env->ie & IE_IE) ? IE_EIE : 0;
                     64:         env->ie &= ~IE_IE;
                     65:         if (env->dc & DC_RE) {
                     66:             env->pc = env->deba + (env->exception_index * 32);
                     67:         } else {
                     68:             env->pc = env->eba + (env->exception_index * 32);
                     69:         }
                     70:         log_cpu_state_mask(CPU_LOG_INT, env, 0);
                     71:         break;
                     72:     case EXCP_BREAKPOINT:
                     73:     case EXCP_WATCHPOINT:
                     74:         /* debug exceptions */
                     75:         env->regs[R_BA] = env->pc;
                     76:         env->ie |= (env->ie & IE_IE) ? IE_BIE : 0;
                     77:         env->ie &= ~IE_IE;
                     78:         env->pc = env->deba + (env->exception_index * 32);
                     79:         log_cpu_state_mask(CPU_LOG_INT, env, 0);
                     80:         break;
                     81:     default:
                     82:         cpu_abort(env, "unhandled exception type=%d\n",
                     83:                   env->exception_index);
                     84:         break;
                     85:     }
                     86: }
                     87: 
                     88: typedef struct {
                     89:     const char *name;
                     90:     uint32_t revision;
                     91:     uint8_t num_interrupts;
                     92:     uint8_t num_breakpoints;
                     93:     uint8_t num_watchpoints;
                     94:     uint32_t features;
                     95: } LM32Def;
                     96: 
                     97: static const LM32Def lm32_defs[] = {
                     98:     {
                     99:         .name = "lm32-basic",
                    100:         .revision = 3,
                    101:         .num_interrupts = 32,
                    102:         .num_breakpoints = 4,
                    103:         .num_watchpoints = 4,
                    104:         .features = (LM32_FEATURE_SHIFT
                    105:                      | LM32_FEATURE_SIGN_EXTEND
                    106:                      | LM32_FEATURE_CYCLE_COUNT),
                    107:     },
                    108:     {
                    109:         .name = "lm32-standard",
                    110:         .revision = 3,
                    111:         .num_interrupts = 32,
                    112:         .num_breakpoints = 4,
                    113:         .num_watchpoints = 4,
                    114:         .features = (LM32_FEATURE_MULTIPLY
                    115:                      | LM32_FEATURE_DIVIDE
                    116:                      | LM32_FEATURE_SHIFT
                    117:                      | LM32_FEATURE_SIGN_EXTEND
                    118:                      | LM32_FEATURE_I_CACHE
                    119:                      | LM32_FEATURE_CYCLE_COUNT),
                    120:     },
                    121:     {
                    122:         .name = "lm32-full",
                    123:         .revision = 3,
                    124:         .num_interrupts = 32,
                    125:         .num_breakpoints = 4,
                    126:         .num_watchpoints = 4,
                    127:         .features = (LM32_FEATURE_MULTIPLY
                    128:                      | LM32_FEATURE_DIVIDE
                    129:                      | LM32_FEATURE_SHIFT
                    130:                      | LM32_FEATURE_SIGN_EXTEND
                    131:                      | LM32_FEATURE_I_CACHE
                    132:                      | LM32_FEATURE_D_CACHE
                    133:                      | LM32_FEATURE_CYCLE_COUNT),
                    134:     }
                    135: };
                    136: 
                    137: void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf)
                    138: {
                    139:     int i;
                    140: 
                    141:     cpu_fprintf(f, "Available CPUs:\n");
                    142:     for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
                    143:         cpu_fprintf(f, "  %s\n", lm32_defs[i].name);
                    144:     }
                    145: }
                    146: 
                    147: static const LM32Def *cpu_lm32_find_by_name(const char *name)
                    148: {
                    149:     int i;
                    150: 
                    151:     for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
                    152:         if (strcasecmp(name, lm32_defs[i].name) == 0) {
                    153:             return &lm32_defs[i];
                    154:         }
                    155:     }
                    156: 
                    157:     return NULL;
                    158: }
                    159: 
                    160: static uint32_t cfg_by_def(const LM32Def *def)
                    161: {
                    162:     uint32_t cfg = 0;
                    163: 
                    164:     if (def->features & LM32_FEATURE_MULTIPLY) {
                    165:         cfg |= CFG_M;
                    166:     }
                    167: 
                    168:     if (def->features & LM32_FEATURE_DIVIDE) {
                    169:         cfg |= CFG_D;
                    170:     }
                    171: 
                    172:     if (def->features & LM32_FEATURE_SHIFT) {
                    173:         cfg |= CFG_S;
                    174:     }
                    175: 
                    176:     if (def->features & LM32_FEATURE_SIGN_EXTEND) {
                    177:         cfg |= CFG_X;
                    178:     }
                    179: 
                    180:     if (def->features & LM32_FEATURE_I_CACHE) {
                    181:         cfg |= CFG_IC;
                    182:     }
                    183: 
                    184:     if (def->features & LM32_FEATURE_D_CACHE) {
                    185:         cfg |= CFG_DC;
                    186:     }
                    187: 
                    188:     if (def->features & LM32_FEATURE_CYCLE_COUNT) {
                    189:         cfg |= CFG_CC;
                    190:     }
                    191: 
                    192:     cfg |= (def->num_interrupts << CFG_INT_SHIFT);
                    193:     cfg |= (def->num_breakpoints << CFG_BP_SHIFT);
                    194:     cfg |= (def->num_watchpoints << CFG_WP_SHIFT);
                    195:     cfg |= (def->revision << CFG_REV_SHIFT);
                    196: 
                    197:     return cfg;
                    198: }
                    199: 
                    200: CPUState *cpu_lm32_init(const char *cpu_model)
                    201: {
                    202:     CPUState *env;
                    203:     const LM32Def *def;
                    204:     static int tcg_initialized;
                    205: 
                    206:     def = cpu_lm32_find_by_name(cpu_model);
                    207:     if (!def) {
                    208:         return NULL;
                    209:     }
                    210: 
1.1.1.2 ! root      211:     env = g_malloc0(sizeof(CPUState));
1.1       root      212: 
                    213:     env->features = def->features;
                    214:     env->num_bps = def->num_breakpoints;
                    215:     env->num_wps = def->num_watchpoints;
                    216:     env->cfg = cfg_by_def(def);
                    217:     env->flags = 0;
                    218: 
                    219:     cpu_exec_init(env);
                    220:     cpu_reset(env);
1.1.1.2 ! root      221:     qemu_init_vcpu(env);
1.1       root      222: 
                    223:     if (!tcg_initialized) {
                    224:         tcg_initialized = 1;
                    225:         lm32_translate_init();
                    226:     }
                    227: 
                    228:     return env;
                    229: }
                    230: 
                    231: /* Some soc ignores the MSB on the address bus. Thus creating a shadow memory
                    232:  * area. As a general rule, 0x00000000-0x7fffffff is cached, whereas
                    233:  * 0x80000000-0xffffffff is not cached and used to access IO devices. */
                    234: void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value)
                    235: {
                    236:     if (value) {
                    237:         env->flags |= LM32_FLAG_IGNORE_MSB;
                    238:     } else {
                    239:         env->flags &= ~LM32_FLAG_IGNORE_MSB;
                    240:     }
                    241: }
                    242: 
                    243: void cpu_reset(CPUState *env)
                    244: {
                    245:     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
                    246:         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
                    247:         log_cpu_state(env, 0);
                    248:     }
                    249: 
                    250:     tlb_flush(env, 1);
                    251: 
                    252:     /* reset cpu state */
                    253:     memset(env, 0, offsetof(CPULM32State, breakpoints));
                    254: }
                    255: 

unix.superglobalmegacorp.com