qemu/target/lm32/cpu.c
<<
>>
Prefs
   1/*
   2 * QEMU LatticeMico32 CPU
   3 *
   4 * Copyright (c) 2012 SUSE LINUX Products GmbH
   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.1 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
  18 * <http://www.gnu.org/licenses/lgpl-2.1.html>
  19 */
  20
  21#include "qemu/osdep.h"
  22#include "qapi/error.h"
  23#include "cpu.h"
  24#include "qemu-common.h"
  25
  26
  27static void lm32_cpu_set_pc(CPUState *cs, vaddr value)
  28{
  29    LM32CPU *cpu = LM32_CPU(cs);
  30
  31    cpu->env.pc = value;
  32}
  33
  34static void lm32_cpu_list_entry(gpointer data, gpointer user_data)
  35{
  36    ObjectClass *oc = data;
  37    CPUListState *s = user_data;
  38    const char *typename = object_class_get_name(oc);
  39    char *name;
  40
  41    name = g_strndup(typename, strlen(typename) - strlen(LM32_CPU_TYPE_SUFFIX));
  42    (*s->cpu_fprintf)(s->file, "  %s\n", name);
  43    g_free(name);
  44}
  45
  46
  47void lm32_cpu_list(FILE *f, fprintf_function cpu_fprintf)
  48{
  49    CPUListState s = {
  50        .file = f,
  51        .cpu_fprintf = cpu_fprintf,
  52    };
  53    GSList *list;
  54
  55    list = object_class_get_list_sorted(TYPE_LM32_CPU, false);
  56    (*cpu_fprintf)(f, "Available CPUs:\n");
  57    g_slist_foreach(list, lm32_cpu_list_entry, &s);
  58    g_slist_free(list);
  59}
  60
  61static void lm32_cpu_init_cfg_reg(LM32CPU *cpu)
  62{
  63    CPULM32State *env = &cpu->env;
  64    uint32_t cfg = 0;
  65
  66    if (cpu->features & LM32_FEATURE_MULTIPLY) {
  67        cfg |= CFG_M;
  68    }
  69
  70    if (cpu->features & LM32_FEATURE_DIVIDE) {
  71        cfg |= CFG_D;
  72    }
  73
  74    if (cpu->features & LM32_FEATURE_SHIFT) {
  75        cfg |= CFG_S;
  76    }
  77
  78    if (cpu->features & LM32_FEATURE_SIGN_EXTEND) {
  79        cfg |= CFG_X;
  80    }
  81
  82    if (cpu->features & LM32_FEATURE_I_CACHE) {
  83        cfg |= CFG_IC;
  84    }
  85
  86    if (cpu->features & LM32_FEATURE_D_CACHE) {
  87        cfg |= CFG_DC;
  88    }
  89
  90    if (cpu->features & LM32_FEATURE_CYCLE_COUNT) {
  91        cfg |= CFG_CC;
  92    }
  93
  94    cfg |= (cpu->num_interrupts << CFG_INT_SHIFT);
  95    cfg |= (cpu->num_breakpoints << CFG_BP_SHIFT);
  96    cfg |= (cpu->num_watchpoints << CFG_WP_SHIFT);
  97    cfg |= (cpu->revision << CFG_REV_SHIFT);
  98
  99    env->cfg = cfg;
 100}
 101
 102static bool lm32_cpu_has_work(CPUState *cs)
 103{
 104    return cs->interrupt_request & CPU_INTERRUPT_HARD;
 105}
 106
 107/* CPUClass::reset() */
 108static void lm32_cpu_reset(CPUState *s)
 109{
 110    LM32CPU *cpu = LM32_CPU(s);
 111    LM32CPUClass *lcc = LM32_CPU_GET_CLASS(cpu);
 112    CPULM32State *env = &cpu->env;
 113
 114    lcc->parent_reset(s);
 115
 116    /* reset cpu state */
 117    memset(env, 0, offsetof(CPULM32State, end_reset_fields));
 118
 119    lm32_cpu_init_cfg_reg(cpu);
 120}
 121
 122static void lm32_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
 123{
 124    info->mach = bfd_mach_lm32;
 125    info->print_insn = print_insn_lm32;
 126}
 127
 128static void lm32_cpu_realizefn(DeviceState *dev, Error **errp)
 129{
 130    CPUState *cs = CPU(dev);
 131    LM32CPUClass *lcc = LM32_CPU_GET_CLASS(dev);
 132    Error *local_err = NULL;
 133
 134    cpu_exec_realizefn(cs, &local_err);
 135    if (local_err != NULL) {
 136        error_propagate(errp, local_err);
 137        return;
 138    }
 139
 140    cpu_reset(cs);
 141
 142    qemu_init_vcpu(cs);
 143
 144    lcc->parent_realize(dev, errp);
 145}
 146
 147static void lm32_cpu_initfn(Object *obj)
 148{
 149    CPUState *cs = CPU(obj);
 150    LM32CPU *cpu = LM32_CPU(obj);
 151    CPULM32State *env = &cpu->env;
 152
 153    cs->env_ptr = env;
 154
 155    env->flags = 0;
 156}
 157
 158static void lm32_basic_cpu_initfn(Object *obj)
 159{
 160    LM32CPU *cpu = LM32_CPU(obj);
 161
 162    cpu->revision = 3;
 163    cpu->num_interrupts = 32;
 164    cpu->num_breakpoints = 4;
 165    cpu->num_watchpoints = 4;
 166    cpu->features = LM32_FEATURE_SHIFT
 167                  | LM32_FEATURE_SIGN_EXTEND
 168                  | LM32_FEATURE_CYCLE_COUNT;
 169}
 170
 171static void lm32_standard_cpu_initfn(Object *obj)
 172{
 173    LM32CPU *cpu = LM32_CPU(obj);
 174
 175    cpu->revision = 3;
 176    cpu->num_interrupts = 32;
 177    cpu->num_breakpoints = 4;
 178    cpu->num_watchpoints = 4;
 179    cpu->features = LM32_FEATURE_MULTIPLY
 180                  | LM32_FEATURE_DIVIDE
 181                  | LM32_FEATURE_SHIFT
 182                  | LM32_FEATURE_SIGN_EXTEND
 183                  | LM32_FEATURE_I_CACHE
 184                  | LM32_FEATURE_CYCLE_COUNT;
 185}
 186
 187static void lm32_full_cpu_initfn(Object *obj)
 188{
 189    LM32CPU *cpu = LM32_CPU(obj);
 190
 191    cpu->revision = 3;
 192    cpu->num_interrupts = 32;
 193    cpu->num_breakpoints = 4;
 194    cpu->num_watchpoints = 4;
 195    cpu->features = LM32_FEATURE_MULTIPLY
 196                  | LM32_FEATURE_DIVIDE
 197                  | LM32_FEATURE_SHIFT
 198                  | LM32_FEATURE_SIGN_EXTEND
 199                  | LM32_FEATURE_I_CACHE
 200                  | LM32_FEATURE_D_CACHE
 201                  | LM32_FEATURE_CYCLE_COUNT;
 202}
 203
 204static ObjectClass *lm32_cpu_class_by_name(const char *cpu_model)
 205{
 206    ObjectClass *oc;
 207    char *typename;
 208
 209    typename = g_strdup_printf(LM32_CPU_TYPE_NAME("%s"), cpu_model);
 210    oc = object_class_by_name(typename);
 211    g_free(typename);
 212    if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_LM32_CPU) ||
 213                       object_class_is_abstract(oc))) {
 214        oc = NULL;
 215    }
 216    return oc;
 217}
 218
 219static void lm32_cpu_class_init(ObjectClass *oc, void *data)
 220{
 221    LM32CPUClass *lcc = LM32_CPU_CLASS(oc);
 222    CPUClass *cc = CPU_CLASS(oc);
 223    DeviceClass *dc = DEVICE_CLASS(oc);
 224
 225    device_class_set_parent_realize(dc, lm32_cpu_realizefn,
 226                                    &lcc->parent_realize);
 227    lcc->parent_reset = cc->reset;
 228    cc->reset = lm32_cpu_reset;
 229
 230    cc->class_by_name = lm32_cpu_class_by_name;
 231    cc->has_work = lm32_cpu_has_work;
 232    cc->do_interrupt = lm32_cpu_do_interrupt;
 233    cc->cpu_exec_interrupt = lm32_cpu_exec_interrupt;
 234    cc->dump_state = lm32_cpu_dump_state;
 235    cc->set_pc = lm32_cpu_set_pc;
 236    cc->gdb_read_register = lm32_cpu_gdb_read_register;
 237    cc->gdb_write_register = lm32_cpu_gdb_write_register;
 238#ifdef CONFIG_USER_ONLY
 239    cc->handle_mmu_fault = lm32_cpu_handle_mmu_fault;
 240#else
 241    cc->get_phys_page_debug = lm32_cpu_get_phys_page_debug;
 242    cc->vmsd = &vmstate_lm32_cpu;
 243#endif
 244    cc->gdb_num_core_regs = 32 + 7;
 245    cc->gdb_stop_before_watchpoint = true;
 246    cc->debug_excp_handler = lm32_debug_excp_handler;
 247    cc->disas_set_info = lm32_cpu_disas_set_info;
 248    cc->tcg_initialize = lm32_translate_init;
 249}
 250
 251#define DEFINE_LM32_CPU_TYPE(cpu_model, initfn) \
 252    { \
 253        .parent = TYPE_LM32_CPU, \
 254        .name = LM32_CPU_TYPE_NAME(cpu_model), \
 255        .instance_init = initfn, \
 256    }
 257
 258static const TypeInfo lm32_cpus_type_infos[] = {
 259    { /* base class should be registered first */
 260         .name = TYPE_LM32_CPU,
 261         .parent = TYPE_CPU,
 262         .instance_size = sizeof(LM32CPU),
 263         .instance_init = lm32_cpu_initfn,
 264         .abstract = true,
 265         .class_size = sizeof(LM32CPUClass),
 266         .class_init = lm32_cpu_class_init,
 267    },
 268    DEFINE_LM32_CPU_TYPE("lm32-basic", lm32_basic_cpu_initfn),
 269    DEFINE_LM32_CPU_TYPE("lm32-standard", lm32_standard_cpu_initfn),
 270    DEFINE_LM32_CPU_TYPE("lm32-full", lm32_full_cpu_initfn),
 271};
 272
 273DEFINE_TYPES(lm32_cpus_type_infos)
 274