Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 1 | /* |
| 2 | * QEMU HPPA CPU |
| 3 | * |
| 4 | * Copyright (c) 2016 Richard Henderson <rth@twiddle.net> |
| 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" |
Markus Armbruster | 0442428 | 2019-04-17 21:17:57 +0200 | [diff] [blame] | 23 | #include "qemu/qemu-print.h" |
Philippe Mathieu-Daudé | b8012ec | 2022-02-07 09:27:54 +0100 | [diff] [blame] | 24 | #include "qemu/timer.h" |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 25 | #include "cpu.h" |
Markus Armbruster | 0b8fa32 | 2019-05-23 16:35:07 +0200 | [diff] [blame] | 26 | #include "qemu/module.h" |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 27 | #include "exec/exec-all.h" |
Alex Bennée | 24f91e8 | 2018-01-19 18:24:22 +0000 | [diff] [blame] | 28 | #include "fpu/softfloat.h" |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 29 | |
| 30 | |
| 31 | static void hppa_cpu_set_pc(CPUState *cs, vaddr value) |
| 32 | { |
| 33 | HPPACPU *cpu = HPPA_CPU(cs); |
| 34 | |
| 35 | cpu->env.iaoq_f = value; |
| 36 | cpu->env.iaoq_b = value + 4; |
| 37 | } |
| 38 | |
Richard Henderson | 04a37d4 | 2020-10-29 12:30:01 -0700 | [diff] [blame] | 39 | static void hppa_cpu_synchronize_from_tb(CPUState *cs, |
| 40 | const TranslationBlock *tb) |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 41 | { |
| 42 | HPPACPU *cpu = HPPA_CPU(cs); |
| 43 | |
Richard Henderson | c301f34 | 2017-10-21 22:53:35 -0700 | [diff] [blame] | 44 | #ifdef CONFIG_USER_ONLY |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 45 | cpu->env.iaoq_f = tb->pc; |
| 46 | cpu->env.iaoq_b = tb->cs_base; |
Richard Henderson | c301f34 | 2017-10-21 22:53:35 -0700 | [diff] [blame] | 47 | #else |
| 48 | /* Recover the IAOQ values from the GVA + PRIV. */ |
| 49 | uint32_t priv = (tb->flags >> TB_FLAG_PRIV_SHIFT) & 3; |
| 50 | target_ulong cs_base = tb->cs_base; |
| 51 | target_ulong iasq_f = cs_base & ~0xffffffffull; |
| 52 | int32_t diff = cs_base; |
| 53 | |
| 54 | cpu->env.iasq_f = iasq_f; |
| 55 | cpu->env.iaoq_f = (tb->pc & ~iasq_f) + priv; |
| 56 | if (diff) { |
| 57 | cpu->env.iaoq_b = cpu->env.iaoq_f + diff; |
| 58 | } |
| 59 | #endif |
| 60 | |
Richard Henderson | 3d68ee7 | 2017-10-09 10:17:24 -0700 | [diff] [blame] | 61 | cpu->env.psw_n = (tb->flags & PSW_N) != 0; |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 62 | } |
| 63 | |
Richard Henderson | 4f5f254 | 2017-12-28 17:36:45 -0800 | [diff] [blame] | 64 | static bool hppa_cpu_has_work(CPUState *cs) |
| 65 | { |
Helge Deller | 4a4554c | 2022-01-05 23:09:04 +0100 | [diff] [blame] | 66 | return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); |
Richard Henderson | 4f5f254 | 2017-12-28 17:36:45 -0800 | [diff] [blame] | 67 | } |
| 68 | |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 69 | static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info) |
| 70 | { |
| 71 | info->mach = bfd_mach_hppa20; |
| 72 | info->print_insn = print_insn_hppa; |
| 73 | } |
| 74 | |
Claudio Fontana | 8535dd7 | 2021-02-04 17:39:19 +0100 | [diff] [blame] | 75 | #ifndef CONFIG_USER_ONLY |
Richard Henderson | fa947a6 | 2021-07-29 10:45:10 -1000 | [diff] [blame] | 76 | static void QEMU_NORETURN |
| 77 | hppa_cpu_do_unaligned_access(CPUState *cs, vaddr addr, |
| 78 | MMUAccessType access_type, int mmu_idx, |
| 79 | uintptr_t retaddr) |
Richard Henderson | 08aec8b | 2017-10-29 16:31:08 +0100 | [diff] [blame] | 80 | { |
| 81 | HPPACPU *cpu = HPPA_CPU(cs); |
| 82 | CPUHPPAState *env = &cpu->env; |
| 83 | |
| 84 | cs->exception_index = EXCP_UNALIGN; |
| 85 | if (env->psw & PSW_Q) { |
| 86 | /* ??? Needs tweaking for hppa64. */ |
| 87 | env->cr[CR_IOR] = addr; |
| 88 | env->cr[CR_ISR] = addr >> 32; |
| 89 | } |
| 90 | |
| 91 | cpu_loop_exit_restore(cs, retaddr); |
| 92 | } |
Claudio Fontana | 8535dd7 | 2021-02-04 17:39:19 +0100 | [diff] [blame] | 93 | #endif /* CONFIG_USER_ONLY */ |
Richard Henderson | 08aec8b | 2017-10-29 16:31:08 +0100 | [diff] [blame] | 94 | |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 95 | static void hppa_cpu_realizefn(DeviceState *dev, Error **errp) |
| 96 | { |
| 97 | CPUState *cs = CPU(dev); |
| 98 | HPPACPUClass *acc = HPPA_CPU_GET_CLASS(dev); |
| 99 | Error *local_err = NULL; |
| 100 | |
| 101 | cpu_exec_realizefn(cs, &local_err); |
| 102 | if (local_err != NULL) { |
| 103 | error_propagate(errp, local_err); |
| 104 | return; |
| 105 | } |
| 106 | |
| 107 | qemu_init_vcpu(cs); |
| 108 | acc->parent_realize(dev, errp); |
Richard Henderson | 49c29d6 | 2017-12-28 17:50:14 -0800 | [diff] [blame] | 109 | |
| 110 | #ifndef CONFIG_USER_ONLY |
| 111 | { |
| 112 | HPPACPU *cpu = HPPA_CPU(cs); |
| 113 | cpu->alarm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, |
| 114 | hppa_cpu_alarm_timer, cpu); |
| 115 | } |
| 116 | #endif |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 117 | } |
| 118 | |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 119 | static void hppa_cpu_initfn(Object *obj) |
| 120 | { |
| 121 | CPUState *cs = CPU(obj); |
| 122 | HPPACPU *cpu = HPPA_CPU(obj); |
| 123 | CPUHPPAState *env = &cpu->env; |
| 124 | |
Richard Henderson | 7506ed9 | 2019-03-28 11:26:22 -1000 | [diff] [blame] | 125 | cpu_set_cpustate_pointers(cpu); |
Richard Henderson | 1a19da0 | 2017-10-11 13:19:11 -0700 | [diff] [blame] | 126 | cs->exception_index = -1; |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 127 | cpu_hppa_loaded_fr0(env); |
Richard Henderson | 1a19da0 | 2017-10-11 13:19:11 -0700 | [diff] [blame] | 128 | cpu_hppa_put_psw(env, PSW_W); |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 129 | } |
| 130 | |
Igor Mammedov | 8fc24ad | 2017-08-24 18:31:33 +0200 | [diff] [blame] | 131 | static ObjectClass *hppa_cpu_class_by_name(const char *cpu_model) |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 132 | { |
Igor Mammedov | 8fc24ad | 2017-08-24 18:31:33 +0200 | [diff] [blame] | 133 | return object_class_by_name(TYPE_HPPA_CPU); |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 134 | } |
| 135 | |
Philippe Mathieu-Daudé | 8b80bd2 | 2021-05-17 12:51:31 +0200 | [diff] [blame] | 136 | #ifndef CONFIG_USER_ONLY |
| 137 | #include "hw/core/sysemu-cpu-ops.h" |
| 138 | |
| 139 | static const struct SysemuCPUOps hppa_sysemu_ops = { |
Philippe Mathieu-Daudé | 08928c6 | 2021-05-17 12:51:37 +0200 | [diff] [blame] | 140 | .get_phys_page_debug = hppa_cpu_get_phys_page_debug, |
Philippe Mathieu-Daudé | 8b80bd2 | 2021-05-17 12:51:31 +0200 | [diff] [blame] | 141 | }; |
| 142 | #endif |
| 143 | |
Claudio Fontana | 7827168 | 2021-02-04 17:39:23 +0100 | [diff] [blame] | 144 | #include "hw/core/tcg-cpu-ops.h" |
| 145 | |
Richard Henderson | 1190655 | 2021-02-27 15:21:17 -0800 | [diff] [blame] | 146 | static const struct TCGCPUOps hppa_tcg_ops = { |
Claudio Fontana | 7827168 | 2021-02-04 17:39:23 +0100 | [diff] [blame] | 147 | .initialize = hppa_translate_init, |
| 148 | .synchronize_from_tb = hppa_cpu_synchronize_from_tb, |
Claudio Fontana | 7827168 | 2021-02-04 17:39:23 +0100 | [diff] [blame] | 149 | |
| 150 | #ifndef CONFIG_USER_ONLY |
Richard Henderson | 860e0b9 | 2021-09-14 16:39:34 -0700 | [diff] [blame] | 151 | .tlb_fill = hppa_cpu_tlb_fill, |
Philippe Mathieu-Daudé | 68fa178 | 2021-09-11 18:54:19 +0200 | [diff] [blame] | 152 | .cpu_exec_interrupt = hppa_cpu_exec_interrupt, |
Claudio Fontana | 7827168 | 2021-02-04 17:39:23 +0100 | [diff] [blame] | 153 | .do_interrupt = hppa_cpu_do_interrupt, |
| 154 | .do_unaligned_access = hppa_cpu_do_unaligned_access, |
| 155 | #endif /* !CONFIG_USER_ONLY */ |
| 156 | }; |
| 157 | |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 158 | static void hppa_cpu_class_init(ObjectClass *oc, void *data) |
| 159 | { |
| 160 | DeviceClass *dc = DEVICE_CLASS(oc); |
| 161 | CPUClass *cc = CPU_CLASS(oc); |
| 162 | HPPACPUClass *acc = HPPA_CPU_CLASS(oc); |
| 163 | |
Philippe Mathieu-Daudé | bf85388 | 2018-01-13 23:04:12 -0300 | [diff] [blame] | 164 | device_class_set_parent_realize(dc, hppa_cpu_realizefn, |
| 165 | &acc->parent_realize); |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 166 | |
Igor Mammedov | 8fc24ad | 2017-08-24 18:31:33 +0200 | [diff] [blame] | 167 | cc->class_by_name = hppa_cpu_class_by_name; |
Richard Henderson | 4f5f254 | 2017-12-28 17:36:45 -0800 | [diff] [blame] | 168 | cc->has_work = hppa_cpu_has_work; |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 169 | cc->dump_state = hppa_cpu_dump_state; |
| 170 | cc->set_pc = hppa_cpu_set_pc; |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 171 | cc->gdb_read_register = hppa_cpu_gdb_read_register; |
| 172 | cc->gdb_write_register = hppa_cpu_gdb_write_register; |
Richard Henderson | 3c7bef0 | 2019-04-02 15:30:10 +0700 | [diff] [blame] | 173 | #ifndef CONFIG_USER_ONLY |
Richard Henderson | c643603 | 2017-11-20 11:06:04 +0100 | [diff] [blame] | 174 | dc->vmsd = &vmstate_hppa_cpu; |
Philippe Mathieu-Daudé | 8b80bd2 | 2021-05-17 12:51:31 +0200 | [diff] [blame] | 175 | cc->sysemu_ops = &hppa_sysemu_ops; |
Helge Deller | 813dff1 | 2017-10-01 22:11:45 +0200 | [diff] [blame] | 176 | #endif |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 177 | cc->disas_set_info = hppa_cpu_disas_set_info; |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 178 | cc->gdb_num_core_regs = 128; |
Claudio Fontana | 7827168 | 2021-02-04 17:39:23 +0100 | [diff] [blame] | 179 | cc->tcg_ops = &hppa_tcg_ops; |
Richard Henderson | 61766fe | 2016-12-15 11:26:14 -0800 | [diff] [blame] | 180 | } |
| 181 | |
| 182 | static const TypeInfo hppa_cpu_type_info = { |
| 183 | .name = TYPE_HPPA_CPU, |
| 184 | .parent = TYPE_CPU, |
| 185 | .instance_size = sizeof(HPPACPU), |
| 186 | .instance_init = hppa_cpu_initfn, |
| 187 | .abstract = false, |
| 188 | .class_size = sizeof(HPPACPUClass), |
| 189 | .class_init = hppa_cpu_class_init, |
| 190 | }; |
| 191 | |
| 192 | static void hppa_cpu_register_types(void) |
| 193 | { |
| 194 | type_register_static(&hppa_cpu_type_info); |
| 195 | } |
| 196 | |
| 197 | type_init(hppa_cpu_register_types) |