1*27a4a30eSYoshinori Sato /* 2*27a4a30eSYoshinori Sato * QEMU RX CPU 3*27a4a30eSYoshinori Sato * 4*27a4a30eSYoshinori Sato * Copyright (c) 2019 Yoshinori Sato 5*27a4a30eSYoshinori Sato * 6*27a4a30eSYoshinori Sato * This program is free software; you can redistribute it and/or modify it 7*27a4a30eSYoshinori Sato * under the terms and conditions of the GNU General Public License, 8*27a4a30eSYoshinori Sato * version 2 or later, as published by the Free Software Foundation. 9*27a4a30eSYoshinori Sato * 10*27a4a30eSYoshinori Sato * This program is distributed in the hope it will be useful, but WITHOUT 11*27a4a30eSYoshinori Sato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12*27a4a30eSYoshinori Sato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13*27a4a30eSYoshinori Sato * more details. 14*27a4a30eSYoshinori Sato * 15*27a4a30eSYoshinori Sato * You should have received a copy of the GNU General Public License along with 16*27a4a30eSYoshinori Sato * this program. If not, see <http://www.gnu.org/licenses/>. 17*27a4a30eSYoshinori Sato */ 18*27a4a30eSYoshinori Sato 19*27a4a30eSYoshinori Sato #include "qemu/osdep.h" 20*27a4a30eSYoshinori Sato #include "qemu/qemu-print.h" 21*27a4a30eSYoshinori Sato #include "qapi/error.h" 22*27a4a30eSYoshinori Sato #include "cpu.h" 23*27a4a30eSYoshinori Sato #include "qemu-common.h" 24*27a4a30eSYoshinori Sato #include "migration/vmstate.h" 25*27a4a30eSYoshinori Sato #include "exec/exec-all.h" 26*27a4a30eSYoshinori Sato #include "hw/loader.h" 27*27a4a30eSYoshinori Sato #include "fpu/softfloat.h" 28*27a4a30eSYoshinori Sato 29*27a4a30eSYoshinori Sato static void rx_cpu_set_pc(CPUState *cs, vaddr value) 30*27a4a30eSYoshinori Sato { 31*27a4a30eSYoshinori Sato RXCPU *cpu = RXCPU(cs); 32*27a4a30eSYoshinori Sato 33*27a4a30eSYoshinori Sato cpu->env.pc = value; 34*27a4a30eSYoshinori Sato } 35*27a4a30eSYoshinori Sato 36*27a4a30eSYoshinori Sato static void rx_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) 37*27a4a30eSYoshinori Sato { 38*27a4a30eSYoshinori Sato RXCPU *cpu = RXCPU(cs); 39*27a4a30eSYoshinori Sato 40*27a4a30eSYoshinori Sato cpu->env.pc = tb->pc; 41*27a4a30eSYoshinori Sato } 42*27a4a30eSYoshinori Sato 43*27a4a30eSYoshinori Sato static bool rx_cpu_has_work(CPUState *cs) 44*27a4a30eSYoshinori Sato { 45*27a4a30eSYoshinori Sato return cs->interrupt_request & 46*27a4a30eSYoshinori Sato (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR); 47*27a4a30eSYoshinori Sato } 48*27a4a30eSYoshinori Sato 49*27a4a30eSYoshinori Sato static void rx_cpu_reset(DeviceState *dev) 50*27a4a30eSYoshinori Sato { 51*27a4a30eSYoshinori Sato RXCPU *cpu = RXCPU(dev); 52*27a4a30eSYoshinori Sato RXCPUClass *rcc = RXCPU_GET_CLASS(cpu); 53*27a4a30eSYoshinori Sato CPURXState *env = &cpu->env; 54*27a4a30eSYoshinori Sato uint32_t *resetvec; 55*27a4a30eSYoshinori Sato 56*27a4a30eSYoshinori Sato rcc->parent_reset(dev); 57*27a4a30eSYoshinori Sato 58*27a4a30eSYoshinori Sato memset(env, 0, offsetof(CPURXState, end_reset_fields)); 59*27a4a30eSYoshinori Sato 60*27a4a30eSYoshinori Sato resetvec = rom_ptr(0xfffffffc, 4); 61*27a4a30eSYoshinori Sato if (resetvec) { 62*27a4a30eSYoshinori Sato /* In the case of kernel, it is ignored because it is not set. */ 63*27a4a30eSYoshinori Sato env->pc = ldl_p(resetvec); 64*27a4a30eSYoshinori Sato } 65*27a4a30eSYoshinori Sato rx_cpu_unpack_psw(env, 0, 1); 66*27a4a30eSYoshinori Sato env->regs[0] = env->isp = env->usp = 0; 67*27a4a30eSYoshinori Sato env->fpsw = 0; 68*27a4a30eSYoshinori Sato set_flush_to_zero(1, &env->fp_status); 69*27a4a30eSYoshinori Sato set_flush_inputs_to_zero(1, &env->fp_status); 70*27a4a30eSYoshinori Sato } 71*27a4a30eSYoshinori Sato 72*27a4a30eSYoshinori Sato static void rx_cpu_list_entry(gpointer data, gpointer user_data) 73*27a4a30eSYoshinori Sato { 74*27a4a30eSYoshinori Sato ObjectClass *oc = data; 75*27a4a30eSYoshinori Sato 76*27a4a30eSYoshinori Sato qemu_printf(" %s\n", object_class_get_name(oc)); 77*27a4a30eSYoshinori Sato } 78*27a4a30eSYoshinori Sato 79*27a4a30eSYoshinori Sato void rx_cpu_list(void) 80*27a4a30eSYoshinori Sato { 81*27a4a30eSYoshinori Sato GSList *list; 82*27a4a30eSYoshinori Sato list = object_class_get_list_sorted(TYPE_RX_CPU, false); 83*27a4a30eSYoshinori Sato qemu_printf("Available CPUs:\n"); 84*27a4a30eSYoshinori Sato g_slist_foreach(list, rx_cpu_list_entry, NULL); 85*27a4a30eSYoshinori Sato g_slist_free(list); 86*27a4a30eSYoshinori Sato } 87*27a4a30eSYoshinori Sato 88*27a4a30eSYoshinori Sato static ObjectClass *rx_cpu_class_by_name(const char *cpu_model) 89*27a4a30eSYoshinori Sato { 90*27a4a30eSYoshinori Sato ObjectClass *oc; 91*27a4a30eSYoshinori Sato char *typename; 92*27a4a30eSYoshinori Sato 93*27a4a30eSYoshinori Sato oc = object_class_by_name(cpu_model); 94*27a4a30eSYoshinori Sato if (oc != NULL && object_class_dynamic_cast(oc, TYPE_RX_CPU) != NULL && 95*27a4a30eSYoshinori Sato !object_class_is_abstract(oc)) { 96*27a4a30eSYoshinori Sato return oc; 97*27a4a30eSYoshinori Sato } 98*27a4a30eSYoshinori Sato typename = g_strdup_printf(RX_CPU_TYPE_NAME("%s"), cpu_model); 99*27a4a30eSYoshinori Sato oc = object_class_by_name(typename); 100*27a4a30eSYoshinori Sato g_free(typename); 101*27a4a30eSYoshinori Sato if (oc != NULL && object_class_is_abstract(oc)) { 102*27a4a30eSYoshinori Sato oc = NULL; 103*27a4a30eSYoshinori Sato } 104*27a4a30eSYoshinori Sato 105*27a4a30eSYoshinori Sato return oc; 106*27a4a30eSYoshinori Sato } 107*27a4a30eSYoshinori Sato 108*27a4a30eSYoshinori Sato static void rx_cpu_realize(DeviceState *dev, Error **errp) 109*27a4a30eSYoshinori Sato { 110*27a4a30eSYoshinori Sato CPUState *cs = CPU(dev); 111*27a4a30eSYoshinori Sato RXCPUClass *rcc = RXCPU_GET_CLASS(dev); 112*27a4a30eSYoshinori Sato Error *local_err = NULL; 113*27a4a30eSYoshinori Sato 114*27a4a30eSYoshinori Sato cpu_exec_realizefn(cs, &local_err); 115*27a4a30eSYoshinori Sato if (local_err != NULL) { 116*27a4a30eSYoshinori Sato error_propagate(errp, local_err); 117*27a4a30eSYoshinori Sato return; 118*27a4a30eSYoshinori Sato } 119*27a4a30eSYoshinori Sato 120*27a4a30eSYoshinori Sato qemu_init_vcpu(cs); 121*27a4a30eSYoshinori Sato cpu_reset(cs); 122*27a4a30eSYoshinori Sato 123*27a4a30eSYoshinori Sato rcc->parent_realize(dev, errp); 124*27a4a30eSYoshinori Sato } 125*27a4a30eSYoshinori Sato 126*27a4a30eSYoshinori Sato static void rx_cpu_set_irq(void *opaque, int no, int request) 127*27a4a30eSYoshinori Sato { 128*27a4a30eSYoshinori Sato RXCPU *cpu = opaque; 129*27a4a30eSYoshinori Sato CPUState *cs = CPU(cpu); 130*27a4a30eSYoshinori Sato int irq = request & 0xff; 131*27a4a30eSYoshinori Sato 132*27a4a30eSYoshinori Sato static const int mask[] = { 133*27a4a30eSYoshinori Sato [RX_CPU_IRQ] = CPU_INTERRUPT_HARD, 134*27a4a30eSYoshinori Sato [RX_CPU_FIR] = CPU_INTERRUPT_FIR, 135*27a4a30eSYoshinori Sato }; 136*27a4a30eSYoshinori Sato if (irq) { 137*27a4a30eSYoshinori Sato cpu->env.req_irq = irq; 138*27a4a30eSYoshinori Sato cpu->env.req_ipl = (request >> 8) & 0x0f; 139*27a4a30eSYoshinori Sato cpu_interrupt(cs, mask[no]); 140*27a4a30eSYoshinori Sato } else { 141*27a4a30eSYoshinori Sato cpu_reset_interrupt(cs, mask[no]); 142*27a4a30eSYoshinori Sato } 143*27a4a30eSYoshinori Sato } 144*27a4a30eSYoshinori Sato 145*27a4a30eSYoshinori Sato static void rx_cpu_disas_set_info(CPUState *cpu, disassemble_info *info) 146*27a4a30eSYoshinori Sato { 147*27a4a30eSYoshinori Sato info->mach = bfd_mach_rx; 148*27a4a30eSYoshinori Sato info->print_insn = print_insn_rx; 149*27a4a30eSYoshinori Sato } 150*27a4a30eSYoshinori Sato 151*27a4a30eSYoshinori Sato static bool rx_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, 152*27a4a30eSYoshinori Sato MMUAccessType access_type, int mmu_idx, 153*27a4a30eSYoshinori Sato bool probe, uintptr_t retaddr) 154*27a4a30eSYoshinori Sato { 155*27a4a30eSYoshinori Sato uint32_t address, physical, prot; 156*27a4a30eSYoshinori Sato 157*27a4a30eSYoshinori Sato /* Linear mapping */ 158*27a4a30eSYoshinori Sato address = physical = addr & TARGET_PAGE_MASK; 159*27a4a30eSYoshinori Sato prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; 160*27a4a30eSYoshinori Sato tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE); 161*27a4a30eSYoshinori Sato return true; 162*27a4a30eSYoshinori Sato } 163*27a4a30eSYoshinori Sato 164*27a4a30eSYoshinori Sato static void rx_cpu_init(Object *obj) 165*27a4a30eSYoshinori Sato { 166*27a4a30eSYoshinori Sato CPUState *cs = CPU(obj); 167*27a4a30eSYoshinori Sato RXCPU *cpu = RXCPU(obj); 168*27a4a30eSYoshinori Sato CPURXState *env = &cpu->env; 169*27a4a30eSYoshinori Sato 170*27a4a30eSYoshinori Sato cpu_set_cpustate_pointers(cpu); 171*27a4a30eSYoshinori Sato cs->env_ptr = env; 172*27a4a30eSYoshinori Sato qdev_init_gpio_in(DEVICE(cpu), rx_cpu_set_irq, 2); 173*27a4a30eSYoshinori Sato } 174*27a4a30eSYoshinori Sato 175*27a4a30eSYoshinori Sato static void rx_cpu_class_init(ObjectClass *klass, void *data) 176*27a4a30eSYoshinori Sato { 177*27a4a30eSYoshinori Sato DeviceClass *dc = DEVICE_CLASS(klass); 178*27a4a30eSYoshinori Sato CPUClass *cc = CPU_CLASS(klass); 179*27a4a30eSYoshinori Sato RXCPUClass *rcc = RXCPU_CLASS(klass); 180*27a4a30eSYoshinori Sato 181*27a4a30eSYoshinori Sato device_class_set_parent_realize(dc, rx_cpu_realize, 182*27a4a30eSYoshinori Sato &rcc->parent_realize); 183*27a4a30eSYoshinori Sato device_class_set_parent_reset(dc, rx_cpu_reset, 184*27a4a30eSYoshinori Sato &rcc->parent_reset); 185*27a4a30eSYoshinori Sato 186*27a4a30eSYoshinori Sato cc->class_by_name = rx_cpu_class_by_name; 187*27a4a30eSYoshinori Sato cc->has_work = rx_cpu_has_work; 188*27a4a30eSYoshinori Sato cc->do_interrupt = rx_cpu_do_interrupt; 189*27a4a30eSYoshinori Sato cc->cpu_exec_interrupt = rx_cpu_exec_interrupt; 190*27a4a30eSYoshinori Sato cc->dump_state = rx_cpu_dump_state; 191*27a4a30eSYoshinori Sato cc->set_pc = rx_cpu_set_pc; 192*27a4a30eSYoshinori Sato cc->synchronize_from_tb = rx_cpu_synchronize_from_tb; 193*27a4a30eSYoshinori Sato cc->gdb_read_register = rx_cpu_gdb_read_register; 194*27a4a30eSYoshinori Sato cc->gdb_write_register = rx_cpu_gdb_write_register; 195*27a4a30eSYoshinori Sato cc->get_phys_page_debug = rx_cpu_get_phys_page_debug; 196*27a4a30eSYoshinori Sato cc->disas_set_info = rx_cpu_disas_set_info; 197*27a4a30eSYoshinori Sato cc->tcg_initialize = rx_translate_init; 198*27a4a30eSYoshinori Sato cc->tlb_fill = rx_cpu_tlb_fill; 199*27a4a30eSYoshinori Sato 200*27a4a30eSYoshinori Sato cc->gdb_num_core_regs = 26; 201*27a4a30eSYoshinori Sato cc->gdb_core_xml_file = "rx-core.xml"; 202*27a4a30eSYoshinori Sato } 203*27a4a30eSYoshinori Sato 204*27a4a30eSYoshinori Sato static const TypeInfo rx_cpu_info = { 205*27a4a30eSYoshinori Sato .name = TYPE_RX_CPU, 206*27a4a30eSYoshinori Sato .parent = TYPE_CPU, 207*27a4a30eSYoshinori Sato .instance_size = sizeof(RXCPU), 208*27a4a30eSYoshinori Sato .instance_init = rx_cpu_init, 209*27a4a30eSYoshinori Sato .abstract = true, 210*27a4a30eSYoshinori Sato .class_size = sizeof(RXCPUClass), 211*27a4a30eSYoshinori Sato .class_init = rx_cpu_class_init, 212*27a4a30eSYoshinori Sato }; 213*27a4a30eSYoshinori Sato 214*27a4a30eSYoshinori Sato static const TypeInfo rx62n_rx_cpu_info = { 215*27a4a30eSYoshinori Sato .name = TYPE_RX62N_CPU, 216*27a4a30eSYoshinori Sato .parent = TYPE_RX_CPU, 217*27a4a30eSYoshinori Sato }; 218*27a4a30eSYoshinori Sato 219*27a4a30eSYoshinori Sato static void rx_cpu_register_types(void) 220*27a4a30eSYoshinori Sato { 221*27a4a30eSYoshinori Sato type_register_static(&rx_cpu_info); 222*27a4a30eSYoshinori Sato type_register_static(&rx62n_rx_cpu_info); 223*27a4a30eSYoshinori Sato } 224*27a4a30eSYoshinori Sato 225*27a4a30eSYoshinori Sato type_init(rx_cpu_register_types) 226