This commit is contained in:
fridtjof 2025-12-05 12:48:56 +01:00
parent c37a4513c2
commit 4abbc2b163
6 changed files with 179 additions and 0 deletions

View file

@ -1,6 +1,7 @@
cr16c_ss = ss.source_set() cr16c_ss = ss.source_set()
cr16c_ss.add(files('virt.c')) cr16c_ss.add(files('virt.c'))
cr16c_ss.add(files('sc14461.c')) cr16c_ss.add(files('sc14461.c'))
cr16c_ss.add(files('sc14480.c'))
cr16c_ss.add(files('de410.c')) cr16c_ss.add(files('de410.c'))
cr16c_ss.add(files('boot.c')) cr16c_ss.add(files('boot.c'))
hw_arch += {'cr16c': cr16c_ss} hw_arch += {'cr16c': cr16c_ss}

67
hw/cr16c/sc14480.c Normal file
View file

@ -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)

30
hw/cr16c/sc14480.h Normal file
View file

@ -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 */

View file

@ -6,6 +6,7 @@
#include "qapi/error.h" #include "qapi/error.h"
#include "qemu/units.h" #include "qemu/units.h"
#include "qom/object.h" #include "qom/object.h"
#include "system/system.h"
typedef struct VirtMachineState { typedef struct VirtMachineState {
MachineState parent_obj; MachineState parent_obj;
@ -22,8 +23,36 @@ typedef struct VirtMachineClass {
DECLARE_OBJ_CHECKERS(VirtMachineState, VirtMachineClass, VIRT_MACHINE, TYPE_VIRT_MACHINE) 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) static void virt_init(MachineState* machine)
{ {
VirtMachineState* m_state = VIRT_MACHINE(machine); VirtMachineState* m_state = VIRT_MACHINE(machine);
object_initialize_child(OBJECT(machine), "cpu", &m_state->cpu, TYPE_CR16C_CPU); 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); memory_region_add_subregion(get_system_memory(), 0, &m_state->flash);
create_unimplemented_device("mmio", 0xFF0000, 0xFFFBFF - 0xFF0000); 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); //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 create_unimplemented_device("icu", 0xFFFC00, 0xFFFFFF - 0xFFFC00); // interrupt controller unit

View file

@ -137,8 +137,35 @@ static int cr16c_cpu_mmu_index(CPUState *cs, bool ifetch)
return 0; 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) static bool cr16c_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{ {
//CPUCR16CState *env = cpu_env(cs);
if (interrupt_request & CPU_INTERRUPT_HARD) {
}
// TODO // TODO
return false; return false;
} }
@ -213,6 +240,21 @@ static void cr16c_cpu_class_init(ObjectClass *oc, const void *data)
cc->tcg_ops = &cr16c_tcg_ops; 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[] = { static const TypeInfo cr16c_cpu_archs[] = {
{ {
.name = TYPE_CR16C_CPU, .name = TYPE_CR16C_CPU,
@ -220,6 +262,7 @@ static const TypeInfo cr16c_cpu_archs[] = {
.instance_size = sizeof(CR16CCPU), .instance_size = sizeof(CR16CCPU),
.class_size = sizeof(CR16CCPUClass), .class_size = sizeof(CR16CCPUClass),
.class_init = cr16c_cpu_class_init, .class_init = cr16c_cpu_class_init,
.instance_init = cr16c_cpu_initfn
}, },
}; };

View file

@ -257,6 +257,8 @@ BR0 0000 11 word:1 ne:1 dest:4 src:4
JCOND 0000 1010 cond:4 ra:4 JCOND 0000 1010 cond:4 ra:4
#JAL 0000 0000 1101 ....
EXCP 0000 0000 1100 id:4 EXCP 0000 0000 1100 id:4
&bal dest &bal dest