File:  [Qemu by Fabrice Bellard] / qemu / target-lm32 / helper.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:52:14 2018 UTC (3 years, 7 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1101, HEAD
qemu 1.1.1

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

unix.superglobalmegacorp.com