From 4abbc2b1630eb398fc20b3fd290877f9afc4abb7 Mon Sep 17 00:00:00 2001 From: fridtjof Date: Fri, 5 Dec 2025 12:48:56 +0100 Subject: [PATCH] wip --- hw/cr16c/meson.build | 1 + hw/cr16c/sc14480.c | 67 ++++++++++++++++++++++++++++++++++++++++ hw/cr16c/sc14480.h | 30 ++++++++++++++++++ hw/cr16c/virt.c | 36 +++++++++++++++++++++ target/cr16c/cpu.c | 43 ++++++++++++++++++++++++++ target/cr16c/insn.decode | 2 ++ 6 files changed, 179 insertions(+) create mode 100644 hw/cr16c/sc14480.c create mode 100644 hw/cr16c/sc14480.h diff --git a/hw/cr16c/meson.build b/hw/cr16c/meson.build index 43bb8b3e6f..e956fa0326 100644 --- a/hw/cr16c/meson.build +++ b/hw/cr16c/meson.build @@ -1,6 +1,7 @@ cr16c_ss = ss.source_set() cr16c_ss.add(files('virt.c')) cr16c_ss.add(files('sc14461.c')) +cr16c_ss.add(files('sc14480.c')) cr16c_ss.add(files('de410.c')) cr16c_ss.add(files('boot.c')) hw_arch += {'cr16c': cr16c_ss} diff --git a/hw/cr16c/sc14480.c b/hw/cr16c/sc14480.c new file mode 100644 index 0000000000..ef0dc4f08e --- /dev/null +++ b/hw/cr16c/sc14480.c @@ -0,0 +1,67 @@ +#include "sc14480.h" +#include "cpu-qom.h" +#include "system/address-spaces.h" +#include "hw/core/cpu.h" +#include "hw/cr16c/boot.h" +#include "qapi/error.h" +#include "qemu/datadir.h" +#include "qemu/units.h" + + +static void sc14480_realize(DeviceState* dev, Error** errp) +{ + SC14480McuState* s = SC14480_MCU(dev); + + object_initialize_child(OBJECT(dev), "cpu", &s->cpu, TYPE_CR16C_CPU); + object_property_set_bool(OBJECT(&s->cpu), "realized", true, &error_abort); + + memory_region_init_ram(&s->non_shared_ram_or_icache, OBJECT(dev), "non_shared_ram_or_icache", 24*KiB, &error_fatal); + memory_region_init_ram(&s->non_shared_ram_or_dcache, OBJECT(dev), "non_shared_ram_or_dcache", 8*KiB, &error_fatal); + memory_region_init_ram(&s->shared_int_ram, OBJECT(dev), "shared_int_ram", 64*KiB, &error_fatal); + memory_region_init_rom(&s->boot_rom, OBJECT(dev), "boot_rom", 2*KiB, &error_fatal); + memory_region_add_subregion(get_system_memory(), 0x00000, &s->non_shared_ram_or_icache); + memory_region_add_subregion(get_system_memory(), 0x08000, &s->non_shared_ram_or_dcache); + memory_region_add_subregion(get_system_memory(), 0x10000, &s->shared_int_ram); + memory_region_add_subregion(get_system_memory(), 0xFEF00, &s->boot_rom); + + char* bios_path = qemu_find_file(QEMU_FILE_TYPE_BIOS, "sc14480-bios.img"); + if (!cr16c_load_firmware(&s->cpu, &s->boot_rom, bios_path)) { + exit(1); + } +} + +static void sc14480_reset_hold(Object *obj, ResetType type) { + SC14480McuClass* mcu_class = SC14480_MCU_GET_CLASS(obj); + SC14480McuState* mcu_state = SC14480_MCU(obj); + CR16CCPU* cpu = &mcu_state->cpu; + CPUState* cpu_state = CPU(cpu); + + if (mcu_class->parent_phases.hold) { + mcu_class->parent_phases.hold(obj, type); + } + + cpu_reset(cpu_state); + cpu_set_pc(cpu_state, 0xFEF00); +} + +static void sc14480_class_init(ObjectClass* oc, const void* data) +{ + DeviceClass* dc = DEVICE_CLASS(oc); + SC14480McuClass* sc14480 = SC14480_MCU_CLASS(oc); + ResettableClass *rc = RESETTABLE_CLASS(oc); + + resettable_class_set_parent_phases(rc, NULL, sc14480_reset_hold, NULL, &sc14480->parent_phases); + + dc->realize = sc14480_realize; +} + +static const TypeInfo sc14480_mcu_types[] = { + { + .name = TYPE_SC14480_MCU, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SC14480McuState), + .class_size = sizeof(SC14480McuClass), + .class_init = sc14480_class_init, + }, +}; +DEFINE_TYPES(sc14480_mcu_types) diff --git a/hw/cr16c/sc14480.h b/hw/cr16c/sc14480.h new file mode 100644 index 0000000000..54fad26104 --- /dev/null +++ b/hw/cr16c/sc14480.h @@ -0,0 +1,30 @@ +#ifndef HW_SC14480_H +#define HW_SC14480_H + +#include "cpu.h" +#include "hw/sysbus.h" + +#define TYPE_SC14480_MCU "SC14480" + +typedef struct SC14480McuState SC14480McuState; +DECLARE_INSTANCE_CHECKER(SC14480McuState, SC14480_MCU, TYPE_SC14480_MCU) + +struct SC14480McuState { + SysBusDevice parent_obj; + + CR16CCPU cpu; + + MemoryRegion non_shared_ram_or_icache; + MemoryRegion non_shared_ram_or_dcache; + MemoryRegion shared_int_ram; + MemoryRegion boot_rom; +}; + +typedef struct SC14480McuClass { + SysBusDeviceClass parent_class; + + ResettablePhases parent_phases; +} SC14480McuClass; +DECLARE_CLASS_CHECKERS(SC14480McuClass, SC14480_MCU, TYPE_SC14480_MCU) + +#endif /* HW_SC14480_H */ diff --git a/hw/cr16c/virt.c b/hw/cr16c/virt.c index cc52786970..4d3a375876 100644 --- a/hw/cr16c/virt.c +++ b/hw/cr16c/virt.c @@ -6,6 +6,7 @@ #include "qapi/error.h" #include "qemu/units.h" #include "qom/object.h" +#include "system/system.h" typedef struct VirtMachineState { MachineState parent_obj; @@ -22,8 +23,36 @@ typedef struct VirtMachineClass { DECLARE_OBJ_CHECKERS(VirtMachineState, VirtMachineClass, VIRT_MACHINE, TYPE_VIRT_MACHINE) +// SC14480 vectors, all with exception priority 4 +enum { + // lowest + ACCESS12_INT = 16, + KEYB_INT = 17, + DMA1_INT = 17, // secondary function with DINT + // RESERVED_INT = 18, + CT_CLASSD_INT = 19, + UART_RI_INT = 20, + DMA2_INT = 20, // secondary function with DINT + UART_TI_INT = 21, + DMA3_INT = 21, // secondary function with DINT + SPI_INT = 22, + DMA0_INT = 22, // secondary function with DINT + TIM0_INT = 23, + TIM1_INT = 24, + CLK100_INT = 25, + DIP_INT = 26, + AD_INT = 27, + SPI2_INT = 28, + DSP_INT = 29, + // RESERVED = 30, + // highest +}; +// TODO map these from qemu irqs somewhere + +DeviceState *sc144uart_create(hwaddr addr, qemu_irq irq, Chardev *chr); static void virt_init(MachineState* machine) { + VirtMachineState* m_state = VIRT_MACHINE(machine); object_initialize_child(OBJECT(machine), "cpu", &m_state->cpu, TYPE_CR16C_CPU); @@ -33,6 +62,13 @@ static void virt_init(MachineState* machine) memory_region_add_subregion(get_system_memory(), 0, &m_state->flash); create_unimplemented_device("mmio", 0xFF0000, 0xFFFBFF - 0xFF0000); + + qemu_irq pic[10]; // TODO pick a reasonable value and name it + for (int n = 0; n < 10; n++) { + pic[n] = qdev_get_gpio_in(&m_state->cpu.parent_obj.parent_obj, n); + } + (void)pic; + sc144uart_create(0xFF4900, pic[0], NULL);//serial_hd(0)); //memory_region_init_alias(&m_state->mmio_alias, NULL, "mmio_alias", &m_state->flash, 0xF0000, 0xFFFFF - 0xF0000); create_unimplemented_device("icu", 0xFFFC00, 0xFFFFFF - 0xFFFC00); // interrupt controller unit diff --git a/target/cr16c/cpu.c b/target/cr16c/cpu.c index 6e12fa0001..eb816f9d6f 100644 --- a/target/cr16c/cpu.c +++ b/target/cr16c/cpu.c @@ -137,8 +137,35 @@ static int cr16c_cpu_mmu_index(CPUState *cs, bool ifetch) return 0; } +// Priority: +// DBG > IAD > NMI > Interrupt > ISE > PSR.P = 1, some instruction suspend stuff +// interrupt dispatch vectors +#define INT_RESERVED_0 0 +#define INT_NMI 1 +#define INT_RESERVED_2 2 +#define INT_RESERVED_3 3 +#define INT_RESERVED_4 4 +#define INT_SVC 5 // Supervisor Call Trap +#define INT_DVZ 6 // Divide By Zero +#define INT_FLG 7 // Flag +#define INT_BPT 8 // Breakpoint +#define INT_TRC 9 // Trace +#define INT_UND 10 // Undefined instruction +#define INT_RESERVED_11 11 +#define INT_IAD 12 // Illegal Address +#define INT_RESERVED_13 13 +#define INT_DBG 14 // Debug +#define INT_ISE 15 // In-System Emulator +#define INT_MASKABLE_MIN 16 +#define INT_MASKABLE_MAX 127 + static bool cr16c_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { + //CPUCR16CState *env = cpu_env(cs); + + if (interrupt_request & CPU_INTERRUPT_HARD) { + + } // TODO return false; } @@ -213,6 +240,21 @@ static void cr16c_cpu_class_init(ObjectClass *oc, const void *data) cc->tcg_ops = &cr16c_tcg_ops; } +static void cr16c_cpu_set_int(void *opaque, int irq, int level) +{ + // TODO +} + +static void cr16c_cpu_initfn(Object *obj) +{ + CR16CCPU *cpu = CR16C_CPU(obj); + + /* Set the number of interrupts supported by the CPU. */ + qdev_init_gpio_in(DEVICE(cpu), cr16c_cpu_set_int, + //sizeof(cpu->env.intsrc) * 8); + 127 - 15); +} + static const TypeInfo cr16c_cpu_archs[] = { { .name = TYPE_CR16C_CPU, @@ -220,6 +262,7 @@ static const TypeInfo cr16c_cpu_archs[] = { .instance_size = sizeof(CR16CCPU), .class_size = sizeof(CR16CCPUClass), .class_init = cr16c_cpu_class_init, + .instance_init = cr16c_cpu_initfn }, }; diff --git a/target/cr16c/insn.decode b/target/cr16c/insn.decode index 76714bdb9c..9e041f4c7d 100644 --- a/target/cr16c/insn.decode +++ b/target/cr16c/insn.decode @@ -257,6 +257,8 @@ BR0 0000 11 word:1 ne:1 dest:4 src:4 JCOND 0000 1010 cond:4 ra:4 +#JAL 0000 0000 1101 .... + EXCP 0000 0000 1100 id:4 &bal dest