From 5a3c71bb9a6f936f44cd3f7e684b35f497954df8 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Fri, 19 Aug 2022 23:11:23 -0400 Subject: [PATCH 01/29] Add Acpi support. Change-Id: I208228b2178cddf365e97c6faf6111ef40e795eb Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- hw/acpi/Kconfig | 8 + hw/acpi/larch_7a.c | 600 +++++++++++++++++++++++++++++++++++++++++ hw/acpi/ls7a.c | 598 ++++++++++++++++++++++++++++++++++++++++ hw/acpi/meson.build | 1 + include/hw/acpi/ls7a.h | 80 ++++++ 5 files changed, 1287 insertions(+) create mode 100644 hw/acpi/larch_7a.c create mode 100644 hw/acpi/ls7a.c create mode 100644 include/hw/acpi/ls7a.h diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig index 622b0b50b7..2f2fb33a7b 100644 --- a/hw/acpi/Kconfig +++ b/hw/acpi/Kconfig @@ -15,6 +15,14 @@ config ACPI_X86_ICH bool select ACPI_X86 +config ACPI_LOONGARCH + bool + select ACPI + select ACPI_CPU_HOTPLUG + select ACPI_MEMORY_HOTPLUG + select ACPI_PIIX4 + select ACPI_PCIHP + config ACPI_CPU_HOTPLUG bool diff --git a/hw/acpi/larch_7a.c b/hw/acpi/larch_7a.c new file mode 100644 index 0000000000..35d4a75266 --- /dev/null +++ b/hw/acpi/larch_7a.c @@ -0,0 +1,600 @@ +#include "qemu/osdep.h" +#include "sysemu/sysemu.h" +#include "sysemu/runstate.h" +#include "sysemu/reset.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/ls7a.h" +#include "hw/nvram/fw_cfg.h" +#include "qemu/config-file.h" +#include "qapi/opts-visitor.h" +#include "qapi/qapi-events-run-state.h" +#include "qapi/error.h" +#include "hw/loongarch/ls7a.h" +#include "hw/mem/pc-dimm.h" +#include "hw/mem/nvdimm.h" +#include "migration/vmstate.h" + +static void ls7a_pm_update_sci_fn(ACPIREGS *regs) +{ + LS7APCIPMRegs *pm = container_of(regs, LS7APCIPMRegs, acpi_regs); + acpi_update_sci(&pm->acpi_regs, pm->irq); +} + +static uint64_t ls7a_gpe_readb(void *opaque, hwaddr addr, unsigned width) +{ + LS7APCIPMRegs *pm = opaque; + return acpi_gpe_ioport_readb(&pm->acpi_regs, addr); +} + +static void ls7a_gpe_writeb(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + LS7APCIPMRegs *pm = opaque; + acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val); + acpi_update_sci(&pm->acpi_regs, pm->irq); +} + +static const MemoryRegionOps ls7a_gpe_ops = { + .read = ls7a_gpe_readb, + .write = ls7a_gpe_writeb, + .valid.min_access_size = 1, + .valid.max_access_size = 8, + .impl.min_access_size = 1, + .impl.max_access_size = 1, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +#define VMSTATE_GPE_ARRAY(_field, _state) \ + { \ + .name = (stringify(_field)), \ + .version_id = 0, \ + .num = ACPI_GPE0_LEN, \ + .info = &vmstate_info_uint8, \ + .size = sizeof(uint8_t), \ + .flags = VMS_ARRAY | VMS_POINTER, \ + .offset = vmstate_offset_pointer(_state, _field, uint8_t), \ + } + +static uint64_t ls7a_reset_readw(void *opaque, hwaddr addr, unsigned width) +{ + return 0; +} + +static void ls7a_reset_writew(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + if (val & 1) { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + return; + } +} + +static const MemoryRegionOps ls7a_reset_ops = { + .read = ls7a_reset_readw, + .write = ls7a_reset_writew, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static bool vmstate_test_use_memhp(void *opaque) +{ + LS7APCIPMRegs *s = opaque; + return s->acpi_memory_hotplug.is_enabled; +} + +static const VMStateDescription vmstate_memhp_state = { + .name = "ls7a_pm/memhp", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .needed = vmstate_test_use_memhp, + .fields = (VMStateField[]) { + VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, LS7APCIPMRegs), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_cpuhp_state = { + .name = "ls7a_pm/cpuhp", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_CPU_HOTPLUG(cpuhp_state, LS7APCIPMRegs), + VMSTATE_END_OF_LIST() + } +}; + +const VMStateDescription vmstate_ls7a_pm = { + .name = "ls7a_pm", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT16(acpi_regs.pm1.evt.sts, LS7APCIPMRegs), + VMSTATE_UINT16(acpi_regs.pm1.evt.en, LS7APCIPMRegs), + VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, LS7APCIPMRegs), + VMSTATE_TIMER_PTR(acpi_regs.tmr.timer, LS7APCIPMRegs), + VMSTATE_INT64(acpi_regs.tmr.overflow_time, LS7APCIPMRegs), + VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, LS7APCIPMRegs), + VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, LS7APCIPMRegs), + VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * []) { + &vmstate_memhp_state, + &vmstate_cpuhp_state, + NULL + } +}; + +static inline int64_t acpi_pm_tmr_get_clock(void) +{ + return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY, + NANOSECONDS_PER_SECOND); +} + +static uint32_t acpi_pm_tmr_get(ACPIREGS *ar) +{ + uint32_t d = acpi_pm_tmr_get_clock(); + return d & 0xffffff; +} + +static void acpi_pm_tmr_timer(void *opaque) +{ + ACPIREGS *ar = opaque; + qemu_system_wakeup_request(QEMU_WAKEUP_REASON_PMTIMER, NULL); + ar->tmr.update_sci(ar); +} + +static uint64_t acpi_pm_tmr_read(void *opaque, hwaddr addr, unsigned width) +{ + return acpi_pm_tmr_get(opaque); +} + +static void acpi_pm_tmr_write(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + /* nothing */ +} + +static const MemoryRegionOps acpi_pm_tmr_ops = { + .read = acpi_pm_tmr_read, + .write = acpi_pm_tmr_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void ls7a_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, + MemoryRegion *parent, uint64_t offset) +{ + ar->tmr.update_sci = update_sci; + ar->tmr.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, acpi_pm_tmr_timer, ar); + memory_region_init_io(&ar->tmr.io, memory_region_owner(parent), + &acpi_pm_tmr_ops, ar, "acpi-tmr", 4); + memory_region_add_subregion(parent, offset, &ar->tmr.io); +} + +static void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val) +{ + uint16_t pm1_sts = acpi_pm1_evt_get_sts(ar); + if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) { + /* if TMRSTS is reset, then compute the new overflow time */ + acpi_pm_tmr_calc_overflow_time(ar); + } + ar->pm1.evt.sts &= ~val; +} + +static uint64_t acpi_pm_evt_read(void *opaque, hwaddr addr, unsigned width) +{ + ACPIREGS *ar = opaque; + switch (addr) { + case 0: + return acpi_pm1_evt_get_sts(ar); + case 4: + return ar->pm1.evt.en; + default: + return 0; + } +} + +static void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val) +{ + ar->pm1.evt.en = val; + qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC, + val & ACPI_BITMASK_RT_CLOCK_ENABLE); + qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_PMTIMER, + val & ACPI_BITMASK_TIMER_ENABLE); +} + +static void acpi_pm_evt_write(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + ACPIREGS *ar = opaque; + switch (addr) { + case 0: + acpi_pm1_evt_write_sts(ar, val); + ar->pm1.evt.update_sci(ar); + break; + case 4: + acpi_pm1_evt_write_en(ar, val); + ar->pm1.evt.update_sci(ar); + break; + } +} + +static const MemoryRegionOps acpi_pm_evt_ops = { + .read = acpi_pm_evt_read, + .write = acpi_pm_evt_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void ls7a_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, + MemoryRegion *parent, uint64_t offset) +{ + ar->pm1.evt.update_sci = update_sci; + memory_region_init_io(&ar->pm1.evt.io, memory_region_owner(parent), + &acpi_pm_evt_ops, ar, "acpi-evt", 8); + memory_region_add_subregion(parent, offset, &ar->pm1.evt.io); +} + +static uint64_t acpi_pm_cnt_read(void *opaque, hwaddr addr, unsigned width) +{ + ACPIREGS *ar = opaque; + return ar->pm1.cnt.cnt; +} + +/* ACPI PM1aCNT */ +static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) +{ + ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE); + if (val & ACPI_BITMASK_SLEEP_ENABLE) { + /* change suspend type */ + uint16_t sus_typ = (val >> 10) & 7; + switch (sus_typ) { + /* s3,s4 not support */ + case 5: + case 6: + warn_report("acpi s3,s4 state not support"); + break; + /* s5: soft off */ + case 7: + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + break; + default: + break; + } + } +} + +static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + acpi_pm1_cnt_write(opaque, val); +} + +static const MemoryRegionOps acpi_pm_cnt_ops = { + .read = acpi_pm_cnt_read, + .write = acpi_pm_cnt_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void acpi_notify_wakeup(Notifier *notifier, void *data) +{ + ACPIREGS *ar = container_of(notifier, ACPIREGS, wakeup); + WakeupReason *reason = data; + + switch (*reason) { + case QEMU_WAKEUP_REASON_RTC: + ar->pm1.evt.sts |= + (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_RT_CLOCK_STATUS); + break; + case QEMU_WAKEUP_REASON_PMTIMER: + ar->pm1.evt.sts |= + (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_TIMER_STATUS); + break; + case QEMU_WAKEUP_REASON_OTHER: + /* ACPI_BITMASK_WAKE_STATUS should be set on resume. + * Pretend that resume was caused by power button */ + ar->pm1.evt.sts |= + (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS); + break; + default: + break; + } +} + +static void ls7a_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, + bool disable_s3, bool disable_s4, uint8_t s4_val, uint64_t offset) +{ + FWCfgState *fw_cfg; + + ar->pm1.cnt.s4_val = s4_val; + ar->wakeup.notify = acpi_notify_wakeup; + qemu_register_wakeup_notifier(&ar->wakeup); + memory_region_init_io(&ar->pm1.cnt.io, memory_region_owner(parent), + &acpi_pm_cnt_ops, ar, "acpi-cnt", 4); + memory_region_add_subregion(parent, offset, &ar->pm1.cnt.io); + + fw_cfg = fw_cfg_find(); + if (fw_cfg) { + uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; + suspend[3] = 1 | ((!disable_s3) << 7); + suspend[4] = s4_val | ((!disable_s4) << 7); + fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); + } +} + +static void ls7a_pm_reset(void *opaque) +{ + LS7APCIPMRegs *pm = opaque; + + acpi_pm1_evt_reset(&pm->acpi_regs); + acpi_pm1_cnt_reset(&pm->acpi_regs); + acpi_pm_tmr_reset(&pm->acpi_regs); + acpi_gpe_reset(&pm->acpi_regs); + + acpi_update_sci(&pm->acpi_regs, pm->irq); +} + +static void pm_powerdown_req(Notifier *n, void *opaque) +{ + LS7APCIPMRegs *pm = container_of(n, LS7APCIPMRegs, powerdown_notifier); + + acpi_pm1_evt_power_down(&pm->acpi_regs); +} + +void ls7a_pm_init(LS7APCIPMRegs *pm, qemu_irq *pic) +{ + unsigned long base, gpe_len, acpi_aci_irq; + + /* ls7a board acpi hardware info, including + * acpi system io base address + * acpi gpe length + * acpi sci irq number + */ + base = ACPI_IO_BASE; + gpe_len = ACPI_GPE0_LEN; + acpi_aci_irq = ACPI_SCI_IRQ; + + pm->irq = pic[acpi_aci_irq - 64]; + memory_region_init(&pm->iomem, NULL, "ls7a_pm", ACPI_IO_SIZE); + memory_region_add_subregion(get_system_memory(), base, &pm->iomem); + + cpu_hotplug_hw_init(get_system_memory(), NULL, + &pm->cpuhp_state, CPU_HOTPLUG_BASE); + + ls7a_pm_tmr_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_TMR_BLK); + ls7a_pm1_evt_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_EVT_BLK); + ls7a_pm1_cnt_init(&pm->acpi_regs, &pm->iomem, false, false, 2, LS7A_PM_CNT_BLK); + + acpi_gpe_init(&pm->acpi_regs, gpe_len); + memory_region_init_io(&pm->iomem_gpe, NULL, &ls7a_gpe_ops, pm, + "acpi-gpe0", gpe_len); + memory_region_add_subregion(&pm->iomem, LS7A_GPE0_STS_REG, &pm->iomem_gpe); + + memory_region_init_io(&pm->iomem_reset, NULL, &ls7a_reset_ops, pm, + "acpi-reset", 4); + memory_region_add_subregion(&pm->iomem, LS7A_GPE0_RESET_REG, &pm->iomem_reset); + + qemu_register_reset(ls7a_pm_reset, pm); + + pm->powerdown_notifier.notify = pm_powerdown_req; + qemu_register_powerdown_notifier(&pm->powerdown_notifier); + + if (pm->acpi_memory_hotplug.is_enabled) { + acpi_memory_hotplug_init(get_system_memory(), NULL, + &pm->acpi_memory_hotplug, MEMORY_HOTPLUG_BASE); + } +} + + +static void ls7a_pm_get_gpe0_blk(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint64_t value = ACPI_IO_BASE + LS7A_GPE0_STS_REG; + + visit_type_uint64(v, name, &value, errp); +} + +static bool ls7a_pm_get_memory_hotplug_support(Object *obj, Error **errp) +{ + LS7APCIState *ls7a = get_ls7a_type(obj); + + return ls7a->pm.acpi_memory_hotplug.is_enabled; +} + +static void ls7a_pm_set_memory_hotplug_support(Object *obj, bool value, + Error **errp) +{ + LS7APCIState *ls7a = get_ls7a_type(obj); + + ls7a->pm.acpi_memory_hotplug.is_enabled = value; +} + +static void ls7a_pm_get_disable_s3(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + uint8_t value = pm->disable_s3; + + visit_type_uint8(v, name, &value, errp); +} + +static void ls7a_pm_set_disable_s3(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + Error *local_err = NULL; + uint8_t value; + + visit_type_uint8(v, name, &value, &local_err); + if (local_err) { + goto out; + } + pm->disable_s3 = value; +out: + error_propagate(errp, local_err); +} + +static void ls7a_pm_get_disable_s4(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + uint8_t value = pm->disable_s4; + + visit_type_uint8(v, name, &value, errp); +} + +static void ls7a_pm_set_disable_s4(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + Error *local_err = NULL; + uint8_t value; + + visit_type_uint8(v, name, &value, &local_err); + if (local_err) { + goto out; + } + pm->disable_s4 = value; +out: + error_propagate(errp, local_err); +} + +static void ls7a_pm_get_s4_val(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + uint8_t value = pm->s4_val; + + visit_type_uint8(v, name, &value, errp); +} + +static void ls7a_pm_set_s4_val(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + Error *local_err = NULL; + uint8_t value; + + visit_type_uint8(v, name, &value, &local_err); + if (local_err) { + goto out; + } + pm->s4_val = value; +out: + error_propagate(errp, local_err); +} + +void ls7a_pm_add_properties(Object *obj, LS7APCIPMRegs *pm, Error **errp) +{ + static const uint32_t gpe0_len = ACPI_GPE0_LEN; + pm->acpi_memory_hotplug.is_enabled = true; + pm->disable_s3 = 0; + pm->disable_s4 = 0; + pm->s4_val = 2; + + object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE, + &pm->pm_io_base, OBJ_PROP_FLAG_READ); + object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32", + ls7a_pm_get_gpe0_blk, + NULL, NULL, pm); + object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN, + &gpe0_len, OBJ_PROP_FLAG_READ); + object_property_add_bool(obj, "memory-hotplug-support", + ls7a_pm_get_memory_hotplug_support, + ls7a_pm_set_memory_hotplug_support); + object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8", + ls7a_pm_get_disable_s3, + ls7a_pm_set_disable_s3, + NULL, pm); + object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8", + ls7a_pm_get_disable_s4, + ls7a_pm_set_disable_s4, + NULL, pm); + object_property_add(obj, ACPI_PM_PROP_S4_VAL, "uint8", + ls7a_pm_get_s4_val, + ls7a_pm_set_s4_val, + NULL, pm); +} + +void ls7a_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); + + if (ls7a->pm.acpi_memory_hotplug.is_enabled && + object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { + nvdimm_acpi_plug_cb(hotplug_dev, dev); + } else { + acpi_memory_plug_cb(hotplug_dev, &ls7a->pm.acpi_memory_hotplug, + dev, errp); + } + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + acpi_cpu_plug_cb(hotplug_dev, &ls7a->pm.cpuhp_state, dev, errp); + } else { + error_setg(errp, "acpi: device plug request for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); + } +} + +void ls7a_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); + + if (ls7a->pm.acpi_memory_hotplug.is_enabled && + object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + acpi_memory_unplug_request_cb(hotplug_dev, + &ls7a->pm.acpi_memory_hotplug, dev, + errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + acpi_cpu_unplug_request_cb(hotplug_dev, &ls7a->pm.cpuhp_state, + dev, errp); + } else { + error_setg(errp, "acpi: device unplug request for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); + } +} + +void ls7a_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); + + if (ls7a->pm.acpi_memory_hotplug.is_enabled && + object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + acpi_memory_unplug_cb(&ls7a->pm.acpi_memory_hotplug, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + acpi_cpu_unplug_cb(&ls7a->pm.cpuhp_state, dev, errp); + } else { + error_setg(errp, "acpi: device unplug for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); + } +} + +void ls7a_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list) +{ + LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); + + acpi_memory_ospm_status(&ls7a->pm.acpi_memory_hotplug, list); + acpi_cpu_ospm_status(&ls7a->pm.cpuhp_state, list); +} + +void ls7a_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev) +{ + LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); + + acpi_send_gpe_event(&ls7a->pm.acpi_regs, ls7a->pm.irq, ev); +} + + + diff --git a/hw/acpi/ls7a.c b/hw/acpi/ls7a.c new file mode 100644 index 0000000000..2de50ccb9c --- /dev/null +++ b/hw/acpi/ls7a.c @@ -0,0 +1,598 @@ +#include "qemu/osdep.h" +#include "sysemu/sysemu.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/ls7a.h" +#include "hw/nvram/fw_cfg.h" +#include "qemu/config-file.h" +#include "qapi/opts-visitor.h" +#include "qapi/qapi-events-run-state.h" +#include "qapi/error.h" +#include "hw/mips/ls7a.h" +#include "hw/mem/pc-dimm.h" +#include "hw/mem/nvdimm.h" + +static void ls7a_pm_update_sci_fn(ACPIREGS *regs) +{ + LS7APCIPMRegs *pm = container_of(regs, LS7APCIPMRegs, acpi_regs); + acpi_update_sci(&pm->acpi_regs, pm->irq); +} + +static uint64_t ls7a_gpe_readb(void *opaque, hwaddr addr, unsigned width) +{ + LS7APCIPMRegs *pm = opaque; + return acpi_gpe_ioport_readb(&pm->acpi_regs, addr); +} + +static void ls7a_gpe_writeb(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + LS7APCIPMRegs *pm = opaque; + acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val); + acpi_update_sci(&pm->acpi_regs, pm->irq); +} + +static const MemoryRegionOps ls7a_gpe_ops = { + .read = ls7a_gpe_readb, + .write = ls7a_gpe_writeb, + .valid.min_access_size = 1, + .valid.max_access_size = 8, + .impl.min_access_size = 1, + .impl.max_access_size = 1, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +#define VMSTATE_GPE_ARRAY(_field, _state) \ + { \ + .name = (stringify(_field)), \ + .version_id = 0, \ + .num = ACPI_GPE0_LEN, \ + .info = &vmstate_info_uint8, \ + .size = sizeof(uint8_t), \ + .flags = VMS_ARRAY | VMS_POINTER, \ + .offset = vmstate_offset_pointer(_state, _field, uint8_t), \ + } + +static uint64_t ls7a_reset_readw(void *opaque, hwaddr addr, unsigned width) +{ + return 0; +} + +static void ls7a_reset_writew(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + if (val & 1) { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + return; + } +} + +static const MemoryRegionOps ls7a_reset_ops = { + .read = ls7a_reset_readw, + .write = ls7a_reset_writew, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static bool vmstate_test_use_memhp(void *opaque) +{ + LS7APCIPMRegs *s = opaque; + return s->acpi_memory_hotplug.is_enabled; +} + +static const VMStateDescription vmstate_memhp_state = { + .name = "ls7a_pm/memhp", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .needed = vmstate_test_use_memhp, + .fields = (VMStateField[]) { + VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, LS7APCIPMRegs), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_cpuhp_state = { + .name = "ls7a_pm/cpuhp", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_CPU_HOTPLUG(cpuhp_state, LS7APCIPMRegs), + VMSTATE_END_OF_LIST() + } +}; + +const VMStateDescription vmstate_ls7a_pm = { + .name = "ls7a_pm", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT16(acpi_regs.pm1.evt.sts, LS7APCIPMRegs), + VMSTATE_UINT16(acpi_regs.pm1.evt.en, LS7APCIPMRegs), + VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, LS7APCIPMRegs), + VMSTATE_TIMER_PTR(acpi_regs.tmr.timer, LS7APCIPMRegs), + VMSTATE_INT64(acpi_regs.tmr.overflow_time, LS7APCIPMRegs), + VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, LS7APCIPMRegs), + VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, LS7APCIPMRegs), + VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * []) { + &vmstate_memhp_state, + &vmstate_cpuhp_state, + NULL + } +}; + +static inline int64_t acpi_pm_tmr_get_clock(void) +{ + return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY, + NANOSECONDS_PER_SECOND); +} + +static uint32_t acpi_pm_tmr_get(ACPIREGS *ar) +{ + uint32_t d = acpi_pm_tmr_get_clock(); + return d & 0xffffff; +} + +static void acpi_pm_tmr_timer(void *opaque) +{ + ACPIREGS *ar = opaque; + qemu_system_wakeup_request(QEMU_WAKEUP_REASON_PMTIMER, NULL); + ar->tmr.update_sci(ar); +} + +static uint64_t acpi_pm_tmr_read(void *opaque, hwaddr addr, unsigned width) +{ + return acpi_pm_tmr_get(opaque); +} + +static void acpi_pm_tmr_write(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + /* nothing */ +} + +static const MemoryRegionOps acpi_pm_tmr_ops = { + .read = acpi_pm_tmr_read, + .write = acpi_pm_tmr_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void ls7a_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, + MemoryRegion *parent, uint64_t offset) +{ + ar->tmr.update_sci = update_sci; + ar->tmr.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, acpi_pm_tmr_timer, ar); + memory_region_init_io(&ar->tmr.io, memory_region_owner(parent), + &acpi_pm_tmr_ops, ar, "acpi-tmr", 4); + memory_region_add_subregion(parent, offset, &ar->tmr.io); +} + +static void acpi_pm1_evt_write_sts(ACPIREGS *ar, uint16_t val) +{ + uint16_t pm1_sts = acpi_pm1_evt_get_sts(ar); + if (pm1_sts & val & ACPI_BITMASK_TIMER_STATUS) { + /* if TMRSTS is reset, then compute the new overflow time */ + acpi_pm_tmr_calc_overflow_time(ar); + } + ar->pm1.evt.sts &= ~val; +} + +static uint64_t acpi_pm_evt_read(void *opaque, hwaddr addr, unsigned width) +{ + ACPIREGS *ar = opaque; + switch (addr) { + case 0: + return acpi_pm1_evt_get_sts(ar); + case 4: + return ar->pm1.evt.en; + default: + return 0; + } +} + +static void acpi_pm1_evt_write_en(ACPIREGS *ar, uint16_t val) +{ + ar->pm1.evt.en = val; + qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_RTC, + val & ACPI_BITMASK_RT_CLOCK_ENABLE); + qemu_system_wakeup_enable(QEMU_WAKEUP_REASON_PMTIMER, + val & ACPI_BITMASK_TIMER_ENABLE); +} + +static void acpi_pm_evt_write(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + ACPIREGS *ar = opaque; + switch (addr) { + case 0: + acpi_pm1_evt_write_sts(ar, val); + ar->pm1.evt.update_sci(ar); + break; + case 4: + acpi_pm1_evt_write_en(ar, val); + ar->pm1.evt.update_sci(ar); + break; + } +} + +static const MemoryRegionOps acpi_pm_evt_ops = { + .read = acpi_pm_evt_read, + .write = acpi_pm_evt_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void ls7a_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, + MemoryRegion *parent, uint64_t offset) +{ + ar->pm1.evt.update_sci = update_sci; + memory_region_init_io(&ar->pm1.evt.io, memory_region_owner(parent), + &acpi_pm_evt_ops, ar, "acpi-evt", 8); + memory_region_add_subregion(parent, offset, &ar->pm1.evt.io); +} + +static uint64_t acpi_pm_cnt_read(void *opaque, hwaddr addr, unsigned width) +{ + ACPIREGS *ar = opaque; + return ar->pm1.cnt.cnt; +} + +/* ACPI PM1aCNT */ +static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) +{ + ar->pm1.cnt.cnt = val & ~(ACPI_BITMASK_SLEEP_ENABLE); + + if (val & ACPI_BITMASK_SLEEP_ENABLE) { + /* change suspend type */ + uint16_t sus_typ = (val >> 10) & 7; + switch (sus_typ) { + case 0: /* soft power off */ + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + break; + case 1: + qemu_system_suspend_request(); + break; + default: + if (sus_typ == ar->pm1.cnt.s4_val) { /* S4 request */ + qapi_event_send_suspend_disk(); + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } + break; + } + } +} + +static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + acpi_pm1_cnt_write(opaque, val); +} + +static const MemoryRegionOps acpi_pm_cnt_ops = { + .read = acpi_pm_cnt_read, + .write = acpi_pm_cnt_write, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void acpi_notify_wakeup(Notifier *notifier, void *data) +{ + ACPIREGS *ar = container_of(notifier, ACPIREGS, wakeup); + WakeupReason *reason = data; + + switch (*reason) { + case QEMU_WAKEUP_REASON_RTC: + ar->pm1.evt.sts |= + (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_RT_CLOCK_STATUS); + break; + case QEMU_WAKEUP_REASON_PMTIMER: + ar->pm1.evt.sts |= + (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_TIMER_STATUS); + break; + case QEMU_WAKEUP_REASON_OTHER: + /* ACPI_BITMASK_WAKE_STATUS should be set on resume. + * Pretend that resume was caused by power button */ + ar->pm1.evt.sts |= + (ACPI_BITMASK_WAKE_STATUS | ACPI_BITMASK_POWER_BUTTON_STATUS); + break; + default: + break; + } +} + +static void ls7a_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, + bool disable_s3, bool disable_s4, uint8_t s4_val, uint64_t offset) +{ + FWCfgState *fw_cfg; + + ar->pm1.cnt.s4_val = s4_val; + ar->wakeup.notify = acpi_notify_wakeup; + qemu_register_wakeup_notifier(&ar->wakeup); + memory_region_init_io(&ar->pm1.cnt.io, memory_region_owner(parent), + &acpi_pm_cnt_ops, ar, "acpi-cnt", 4); + memory_region_add_subregion(parent, offset, &ar->pm1.cnt.io); + + fw_cfg = fw_cfg_find(); + if (fw_cfg) { + uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; + suspend[3] = 1 | ((!disable_s3) << 7); + suspend[4] = s4_val | ((!disable_s4) << 7); + fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); + } +} + +static void ls7a_pm_reset(void *opaque) +{ + LS7APCIPMRegs *pm = opaque; + + acpi_pm1_evt_reset(&pm->acpi_regs); + acpi_pm1_cnt_reset(&pm->acpi_regs); + acpi_pm_tmr_reset(&pm->acpi_regs); + acpi_gpe_reset(&pm->acpi_regs); + + acpi_update_sci(&pm->acpi_regs, pm->irq); +} + +static void pm_powerdown_req(Notifier *n, void *opaque) +{ + LS7APCIPMRegs *pm = container_of(n, LS7APCIPMRegs, powerdown_notifier); + + acpi_pm1_evt_power_down(&pm->acpi_regs); +} + +void ls7a_pm_init(LS7APCIPMRegs *pm, qemu_irq *pic) +{ + unsigned long base, gpe_len, acpi_aci_irq; + + /* ls7a board acpi hardware info, including + * acpi system io base address + * acpi gpe length + * acpi sci irq number + */ + base = ACPI_IO_BASE; + gpe_len = ACPI_GPE0_LEN; + acpi_aci_irq = ACPI_SCI_IRQ; + + pm->irq = pic[acpi_aci_irq - 64]; + memory_region_init(&pm->iomem, NULL, "ls7a_pm", ACPI_IO_SIZE); + memory_region_add_subregion(get_system_memory(), base, &pm->iomem); + + cpu_hotplug_hw_init(get_system_memory(), NULL, &pm->cpuhp_state, CPU_HOTPLUG_BASE); + + ls7a_pm_tmr_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_TMR_BLK); + ls7a_pm1_evt_init(&pm->acpi_regs, ls7a_pm_update_sci_fn, &pm->iomem, LS7A_PM_EVT_BLK); + ls7a_pm1_cnt_init(&pm->acpi_regs, &pm->iomem, false, false, 2, LS7A_PM_CNT_BLK); + + acpi_gpe_init(&pm->acpi_regs, gpe_len); + memory_region_init_io(&pm->iomem_gpe, NULL, &ls7a_gpe_ops, pm, + "acpi-gpe0", gpe_len); + memory_region_add_subregion(&pm->iomem, LS7A_GPE0_STS_REG, &pm->iomem_gpe); + + memory_region_init_io(&pm->iomem_reset, NULL, &ls7a_reset_ops, pm, + "acpi-reset", 4); + memory_region_add_subregion(&pm->iomem, LS7A_GPE0_RESET_REG, &pm->iomem_reset); + + qemu_register_reset(ls7a_pm_reset, pm); + + pm->powerdown_notifier.notify = pm_powerdown_req; + qemu_register_powerdown_notifier(&pm->powerdown_notifier); + + if (pm->acpi_memory_hotplug.is_enabled) { + acpi_memory_hotplug_init(get_system_memory(), NULL, + &pm->acpi_memory_hotplug, MEMORY_HOTPLUG_BASE); + } +} + + +static void ls7a_pm_get_gpe0_blk(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint64_t value = ACPI_IO_BASE + LS7A_GPE0_STS_REG; + + visit_type_uint64(v, name, &value, errp); +} + +static bool ls7a_pm_get_memory_hotplug_support(Object *obj, Error **errp) +{ + LS7APCIState *ls7a = get_ls7a_type(obj); + + return ls7a->pm.acpi_memory_hotplug.is_enabled; +} + +static void ls7a_pm_set_memory_hotplug_support(Object *obj, bool value, + Error **errp) +{ + LS7APCIState *ls7a = get_ls7a_type(obj); + + ls7a->pm.acpi_memory_hotplug.is_enabled = value; +} + +static void ls7a_pm_get_disable_s3(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + uint8_t value = pm->disable_s3; + + visit_type_uint8(v, name, &value, errp); +} + +static void ls7a_pm_set_disable_s3(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + Error *local_err = NULL; + uint8_t value; + + visit_type_uint8(v, name, &value, &local_err); + if (local_err) { + goto out; + } + pm->disable_s3 = value; +out: + error_propagate(errp, local_err); +} + +static void ls7a_pm_get_disable_s4(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + uint8_t value = pm->disable_s4; + + visit_type_uint8(v, name, &value, errp); +} + +static void ls7a_pm_set_disable_s4(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + Error *local_err = NULL; + uint8_t value; + + visit_type_uint8(v, name, &value, &local_err); + if (local_err) { + goto out; + } + pm->disable_s4 = value; +out: + error_propagate(errp, local_err); +} + +static void ls7a_pm_get_s4_val(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + uint8_t value = pm->s4_val; + + visit_type_uint8(v, name, &value, errp); +} + +static void ls7a_pm_set_s4_val(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LS7APCIPMRegs *pm = opaque; + Error *local_err = NULL; + uint8_t value; + + visit_type_uint8(v, name, &value, &local_err); + if (local_err) { + goto out; + } + pm->s4_val = value; +out: + error_propagate(errp, local_err); +} + +void ls7a_pm_add_properties(Object *obj, LS7APCIPMRegs *pm, Error **errp) +{ + static const uint32_t gpe0_len = ACPI_GPE0_LEN; + pm->acpi_memory_hotplug.is_enabled = true; + pm->disable_s3 = 0; + pm->disable_s4 = 0; + pm->s4_val = 2; + + object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE, + &pm->pm_io_base, OBJ_PROP_FLAG_READ); + object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32", + ls7a_pm_get_gpe0_blk, + NULL, NULL, pm); + object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN, + &gpe0_len, OBJ_PROP_FLAG_READ); + object_property_add_bool(obj, "memory-hotplug-support", + ls7a_pm_get_memory_hotplug_support, + ls7a_pm_set_memory_hotplug_support); + object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8", + ls7a_pm_get_disable_s3, + ls7a_pm_set_disable_s3, + NULL, pm); + object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8", + ls7a_pm_get_disable_s4, + ls7a_pm_set_disable_s4, + NULL, pm); + object_property_add(obj, ACPI_PM_PROP_S4_VAL, "uint8", + ls7a_pm_get_s4_val, + ls7a_pm_set_s4_val, + NULL, pm); +} + +void ls7a_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); + + if (ls7a->pm.acpi_memory_hotplug.is_enabled && + object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { + nvdimm_acpi_plug_cb(hotplug_dev, dev); + } else { + acpi_memory_plug_cb(hotplug_dev, &ls7a->pm.acpi_memory_hotplug, + dev, errp); + } + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + acpi_cpu_plug_cb(hotplug_dev, &ls7a->pm.cpuhp_state, dev, errp); + } else { + error_setg(errp, "acpi: device plug request for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); + } +} + +void ls7a_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); + + if (ls7a->pm.acpi_memory_hotplug.is_enabled && + object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + acpi_memory_unplug_request_cb(hotplug_dev, + &ls7a->pm.acpi_memory_hotplug, dev, + errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + acpi_cpu_unplug_request_cb(hotplug_dev, &ls7a->pm.cpuhp_state, + dev, errp); + } else { + error_setg(errp, "acpi: device unplug request for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); + } +} + +void ls7a_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + LS7APCIState *ls7a = get_ls7a_type(OBJECT(hotplug_dev)); + + if (ls7a->pm.acpi_memory_hotplug.is_enabled && + object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + acpi_memory_unplug_cb(&ls7a->pm.acpi_memory_hotplug, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + acpi_cpu_unplug_cb(&ls7a->pm.cpuhp_state, dev, errp); + } else { + error_setg(errp, "acpi: device unplug for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); + } +} + +void ls7a_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list) +{ + LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); + + acpi_memory_ospm_status(&ls7a->pm.acpi_memory_hotplug, list); + acpi_cpu_ospm_status(&ls7a->pm.cpuhp_state, list); +} + +void ls7a_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev) +{ + LS7APCIState *ls7a = get_ls7a_type(OBJECT(adev)); + + acpi_send_gpe_event(&ls7a->pm.acpi_regs, ls7a->pm.irq, ev); +} + + + diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build index adf6347bc4..5fe4cfa4f1 100644 --- a/hw/acpi/meson.build +++ b/hw/acpi/meson.build @@ -6,6 +6,7 @@ acpi_ss.add(files( 'core.c', 'utils.c', )) +acpi_ss.add(when: 'CONFIG_ACPI_LOONGARCH', if_true: files('larch_7a.c')) acpi_ss.add(when: 'CONFIG_ACPI_CPU_HOTPLUG', if_true: files('cpu.c', 'cpu_hotplug.c')) acpi_ss.add(when: 'CONFIG_ACPI_CPU_HOTPLUG', if_false: files('acpi-cpu-hotplug-stub.c')) acpi_ss.add(when: 'CONFIG_ACPI_MEMORY_HOTPLUG', if_true: files('memory_hotplug.c')) diff --git a/include/hw/acpi/ls7a.h b/include/hw/acpi/ls7a.h new file mode 100644 index 0000000000..4401515c7b --- /dev/null +++ b/include/hw/acpi/ls7a.h @@ -0,0 +1,80 @@ +/* + * QEMU GMCH/LS7A PCI PM Emulation + * + * Copyright (c) 2009 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + */ + +#ifndef HW_ACPI_LS7A_H +#define HW_ACPI_LS7A_H + +#include "hw/acpi/acpi.h" +#include "hw/acpi/cpu_hotplug.h" +#include "hw/acpi/cpu.h" +#include "hw/acpi/memory_hotplug.h" +#include "hw/acpi/acpi_dev_interface.h" +#include "hw/acpi/tco.h" + +#define CPU_HOTPLUG_BASE 0x1e000000 +#define MEMORY_HOTPLUG_BASE 0x1e00000c + +typedef struct LS7APCIPMRegs { + /* + * In ls7a spec says that pm1_cnt register is 32bit width and + * that the upper 16bits are reserved and unused. + * PM1a_CNT_BLK = 2 in FADT so it is defined as uint16_t. + */ + ACPIREGS acpi_regs; + + MemoryRegion iomem; + MemoryRegion iomem_gpe; + MemoryRegion iomem_smi; + MemoryRegion iomem_reset; + + qemu_irq irq; /* SCI */ + + uint32_t pm_io_base; + Notifier powerdown_notifier; + + bool cpu_hotplug_legacy; + AcpiCpuHotplug gpe_cpu; + CPUHotplugState cpuhp_state; + + MemHotplugState acpi_memory_hotplug; + + uint8_t disable_s3; + uint8_t disable_s4; + uint8_t s4_val; +} LS7APCIPMRegs; + +void ls7a_pm_init(LS7APCIPMRegs *ls7a, qemu_irq *sci_irq); + +void ls7a_pm_iospace_update(LS7APCIPMRegs *pm, uint32_t pm_io_base); +extern const VMStateDescription vmstate_ls7a_pm; + +void ls7a_pm_add_properties(Object *obj, LS7APCIPMRegs *pm, Error **errp); + +void ls7a_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); +void ls7a_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +void ls7a_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); + +void ls7a_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list); + +void ls7a_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev); +#endif /* HW_ACPI_LS7A_H */ -- Gitee From 80bf985797046e7ed1fcef51236d2379726f568a Mon Sep 17 00:00:00 2001 From: lixianglai Date: Fri, 19 Aug 2022 23:15:49 -0400 Subject: [PATCH 02/29] Support rtc. Change-Id: Idd50274dd2a6c00b21ec0cd099f8d115ab4fa449 Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- hw/timer/Kconfig | 2 + hw/timer/ls7a_rtc.c | 325 +++++++++++++++++++++++++++++++++++++++++++ hw/timer/meson.build | 1 + 3 files changed, 328 insertions(+) create mode 100644 hw/timer/ls7a_rtc.c diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig index 010be7ed1f..b395c72d7d 100644 --- a/hw/timer/Kconfig +++ b/hw/timer/Kconfig @@ -60,3 +60,5 @@ config STELLARIS_GPTM config AVR_TIMER16 bool +config LS7A_RTC + bool diff --git a/hw/timer/ls7a_rtc.c b/hw/timer/ls7a_rtc.c new file mode 100644 index 0000000000..756f2fc9ce --- /dev/null +++ b/hw/timer/ls7a_rtc.c @@ -0,0 +1,325 @@ +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "include/hw/register.h" +#include "qemu/timer.h" +#include "sysemu/sysemu.h" +#include "qemu/cutils.h" +#include "qemu/log.h" +#include "qemu-common.h" +#include "migration/vmstate.h" + +#ifdef DEBUG_LS7A_RTC +#define DPRINTF (fmt, ...) \ +do { printf("ls7a_rtc: " fmt , ## __VA_ARGS__); } while (0) +#else +#define DPRINTF (fmt, ...) do {} while (0) +#endif + + +#define SYS_TOYTRIM 0x20 +#define SYS_TOYWRITE0 0x24 +#define SYS_TOYWRITE1 0x28 +#define SYS_TOYREAD0 0x2C +#define SYS_TOYREAD1 0x30 +#define SYS_TOYMATCH0 0x34 +#define SYS_TOYMATCH1 0x38 +#define SYS_TOYMATCH2 0x3C +#define SYS_RTCCTRL 0x40 +#define SYS_RTCTRIM 0x60 +#define SYS_RTCWRTIE0 0x64 +#define SYS_RTCREAD0 0x68 +#define SYS_RTCMATCH0 0x6C +#define SYS_RTCMATCH1 0x70 +#define SYS_RTCMATCH2 0x74 + +/** + ** shift bits and filed mask + **/ +#define TOY_MON_MASK 0x3f +#define TOY_DAY_MASK 0x1f +#define TOY_HOUR_MASK 0x1f +#define TOY_MIN_MASK 0x3f +#define TOY_SEC_MASK 0x3f +#define TOY_MSEC_MASK 0xf + +#define TOY_MON_SHIFT 26 +#define TOY_DAY_SHIFT 21 +#define TOY_HOUR_SHIFT 16 +#define TOY_MIN_SHIFT 10 +#define TOY_SEC_SHIFT 4 +#define TOY_MSEC_SHIFT 0 + +#define TOY_MATCH_YEAR_MASK 0x3f +#define TOY_MATCH_MON_MASK 0xf +#define TOY_MATCH_DAY_MASK 0x1f +#define TOY_MATCH_HOUR_MASK 0x1f +#define TOY_MATCH_MIN_MASK 0x3f +#define TOY_MATCH_SEC_MASK 0x3f + + +#define TOY_MATCH_YEAR_SHIFT 26 +#define TOY_MATCH_MON_SHIFT 22 +#define TOY_MATCH_DAY_SHIFT 17 +#define TOY_MATCH_HOUR_SHIFT 12 +#define TOY_MATCH_MIN_SHIFT 6 +#define TOY_MATCH_SEC_SHIFT 0 + +#define TOY_ENABLE_BIT (1U << 11) + +#define TYPE_LS7A_RTC "ls7a_rtc" +#define LS7A_RTC(obj) OBJECT_CHECK(LS7A_RTCState, (obj), TYPE_LS7A_RTC) + +typedef struct LS7A_RTCState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + QEMUTimer *timer; + /* Needed to preserve the tick_count across migration, even if the + * absolute value of the rtc_clock is different on the source and + * destination. + */ + int64_t offset; + int64_t data; + int64_t save_alarm_offset; + int tidx; + uint32_t toymatch[3]; + uint32_t toytrim; + uint32_t cntrctl; + uint32_t rtctrim; + uint32_t rtccount; + uint32_t rtcmatch[3]; + qemu_irq toy_irq; +} LS7A_RTCState; + +enum { +TOYEN = 1UL << 11, +RTCEN = 1UL << 13, +}; + +static uint64_t ls7a_rtc_read(void *opaque, hwaddr addr, + unsigned size) +{ + LS7A_RTCState *s = (LS7A_RTCState *)opaque; + struct tm tm; + unsigned int val; + + val = 0; + + switch (addr) { + case SYS_TOYREAD0: + qemu_get_timedate(&tm, s->offset); + val = (((tm.tm_mon + 1) & TOY_MON_MASK) << TOY_MON_SHIFT) + | (((tm.tm_mday) & TOY_DAY_MASK) << TOY_DAY_SHIFT) + | (((tm.tm_hour) & TOY_HOUR_MASK) << TOY_HOUR_SHIFT) + | (((tm.tm_min) & TOY_MIN_MASK) << TOY_MIN_SHIFT) + | (((tm.tm_sec) & TOY_SEC_MASK) << TOY_SEC_SHIFT) | 0x0; + break; + case SYS_TOYREAD1: + qemu_get_timedate(&tm, s->offset); + val = tm.tm_year; + break; + case SYS_TOYMATCH0: + val = s->toymatch[0]; + break; + case SYS_TOYMATCH1: + val = s->toymatch[1]; + break; + case SYS_TOYMATCH2: + val = s->toymatch[2]; + break; + case SYS_RTCCTRL: + val = s->cntrctl; + break; + case SYS_RTCREAD0: + val = s->rtccount; + break; + case SYS_RTCMATCH0: + val = s->rtcmatch[0]; + break; + case SYS_RTCMATCH1: + val = s->rtcmatch[1]; + break; + case SYS_RTCMATCH2: + val = s->rtcmatch[2]; + break; + default: + val = 0; + break; + } + return val; +} + + +static void ls7a_rtc_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + LS7A_RTCState *s = (LS7A_RTCState *)opaque; + struct tm tm; + int64_t alarm_offset, year_diff, expire_time; + + switch (addr) { + case SYS_TOYWRITE0: + qemu_get_timedate(&tm, s->offset); + tm.tm_sec = (val >> TOY_SEC_SHIFT) & TOY_SEC_MASK; + tm.tm_min = (val >> TOY_MIN_SHIFT) & TOY_MIN_MASK; + tm.tm_hour = (val >> TOY_HOUR_SHIFT) & TOY_HOUR_MASK; + tm.tm_mday = ((val >> TOY_DAY_SHIFT) & TOY_DAY_MASK); + tm.tm_mon = ((val >> TOY_MON_SHIFT) & TOY_MON_MASK) - 1; + s->offset = qemu_timedate_diff(&tm); + break; + case SYS_TOYWRITE1: + qemu_get_timedate(&tm, s->offset); + tm.tm_year = val; + s->offset = qemu_timedate_diff(&tm); + break; + case SYS_TOYMATCH0: + s->toymatch[0] = val; + qemu_get_timedate(&tm, s->offset); + tm.tm_sec = (val >> TOY_MATCH_SEC_SHIFT) & TOY_MATCH_SEC_MASK; + tm.tm_min = (val >> TOY_MATCH_MIN_SHIFT) & TOY_MATCH_MIN_MASK; + tm.tm_hour = ((val >> TOY_MATCH_HOUR_SHIFT) & TOY_MATCH_HOUR_MASK); + tm.tm_mday = ((val >> TOY_MATCH_DAY_SHIFT) & TOY_MATCH_DAY_MASK); + tm.tm_mon = ((val >> TOY_MATCH_MON_SHIFT) & TOY_MATCH_MON_MASK) - 1; + year_diff = ((val >> TOY_MATCH_YEAR_SHIFT) & TOY_MATCH_YEAR_MASK); + year_diff = year_diff - (tm.tm_year & TOY_MATCH_YEAR_MASK); + tm.tm_year = tm.tm_year + year_diff; + alarm_offset = qemu_timedate_diff(&tm) - s->offset; + if ((alarm_offset < 0) && (alarm_offset > -5)) { + alarm_offset = 0; + } + expire_time = qemu_clock_get_ms(rtc_clock); + expire_time += ((alarm_offset * 1000) + 100); + timer_mod(s->timer, expire_time); + break; + case SYS_TOYMATCH1: + s->toymatch[1] = val; + break; + case SYS_TOYMATCH2: + s->toymatch[2] = val; + break; + case SYS_RTCCTRL: + s->cntrctl = val; + break; + case SYS_RTCWRTIE0: + s->rtccount = val; + break; + case SYS_RTCMATCH0: + s->rtcmatch[0] = val; + break; + case SYS_RTCMATCH1: + val = s->rtcmatch[1]; + break; + case SYS_RTCMATCH2: + val = s->rtcmatch[2]; + break; + default: + break; + } +} + +static const MemoryRegionOps ls7a_rtc_ops = { + .read = ls7a_rtc_read, + .write = ls7a_rtc_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, + +}; + +static void toy_timer(void *opaque) +{ + LS7A_RTCState *s = (LS7A_RTCState *) opaque; + + if (s->cntrctl & TOY_ENABLE_BIT) { + qemu_irq_pulse(s->toy_irq); + } +} + +static void ls7a_rtc_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + LS7A_RTCState *d = LS7A_RTC(sbd); + memory_region_init_io(&d->iomem, NULL, &ls7a_rtc_ops, + (void *)d, "ls7a_rtc", 0x100); + + sysbus_init_irq(sbd, &d->toy_irq); + + sysbus_init_mmio(sbd, &d->iomem); + d->timer = timer_new_ms(rtc_clock, toy_timer, d); + timer_mod(d->timer, qemu_clock_get_ms(rtc_clock) + 100); + d->offset = 0; +} + +static int ls7a_rtc_pre_save(void *opaque) +{ + LS7A_RTCState *s = (LS7A_RTCState *)opaque; + struct tm tm; + int64_t year_diff, value; + + value = s->toymatch[0]; + qemu_get_timedate(&tm, s->offset); + tm.tm_sec = (value >> TOY_MATCH_SEC_SHIFT) & TOY_MATCH_SEC_MASK; + tm.tm_min = (value >> TOY_MATCH_MIN_SHIFT) & TOY_MATCH_MIN_MASK; + tm.tm_hour = ((value >> TOY_MATCH_HOUR_SHIFT) & TOY_MATCH_HOUR_MASK); + tm.tm_mday = ((value >> TOY_MATCH_DAY_SHIFT) & TOY_MATCH_DAY_MASK); + tm.tm_mon = ((value >> TOY_MATCH_MON_SHIFT) & TOY_MATCH_MON_MASK) - 1; + year_diff = ((value >> TOY_MATCH_YEAR_SHIFT) & TOY_MATCH_YEAR_MASK); + year_diff = year_diff - (tm.tm_year & TOY_MATCH_YEAR_MASK); + tm.tm_year = tm.tm_year + year_diff; + s->save_alarm_offset = qemu_timedate_diff(&tm) - s->offset; + + return 0; +} + + +static int ls7a_rtc_post_load(void *opaque, int version_id) +{ + LS7A_RTCState *s = (LS7A_RTCState *)opaque; + int64_t expire_time; + + expire_time = qemu_clock_get_ms(rtc_clock) + (s->save_alarm_offset * 1000); + timer_mod(s->timer, expire_time); + + return 0; +} + +static const VMStateDescription vmstate_ls7a_rtc = { + .name = "ls7a_rtc", + .version_id = 1, + .minimum_version_id = 1, + .pre_save = ls7a_rtc_pre_save, + .post_load = ls7a_rtc_post_load, + .fields = (VMStateField[]) { + VMSTATE_INT64(offset, LS7A_RTCState), + VMSTATE_INT64(save_alarm_offset, LS7A_RTCState), + VMSTATE_UINT32(toymatch[0], LS7A_RTCState), + VMSTATE_UINT32(cntrctl, LS7A_RTCState), + VMSTATE_END_OF_LIST() + } +}; + + +static void ls7a_rtc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + dc->vmsd = &vmstate_ls7a_rtc; + dc->realize = ls7a_rtc_realize; + dc->desc = "ls7a rtc"; +} + +static const TypeInfo ls7a_rtc_info = { + .name = TYPE_LS7A_RTC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(LS7A_RTCState), + .class_init = ls7a_rtc_class_init, +}; + +static void ls7a_rtc_register_types(void) +{ + type_register_static(&ls7a_rtc_info); +} + +type_init(ls7a_rtc_register_types) diff --git a/hw/timer/meson.build b/hw/timer/meson.build index 03092e2ceb..e841a2f6ee 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -16,6 +16,7 @@ softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_mct.c')) softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pwm.c')) softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_gptimer.c')) softmmu_ss.add(when: 'CONFIG_HPET', if_true: files('hpet.c')) +softmmu_ss.add(when: 'CONFIG_LS7A_RTC', if_true: files('ls7a_rtc.c')) softmmu_ss.add(when: 'CONFIG_I8254', if_true: files('i8254_common.c', 'i8254.c')) softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_epit.c')) softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_gpt.c')) -- Gitee From cc64637b5da0a5a306396764f5af992feb69e537 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Fri, 19 Aug 2022 23:39:00 -0400 Subject: [PATCH 03/29] Add loongarch machine. Change-Id: I7e31f874c676b740269945d5e19c6bc836de6a99 Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- hw/loongarch/Kconfig | 17 + hw/loongarch/acpi-build.c | 783 ++++++++++++ hw/loongarch/acpi-build.h | 16 + hw/loongarch/apic.c | 675 +++++++++++ hw/loongarch/ioapic.c | 422 +++++++ hw/loongarch/iocsr.c | 219 ++++ hw/loongarch/ipi.c | 267 +++++ hw/loongarch/larch_3a.c | 2026 ++++++++++++++++++++++++++++++++ hw/loongarch/larch_hotplug.c | 355 ++++++ hw/loongarch/larch_int.c | 91 ++ hw/loongarch/ls7a_nb.c | 352 ++++++ hw/loongarch/meson.build | 15 + include/hw/loongarch/bios.h | 5 + include/hw/loongarch/cpudevs.h | 53 + include/hw/loongarch/larch.h | 163 +++ include/hw/loongarch/ls7a.h | 152 +++ 16 files changed, 5611 insertions(+) create mode 100644 hw/loongarch/Kconfig create mode 100644 hw/loongarch/acpi-build.c create mode 100644 hw/loongarch/acpi-build.h create mode 100644 hw/loongarch/apic.c create mode 100644 hw/loongarch/ioapic.c create mode 100644 hw/loongarch/iocsr.c create mode 100644 hw/loongarch/ipi.c create mode 100644 hw/loongarch/larch_3a.c create mode 100644 hw/loongarch/larch_hotplug.c create mode 100644 hw/loongarch/larch_int.c create mode 100644 hw/loongarch/ls7a_nb.c create mode 100644 hw/loongarch/meson.build create mode 100644 include/hw/loongarch/bios.h create mode 100644 include/hw/loongarch/cpudevs.h create mode 100644 include/hw/loongarch/larch.h create mode 100644 include/hw/loongarch/ls7a.h diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig new file mode 100644 index 0000000000..3fe2677fda --- /dev/null +++ b/hw/loongarch/Kconfig @@ -0,0 +1,17 @@ +config LS7A_APIC + bool + +config LS7A_RTC + bool + +config LOONGSON3A + bool + +config MEM_HOTPLUG + bool + +config ACPI_LOONGARCH + bool + +config E1000E_PCI + bool diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c new file mode 100644 index 0000000000..6ba637be53 --- /dev/null +++ b/hw/loongarch/acpi-build.c @@ -0,0 +1,783 @@ +/* Support for generating ACPI tables and passing them to Guests + * + * Copyright (C) 2008-2010 Kevin O'Connor + * Copyright (C) 2006 Fabrice Bellard + * Copyright (C) 2013 Red Hat Inc + * + * Author: Michael S. Tsirkin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qapi/qmp/qnum.h" +#include "acpi-build.h" +#include "qemu-common.h" +#include "qemu/bitmap.h" +#include "qemu/error-report.h" +#include "hw/pci/pci.h" +#include "hw/boards.h" +#include "hw/core/cpu.h" +#include "target/loongarch64/cpu.h" +#include "hw/misc/pvpanic.h" +#include "hw/timer/hpet.h" +#include "hw/acpi/acpi-defs.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/cpu.h" +#include "hw/nvram/fw_cfg.h" +#include "hw/acpi/bios-linker-loader.h" +#include "hw/loader.h" +#include "hw/isa/isa.h" +#include "hw/block/fdc.h" +#include "hw/acpi/memory_hotplug.h" +#include "sysemu/tpm.h" +#include "hw/acpi/tpm.h" +#include "hw/acpi/vmgenid.h" +#include "sysemu/tpm_backend.h" +#include "hw/rtc/mc146818rtc_regs.h" +#include "sysemu/numa.h" +#include "sysemu/runstate.h" +#include "sysemu/reset.h" +#include "migration/vmstate.h" +#include "hw/mem/memory-device.h" +#include "hw/acpi/utils.h" +#include "hw/acpi/pci.h" +/* Supported chipsets: */ +#include "hw/acpi/aml-build.h" +#include "hw/loongarch/larch.h" +#include "hw/loongarch/ls7a.h" + +#include "hw/acpi/ipmi.h" +#include "hw/acpi/ls7a.h" + +/* These are used to size the ACPI tables for -M pc-i440fx-1.7 and + * -M pc-i440fx-2.0. Even if the actual amount of AML generated grows + * a little bit, there should be plenty of free space since the DSDT + * shrunk by ~1.5k between QEMU 2.0 and QEMU 2.1. + */ +#define ACPI_BUILD_ALIGN_SIZE 0x1000 + +#define ACPI_BUILD_TABLE_SIZE 0x20000 + +/* #define DEBUG_ACPI_BUILD */ +#ifdef DEBUG_ACPI_BUILD +#define ACPI_BUILD_DPRINTF(fmt, ...) \ + do {printf("ACPI_BUILD: " fmt, ## __VA_ARGS__); } while (0) +#else +#define ACPI_BUILD_DPRINTF(fmt, ...) +#endif + +/* Default IOAPIC ID */ +#define ACPI_BUILD_IOAPIC_ID 0x0 + +/* PCI fw r3.0 MCFG table. */ +/* Subtable */ + +typedef struct AcpiMiscInfo { + bool is_piix4; + bool has_hpet; + TPMVersion tpm_version; + const unsigned char *dsdt_code; + unsigned dsdt_size; + uint16_t pvpanic_port; + uint16_t applesmc_io_base; +} AcpiMiscInfo; + +typedef struct AcpiBuildPciBusHotplugState { + GArray *device_table; + GArray *notify_table; + struct AcpiBuildPciBusHotplugState *parent; + bool pcihp_bridge_en; +} AcpiBuildPciBusHotplugState; + +static void init_common_fadt_data(AcpiFadtData *data) +{ + AmlAddressSpace as = AML_AS_SYSTEM_MEMORY; + uint64_t base = LS7A_ACPI_REG_BASE; + AcpiFadtData fadt = { + .rev = 3, + .flags = + (1 << ACPI_FADT_F_WBINVD) | + (1 << ACPI_FADT_F_PROC_C1) | + (1 << ACPI_FADT_F_SLP_BUTTON) | + (1 << ACPI_FADT_F_TMR_VAL_EXT) | + (1 << ACPI_FADT_F_RESET_REG_SUP) , + .plvl2_lat = 0xfff /* C2 state not supported */, + .plvl3_lat = 0xfff /* C3 state not supported */, + .smi_cmd = 0x00, + .sci_int = ACPI_SCI_IRQ, + .acpi_enable_cmd = 0x00, + .acpi_disable_cmd = 0x00, + .pm1a_evt = { .space_id = as, .bit_width = 8 * 8, + .address = base + LS7A_PM_EVT_BLK }, + .pm1a_cnt = { .space_id = as, .bit_width = 4 * 8, + .address = base + LS7A_PM_CNT_BLK }, + .pm_tmr = { .space_id = as, .bit_width = 4 * 8, + .address = base + LS7A_PM_TMR_BLK }, + .gpe0_blk = { .space_id = as, .bit_width = 8 * 8, + .address = base + LS7A_GPE0_STS_REG}, + .reset_reg = { .space_id = as, .bit_width = 4 * 8, + .address = base + LS7A_GPE0_RESET_REG}, + .reset_val = 0x1, + }; + *data = fadt; +} + +static void acpi_align_size(GArray *blob, unsigned align) +{ + /* Align size to multiple of given size. This reduces the chance + * we need to change size in the future (breaking cross version migration). + */ + g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); +} + +/* FACS */ +static void +build_facs(GArray *table_data) +{ + const char *sig = "FACS"; + const uint8_t reserved[40] = {}; + + g_array_append_vals(table_data, sig, 4); /* Signature */ + build_append_int_noprefix(table_data, 64, 4); /* Length */ + build_append_int_noprefix(table_data, 0, 4); /* Hardware Signature */ + build_append_int_noprefix(table_data, 0, 4); /* Firmware Waking Vector */ + build_append_int_noprefix(table_data, 0, 4); /* Global Lock */ + build_append_int_noprefix(table_data, 0, 4); /* Flags */ + g_array_append_vals(table_data, reserved, 40); /* Reserved */ +} + +void ls7a_madt_cpu_entry(AcpiDeviceIf *adev, int uid, + const CPUArchIdList *apic_ids, GArray *entry, bool force_enabled) +{ + uint32_t apic_id = apic_ids->cpus[uid].arch_id; + /* Flags – Local APIC Flags */ + uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ? + 1 /* Enabled */ : 0; + + /* Rev 1.0b, Table 5-13 Processor Local APIC Structure */ + build_append_int_noprefix(entry, 0, 1); /* Type */ + build_append_int_noprefix(entry, 8, 1); /* Length */ + build_append_int_noprefix(entry, uid, 1); /* ACPI Processor ID */ + build_append_int_noprefix(entry, apic_id, 1); /* APIC ID */ + build_append_int_noprefix(entry, flags, 4); /* Flags */ +} +static void build_ioapic(GArray *entry, uint8_t id, uint32_t addr, uint32_t irq) +{ + /* Rev 1.0b, 5.2.8.2 IO APIC */ + build_append_int_noprefix(entry, 1, 1); /* Type */ + build_append_int_noprefix(entry, 12, 1); /* Length */ + build_append_int_noprefix(entry, id, 1); /* IO APIC ID */ + build_append_int_noprefix(entry, 0, 1); /* Reserved */ + build_append_int_noprefix(entry, addr, 4); /* IO APIC Address */ + build_append_int_noprefix(entry, irq, 4); /* System Vector Base */ +} + +static void +build_madt(GArray *table_data, BIOSLinker *linker, LoongarchMachineState *lsms) +{ + LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + MachineClass *mc = MACHINE_GET_CLASS(lsms); + const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(lsms)); + AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(lsms->acpi_dev); + AcpiDeviceIf *adev = ACPI_DEVICE_IF(lsms->acpi_dev); + int i; + AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = lsms->oem_id, + .oem_table_id = lsms->oem_table_id}; + + acpi_table_begin(&table, table_data); + + /* Local APIC Address */ + build_append_int_noprefix(table_data, 0, 4); + build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */ + + + for (i = 0; i < apic_ids->len; i++) { + adevc->madt_cpu(adev, i, apic_ids, table_data, false); + } + + + build_ioapic(table_data, ACPI_BUILD_IOAPIC_ID, lsmc->ls7a_ioapic_reg_base, LOONGARCH_PCH_IRQ_BASE); + + /* Rev 1.0b, 5.2.8.3.3 Local APIC NMI */ + build_append_int_noprefix(table_data, 3, 1); /* Type */ + build_append_int_noprefix(table_data, 6, 1); /* Length */ + /* ACPI Processor ID */ + build_append_int_noprefix(table_data, 0xFF /* all processors */, 1); + build_append_int_noprefix(table_data, 0, 2); /* Flags */ + /* Local APIC INTI# */ + build_append_int_noprefix(table_data, 1 /* ACPI_LINT1 */, 1); + + /* Rev 1.0b, 5.2.8.3.3 Local APIC NMI */ + build_append_int_noprefix(table_data, 4, 1); /* Type */ + build_append_int_noprefix(table_data, 6, 1); /* Length */ + /* ACPI Processor ID */ + build_append_int_noprefix(table_data, 0xFF /* all processors */, 1); + build_append_int_noprefix(table_data, 0, 2); /* Flags */ + /* Local APIC INTI# */ + build_append_int_noprefix(table_data, 1 /* ACPI_LINT1 */, 1); + + + acpi_table_end(linker, &table); +} + +static void +build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) +{ + uint64_t i, mem_len, mem_base; + MachineClass *mc = MACHINE_GET_CLASS(machine); + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine); + int nb_numa_nodes = machine->numa_state->num_nodes; + NodeInfo *numa_info = machine->numa_state->nodes; + AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = lsms->oem_id, + .oem_table_id = lsms->oem_table_id}; + + acpi_table_begin(&table, table_data); + build_append_int_noprefix(table_data, 1, 4); /* Reserved */ + build_append_int_noprefix(table_data, 0, 8); /* Reserved */ + + for (i = 0; i < apic_ids->len; ++i) { + /* 5.2.15.1 Processor Local APIC/SAPIC Affinity Structure */ + build_append_int_noprefix(table_data, 0, 1); /* Type */ + build_append_int_noprefix(table_data, 16, 1); /* Length */ + /* Proximity Domain [7:0] */ + build_append_int_noprefix(table_data, apic_ids->cpus[i].props.node_id, 1); + build_append_int_noprefix(table_data, apic_ids->cpus[i].arch_id, 1); /* APIC ID */ + /* Flags, Table 5-36 */ + build_append_int_noprefix(table_data, 1, 4); + build_append_int_noprefix(table_data, 0, 1); /* Local SAPIC EID */ + /* Proximity Domain [31:8] */ + build_append_int_noprefix(table_data, 0, 3); + build_append_int_noprefix(table_data, 0, 4); /* Reserved */ + } + + /* node0 */ + mem_base = (uint64_t)0; + mem_len = 0x10000000; + build_srat_memory(table_data, mem_base, mem_len, + 0, MEM_AFFINITY_ENABLED); + mem_base = 0x90000000; + if (!nb_numa_nodes) { + mem_len = machine->ram_size - 0x10000000; + } else { + mem_len = numa_info[0].node_mem - 0x10000000; + } + + build_srat_memory(table_data, mem_base, mem_len, + 0, MEM_AFFINITY_ENABLED); + mem_base += mem_len; + + /* node1 ~ nodemax */ + for (i = 1; i < nb_numa_nodes; ++i) { + mem_len = numa_info[i].node_mem; + build_srat_memory(table_data, mem_base, mem_len, + i, MEM_AFFINITY_ENABLED); + mem_base += mem_len; + } + + if (lsms->hotplug_memory_size) { + build_srat_memory(table_data, machine->device_memory->base, + lsms->hotplug_memory_size, 0, + MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); + } + + acpi_table_end(linker, &table); + +} + +typedef +struct AcpiBuildState { + /* Copy of table in RAM (for patching). */ + MemoryRegion *table_mr; + /* Is table patched? */ + uint8_t patched; + void *rsdp; + MemoryRegion *rsdp_mr; + MemoryRegion *linker_mr; +} AcpiBuildState; + +static void build_ls7a_pci0_int(Aml *table) +{ + Aml *sb_scope = aml_scope("_SB"); + Aml *pci0_scope = aml_scope("PCI0"); + Aml *prt_pkg = aml_varpackage(128); + int slot, pin; + + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { + for (pin = 0; pin < PCI_NUM_PINS; pin++) { + Aml *pkg = aml_package(4); + aml_append(pkg, aml_int((slot << 16) | 0xFFFF)); + aml_append(pkg, aml_int(pin)); + aml_append(pkg, aml_int(0)); + aml_append(pkg, aml_int(LOONGARCH_PCH_IRQ_BASE + 16 + (slot * 4 + pin) % 16)); + aml_append(prt_pkg, pkg); + } + } + aml_append(pci0_scope, + aml_name_decl("_PRT", prt_pkg)); + + aml_append(sb_scope, pci0_scope); + + aml_append(table, sb_scope); +} + +static void build_dbg_aml(Aml *table) +{ + Aml *field; + Aml *method; + Aml *while_ctx; + Aml *scope = aml_scope("\\"); + Aml *buf = aml_local(0); + Aml *len = aml_local(1); + Aml *idx = aml_local(2); + + aml_append(scope, + aml_operation_region("DBG", AML_SYSTEM_IO, aml_int(0x0402), 0x01)); + field = aml_field("DBG", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); + aml_append(field, aml_named_field("DBGB", 8)); + aml_append(scope, field); + + method = aml_method("DBUG", 1, AML_NOTSERIALIZED); + + aml_append(method, aml_to_hexstring(aml_arg(0), buf)); + aml_append(method, aml_to_buffer(buf, buf)); + aml_append(method, aml_subtract(aml_sizeof(buf), aml_int(1), len)); + aml_append(method, aml_store(aml_int(0), idx)); + + while_ctx = aml_while(aml_lless(idx, len)); + aml_append(while_ctx, + aml_store(aml_derefof(aml_index(buf, idx)), aml_name("DBGB"))); + aml_append(while_ctx, aml_increment(idx)); + aml_append(method, while_ctx); + + aml_append(method, aml_store(aml_int(0x0A), aml_name("DBGB"))); + aml_append(scope, method); + + aml_append(table, scope); +} + +static Aml *build_ls7a_osc_method(void) +{ + Aml *if_ctx; + Aml *if_ctx2; + Aml *else_ctx; + Aml *method; + Aml *a_cwd1 = aml_name("CDW1"); + Aml *a_ctrl = aml_local(0); + + method = aml_method("_OSC", 4, AML_NOTSERIALIZED); + aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1")); + + if_ctx = aml_if(aml_equal( + aml_arg(0), aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766"))); + aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2")); + aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3")); + + aml_append(if_ctx, aml_store(aml_name("CDW3"), a_ctrl)); + + /* + * Always allow native PME, AER (no dependencies) + * Allow SHPC (PCI bridges can have SHPC controller) + */ + aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl)); + + if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1)))); + /* Unknown revision */ + aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x08), a_cwd1)); + aml_append(if_ctx, if_ctx2); + + if_ctx2 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl))); + /* Capabilities bits were masked */ + aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x10), a_cwd1)); + aml_append(if_ctx, if_ctx2); + + /* Update DWORD3 in the buffer */ + aml_append(if_ctx, aml_store(a_ctrl, aml_name("CDW3"))); + aml_append(method, if_ctx); + + else_ctx = aml_else(); + /* Unrecognized UUID */ + aml_append(else_ctx, aml_or(a_cwd1, aml_int(4), a_cwd1)); + aml_append(method, else_ctx); + + aml_append(method, aml_return(aml_arg(3))); + return method; +} + +static void build_ls7a_rtc_device_aml(Aml *table) +{ + Aml *dev; + Aml *crs; + uint32_t rtc_irq = LS7A_RTC_IRQ; + + Aml *scope = aml_scope("_SB"); + dev = aml_device("RTC"); + aml_append(dev, aml_name_decl("_HID", aml_string("LOON0001"))); + crs = aml_resource_template(); + aml_append(crs, + aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, + AML_NON_CACHEABLE, AML_READ_WRITE, + 0, LS7A_RTC_REG_BASE, + LS7A_RTC_REG_BASE + LS7A_RTC_LEN - 1, 0, LS7A_RTC_LEN)); + aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &rtc_irq, 1)); + + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); + aml_append(table, scope); +} + +static void build_ls7a_uart_device_aml(Aml *table) +{ + Aml *dev; + Aml *crs; + Aml *pkg0, *pkg1, *pkg2; + uint32_t uart_irq = LS7A_UART_IRQ; + + Aml *scope = aml_scope("_SB"); + dev = aml_device("COMA"); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0501"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); + crs = aml_resource_template(); + aml_append(crs, + aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, + AML_NON_CACHEABLE, AML_READ_WRITE, + 0, LS7A_UART_BASE, LS7A_UART_BASE + LS7A_UART_LEN - 1, 0, 0x8)); + aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &uart_irq, 1)); + aml_append(dev, aml_name_decl("_CRS", crs)); + pkg0 = aml_package(0x2); + aml_append(pkg0, aml_int(0x01F78A40)); + aml_append(pkg0, aml_string("clock-frenquency")); + pkg1 = aml_package(0x1); + aml_append(pkg1, pkg0); + pkg2 = aml_package(0x2); + aml_append(pkg2, aml_touuid("DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301")); + aml_append(pkg2, pkg1); + + aml_append(dev, aml_name_decl("_DSD", pkg2)); + + aml_append(scope, dev); + aml_append(table, scope); +} + +static void +build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) +{ + Aml *dsdt, *sb_scope, *scope, *dev, *crs, *pkg; + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + uint32_t nr_mem = machine->ram_slots; + uint64_t base = LS7A_ACPI_REG_BASE; + int root_bus_limit = PCIE_MMCFG_BUS(LS_PCIECFG_SIZE - 1); + AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = lsms->oem_id, + .oem_table_id = lsms->oem_table_id}; + + acpi_table_begin(&table, table_data); + dsdt = init_aml_allocator(); + + build_dbg_aml(dsdt); + + sb_scope = aml_scope("_SB"); + dev = aml_device("PCI0"); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); + aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); + aml_append(dev, aml_name_decl("_ADR", aml_int(0))); + aml_append(dev, aml_name_decl("_BBN", aml_int(0))); + aml_append(dev, aml_name_decl("_UID", aml_int(1))); + aml_append(dev, build_ls7a_osc_method()); + aml_append(sb_scope, dev); + aml_append(dsdt, sb_scope); + + build_ls7a_pci0_int(dsdt); + build_ls7a_rtc_device_aml(dsdt); + build_ls7a_uart_device_aml(dsdt); + + if (lsms->acpi_dev) { + CPUHotplugFeatures opts = { + .acpi_1_compatible = true, .has_legacy_cphp = false + }; + build_cpus_aml(dsdt, machine, opts, CPU_HOTPLUG_BASE, + "\\_SB.PCI0", "\\_GPE._E02"); + + build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0", + "\\_GPE._E03", AML_SYSTEM_MEMORY, + MEMORY_HOTPLUG_BASE); + } + + scope = aml_scope("_GPE"); + { + aml_append(scope, aml_name_decl("_HID", aml_string("ACPI0006"))); + } + aml_append(dsdt, scope); + + scope = aml_scope("\\_SB.PCI0"); + /* build PCI0._CRS */ + crs = aml_resource_template(); + aml_append(crs, + aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, + 0x0000, 0x0, root_bus_limit, + 0x0000, root_bus_limit + 1)); + aml_append(crs, + aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED, + AML_POS_DECODE, AML_ENTIRE_RANGE, + 0x0000, 0x4000, 0xFFFF, 0x0000, 0xC000)); + aml_append(crs, + aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, + AML_CACHEABLE, AML_READ_WRITE, + 0, 0x40000000, 0x7FFFFFFF, 0, 0x40000000)); + aml_append(scope, aml_name_decl("_CRS", crs)); + + /* reserve GPE0 block resources */ + dev = aml_device("GPE0"); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06"))); + aml_append(dev, aml_name_decl("_UID", aml_string("GPE0 resources"))); + /* device present, functioning, decoding, not shown in UI */ + aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); + crs = aml_resource_template(); + aml_append(crs, + aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, + AML_CACHEABLE, AML_READ_WRITE, + 0, base + LS7A_GPE0_STS_REG, + base + LS7A_GPE0_STS_REG + 0x3, 0, 0x4)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); + aml_append(dsdt, scope); + + scope = aml_scope("\\"); + pkg = aml_package(4); + aml_append(pkg, aml_int(7)); /* PM1a_CNT.SLP_TYP */ + aml_append(pkg, aml_int(7)); /* PM1b_CNT.SLP_TYP not impl. */ + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(scope, aml_name_decl("_S5", pkg)); + aml_append(dsdt, scope); + + /* copy AML table into ACPI tables blob and patch header there */ + g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); + acpi_table_end(linker, &table); + free_aml_allocator(); +} + + +static +void acpi_build(AcpiBuildTables *tables, MachineState *machine) +{ + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + GArray *table_offsets; + AcpiFadtData fadt_data; + unsigned facs, rsdt, fadt, dsdt; + uint8_t *u; + size_t aml_len = 0; + GArray *tables_blob = tables->table_data; + + init_common_fadt_data(&fadt_data); + + table_offsets = g_array_new(false, true /* clear */, + sizeof(uint32_t)); + ACPI_BUILD_DPRINTF("init ACPI tables\n"); + + bios_linker_loader_alloc(tables->linker, + ACPI_BUILD_TABLE_FILE, tables_blob, + 64 /* Ensure FACS is aligned */, + false /* high memory */); + + /* + * FACS is pointed to by FADT. + * We place it first since it's the only table that has alignment + * requirements. + */ + facs = tables_blob->len; + build_facs(tables_blob); + + /* DSDT is pointed to by FADT */ + dsdt = tables_blob->len; + build_dsdt(tables_blob, tables->linker, MACHINE(qdev_get_machine())); + + /* Count the size of the DSDT and SSDT, we will need it for legacy + * sizing of ACPI tables. + */ + aml_len += tables_blob->len - dsdt; + + /* ACPI tables pointed to by RSDT */ + fadt = tables_blob->len; + acpi_add_table(table_offsets, tables_blob); + fadt_data.facs_tbl_offset = &facs; + fadt_data.dsdt_tbl_offset = &dsdt; + fadt_data.xdsdt_tbl_offset = &dsdt; + build_fadt(tables_blob, tables->linker, &fadt_data, + "LOONGS", "TP-R00"); + aml_len += tables_blob->len - fadt; + + acpi_add_table(table_offsets, tables_blob); + build_madt(tables_blob, tables->linker, lsms); + + acpi_add_table(table_offsets, tables_blob); + build_srat(tables_blob, tables->linker, machine); + if (machine->numa_state->have_numa_distance) { + acpi_add_table(table_offsets, tables_blob); + build_slit(tables_blob, tables->linker, machine, lsms->oem_id, + lsms->oem_table_id); + } + + /* Build mcfg */ + acpi_add_table(table_offsets, tables_blob); + { + AcpiMcfgInfo mcfg = { + .base = LS_PCIECFG_BASE, + .size = LS_PCIECFG_SIZE, + }; + build_mcfg(tables_blob, tables->linker, &mcfg, lsms->oem_id, + lsms->oem_table_id); + } + + /* Add tables supplied by user (if any) */ + for (u = acpi_table_first(); u; u = acpi_table_next(u)) { + unsigned len = acpi_table_len(u); + + acpi_add_table(table_offsets, tables_blob); + g_array_append_vals(tables_blob, u, len); + } + + /* RSDT is pointed to by RSDP */ + rsdt = tables_blob->len; + build_rsdt(tables_blob, tables->linker, table_offsets, + "LOONGS", "TP-R00"); + + /* RSDP is in FSEG memory, so allocate it separately */ + { + AcpiRsdpData rsdp_data = { + .revision = 0, + .oem_id = lsms->oem_id, + .xsdt_tbl_offset = NULL, + .rsdt_tbl_offset = &rsdt, + }; + build_rsdp(tables->rsdp, tables->linker, &rsdp_data); + } + acpi_align_size(tables->linker->cmd_blob, ACPI_BUILD_ALIGN_SIZE); + + /* Cleanup memory that's no longer used. */ + g_array_free(table_offsets, true); +} + +static void acpi_ram_update(MemoryRegion *mr, GArray *data) +{ + uint32_t size = acpi_data_len(data); + + /* Make sure RAM size is correct - + in case it got changed e.g. by migration */ + memory_region_ram_resize(mr, size, &error_abort); + + memcpy(memory_region_get_ram_ptr(mr), data->data, size); + memory_region_set_dirty(mr, 0, size); +} + +static void acpi_build_update(void *build_opaque) +{ + AcpiBuildState *build_state = build_opaque; + AcpiBuildTables tables; + + /* No state to update or already patched? Nothing to do. */ + if (!build_state || build_state->patched) { + return; + } + build_state->patched = 1; + + acpi_build_tables_init(&tables); + + acpi_build(&tables, MACHINE(qdev_get_machine())); + + acpi_ram_update(build_state->table_mr, tables.table_data); + + if (build_state->rsdp) { + memcpy(build_state->rsdp, tables.rsdp->data, + acpi_data_len(tables.rsdp)); + } else { + acpi_ram_update(build_state->rsdp_mr, tables.rsdp); + } + + acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob); + acpi_build_tables_cleanup(&tables, true); +} + +static void acpi_build_reset(void *build_opaque) +{ + AcpiBuildState *build_state = build_opaque; + build_state->patched = 0; +} + +static const VMStateDescription vmstate_acpi_build = { + .name = "acpi_build", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(patched, AcpiBuildState), + VMSTATE_END_OF_LIST() + }, +}; + +void loongarch_acpi_setup(void) +{ + LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); + AcpiBuildTables tables; + AcpiBuildState *build_state; + + if (!lsms->fw_cfg) { + ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n"); + return; + } + + if (!lsms->acpi_build_enabled) { + ACPI_BUILD_DPRINTF("ACPI build disabled. Bailing out.\n"); + return; + } + + if (!loongarch_is_acpi_enabled(lsms)) { + ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n"); + return; + } + + build_state = g_malloc0(sizeof *build_state); + + acpi_build_tables_init(&tables); + acpi_build(&tables, MACHINE(lsms)); + + /* Now expose it all to Guest */ + build_state->table_mr = acpi_add_rom_blob(acpi_build_update, build_state, + tables.table_data, + ACPI_BUILD_TABLE_FILE); + assert(build_state->table_mr != NULL); + + build_state->linker_mr = + acpi_add_rom_blob(acpi_build_update, build_state, tables.linker->cmd_blob, + "etc/table-loader"); + + fw_cfg_add_file(lsms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, + tables.tcpalog->data, acpi_data_len(tables.tcpalog)); + + build_state->rsdp = NULL; + build_state->rsdp_mr = acpi_add_rom_blob(acpi_build_update, build_state, tables.rsdp, + ACPI_BUILD_RSDP_FILE); + + qemu_register_reset(acpi_build_reset, build_state); + acpi_build_reset(build_state); + vmstate_register(NULL, 0, &vmstate_acpi_build, build_state); + + /* Cleanup tables but don't free the memory: we track it + * in build_state. + */ + acpi_build_tables_cleanup(&tables, false); +} diff --git a/hw/loongarch/acpi-build.h b/hw/loongarch/acpi-build.h new file mode 100644 index 0000000000..a914268bbe --- /dev/null +++ b/hw/loongarch/acpi-build.h @@ -0,0 +1,16 @@ + +#ifndef HW_LARCH_ACPI_BUILD_H +#define HW_LARCH_ACPI_BUILD_H + +#define EFI_ACPI_OEM_ID "LARCH" +#define EFI_ACPI_OEM_TABLE_ID "LARCH" /* OEM table id 8 bytes long */ +#define EFI_ACPI_OEM_REVISION 0x00000002 +#define EFI_ACPI_CREATOR_ID "LINUX" +#define EFI_ACPI_CREATOR_REVISION 0x01000013 + +#define ACPI_COMPATIBLE_1_0 0 +#define ACPI_COMPATIBLE_2_0 1 + +void loongarch_acpi_setup(void); + +#endif diff --git a/hw/loongarch/apic.c b/hw/loongarch/apic.c new file mode 100644 index 0000000000..d6ba2a2cec --- /dev/null +++ b/hw/loongarch/apic.c @@ -0,0 +1,675 @@ +/* + * Loongarch 3A5000 interrupt controller emulation + * + * Copyright (C) 2020 Lu Zeng + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/boards.h" +#include "hw/irq.h" +#include "hw/loongarch/cpudevs.h" +#include "hw/sysbus.h" +#include "qemu/host-utils.h" +#include "qemu/error-report.h" +#include "sysemu/kvm.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "target/loongarch64/cpu.h" +#include "exec/address-spaces.h" +#include "hw/loongarch/larch.h" +#include "migration/vmstate.h" + +#define DEBUG_APIC 0 + +#define DPRINTF(fmt, ...) \ +do { \ + if (DEBUG_APIC) { \ + fprintf(stderr, "APIC: " fmt , ## __VA_ARGS__); \ + } \ +} while (0) + +#define APIC_OFFSET 0x400 +#define APIC_BASE (0x1f010000ULL) +#define EXTIOI_NODETYPE_START (0x4a0 - APIC_OFFSET) +#define EXTIOI_NODETYPE_END (0x4c0 - APIC_OFFSET) +#define EXTIOI_IPMAP_START (0x4c0 - APIC_OFFSET) +#define EXTIOI_IPMAP_END (0x4c8 - APIC_OFFSET) +#define EXTIOI_ENABLE_START (0x600 - APIC_OFFSET) +#define EXTIOI_ENABLE_END (0x620 - APIC_OFFSET) +#define EXTIOI_BOUNCE_START (0x680 - APIC_OFFSET) +#define EXTIOI_BOUNCE_END (0x6a0 - APIC_OFFSET) +#define EXTIOI_ISR_START (0x700 - APIC_OFFSET) +#define EXTIOI_ISR_END (0x720 - APIC_OFFSET) +#define EXTIOI_COREMAP_START (0xC00 - APIC_OFFSET) +#define EXTIOI_COREMAP_END (0xD00 - APIC_OFFSET) +#define EXTIOI_COREISR_START (0x10000) +#define EXTIOI_COREISR_END (EXTIOI_COREISR_START + 0x10000) + +static int ext_irq_pre_save(void *opaque) +{ +#ifdef CONFIG_KVM + apicState *apic = opaque; + struct loongarch_kvm_irqchip *chip; + struct kvm_loongarch_ls3a_extirq_state *kstate; + int ret, length, i, vcpuid; +#endif + if (!kvm_irqchip_in_kernel()) { + return 0; + } +#ifdef CONFIG_KVM + length = sizeof(struct loongarch_kvm_irqchip) + + sizeof(struct kvm_loongarch_ls3a_extirq_state); + chip = g_malloc0(length); + memset(chip, 0, length); + chip->chip_id = KVM_IRQCHIP_LS3A_EXTIRQ; + chip->len = length; + + ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip); + if (ret < 0) { + fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); + abort(); + } + + kstate = (struct kvm_loongarch_ls3a_extirq_state *)chip->data; + for (i = 0; i < EXTIOI_IRQS_BITMAP_SIZE; i++) { + apic->ext_en[i] = kstate->ext_en_r.reg_u8[i]; + apic->ext_bounce[i] = kstate->bounce_r.reg_u8[i]; + apic->ext_isr[i] = kstate->ext_isr_r.reg_u8[i]; + for (vcpuid = 0; vcpuid < MAX_CORES; vcpuid++) { + apic->ext_coreisr[vcpuid][i] = kstate->ext_core_isr_r.reg_u8[vcpuid][i]; + } + } + for (i = 0; i < EXTIOI_IRQS_IPMAP_SIZE; i++) { + apic->ext_ipmap[i] = kstate->ip_map_r.reg_u8[i]; + } + for (i = 0; i < EXTIOI_IRQS; i++) { + apic->ext_coremap[i] = kstate->core_map_r.reg_u8[i];; + } + for (i = 0; i < 16; i++) { + apic->ext_nodetype[i] = kstate->node_type_r.reg_u16[i]; + } + g_free(chip); +#endif + return 0; +} + +static int ext_irq_post_load(void *opaque, int version) +{ +#ifdef CONFIG_KVM + apicState *apic = opaque; + struct loongarch_kvm_irqchip *chip; + struct kvm_loongarch_ls3a_extirq_state *kstate; + int ret, length, i, vcpuid; +#endif + if (!kvm_irqchip_in_kernel()) { + return 0; + } +#ifdef CONFIG_KVM + length = sizeof(struct loongarch_kvm_irqchip) + + sizeof(struct kvm_loongarch_ls3a_extirq_state); + chip = g_malloc0(length); + + chip->chip_id = KVM_IRQCHIP_LS3A_EXTIRQ; + chip->len = length; + + kstate = (struct kvm_loongarch_ls3a_extirq_state *)chip->data; + for (i = 0; i < EXTIOI_IRQS_BITMAP_SIZE; i++) { + kstate->ext_en_r.reg_u8[i] = apic->ext_en[i]; + kstate->bounce_r.reg_u8[i] = apic->ext_bounce[i]; + kstate->ext_isr_r.reg_u8[i] = apic->ext_isr[i]; + for (vcpuid = 0; vcpuid < MAX_CORES; vcpuid++) { + kstate->ext_core_isr_r.reg_u8[vcpuid][i] = apic->ext_coreisr[vcpuid][i]; + } + } + for (i = 0; i < EXTIOI_IRQS_IPMAP_SIZE; i++) { + kstate->ip_map_r.reg_u8[i] = apic->ext_ipmap[i]; + } + for (i = 0; i < EXTIOI_IRQS; i++) { + kstate->core_map_r.reg_u8[i] = apic->ext_coremap[i]; + } + for (i = 0; i < 16; i++) { + kstate->node_type_r.reg_u16[i] = apic->ext_nodetype[i]; + } + + ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); + if (ret < 0) { + fprintf(stderr, "KVM_SET_IRQCHIP failed: %s\n", strerror(ret)); + abort(); + } + g_free(chip); +#endif + return 0; +} +typedef struct nodeApicState { + unsigned long addr; + int nodeid; + apicState *apic; +} nodeApicState; + +static void ioapic_update_irq(void *opaque, int irq, int level) +{ + apicState *s = opaque; + uint8_t ipnum, cpu, cpu_ipnum; + unsigned long found1, found2; + uint8_t reg_count, reg_bit; + + reg_count = irq / 32; + reg_bit = irq % 32; + + ipnum = s->ext_sw_ipmap[irq]; + cpu = s->ext_sw_coremap[irq]; + cpu_ipnum = cpu * LS3A_INTC_IP + ipnum; + if (level == 1) { + if (test_bit(reg_bit, ((void *)s->ext_en + 0x4 * reg_count)) == false) { + return; + } + + if (test_bit(reg_bit, ((void *)s->ext_isr + 0x4 * reg_count)) == false) { + return; + } + bitmap_set(((void *)s->ext_coreisr[cpu] + 0x4 * reg_count), reg_bit, 1); + found1 = find_next_bit(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), + EXTIOI_IRQS, 0); + bitmap_set(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), reg_bit, 1); + if (found1 >= EXTIOI_IRQS) { + qemu_set_irq(s->parent_irq[cpu][ipnum], level); + } + } else { + bitmap_clear(((void *)s->ext_isr + 0x4 * reg_count), reg_bit, 1); + bitmap_clear(((void *)s->ext_coreisr[cpu] + 0x4 * reg_count), reg_bit, 1); + found1 = find_next_bit(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), + EXTIOI_IRQS, 0); + found1 += reg_count * 32; + bitmap_clear(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), reg_bit, 1); + found2 = find_next_bit(((void *)s->ext_ipisr[cpu_ipnum] + 0x4 * reg_count), + EXTIOI_IRQS, 0); + if ((found1 < EXTIOI_IRQS) && (found2 >= EXTIOI_IRQS)) { + qemu_set_irq(s->parent_irq[cpu][ipnum], level); + } + } +} + +static void ioapic_setirq(void *opaque, int irq, int level) +{ + apicState *s = opaque; + uint8_t reg_count, reg_bit; + + reg_count = irq / 32; + reg_bit = irq % 32; + + if (level) { + bitmap_set(((void *)s->ext_isr + 0x4 * reg_count), reg_bit, 1); + } else { + bitmap_clear(((void *)s->ext_isr + 0x4 * reg_count), reg_bit, 1); + } + + ioapic_update_irq(s, irq, level); +} + +static uint32_t apic_readb(void *opaque, hwaddr addr) +{ + nodeApicState *node; + apicState *state; + unsigned long off; + uint8_t ret; + int cpu; + + node = (nodeApicState *)opaque; + state = node->apic; + off = addr & 0xfffff; + ret = 0; + if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { + off -= EXTIOI_ENABLE_START; + ret = *(uint8_t *)((void *)state->ext_en + off); + } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { + off -= EXTIOI_BOUNCE_START; + ret = *(uint8_t *)((void *)state->ext_bounce + off); + } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { + off -= EXTIOI_ISR_START; + ret = *(uint8_t *)((void *)state->ext_isr + off); + } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { + off -= EXTIOI_COREISR_START; + cpu = (off >> 8) & 0xff; + ret = *(uint8_t *)((void *)state->ext_coreisr[cpu] + (off & 0x1f)); + } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { + off -= EXTIOI_IPMAP_START; + ret = *(uint8_t *)((void *)state->ext_ipmap + off); + } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { + off -= EXTIOI_COREMAP_START; + ret = *(uint8_t *)((void *)state->ext_coremap + off); + } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { + off -= EXTIOI_NODETYPE_START; + ret = *(uint8_t *)((void *)state->ext_nodetype + off); + } + + DPRINTF("readb reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, ret); + return ret; +} + +static uint32_t apic_readw(void *opaque, hwaddr addr) +{ + nodeApicState *node; + apicState *state; + unsigned long off; + uint16_t ret; + int cpu; + + node = (nodeApicState *)opaque; + state = node->apic; + off = addr & 0xfffff; + ret = 0; + if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { + off -= EXTIOI_ENABLE_START; + ret = *(uint16_t *)((void *)state->ext_en + off); + } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { + off -= EXTIOI_BOUNCE_START; + ret = *(uint16_t *)((void *)state->ext_bounce + off); + } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { + off -= EXTIOI_ISR_START; + ret = *(uint16_t *)((void *)state->ext_isr + off); + } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { + off -= EXTIOI_COREISR_START; + cpu = (off >> 8) & 0xff; + ret = *(uint16_t *)((void *)state->ext_coreisr[cpu] + (off & 0x1f)); + } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { + off -= EXTIOI_IPMAP_START; + ret = *(uint16_t *)((void *)state->ext_ipmap + off); + } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { + off -= EXTIOI_COREMAP_START; + ret = *(uint16_t *)((void *)state->ext_coremap + off); + } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { + off -= EXTIOI_NODETYPE_START; + ret = *(uint16_t *)((void *)state->ext_nodetype + off); + } + + DPRINTF("readw reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, ret); + return ret; +} + +static uint32_t apic_readl(void *opaque, hwaddr addr) +{ + nodeApicState *node; + apicState *state; + unsigned long off; + uint32_t ret; + int cpu; + + node = (nodeApicState *)opaque; + state = node->apic; + off = addr & 0xfffff; + ret = 0; + if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { + off -= EXTIOI_ENABLE_START; + ret = *(uint32_t *)((void *)state->ext_en + off); + } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { + off -= EXTIOI_BOUNCE_START; + ret = *(uint32_t *)((void *)state->ext_bounce + off); + } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { + off -= EXTIOI_ISR_START; + ret = *(uint32_t *)((void *)state->ext_isr + off); + } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { + off -= EXTIOI_COREISR_START; + cpu = (off >> 8) & 0xff; + ret = *(uint32_t *)((void *)state->ext_coreisr[cpu] + (off & 0x1f)); + } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { + off -= EXTIOI_IPMAP_START; + ret = *(uint32_t *)((void *)state->ext_ipmap + off); + } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { + off -= EXTIOI_COREMAP_START; + ret = *(uint32_t *)((void *)state->ext_coremap + off); + } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { + off -= EXTIOI_NODETYPE_START; + ret = *(uint32_t *)((void *)state->ext_nodetype + off); + } + + DPRINTF("readl reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, ret); + return ret; + +} + +static void apic_writeb(void *opaque, hwaddr addr, uint32_t val) +{ + nodeApicState *node; + apicState *state; + unsigned long off; + uint8_t old; + int cpu, i, ipnum, level, mask; + + node = (nodeApicState *)opaque; + state = node->apic; + off = addr & 0xfffff; + if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { + off -= EXTIOI_ENABLE_START; + old = *(uint8_t *)((void *)state->ext_en + off); + if (old != val) { + *(uint8_t *)((void *)state->ext_en + off) = val; + old = old ^ val; + mask = 0x1; + for (i = 0; i < 8; i++) { + if (old & mask) { + level = !!(val & (0x1 << i)); + ioapic_update_irq(state, i + off * 8, level); + } + mask = mask << 1; + } + } + } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { + off -= EXTIOI_BOUNCE_START; + *(uint8_t *)((void *)state->ext_bounce + off) = val; + } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { + off -= EXTIOI_ISR_START; + old = *(uint8_t *)((void *)state->ext_isr + off); + *(uint8_t *)((void *)state->ext_isr + off) = old & ~val; + mask = 0x1; + for (i = 0; i < 8; i++) { + if ((old & mask) && (val & mask)) { + ioapic_update_irq(state, i + off * 8, 0); + } + mask = mask << 1; + } + } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { + off -= EXTIOI_COREISR_START; + cpu = (off >> 8) & 0xff; + off = off & 0x1f; + old = *(uint8_t *)((void *)state->ext_coreisr[cpu] + off); + *(uint8_t *)((void *)state->ext_coreisr[cpu] + off) = old & ~val; + mask = 0x1; + for (i = 0; i < 8; i++) { + if ((old & mask) && (val & mask)) { + ioapic_update_irq(state, i + off * 8, 0); + } + mask = mask << 1; + } + } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { + off -= EXTIOI_IPMAP_START; + val = val & 0xf; + *(uint8_t *)((void *)state->ext_ipmap + off) = val; + ipnum = 0; + for (i = 0; i < 4; i++) { + if (val & (0x1 << i)) { + ipnum = i; + break; + } + } + if (val) { + for (i = 0; i < 32; i++) { + cpu = off * 32 + i; + state->ext_sw_ipmap[cpu] = ipnum; + } + } + } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { + off -= EXTIOI_COREMAP_START; + val = val & 0xff; + *(uint8_t *)((void *)state->ext_coremap + off) = val; + state->ext_sw_coremap[off] = val; + } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { + off -= EXTIOI_NODETYPE_START; + *(uint8_t *)((void *)state->ext_nodetype + off) = val; + } + + DPRINTF("writeb reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, val); +} + +static void apic_writew(void *opaque, hwaddr addr, uint32_t val) +{ + nodeApicState *node; + apicState *state; + unsigned long off; + uint16_t old; + int cpu, i, level, mask; + + node = (nodeApicState *)opaque; + state = node->apic; + off = addr & 0xfffff; + if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { + off -= EXTIOI_ENABLE_START; + old = *(uint16_t *)((void *)state->ext_en + off); + if (old != val) { + *(uint16_t *)((void *)state->ext_en + off) = val; + old = old ^ val; + mask = 0x1; + for (i = 0; i < 16; i++) { + if (old & mask) { + level = !!(val & (0x1 << i)); + ioapic_update_irq(state, i + off * 8, level); + } + mask = mask << 1; + } + } + } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { + off -= EXTIOI_BOUNCE_START; + *(uint16_t *)((void *)state->ext_bounce + off) = val; + } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { + off -= EXTIOI_ISR_START; + old = *(uint16_t *)((void *)state->ext_isr + off); + *(uint16_t *)((void *)state->ext_isr + off) = old & ~val; + mask = 0x1; + for (i = 0; i < 16; i++) { + if ((old & mask) && (val & mask)) { + ioapic_update_irq(state, i + off * 8, 0); + } + mask = mask << 1; + } + } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { + off -= EXTIOI_COREISR_START; + cpu = (off >> 8) & 0xff; + off = off & 0x1f; + old = *(uint16_t *)((void *)state->ext_coreisr[cpu] + off); + *(uint16_t *)((void *)state->ext_coreisr[cpu] + off) = old & ~val; + mask = 0x1; + for (i = 0; i < 16; i++) { + if ((old & mask) && (val & mask)) { + ioapic_update_irq(state, i + off * 8, 0); + } + mask = mask << 1; + } + } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { + apic_writeb(opaque, addr, val & 0xff); + apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); + + } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { + apic_writeb(opaque, addr, val & 0xff); + apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); + + } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { + off -= EXTIOI_NODETYPE_START; + *(uint16_t *)((void *)state->ext_nodetype + off) = val; + } + + DPRINTF("writew reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, val); +} + +static void apic_writel(void *opaque, hwaddr addr, uint32_t val) +{ + nodeApicState *node; + apicState *state; + unsigned long off; + uint32_t old; + int cpu, i, level, mask; + + node = (nodeApicState *)opaque; + state = node->apic; + off = addr & 0xfffff; + if ((off >= EXTIOI_ENABLE_START) && (off < EXTIOI_ENABLE_END)) { + off -= EXTIOI_ENABLE_START; + old = *(uint32_t *)((void *)state->ext_en + off); + if (old != val) { + *(uint32_t *)((void *)state->ext_en + off) = val; + old = old ^ val; + mask = 0x1; + for (i = 0; i < 32; i++) { + if (old & mask) { + level = !!(val & (0x1 << i)); + ioapic_update_irq(state, i + off * 8, level); + } + mask = mask << 1; + } + } + } else if ((off >= EXTIOI_BOUNCE_START) && (off < EXTIOI_BOUNCE_END)) { + off -= EXTIOI_BOUNCE_START; + *(uint32_t *)((void *)state->ext_bounce + off) = val; + } else if ((off >= EXTIOI_ISR_START) && (off < EXTIOI_ISR_END)) { + off -= EXTIOI_ISR_START; + old = *(uint32_t *)((void *)state->ext_isr + off); + *(uint32_t *)((void *)state->ext_isr + off) = old & ~val; + mask = 0x1; + for (i = 0; i < 32; i++) { + if ((old & mask) && (val & mask)) { + ioapic_update_irq(state, i + off * 8, 0); + } + mask = mask << 1; + } + } else if ((off >= EXTIOI_COREISR_START) && (off < EXTIOI_COREISR_END)) { + off -= EXTIOI_COREISR_START; + cpu = (off >> 8) & 0xff; + off = off & 0x1f; + old = *(uint32_t *)((void *)state->ext_coreisr[cpu] + off); + *(uint32_t *)((void *)state->ext_coreisr[cpu] + off) = old & ~val; + mask = 0x1; + for (i = 0; i < 32; i++) { + if ((old & mask) && (val & mask)) { + ioapic_update_irq(state, i + off * 8, 0); + } + mask = mask << 1; + } + } else if ((off >= EXTIOI_IPMAP_START) && (off < EXTIOI_IPMAP_END)) { + apic_writeb(opaque, addr, val & 0xff); + apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); + apic_writeb(opaque, addr + 2, (val >> 16) & 0xff); + apic_writeb(opaque, addr + 3, (val >> 24) & 0xff); + + } else if ((off >= EXTIOI_COREMAP_START) && (off < EXTIOI_COREMAP_END)) { + apic_writeb(opaque, addr, val & 0xff); + apic_writeb(opaque, addr + 1, (val >> 8) & 0xff); + apic_writeb(opaque, addr + 2, (val >> 16) & 0xff); + apic_writeb(opaque, addr + 3, (val >> 24) & 0xff); + + } else if ((off >= EXTIOI_NODETYPE_START) && (off < EXTIOI_NODETYPE_END)) { + off -= EXTIOI_NODETYPE_START; + *(uint32_t *)((void *)state->ext_nodetype + off) = val; + } + + DPRINTF("writel reg 0x" TARGET_FMT_plx " = %x\n", node->addr + addr, val); +} + +static uint64_t apic_readfn(void *opaque, hwaddr addr, + unsigned size) +{ + switch (size) { + case 1: + return apic_readb(opaque, addr); + case 2: + return apic_readw(opaque, addr); + case 4: + return apic_readl(opaque, addr); + default: + g_assert_not_reached(); + } +} + +static void apic_writefn(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + switch (size) { + case 1: + apic_writeb(opaque, addr, value); + break; + case 2: + apic_writew(opaque, addr, value); + break; + case 4: + apic_writel(opaque, addr, value); + break; + default: + g_assert_not_reached(); + } +} + +static const VMStateDescription vmstate_apic = { + .name = "apic", + .version_id = 1, + .minimum_version_id = 1, + .pre_save = ext_irq_pre_save, + .post_load = ext_irq_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(ext_en, apicState, EXTIOI_IRQS_BITMAP_SIZE), + VMSTATE_UINT8_ARRAY(ext_bounce, apicState, EXTIOI_IRQS_BITMAP_SIZE), + VMSTATE_UINT8_ARRAY(ext_isr, apicState, EXTIOI_IRQS_BITMAP_SIZE), + VMSTATE_UINT8_2DARRAY(ext_coreisr, apicState, MAX_CORES, + EXTIOI_IRQS_BITMAP_SIZE), + VMSTATE_UINT8_ARRAY(ext_ipmap, apicState, EXTIOI_IRQS_IPMAP_SIZE), + VMSTATE_UINT8_ARRAY(ext_coremap, apicState, EXTIOI_IRQS), + VMSTATE_UINT16_ARRAY(ext_nodetype, apicState, 16), + VMSTATE_UINT64(ext_control, apicState), + VMSTATE_UINT8_ARRAY(ext_sw_ipmap, apicState, EXTIOI_IRQS), + VMSTATE_UINT8_ARRAY(ext_sw_coremap, apicState, EXTIOI_IRQS), + VMSTATE_UINT8_2DARRAY(ext_ipisr, apicState, MAX_CORES * LS3A_INTC_IP, + EXTIOI_IRQS_BITMAP_SIZE), + VMSTATE_END_OF_LIST() + } +}; + +static const MemoryRegionOps apic_ops = { + .read = apic_readfn, + .write = apic_writefn, + .impl.min_access_size = 1, + .impl.max_access_size = 4, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +int cpu_init_apic(LoongarchMachineState *ms, CPULOONGARCHState *env, int cpu) +{ + apicState *apic; + nodeApicState *node; + MemoryRegion *iomem; + unsigned long base; + int pin; + char str[32]; + + if (ms->apic == NULL) { + apic = g_malloc0(sizeof(apicState)); + vmstate_register(NULL, 0, &vmstate_apic, apic); + apic->irq = qemu_allocate_irqs(ioapic_setirq, apic, EXTIOI_IRQS); + + for (pin = 0; pin < LS3A_INTC_IP; pin++) { + /* cpu_pin[9:2] <= intc_pin[7:0] */ + apic->parent_irq[cpu][pin] = env->irq[pin + 2]; + } + ms->apic = apic; + + if (cpu == 0) { + base = APIC_BASE; + node = g_malloc0(sizeof(nodeApicState)); + node->apic = ms->apic; + node->addr = base; + + iomem = g_new(MemoryRegion, 1); + sprintf(str, "apic%d", cpu); + /* extioi addr 0x1f010000~0x1f02ffff */ + memory_region_init_io(iomem, NULL, &apic_ops, node, str, 0x20000); + memory_region_add_subregion(get_system_memory(), base, iomem); + } + + } else { + if (cpu != 0) { + for (pin = 0; pin < LS3A_INTC_IP; pin++) { + ms->apic->parent_irq[cpu][pin] = env->irq[pin + 2]; + } + } + } + return 0; +} + diff --git a/hw/loongarch/ioapic.c b/hw/loongarch/ioapic.c new file mode 100644 index 0000000000..3de0ed88da --- /dev/null +++ b/hw/loongarch/ioapic.c @@ -0,0 +1,422 @@ +/* + * LS7A1000 Northbridge IOAPIC support + * + * Copyright (c) 2019 Loongarch Technology + * Authors: + * Zhu Chen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "qemu/log.h" +#include "sysemu/kvm.h" +#include "linux/kvm.h" +#include "migration/vmstate.h" + +#define DEBUG_LS7A_APIC 0 + +#define DPRINTF(fmt, ...) \ +do { \ + if (DEBUG_LS7A_APIC) { \ + fprintf(stderr, "IOAPIC: " fmt , ## __VA_ARGS__); \ + } \ +} while (0) + +#define TYPE_LS7A_APIC "ioapic" +#define LS7A_APIC(obj) OBJECT_CHECK(LS7AApicState, (obj), TYPE_LS7A_APIC) + +#define LS7A_IOAPIC_ROUTE_ENTRY_OFFSET 0x100 +#define LS7A_IOAPIC_INT_ID_OFFSET 0x00 +#define LS7A_INT_ID_VAL 0x7000000UL +#define LS7A_INT_ID_VER 0x1f0001UL +#define LS7A_IOAPIC_INT_MASK_OFFSET 0x20 +#define LS7A_IOAPIC_INT_EDGE_OFFSET 0x60 +#define LS7A_IOAPIC_INT_CLEAR_OFFSET 0x80 +#define LS7A_IOAPIC_INT_STATUS_OFFSET 0x3a0 +#define LS7A_IOAPIC_INT_POL_OFFSET 0x3e0 +#define LS7A_IOAPIC_HTMSI_EN_OFFSET 0x40 +#define LS7A_IOAPIC_HTMSI_VEC_OFFSET 0x200 +#define LS7A_AUTO_CTRL0_OFFSET 0xc0 +#define LS7A_AUTO_CTRL1_OFFSET 0xe0 + +typedef struct LS7AApicState { + SysBusDevice parent_obj; + qemu_irq parent_irq[257]; + uint64_t int_id; + uint64_t int_mask; /*0x020 interrupt mask register*/ + uint64_t htmsi_en;/*0x040 1=msi*/ + uint64_t intedge; /*0x060 edge=1 level =0*/ + uint64_t intclr; /*0x080 for clean edge int,set 1 clean,set 0 is noused*/ + uint64_t auto_crtl0; /*0x0c0*/ + uint64_t auto_crtl1; /*0x0e0*/ + uint8_t route_entry[64]; /*0x100 - 0x140*/ + uint8_t htmsi_vector[64]; /*0x200 - 0x240*/ + uint64_t intisr_chip0; /*0x300*/ + uint64_t intisr_chip1;/*0x320*/ + uint64_t last_intirr; /* edge detection */ + uint64_t intirr; /* 0x380 interrupt request register */ + uint64_t intisr; /* 0x3a0 interrupt service register */ + uint64_t int_polarity; /*0x3e0 interrupt level polarity + selection register 0 for high level tirgger*/ + MemoryRegion iomem; +} LS7AApicState; + +static void update_irq(LS7AApicState *s) +{ + int i; + if ((s->intirr & (~s->int_mask)) & (~s->htmsi_en)) { + DPRINTF("7a update irqline up\n"); + s->intisr = (s->intirr & (~s->int_mask) & (~s->htmsi_en)); + qemu_set_irq(s->parent_irq[256], 1); + } else { + DPRINTF("7a update irqline down\n"); + s->intisr &= (~s->htmsi_en); + qemu_set_irq(s->parent_irq[256], 0); + } + if (s->htmsi_en) { + for (i = 0; i < 64; i++) { + if ((((~s->intisr) & s->intirr) & s->htmsi_en) & (1ULL << i)) { + s->intisr |= 1ULL << i; + qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 1); + } else if (((~(s->intisr | s->intirr)) & s->htmsi_en) & + (1ULL << i)) { + qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 0); + } + } + } +} + +static void irq_handler(void *opaque, int irq, int level) +{ + LS7AApicState *s = opaque; + + assert(irq < 64); + uint64_t mask = 1ULL << irq; + DPRINTF("------ %s irq %d %d\n", __func__, irq, level); + + if (s->intedge & mask) { + /* edge triggered */ + /*TODO*/ + } else { + /* level triggered */ + if (level) { + s->intirr |= mask; + } else { + s->intirr &= ~mask; + } + + } + update_irq(s); + +} + +static uint64_t ls7a_apic_reg_read(void *opaque, hwaddr addr, unsigned size) +{ + LS7AApicState *a = opaque; + uint64_t val = 0; + uint64_t offset; + int64_t offset_tmp; + offset = addr & 0xfff; + if (8 == size) { + switch (offset) { + case LS7A_IOAPIC_INT_ID_OFFSET: + val = LS7A_INT_ID_VER; + val = (val << 32) + LS7A_INT_ID_VAL; + break; + case LS7A_IOAPIC_INT_MASK_OFFSET: + val = a->int_mask; + break; + case LS7A_IOAPIC_INT_STATUS_OFFSET: + val = a->intisr & (~a->int_mask); + break; + case LS7A_IOAPIC_INT_EDGE_OFFSET: + val = a->intedge; + break; + case LS7A_IOAPIC_INT_POL_OFFSET: + val = a->int_polarity; + break; + case LS7A_IOAPIC_HTMSI_EN_OFFSET: + val = a->htmsi_en; + break; + case LS7A_AUTO_CTRL0_OFFSET: + case LS7A_AUTO_CTRL1_OFFSET: + break; + default: + break; + } + } else if (1 == size) { + if (offset >= LS7A_IOAPIC_HTMSI_VEC_OFFSET) { + offset_tmp = offset - LS7A_IOAPIC_HTMSI_VEC_OFFSET; + if (offset_tmp >= 0 && offset_tmp < 64) { + val = a->htmsi_vector[offset_tmp]; + } + } else if (offset >= LS7A_IOAPIC_ROUTE_ENTRY_OFFSET) { + offset_tmp = offset - LS7A_IOAPIC_ROUTE_ENTRY_OFFSET; + if (offset_tmp >= 0 && offset_tmp < 64) { + val = a->route_entry[offset_tmp]; + DPRINTF("addr %lx val %lx\n", addr, val); + } + } + } + DPRINTF(TARGET_FMT_plx" val %lx\n", addr, val); + return val; +} + +static void ls7a_apic_reg_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) +{ + LS7AApicState *a = opaque; + int64_t offset_tmp; + uint64_t offset; + offset = addr & 0xfff; + DPRINTF(TARGET_FMT_plx" size %d val %lx\n", addr, size, data); + if (8 == size) { + switch (offset) { + case LS7A_IOAPIC_INT_MASK_OFFSET: + a->int_mask = data; + update_irq(a); + break; + case LS7A_IOAPIC_INT_STATUS_OFFSET: + a->intisr = data; + break; + case LS7A_IOAPIC_INT_EDGE_OFFSET: + a->intedge = data; + break; + case LS7A_IOAPIC_INT_CLEAR_OFFSET: + a->intisr &= (~data); + update_irq(a); + break; + case LS7A_IOAPIC_INT_POL_OFFSET: + a->int_polarity = data; + break; + case LS7A_IOAPIC_HTMSI_EN_OFFSET: + a->htmsi_en = data; + break; + case LS7A_AUTO_CTRL0_OFFSET: + case LS7A_AUTO_CTRL1_OFFSET: + break; + default: + break; + } + } else if (1 == size) { + if (offset >= LS7A_IOAPIC_HTMSI_VEC_OFFSET) { + offset_tmp = offset - LS7A_IOAPIC_HTMSI_VEC_OFFSET; + if (offset_tmp >= 0 && offset_tmp < 64) { + a->htmsi_vector[offset_tmp] = (uint8_t)(data & 0xff); + } + } else if (offset >= LS7A_IOAPIC_ROUTE_ENTRY_OFFSET) { + offset_tmp = offset - LS7A_IOAPIC_ROUTE_ENTRY_OFFSET; + if (offset_tmp >= 0 && offset_tmp < 64) { + a->route_entry[offset_tmp] = (uint8_t)(data & 0xff); + } + } + } +} + +static const MemoryRegionOps ls7a_apic_ops = { + .read = ls7a_apic_reg_read, + .write = ls7a_apic_reg_write, + .valid = { + .min_access_size = 1, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 1, + .max_access_size = 8, + }, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static int kvm_ls7a_pre_save(void *opaque) +{ +#ifdef CONFIG_KVM + LS7AApicState *s = opaque; + struct loongarch_kvm_irqchip *chip; + struct ls7a_ioapic_state *state; + int ret, i, length; + + if (!kvm_irqchip_in_kernel()) { + return 0; + } + + length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct ls7a_ioapic_state); + chip = g_malloc0(length); + memset(chip, 0, length); + chip->chip_id = KVM_IRQCHIP_LS7A_IOAPIC; + chip->len = length; + ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip); + if (ret < 0) { + fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); + abort(); + } + state = (struct ls7a_ioapic_state *)chip->data; + s->int_id = state->int_id; + s->int_mask = state->int_mask; + s->htmsi_en = state->htmsi_en; + s->intedge = state->intedge; + s->intclr = state->intclr; + s->auto_crtl0 = state->auto_crtl0; + s->auto_crtl1 = state->auto_crtl1; + for (i = 0; i < 64; i++) { + s->route_entry[i] = state->route_entry[i]; + s->htmsi_vector[i] = state->htmsi_vector[i]; + } + s->intisr_chip0 = state->intisr_chip0; + s->intisr_chip1 = state->intisr_chip1; + s->intirr = state->intirr; + s->intisr = state->intisr; + s->int_polarity = state->int_polarity; + g_free(chip); +#endif + return 0; +} + +static int kvm_ls7a_post_load(void *opaque, int version) +{ +#ifdef CONFIG_KVM + LS7AApicState *s = opaque; + struct loongarch_kvm_irqchip *chip; + struct ls7a_ioapic_state *state; + int ret, i, length; + + if (!kvm_irqchip_in_kernel()) { + return 0; + } + length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct ls7a_ioapic_state); + chip = g_malloc0(length); + memset(chip, 0, length); + chip->chip_id = KVM_IRQCHIP_LS7A_IOAPIC; + chip->len = length; + + state = (struct ls7a_ioapic_state *)chip->data; + state->int_id = s->int_id; + state->int_mask = s->int_mask; + state->htmsi_en = s->htmsi_en; + state->intedge = s->intedge; + state->intclr = s->intclr; + state->auto_crtl0 = s->auto_crtl0; + state->auto_crtl1 = s->auto_crtl1; + for (i = 0; i < 64; i++) { + state->route_entry[i] = s->route_entry[i]; + state->htmsi_vector[i] = s->htmsi_vector[i]; + } + state->intisr_chip0 = s->intisr_chip0; + state->intisr_chip1 = s->intisr_chip1; + state->last_intirr = 0; + state->intirr = s->intirr; + state->intisr = s->intisr; + state->int_polarity = s->int_polarity; + + ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); + if (ret < 0) { + fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); + abort(); + } + g_free(chip); +#endif + return 0; +} + +static void ls7a_apic_reset(DeviceState *d) +{ + LS7AApicState *s = LS7A_APIC(d); + int i; + + s->int_id = 0x001f000107000000; + s->int_mask = 0xffffffffffffffff; + s->htmsi_en = 0x0; + s->intedge = 0x0; + s->intclr = 0x0; + s->auto_crtl0 = 0x0; + s->auto_crtl1 = 0x0; + for (i = 0; i < 64; i++) { + s->route_entry[i] = 0x1; + s->htmsi_vector[i] = 0x0; + } + s->intisr_chip0 = 0x0; + s->intisr_chip1 = 0x0; + s->intirr = 0x0; + s->intisr = 0x0; + s->int_polarity = 0x0; + kvm_ls7a_post_load(s, 0); +} + +static void ls7a_apic_init(Object *obj) +{ + DeviceState *dev = DEVICE(obj); + LS7AApicState *s = LS7A_APIC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + int tmp; + memory_region_init_io(&s->iomem, obj, &ls7a_apic_ops, s, TYPE_LS7A_APIC, 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + for (tmp = 0; tmp < 257; tmp++) { + sysbus_init_irq(sbd, &s->parent_irq[tmp]); + } + qdev_init_gpio_in(dev, irq_handler, 64); +} + +static const VMStateDescription vmstate_ls7a_apic = { + .name = TYPE_LS7A_APIC, + .version_id = 1, + .minimum_version_id = 1, + .pre_save = kvm_ls7a_pre_save, + .post_load = kvm_ls7a_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT64(int_mask, LS7AApicState), + VMSTATE_UINT64(htmsi_en, LS7AApicState), + VMSTATE_UINT64(intedge, LS7AApicState), + VMSTATE_UINT64(intclr, LS7AApicState), + VMSTATE_UINT64(auto_crtl0, LS7AApicState), + VMSTATE_UINT64(auto_crtl1, LS7AApicState), + VMSTATE_UINT8_ARRAY(route_entry, LS7AApicState, 64), + VMSTATE_UINT8_ARRAY(htmsi_vector, LS7AApicState, 64), + VMSTATE_UINT64(intisr_chip0, LS7AApicState), + VMSTATE_UINT64(intisr_chip1, LS7AApicState), + VMSTATE_UINT64(last_intirr, LS7AApicState), + VMSTATE_UINT64(intirr, LS7AApicState), + VMSTATE_UINT64(intisr, LS7AApicState), + VMSTATE_UINT64(int_polarity, LS7AApicState), + VMSTATE_END_OF_LIST() + } +}; + +static void ls7a_apic_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = ls7a_apic_reset; + dc->vmsd = &vmstate_ls7a_apic; +} + +static const TypeInfo ls7a_apic_info = { + .name = TYPE_LS7A_APIC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(LS7AApicState), + .instance_init = ls7a_apic_init, + .class_init = ls7a_apic_class_init, +}; + +static void ls7a_apic_register_types(void) +{ + type_register_static(&ls7a_apic_info); +} + +type_init(ls7a_apic_register_types) diff --git a/hw/loongarch/iocsr.c b/hw/loongarch/iocsr.c new file mode 100644 index 0000000000..14521c2d5c --- /dev/null +++ b/hw/loongarch/iocsr.c @@ -0,0 +1,219 @@ +/* + * LOONGARCH IOCSR support + * + * Copyright (c) 2021 Loongarch Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "qemu/log.h" +#include "sysemu/kvm.h" +#include "linux/kvm.h" +#include "migration/vmstate.h" +#include "hw/boards.h" +#include "hw/loongarch/larch.h" + +#define BIT_ULL(nr) (1ULL << (nr)) +#define LOONGARCH_IOCSR_FEATURES 0x8 +#define IOCSRF_TEMP BIT_ULL(0) +#define IOCSRF_NODECNT BIT_ULL(1) +#define IOCSRF_MSI BIT_ULL(2) +#define IOCSRF_EXTIOI BIT_ULL(3) +#define IOCSRF_CSRIPI BIT_ULL(4) +#define IOCSRF_FREQCSR BIT_ULL(5) +#define IOCSRF_FREQSCALE BIT_ULL(6) +#define IOCSRF_DVFSV1 BIT_ULL(7) +#define IOCSRF_GMOD BIT_ULL(9) +#define IOCSRF_VM BIT_ULL(11) +#define LOONGARCH_IOCSR_VENDOR 0x10 +#define LOONGARCH_IOCSR_CPUNAME 0x20 +#define LOONGARCH_IOCSR_NODECNT 0x408 +#define LOONGARCH_IOCSR_MISC_FUNC 0x420 +#define IOCSR_MISC_FUNC_TIMER_RESET BIT_ULL(21) +#define IOCSR_MISC_FUNC_EXT_IOI_EN BIT_ULL(48) + +enum { + IOCSR_FEATURES, + IOCSR_VENDOR, + IOCSR_CPUNAME, + IOCSR_NODECNT, + IOCSR_MISC_FUNC, + IOCSR_MAX +}; + +static uint32_t iocsr_array[IOCSR_MAX] = { + [IOCSR_FEATURES] = LOONGARCH_IOCSR_FEATURES, + [IOCSR_VENDOR] = LOONGARCH_IOCSR_VENDOR, + [IOCSR_CPUNAME] = LOONGARCH_IOCSR_CPUNAME, + [IOCSR_NODECNT] = LOONGARCH_IOCSR_NODECNT, + [IOCSR_MISC_FUNC] = LOONGARCH_IOCSR_MISC_FUNC, +}; + + +#define TYPE_IOCSR "iocsr" +#define IOCSR(obj) OBJECT_CHECK(IOCSRState, (obj), TYPE_IOCSR) + +typedef struct IOCSRState { + SysBusDevice parent_obj; + uint64_t iocsr_val[IOCSR_MAX]; +} IOCSRState; + +IOCSRState iocsr_init = { + .iocsr_val = { + IOCSRF_NODECNT | IOCSRF_MSI | IOCSRF_EXTIOI + | IOCSRF_CSRIPI | IOCSRF_GMOD | IOCSRF_VM, + 0x6e6f73676e6f6f4c, /* Loongson */ + 0x303030354133, /*3A5000*/ + 0x4, + 0x0, + } +}; + +static int kvm_iocsr_pre_save(void *opaque) +{ +#ifdef CONFIG_KVM + IOCSRState *s = opaque; + struct kvm_iocsr_entry entry; + int i = 0; + for (i = 0; i < IOCSR_MAX; i++) { + entry.addr = iocsr_array[i]; + kvm_vm_ioctl(kvm_state, KVM_LOONGARCH_GET_IOCSR, &entry); + s->iocsr_val[i] = entry.data; + } +#endif + return 0; +} + +static int kvm_iocsr_post_load(void *opaque, int version) +{ +#ifdef CONFIG_KVM + IOCSRState *s = opaque; + struct kvm_iocsr_entry entry; + int i = 0; + + if (!kvm_enabled()) { + return 0; + } + + for (i = 0; i < IOCSR_MAX; i++) { + entry.addr = iocsr_array[i]; + entry.data = s->iocsr_val[i]; + kvm_vm_ioctl(kvm_state, KVM_LOONGARCH_SET_IOCSR, &entry); + } +#endif + return 0; +} + +static void iocsr_reset(DeviceState *d) +{ + IOCSRState *s = IOCSR(d); + int i; + + for (i = 0; i < IOCSR_MAX; i++) { + s->iocsr_val[i] = iocsr_init.iocsr_val[i]; + } + kvm_iocsr_post_load(s, 0); +} +static void init_vendor_cpuname(uint64_t *vendor, + uint64_t *cpu_name, char *cpuname) +{ + int i = 0, len = 0; + char *index = NULL, *index_end = NULL; + char *vendor_c = (char *)vendor; + char *cpu_name_c = (char *)cpu_name; + + index = strstr(cpuname, "-"); + len = strlen(cpuname); + if ((index == NULL) || (len <= 0)) { + return ; + } + + *vendor = 0; + *cpu_name = 0; + index_end = cpuname + len; + + while (((cpuname + i) < index) && (i < sizeof(uint64_t))) { + vendor_c[i] = cpuname[i]; + i++; + } + + index += 1; + i = 0; + + while (((index + i) < index_end) && (i < sizeof(uint64_t))) { + cpu_name_c[i] = index[i]; + i++; + } + + return ; +} + +static void iocsr_instance_init(Object *obj) +{ + IOCSRState *s = IOCSR(obj); + int i; + LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); + LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + + init_vendor_cpuname((uint64_t *)&iocsr_init.iocsr_val[IOCSR_VENDOR], + (uint64_t *)&iocsr_init.iocsr_val[IOCSR_CPUNAME], + lsmc->cpu_name); + + for (i = 0; i < IOCSR_MAX; i++) { + s->iocsr_val[i] = iocsr_init.iocsr_val[i]; + } +} + +static const VMStateDescription vmstate_iocsr = { + .name = TYPE_IOCSR, + .version_id = 1, + .minimum_version_id = 1, + .pre_save = kvm_iocsr_pre_save, + .post_load = kvm_iocsr_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT64_ARRAY(iocsr_val, IOCSRState, IOCSR_MAX), + VMSTATE_END_OF_LIST() + } +}; + +static void iocsr_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = iocsr_reset; + dc->vmsd = &vmstate_iocsr; + +} + +static const TypeInfo iocsr_info = { + .name = TYPE_IOCSR, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(IOCSRState), + .instance_init = iocsr_instance_init, + .class_init = iocsr_class_init, +}; + +static void iocsr_register_types(void) +{ + type_register_static(&iocsr_info); +} + +type_init(iocsr_register_types) diff --git a/hw/loongarch/ipi.c b/hw/loongarch/ipi.c new file mode 100644 index 0000000000..ade182abcc --- /dev/null +++ b/hw/loongarch/ipi.c @@ -0,0 +1,267 @@ +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/loongarch/cpudevs.h" +#include "sysemu/sysemu.h" +#include "sysemu/cpus.h" +#include "sysemu/kvm.h" +#include "hw/core/cpu.h" +#include "qemu/log.h" +#include "hw/loongarch/bios.h" +#include "elf.h" +#include "linux/kvm.h" +#include "hw/loongarch/larch.h" +#include "hw/loongarch/ls7a.h" +#include "migration/vmstate.h" + +static int gipi_pre_save(void *opaque) +{ +#ifdef CONFIG_KVM + gipiState *state = opaque; + struct loongarch_gipiState *kstate; + struct loongarch_kvm_irqchip *chip; + int ret, i, j, length; +#endif + + if (!kvm_irqchip_in_kernel()) { + return 0; + } + +#ifdef CONFIG_KVM + length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct loongarch_gipiState); + chip = g_malloc0(length); + memset(chip, 0, length); + chip->chip_id = KVM_IRQCHIP_LS3A_GIPI; + chip->len = length; + ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip); + if (ret < 0) { + fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); + abort(); + } + + kstate = (struct loongarch_gipiState *)chip->data; + + for (i = 0; i < MAX_GIPI_CORE_NUM; i++) { + state->core[i].status = kstate->core[i].status; + state->core[i].en = kstate->core[i].en; + state->core[i].set = kstate->core[i].set; + state->core[i].clear = kstate->core[i].clear; + for (j = 0; j < MAX_GIPI_MBX_NUM; j++) { + state->core[i].buf[j] = kstate->core[i].buf[j]; + } + } + g_free(chip); +#endif + + return 0; +} + +static int gipi_post_load(void *opaque, int version) +{ +#ifdef CONFIG_KVM + gipiState *state = opaque; + struct loongarch_gipiState *kstate; + struct loongarch_kvm_irqchip *chip; + int ret, i, j, length; +#endif + + if (!kvm_irqchip_in_kernel()) { + return 0; + } + +#ifdef CONFIG_KVM + length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct loongarch_gipiState); + chip = g_malloc0(length); + memset(chip, 0, length); + chip->chip_id = KVM_IRQCHIP_LS3A_GIPI; + chip->len = length; + kstate = (struct loongarch_gipiState *)chip->data; + + for (i = 0; i < MAX_GIPI_CORE_NUM; i++) { + kstate->core[i].status = state->core[i].status; + kstate->core[i].en = state->core[i].en; + kstate->core[i].set = state->core[i].set; + kstate->core[i].clear = state->core[i].clear; + for (j = 0; j < MAX_GIPI_MBX_NUM; j++) { + kstate->core[i].buf[j] = state->core[i].buf[j]; + } + } + + ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); + if (ret < 0) { + fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret)); + abort(); + } + g_free(chip); +#endif + + return 0; +} + +static const VMStateDescription vmstate_gipi_core = { + .name = "gipi-single", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(status, gipi_core), + VMSTATE_UINT32(en, gipi_core), + VMSTATE_UINT32(set, gipi_core), + VMSTATE_UINT32(clear, gipi_core), + VMSTATE_UINT64_ARRAY(buf, gipi_core, MAX_GIPI_MBX_NUM), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_gipi = { + .name = "gipi", + .pre_save = gipi_pre_save, + .post_load = gipi_post_load, + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_STRUCT_ARRAY(core, gipiState, MAX_GIPI_CORE_NUM, 0, + vmstate_gipi_core, gipi_core), + VMSTATE_END_OF_LIST() + } +}; + + +static void gipi_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ + gipi_core *s = opaque; + gipi_core *ss; + void *pbuf; + uint32_t cpu, action_data, mailaddr; + LoongarchMachineState *ms = LoongarchMACHINE(qdev_get_machine()); + + if ((size != 4) && (size != 8)) { + hw_error("size not 4 and not 8"); + } + addr &= 0xff; + switch (addr) { + case CORE0_STATUS_OFF: + hw_error("CORE0_STATUS_OFF Can't be write\n"); + break; + case CORE0_EN_OFF: + s->en = val; + break; + case CORE0_IPI_SEND: + cpu = (val >> 16) & 0x3ff; + action_data = 1UL << (val & 0x1f); + ss = &ms->gipi->core[cpu]; + ss->status |= action_data; + if (ss->status != 0) { + qemu_irq_raise(ss->irq); + } + break; + case CORE0_MAIL_SEND: + cpu = (val >> 16) & 0x3ff; + mailaddr = (val >> 2) & 0x7; + ss = &ms->gipi->core[cpu]; + pbuf = (void *)ss->buf + mailaddr * 4; + *(unsigned int *)pbuf = (val >> 32); + break; + case CORE0_SET_OFF: + hw_error("CORE0_SET_OFF Can't be write\n"); + break; + case CORE0_CLEAR_OFF: + s->status ^= val; + if (s->status == 0) { + qemu_irq_lower(s->irq); + } + break; + case 0x20 ... 0x3c: + pbuf = (void *)s->buf + (addr - 0x20); + if (size == 1) { + *(unsigned char *)pbuf = (unsigned char)val; + } else if (size == 2) { + *(unsigned short *)pbuf = (unsigned short)val; + } else if (size == 4) { + *(unsigned int *)pbuf = (unsigned int)val; + } else if (size == 8) { + *(unsigned long *)pbuf = (unsigned long)val; + } + break; + default: + break; + } +} + +static uint64_t gipi_readl(void *opaque, hwaddr addr, unsigned size) +{ + gipi_core *s = opaque; + uint64_t ret = 0; + void *pbuf; + + addr &= 0xff; + if ((size != 4) && (size != 8)) { + hw_error("size not 4 and not 8 size:%d\n", size); + } + switch (addr) { + case CORE0_STATUS_OFF: + ret = s->status; + break; + case CORE0_EN_OFF: + ret = s->en; + break; + case CORE0_SET_OFF: + ret = 0; + break; + case CORE0_CLEAR_OFF: + ret = 0; + break; + case 0x20 ... 0x3c: + pbuf = (void *)s->buf + (addr - 0x20); + if (size == 1) { + ret = *(unsigned char *)pbuf; + } else if (size == 2) { + ret = *(unsigned short *)pbuf; + } else if (size == 4) { + ret = *(unsigned int *)pbuf; + } else if (size == 8) { + ret = *(unsigned long *)pbuf; + } + break; + default: + break; + } + + return ret; +} + +static const MemoryRegionOps gipi_ops = { + .read = gipi_readl, + .write = gipi_writel, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 4, + .max_access_size = 8, + }, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +int cpu_init_ipi(LoongarchMachineState *ms, qemu_irq parent, int cpu) +{ + hwaddr addr; + MemoryRegion *region; + char str[32]; + + if (ms->gipi == NULL) { + ms->gipi = g_malloc0(sizeof(gipiState)); + vmstate_register(NULL, 0, &vmstate_gipi, ms->gipi); + } + + ms->gipi->core[cpu].irq = parent; + + addr = SMP_GIPI_MAILBOX | (cpu << 8); + region = g_new(MemoryRegion, 1); + sprintf(str, "gipi%d", cpu); + memory_region_init_io(region, NULL, &gipi_ops, &ms->gipi->core[cpu], str, 0x100); + memory_region_add_subregion(get_system_memory(), addr, region); + return 0; +} diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c new file mode 100644 index 0000000000..3db269274f --- /dev/null +++ b/hw/loongarch/larch_3a.c @@ -0,0 +1,2026 @@ +/* + * QEMU loongarch 3a develop board emulation + * + * Copyright (C) 2013-2014 qiaochong + * Copyright (C) 2016-2017 zhangshuangshuang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "qemu/datadir.h" +#include "hw/hw.h" +#include "hw/loongarch/cpudevs.h" +#include "hw/i386/pc.h" +#include "hw/char/serial.h" +#include "hw/isa/isa.h" +#include "hw/qdev-core.h" +#include "sysemu/sysemu.h" +#include "sysemu/runstate.h" +#include "sysemu/reset.h" +#include "migration/vmstate.h" +#include "sysemu/cpus.h" +#include "hw/boards.h" +#include "qemu/log.h" +#include "hw/loongarch/bios.h" +#include "hw/loader.h" +#include "elf.h" +#include "exec/address-spaces.h" +#include "hw/ide.h" +#include "hw/pci/pci_host.h" +#include "hw/pci/msi.h" +#include "linux/kvm.h" +#include "sysemu/kvm.h" +#include "sysemu/numa.h" +#include "hw/rtc/mc146818rtc.h" +#include "hw/irq.h" +#include "net/net.h" +#include "hw/timer/i8254.h" +#include "hw/loongarch/larch.h" +#include "hw/loongarch/ls7a.h" +#include "hw/nvram/fw_cfg.h" +#include "hw/firmware/smbios.h" +#include "acpi-build.h" +#include +#include +#include "sysemu/block-backend.h" +#include "hw/block/flash.h" +#include "sysemu/device_tree.h" +#include "qapi/visitor.h" +#include "qapi/qapi-visit-common.h" + +#include + +#define DMA64_SUPPORTED 0x2 +#define MAX_IDE_BUS 2 + +#define BOOTPARAM_PHYADDR 0x0ff00000ULL +#define BOOTPARAM_ADDR (0x9000000000000000ULL + BOOTPARAM_PHYADDR) +#define SMBIOS_PHYSICAL_ADDRESS 0x0fe00000 +#define SMBIOS_SIZE_LIMIT 0x200000 +#define RESERVED_SIZE_LIMIT 0x1100000 +#define COMMAND_LINE_SIZE 4096 +#define FW_CONF_ADDR 0x0fff0000 + +#define PHYS_TO_VIRT(x) ((x) | 0x9000000000000000ULL) + +#define TARGET_REALPAGE_MASK (TARGET_PAGE_MASK << 2) + +#ifdef CONFIG_KVM +#define LS_ISA_IO_SIZE 0x02000000 +#define LS_ISA_MEM_SIZE 0x40000000 +#else +#define LS_ISA_IO_SIZE 0x00010000 +#define LS_ISA_MEM_SIZE 0x01000000 +#endif + +#ifdef CONFIG_KVM +#define align(x) (((x) + 63) & ~63) +#else +#define align(x) (((x) + 15) & ~15) +#endif + +#define DEBUG_LOONGARCH3A 0 +#define FLASH_SECTOR_SIZE 4096 + +#define DPRINTF(fmt, ...) \ + do { if (DEBUG_LOONGARCH3A) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) + +#define DEFINE_LS3A5K_MACHINE(suffix, name, optionfn) \ + static void ls3a5k_init_##suffix(MachineState *machine) \ + { \ + ls3a5k_init(machine); \ + } \ + DEFINE_LOONGARCH_MACHINE(suffix, name, ls3a5k_init_##suffix, optionfn) + +struct efi_memory_map_loongarch { + uint16_t vers; /* version of efi_memory_map */ + uint32_t nr_map; /* number of memory_maps */ + uint32_t mem_freq; /* memory frequence */ + struct mem_map { + uint32_t node_id; /* node_id which memory attached to */ + uint32_t mem_type; /* system memory, pci memory, pci io, etc. */ + uint64_t mem_start; /* memory map start address */ + uint32_t mem_size; /* each memory_map size, not the total size */ + } map[128]; +} __attribute__((packed)); + +enum loongarch_cpu_type { + Loongson3 = 0x1, + Loongson3_comp = 0x2 +}; + +struct GlobalProperty loongarch_compat[] = { + { + .driver = "rtl8139", + .property = "romfile", + .value = "", + },{ + .driver = "e1000", + .property = "romfile", + .value = "", + },{ + .driver = "virtio-net-pci", + .property = "romfile", + .value = "", + },{ + .driver = "qxl-vga", + .property = "romfile", + .value = "", + },{ + .driver = "VGA", + .property = "romfile", + .value = "", + },{ + .driver = "cirrus-vga", + .property = "romfile", + .value = "", + },{ + .driver = "virtio-vga", + .property = "romfile", + .value = "", + },{ + .driver = "vmware-svga", + .property = "romfile", + .value = "", + }, +}; +const size_t loongarch_compat_len = G_N_ELEMENTS(loongarch_compat); + +/* + * Capability and feature descriptor structure for LOONGARCH CPU + */ +struct efi_cpuinfo_loongarch { + uint16_t vers; /* version of efi_cpuinfo_loongarch */ + uint32_t processor_id; /* PRID, e.g. 6305, 6306 */ + enum loongarch_cpu_type cputype; /* 3A, 3B, etc. */ + uint32_t total_node; /* num of total numa nodes */ + uint16_t cpu_startup_core_id; /* Core id */ + uint16_t reserved_cores_mask; + uint32_t cpu_clock_freq; /* cpu_clock */ + uint32_t nr_cpus; +} __attribute__((packed)); + +#define MAX_UARTS 64 +struct uart_device { + uint32_t iotype; /* see include/linux/serial_core.h */ + uint32_t uartclk; + uint32_t int_offset; + uint64_t uart_base; +} __attribute__((packed)); + +#define MAX_SENSORS 64 +#define SENSOR_TEMPER 0x00000001 +#define SENSOR_VOLTAGE 0x00000002 +#define SENSOR_FAN 0x00000004 +struct sensor_device { + char name[32]; /* a formal name */ + char label[64]; /* a flexible description */ + uint32_t type; /* SENSOR_* */ + uint32_t id; /* instance id of a sensor-class */ + uint32_t fan_policy; /* see arch/loongarch/include/ + asm/mach-loongarch/loongarch_hwmon.h */ + uint32_t fan_percent;/* only for constant speed policy */ + uint64_t base_addr; /* base address of device registers */ +} __attribute__((packed)); + +struct system_loongarch { + uint16_t vers; /* version of system_loongarch */ + uint32_t ccnuma_smp; /* 0: no numa; 1: has numa */ + uint32_t sing_double_channel;/* 1:single; 2:double */ + uint32_t nr_uarts; + struct uart_device uarts[MAX_UARTS]; + uint32_t nr_sensors; + struct sensor_device sensors[MAX_SENSORS]; + char has_ec; + char ec_name[32]; + uint64_t ec_base_addr; + char has_tcm; + char tcm_name[32]; + uint64_t tcm_base_addr; + uint64_t workarounds; /* see workarounds.h */ +} __attribute__((packed)); + +struct irq_source_routing_table { + uint16_t vers; + uint16_t size; + uint16_t rtr_bus; + uint16_t rtr_devfn; + uint32_t vendor; + uint32_t device; + uint32_t PIC_type; /* conform use HT or PCI to route to CPU-PIC */ + uint64_t ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */ + uint64_t ht_enable; /* irqs used in this PIC */ + uint32_t node_id; /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */ + uint64_t pci_mem_start_addr; + uint64_t pci_mem_end_addr; + uint64_t pci_io_start_addr; + uint64_t pci_io_end_addr; + uint64_t pci_config_addr; + uint32_t dma_mask_bits; + uint16_t dma_noncoherent; +} __attribute__((packed)); + +struct interface_info { + uint16_t vers; /* version of the specificition */ + uint16_t size; + uint8_t flag; + char description[64]; +} __attribute__((packed)); + +#define MAX_RESOURCE_NUMBER 128 +struct resource_loongarch { + uint64_t start; /* resource start address */ + uint64_t end; /* resource end address */ + char name[64]; + uint32_t flags; +}; + +struct archdev_data {}; /* arch specific additions */ + +struct board_devices { + char name[64]; /* hold the device name */ + uint32_t num_resources; /* number of device_resource */ + /* for each device's resource */ + struct resource_loongarch resource[MAX_RESOURCE_NUMBER]; + /* arch specific additions */ + struct archdev_data archdata; +}; + +struct loongarch_special_attribute { + uint16_t vers; /* version of this special */ + char special_name[64]; /* special_atribute_name */ + uint32_t loongarch_special_type; /* type of special device */ + /* for each device's resource */ + struct resource_loongarch resource[MAX_RESOURCE_NUMBER]; +}; + +struct loongarch_params { + uint64_t memory_offset; /* efi_memory_map_loongarch struct offset */ + uint64_t cpu_offset; /* efi_cpuinfo_loongarch struct offset */ + uint64_t system_offset; /* system_loongarch struct offset */ + uint64_t irq_offset; /* irq_source_routing_table struct offset */ + uint64_t interface_offset; /* interface_info struct offset */ + uint64_t special_offset; /* loongarch_special_attribute struct offset */ + uint64_t boarddev_table_offset; /* board_devices offset */ +}; + +struct smbios_tables { + uint16_t vers; /* version of smbios */ + uint64_t vga_bios; /* vga_bios address */ + struct loongarch_params lp; +}; + +struct efi_reset_system_t { + uint64_t ResetCold; + uint64_t ResetWarm; + uint64_t ResetType; + uint64_t Shutdown; + uint64_t DoSuspend; /* NULL if not support */ +}; + +struct efi_loongarch { + uint64_t mps; /* MPS table */ + uint64_t acpi; /* ACPI table (IA64 ext 0.71) */ + uint64_t acpi20; /* ACPI table (ACPI 2.0) */ + struct smbios_tables smbios; /* SM BIOS table */ + uint64_t sal_systab; /* SAL system table */ + uint64_t boot_info; /* boot info table */ +}; + +struct boot_params { + struct efi_loongarch efi; + struct efi_reset_system_t reset_system; +}; + +static struct _loaderparams { + unsigned long ram_size; + const char *kernel_filename; + const char *kernel_cmdline; + const char *initrd_filename; + unsigned long a0, a1, a2; +} loaderparams; + +static struct _firmware_config { + unsigned long ram_size; + unsigned int mem_freq; + unsigned int cpu_nr; + unsigned int cpu_clock_freq; +} fw_config; + +struct la_memmap_entry { + uint64_t address; + uint64_t length; + uint32_t type; + uint32_t reserved; +} ; + +static void *boot_params_buf; +static void *boot_params_p; +static struct la_memmap_entry *la_memmap_table; +static unsigned la_memmap_entries; + +CPULOONGARCHState *cpu_states[LOONGARCH_MAX_VCPUS]; + +struct kvm_cpucfg ls3a5k_cpucfgs = { + .cpucfg[LOONGARCH_CPUCFG0] = CPUCFG0_3A5000_PRID, + .cpucfg[LOONGARCH_CPUCFG1] = CPUCFG1_ISGR64 | CPUCFG1_PAGING | + CPUCFG1_IOCSR | CPUCFG1_PABITS | CPUCFG1_VABITS | CPUCFG1_UAL | + CPUCFG1_RI | CPUCFG1_XI | CPUCFG1_RPLV | CPUCFG1_HUGEPG | + CPUCFG1_IOCSRBRD, + .cpucfg[LOONGARCH_CPUCFG2] = CPUCFG2_FP | CPUCFG2_FPSP | CPUCFG2_FPDP | + CPUCFG2_FPVERS | CPUCFG2_LSX | CPUCFG2_LASX | CPUCFG2_COMPLEX | + CPUCFG2_CRYPTO | CPUCFG2_LLFTP | CPUCFG2_LLFTPREV | CPUCFG2_LSPW | + CPUCFG2_LAM, + .cpucfg[LOONGARCH_CPUCFG3] = CPUCFG3_CCDMA | CPUCFG3_SFB | CPUCFG3_UCACC | + CPUCFG3_LLEXC | CPUCFG3_SCDLY | CPUCFG3_LLDBAR | CPUCFG3_ITLBT | + CPUCFG3_ICACHET | CPUCFG3_SPW_LVL | CPUCFG3_SPW_HG_HF | CPUCFG3_RVA | + CPUCFG3_RVAMAX, + .cpucfg[LOONGARCH_CPUCFG4] = CCFREQ_100M, + .cpucfg[LOONGARCH_CPUCFG5] = CPUCFG5_CCMUL | CPUCFG5_CCDIV, + .cpucfg[LOONGARCH_CPUCFG6] = CPUCFG6_PMP | CPUCFG6_PAMVER | CPUCFG6_PMNUM | + CPUCFG6_PMBITS | CPUCFG6_UPM, + .cpucfg[LOONGARCH_CPUCFG16] = CPUCFG16_L1_IUPRE | CPUCFG16_L1_DPRE | + CPUCFG16_L2_IUPRE | CPUCFG16_L2_IUUNIFY | CPUCFG16_L2_IUPRIV | + CPUCFG16_L3_IUPRE | CPUCFG16_L3_IUUNIFY | CPUCFG16_L3_IUINCL, + .cpucfg[LOONGARCH_CPUCFG17] = CPUCFG17_L1I_WAYS_M | CPUCFG17_L1I_SETS_M | + CPUCFG17_L1I_SIZE_M, + .cpucfg[LOONGARCH_CPUCFG18] = CPUCFG18_L1D_WAYS_M | CPUCFG18_L1D_SETS_M | + CPUCFG18_L1D_SIZE_M, + .cpucfg[LOONGARCH_CPUCFG19] = CPUCFG19_L2_WAYS_M | CPUCFG19_L2_SETS_M | + CPUCFG19_L2_SIZE_M, + .cpucfg[LOONGARCH_CPUCFG20] = CPUCFG20_L3_WAYS_M | CPUCFG20_L3_SETS_M | + CPUCFG20_L3_SIZE_M, +}; + +bool loongarch_is_acpi_enabled(LoongarchMachineState *vms) +{ + if (vms->acpi == ON_OFF_AUTO_OFF) { + return false; + } + return true; +} +static void loongarch_get_acpi(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LoongarchMachineState *lsms = LoongarchMACHINE(obj); + OnOffAuto acpi = lsms->acpi; + + visit_type_OnOffAuto(v, name, &acpi, errp); +} + +static void loongarch_set_acpi(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + LoongarchMachineState *lsms = LoongarchMACHINE(obj); + + visit_type_OnOffAuto(v, name, &lsms->acpi, errp); +} +int la_memmap_add_entry(uint64_t address, uint64_t length, uint32_t type) +{ + int i; + + for (i = 0; i < la_memmap_entries; i++) { + if (la_memmap_table[i].address == address) { + fprintf(stderr, "%s address:0x%lx length:0x%lx already exists\n", + __func__, address, length); + return 0; + } + } + + la_memmap_table = g_renew(struct la_memmap_entry, la_memmap_table, + la_memmap_entries + 1); + la_memmap_table[la_memmap_entries].address = cpu_to_le64(address); + la_memmap_table[la_memmap_entries].length = cpu_to_le64(length); + la_memmap_table[la_memmap_entries].type = cpu_to_le32(type); + la_memmap_entries++; + + return la_memmap_entries; +} + +static ram_addr_t get_hotplug_membase(ram_addr_t ram_size) +{ + ram_addr_t sstart; + + if (ram_size <= 0x10000000) { + sstart = 0x90000000; + } else { + sstart = 0x90000000 + ROUND_UP((ram_size - 0x10000000), + LOONGARCH_HOTPLUG_MEM_ALIGN); + } + return sstart; +} + +static struct efi_memory_map_loongarch *init_memory_map(void *g_map) +{ + struct efi_memory_map_loongarch *emap = g_map; + + emap->nr_map = 4; + emap->mem_freq = 266000000; + + emap->map[0].node_id = 0; + emap->map[0].mem_type = 1; + emap->map[0].mem_start = 0x0; +#ifdef CONFIG_KVM + emap->map[0].mem_size = (loaderparams.ram_size > 0x10000000 + ? 256 : (loaderparams.ram_size >> 20)) - 18; +#else + emap->map[0].mem_size = atoi(getenv("memsize")); +#endif + + emap->map[1].node_id = 0; + emap->map[1].mem_type = 2; + emap->map[1].mem_start = 0x90000000; +#ifdef CONFIG_KVM + emap->map[1].mem_size = (loaderparams.ram_size > 0x10000000 + ? (loaderparams.ram_size >> 20) - 256 : 0); +#else + emap->map[1].mem_size = atoi(getenv("highmemsize")); +#endif + + /* support for smbios */ + emap->map[2].node_id = 0; + emap->map[2].mem_type = 10; + emap->map[2].mem_start = SMBIOS_PHYSICAL_ADDRESS; + emap->map[2].mem_size = SMBIOS_SIZE_LIMIT >> 20; + + emap->map[3].node_id = 0; + emap->map[3].mem_type = 3; + emap->map[3].mem_start = 0xee00000; + emap->map[3].mem_size = RESERVED_SIZE_LIMIT >> 20; + + return emap; +} + +static uint64_t get_host_cpu_freq(void) +{ + int fd = 0; + char buf[1024]; + uint64_t freq = 0, size = 0; + char *buf_p; + + fd = open("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", O_RDONLY); + if (fd == -1) { + fprintf(stderr, "/sys/devices/system/cpu/cpu0/cpufreq/ \ + cpuinfo_max_freq not exist!\n"); + fprintf(stderr, "Trying /proc/cpuinfo...\n"); + } else { + size = read(fd, buf, 16); + if (size == -1) { + fprintf(stderr, "read err...\n"); + } + close(fd); + freq = (uint64_t)atoi(buf); + return freq * 1000; + } + + fd = open("/proc/cpuinfo", O_RDONLY); + if (fd == -1) { + fprintf(stderr, "Failed to open /proc/cpuinfo!\n"); + return 0; + } + + size = read(fd, buf, 1024); + if (size == -1) { + fprintf(stderr, "read err...\n"); + } + close(fd); + + buf_p = strstr(buf, "MHz"); + if (buf_p) { + while (*buf_p != ':') { + buf_p++; + } + buf_p += 2; + } else { + buf_p = strstr(buf, "name"); + while (*buf_p != '@') { + buf_p++; + } + buf_p += 2; + } + + memcpy(buf, buf_p, 12); + buf_p = buf; + while ((*buf_p >= '0') && (*buf_p <= '9')) { + buf_p++; + } + *buf_p = '\0'; + + freq = (uint64_t)atoi(buf); + return freq * 1000 * 1000; +} + +static char *get_host_cpu_model_name(void) +{ + int fd = 0; + int size = 0; + static char buf[1024]; + char *buf_p; + + fd = open("/proc/cpuinfo", O_RDONLY); + if (fd == -1) { + fprintf(stderr, "Failed to open /proc/cpuinfo!\n"); + return 0; + } + + size = read(fd, buf, 1024); + if (size == -1) { + fprintf(stderr, "read err...\n"); + } + close(fd); + buf_p = strstr(buf, "name"); + + while (*buf_p != ':') { + buf_p++; + } + buf_p = buf_p + 2; + memcpy(buf, buf_p, 40); + buf_p = buf; + while (*buf_p != '\n') { + buf_p++; + } + + *(buf_p) = '\0'; + + return buf; +} + +static void fw_conf_init(unsigned long ramsize) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + int smp_cpus = ms->smp.cpus; + fw_config.ram_size = ramsize; + fw_config.mem_freq = 266000000; + fw_config.cpu_nr = smp_cpus ; + fw_config.cpu_clock_freq = get_host_cpu_freq(); +} + +static struct efi_cpuinfo_loongarch *init_cpu_info(void *g_cpuinfo_loongarch) +{ + struct efi_cpuinfo_loongarch *c = g_cpuinfo_loongarch; + MachineState *ms = MACHINE(qdev_get_machine()); + int smp_cpus = ms->smp.cpus; + LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); + LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + + if (strstr(lsmc->cpu_name, "5000")) { + c->processor_id = 0x14c010; + } + c->cputype = Loongson3_comp; + c->cpu_clock_freq = get_host_cpu_freq(); + if (!c->cpu_clock_freq) { + c->cpu_clock_freq = 200000000; + } + c->total_node = 1; + c->nr_cpus = smp_cpus; + c->cpu_startup_core_id = 0; + c->reserved_cores_mask = 0xffff & (0xffff << smp_cpus); + + return c; +} + +static struct system_loongarch *init_system_loongarch(void *g_sysitem) +{ + struct system_loongarch *s = g_sysitem; + + s->ccnuma_smp = 1; + s->ccnuma_smp = 0; + s->sing_double_channel = 1; + + return s; +} + +enum loongarch_irq_source_enum { + HT, I8259, UNKNOWN +}; + +static struct irq_source_routing_table *init_irq_source(void *g_irq_source) +{ + struct irq_source_routing_table *irq_info = g_irq_source; + LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); + LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + + irq_info->PIC_type = HT; + irq_info->ht_int_bit = 1 << 24; + irq_info->ht_enable = 0x0000d17b; + irq_info->node_id = 0; + + irq_info->pci_mem_start_addr = LS_ISA_MEM_BASE; + irq_info->pci_mem_end_addr = irq_info->pci_mem_start_addr + LS_ISA_MEM_SIZE - 1; + + if (strstr(lsmc->cpu_name, "5000")) { + irq_info->pci_io_start_addr = LS3A5K_ISA_IO_BASE; + } + irq_info->dma_noncoherent = 1; + return irq_info; +} + +static struct interface_info *init_interface_info(void *g_interface) +{ + struct interface_info *inter = g_interface; + int flashsize = 0x80000; + + inter->vers = 0x0001; + inter->size = flashsize / 0x400; + inter->flag = 1; + + strcpy(inter->description, "PMON_Version_v2.1"); + + return inter; +} + +static struct board_devices *board_devices_info(void *g_board) +{ + struct board_devices *bd = g_board; + LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); + LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + + if (!strcmp(lsmc->bridge_name, "ls7a")) { + strcpy(bd->name, "Loongarch-3A-7A-1w-V1.03-demo"); + } + bd->num_resources = 10; + + return bd; +} + +static struct loongarch_special_attribute *init_special_info(void *g_special) +{ + struct loongarch_special_attribute *special = g_special; + char update[11] = "2013-01-01"; + int VRAM_SIZE = 0x20000; + + strcpy(special->special_name, update); + special->resource[0].flags = 0; + special->resource[0].start = 0; + special->resource[0].end = VRAM_SIZE; + strcpy(special->resource[0].name, "SPMODULE"); + special->resource[0].flags |= DMA64_SUPPORTED; + + return special; +} + +static void init_loongarch_params(struct loongarch_params *lp) +{ + void *p = boot_params_p; + + lp->memory_offset = (unsigned long long)init_memory_map(p) + - (unsigned long long)lp; + p += align(sizeof(struct efi_memory_map_loongarch)); + + lp->cpu_offset = (unsigned long long)init_cpu_info(p) + - (unsigned long long)lp; + p += align(sizeof(struct efi_cpuinfo_loongarch)); + + lp->system_offset = (unsigned long long)init_system_loongarch(p) + - (unsigned long long)lp; + p += align(sizeof(struct system_loongarch)); + + lp->irq_offset = (unsigned long long)init_irq_source(p) + - (unsigned long long)lp; + p += align(sizeof(struct irq_source_routing_table)); + + lp->interface_offset = (unsigned long long)init_interface_info(p) + - (unsigned long long)lp; + p += align(sizeof(struct interface_info)); + + lp->boarddev_table_offset = (unsigned long long)board_devices_info(p) + - (unsigned long long)lp; + p += align(sizeof(struct board_devices)); + + lp->special_offset = (unsigned long long)init_special_info(p) + - (unsigned long long)lp; + p += align(sizeof(struct loongarch_special_attribute)); + + boot_params_p = p; +} + +static void init_smbios(struct smbios_tables *smbios) +{ + smbios->vers = 1; + smbios->vga_bios = 1; + init_loongarch_params(&(smbios->lp)); +} + +static void init_efi(struct efi_loongarch *efi) +{ + init_smbios(&(efi->smbios)); +} + +static int init_boot_param(struct boot_params *bp) +{ + init_efi(&(bp->efi)); + + return 0; +} + +static unsigned int ls3a5k_aui_boot_code[] = { + 0x0380200d, /* ori $r13,$r0,0x8 */ + 0x0400002d, /* csrwr $r13,0x0 */ + 0x0401000e, /* csrrd $r14,0x40 */ + 0x0343fdce, /* andi $r14,$r14,0xff */ + 0x143fc02c, /* lu12i.w $r12,261889(0x1fe01) */ + 0x1600000c, /* lu32i.d $r12,0 */ + 0x0320018c, /* lu52i.d $r12,$r12,-1792(0x800) */ + 0x03400dcf, /* andi $r15,$r14,0x3 */ + 0x004121ef, /* slli.d $r15,$r15,0x8 */ + 0x00153d8c, /* or $r12,$r12,$r15 */ + 0x034031d0, /* andi $r16,$r14,0xc */ + 0x0041aa10, /* slli.d $r16,$r16,0x2a */ + 0x0015418c, /* or $r12,$r12,$r16 */ + 0x28808184, /* ld.w $r4,$r12,32(0x20) */ + 0x43fffc9f, /* beqz $r4,0 -4 */ + 0x28c08184, /* ld.d $r4,$r12,32(0x20) */ + 0x28c0a183, /* ld.d $r3,$r12,40(0x28) */ + 0x28c0c182, /* ld.d $r2,$r12,48(0x30) */ + 0x28c0e185, /* ld.d $r5,$r12,56(0x38) */ + 0x4c000080, /* jirl $r0,$r4,0 */ +}; + +static int set_bootparam_uefi(ram_addr_t initrd_offset, long initrd_size) +{ + long params_size; + char memenv[32]; + char highmemenv[32]; + void *params_buf; + unsigned long *parg_env; + int ret = 0; + + /* Allocate params_buf for command line. */ + params_size = 0x100000; + params_buf = g_malloc0(params_size); + + /* + * Layout of params_buf looks like this: + * argv[0], argv[1], 0, env[0], env[1], ...env[i], 0, + * argv[0]'s data, argv[1]'s data, env[0]'data, ..., env[i]'s data, 0 + */ + parg_env = (void *)params_buf; + + ret = (3 + 1) * sizeof(target_ulong); + *parg_env++ = (BOOTPARAM_ADDR + ret); + ret += (1 + snprintf(params_buf + ret, COMMAND_LINE_SIZE - ret, "g")); + + /* argv1 */ + *parg_env++ = BOOTPARAM_ADDR + ret; + if (initrd_size > 0) + ret += (1 + snprintf(params_buf + ret, COMMAND_LINE_SIZE - ret, + "rd_start=0x%llx rd_size=%li %s", + PHYS_TO_VIRT((uint32_t)initrd_offset), + initrd_size, loaderparams.kernel_cmdline)); + else + ret += (1 + snprintf(params_buf + ret, COMMAND_LINE_SIZE - ret, "%s", + loaderparams.kernel_cmdline)); + + /* argv2 */ + *parg_env++ = 0; + + /* env */ + sprintf(memenv, "%lu", loaderparams.ram_size > 0x10000000 + ? 256 : (loaderparams.ram_size >> 20)); + sprintf(highmemenv, "%lu", loaderparams.ram_size > 0x10000000 + ? (loaderparams.ram_size >> 20) - 256 : 0); + + setenv("memsize", memenv, 1); + setenv("highmemsize", highmemenv, 1); + + ret = ((ret + 32) & ~31); + + boot_params_buf = (void *)(params_buf + ret); + boot_params_p = boot_params_buf + align(sizeof(struct boot_params)); + init_boot_param(boot_params_buf); + rom_add_blob_fixed("params", params_buf, params_size, + BOOTPARAM_PHYADDR); + loaderparams.a0 = 2; + loaderparams.a1 = BOOTPARAM_ADDR; + loaderparams.a2 = BOOTPARAM_ADDR + ret; + + return 0; +} + +static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr) +{ + return addr & 0x1fffffffll; +} + +static void fw_cfg_add_kernel_info(FWCfgState *fw_cfg, + uint64_t highram_size, + uint64_t phyAddr_initrd) +{ + int64_t entry, kernel_low, kernel_high; + long initrd_size = 0; + uint64_t initrd_offset = 0; + void *cmdline_buf; + int ret = 0; + + ret = load_elf(loaderparams.kernel_filename, NULL, cpu_loongarch_virt_to_phys, NULL, + (uint64_t *)&entry, (uint64_t *)&kernel_low, + (uint64_t *)&kernel_high, NULL, 0, EM_LOONGARCH, 1, 0); + + if(0 > ret) { + error_report("kernel image load error"); + exit(1); + } + + fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ENTRY, entry); + + if (loaderparams.initrd_filename) { + initrd_size = get_image_size(loaderparams.initrd_filename); + if (0 < initrd_size) { + if (initrd_size > highram_size) { + error_report("initrd size is too big, should below %ld MB", + highram_size / S_1MiB); + /*prevent write io memory address space*/ + exit(1); + } + initrd_offset = (phyAddr_initrd - initrd_size) & TARGET_REALPAGE_MASK; + initrd_size = load_image_targphys(loaderparams.initrd_filename, + initrd_offset, + loaderparams.ram_size - initrd_offset); + fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_offset); + fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); + } else { + error_report("initrd image size is error"); + } + } + + cmdline_buf = g_malloc0(COMMAND_LINE_SIZE); + if (initrd_size > 0) + ret = (1 + snprintf(cmdline_buf, COMMAND_LINE_SIZE, + "rd_start=0x%llx rd_size=%li %s", + PHYS_TO_VIRT(initrd_offset), + initrd_size, loaderparams.kernel_cmdline)); + else + ret = (1 + snprintf(cmdline_buf, COMMAND_LINE_SIZE, "%s", + loaderparams.kernel_cmdline)); + + fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, ret); + fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, (const char *)cmdline_buf); + + return ; +} + +static int64_t load_kernel(void) +{ + int64_t entry, kernel_low, kernel_high; + long initrd_size = 0; + ram_addr_t initrd_offset = 0; + + load_elf(loaderparams.kernel_filename, NULL, cpu_loongarch_virt_to_phys, NULL, + (uint64_t *)&entry, (uint64_t *)&kernel_low, + (uint64_t *)&kernel_high, NULL, 0, EM_LOONGARCH, 1, 0); + + if (loaderparams.initrd_filename) { + initrd_size = get_image_size(loaderparams.initrd_filename); + + if (initrd_size > 0) { + initrd_offset = (kernel_high * 4 + ~TARGET_REALPAGE_MASK) + & TARGET_REALPAGE_MASK; + initrd_size = load_image_targphys(loaderparams.initrd_filename, + initrd_offset, + loaderparams.ram_size - initrd_offset); + } + } + set_bootparam_uefi(initrd_offset, initrd_size); + + return entry; +} + +static void main_cpu_reset(void *opaque) +{ + ResetData *s = (ResetData *)opaque; + CPULOONGARCHState *env = &s->cpu->env; + + cpu_reset(CPU(s->cpu)); + env->active_tc.PC = s->vector; + env->active_tc.gpr[4] = loaderparams.a0; + env->active_tc.gpr[5] = loaderparams.a1; + env->active_tc.gpr[6] = loaderparams.a2; +} + +void slave_cpu_reset(void *opaque) +{ + ResetData *s = (ResetData *)opaque; + + cpu_reset(CPU(s->cpu)); +} + + +/* KVM_IRQ_LINE irq field index values */ +#define KVM_LOONGARCH_IRQ_TYPE_SHIFT 24 +#define KVM_LOONGARCH_IRQ_TYPE_MASK 0xff +#define KVM_LOONGARCH_IRQ_VCPU_SHIFT 16 +#define KVM_LOONGARCH_IRQ_VCPU_MASK 0xff +#define KVM_LOONGARCH_IRQ_NUM_SHIFT 0 +#define KVM_LOONGARCH_IRQ_NUM_MASK 0xffff + +/* irq_type field */ +#define KVM_LOONGARCH_IRQ_TYPE_CPU_IP 0 +#define KVM_LOONGARCH_IRQ_TYPE_CPU_IO 1 +#define KVM_LOONGARCH_IRQ_TYPE_HT 2 +#define KVM_LOONGARCH_IRQ_TYPE_MSI 3 +#define KVM_LOONGARCH_IRQ_TYPE_IOAPIC 4 + +static void legacy_set_irq(void *opaque, int irq, int level) +{ + qemu_irq *pic = opaque; + + qemu_set_irq(pic[irq], level); +} + +typedef struct ls3a_intctlstate { + uint8_t nodecounter_reg[0x100]; + uint8_t pm_reg[0x100]; + uint8_t msi_reg[0x8]; + CPULOONGARCHState **env; + DeviceState *apicdev; + qemu_irq *ioapic_irq; +#ifdef CONFIG_KVM + struct loongarch_kvm_irqchip chip; +#endif +} ls3a_intctlstate; + +typedef struct ls3a_func_args { + ls3a_intctlstate *state; + uint64_t base; + uint32_t mask; + uint8_t *mem; +} ls3a_func_args; + +static uint64_t ls3a_msi_mem_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + +static void ls3a_msi_mem_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + struct kvm_msi msi; + apicState *apic; + + apic = (apicState *)opaque; + msi.address_lo = 0; + msi.address_hi = 0; + msi.data = val & 0xff; + msi.flags = 0; + memset(msi.pad, 0, sizeof(msi.pad)); + + if (kvm_irqchip_in_kernel()) { + kvm_vm_ioctl(kvm_state, KVM_SIGNAL_MSI, &msi); + } else { + qemu_set_irq(apic->irq[msi.data], 1); + } +} + + +static const MemoryRegionOps ls3a_msi_ops = { + .read = ls3a_msi_mem_read, + .write = ls3a_msi_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + + +static const VMStateDescription vmstate_ls3a_msi = { + .name = "ls3a-msi", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(msi_reg, ls3a_intctlstate, 0x8), + VMSTATE_END_OF_LIST() + } +}; + +static void ioapic_handler(void *opaque, int irq, int level) +{ + apicState *apic; + int kvm_irq; + + apic = (apicState *)opaque; + + if (kvm_irqchip_in_kernel()) { + kvm_irq = (KVM_LOONGARCH_IRQ_TYPE_IOAPIC << KVM_LOONGARCH_IRQ_TYPE_SHIFT) + | (0 << KVM_LOONGARCH_IRQ_VCPU_SHIFT) | irq; + kvm_set_irq(kvm_state, kvm_irq, !!level); + } else { + qemu_set_irq(apic->irq[irq], level); + } +} + +static void *ls3a_intctl_init(MachineState *machine, CPULOONGARCHState *env[]) +{ + qemu_irq *irqhandler; + ls3a_intctlstate *s; + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + LoongarchMachineClass *mc = LoongarchMACHINE_GET_CLASS(lsms); + DeviceState *dev; + SysBusDevice *busdev; + MemoryRegion *address_space_mem = get_system_memory(); + MemoryRegion *iomem = NULL; + int i; + + s = g_malloc0(sizeof(ls3a_intctlstate)); + + if (!s) { + return NULL; + } + + /*Add MSI mmio memory*/ + iomem = g_new(MemoryRegion, 1); + memory_region_init_io(iomem, NULL, &ls3a_msi_ops, lsms->apic, + "ls3a_msi", 0x8); + memory_region_add_subregion(address_space_mem, + MSI_ADDR_LOW, iomem); + vmstate_register(NULL, 0, &vmstate_ls3a_msi, s); + + s->env = env; + + if (!strcmp(mc->bridge_name, "ls7a")) { + if (lsms->apic_xrupt_override) { + DPRINTF("irqchip in kernel %d\n", kvm_irqchip_in_kernel()); +#ifdef CONFIG_KVM + if (kvm_has_gsi_routing()) { + for (i = 0; i < 32; ++i) { + kvm_irqchip_add_irq_route(kvm_state, i, 0, i); + } + kvm_gsi_routing_allowed = true; + } + kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled(); +#endif + } + + irqhandler = qemu_allocate_irqs(ioapic_handler, lsms->apic, 64); + dev = qdev_new("ioapic"); + busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); + sysbus_mmio_map(busdev, 0, mc->ls7a_ioapic_reg_base); + s->ioapic_irq = irqhandler; + s->apicdev = dev; + return s->ioapic_irq; + } + return NULL; +} + +/* Network support */ +static void network_init(PCIBus *pci_bus) +{ + int i; + + for (i = 0; i < nb_nics; i++) { + NICInfo *nd = &nd_table[i]; + + if (!nd->model) { + nd->model = g_strdup("virtio-net-pci"); + } + + pci_nic_init_nofail(nd, pci_bus, nd->model, NULL); + } +} + +void loongarch_cpu_destroy(MachineState *machine, LOONGARCHCPU *cpu) +{ + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + unsigned int id; + int smp_cpus = machine->smp.cpus; + id = cpu->id; + qemu_unregister_reset(slave_cpu_reset, lsms->reset_info[id]); + g_free(lsms->reset_info[id]); + lsms->reset_info[id] = NULL; + + smp_cpus -= 1; + if (lsms->fw_cfg) { + fw_cfg_modify_i16(lsms->fw_cfg, FW_CFG_NB_CPUS, + (uint16_t)smp_cpus); + } + + qemu_del_vm_change_state_handler(cpu->cpuStateEntry); +} + +LOONGARCHCPU *loongarch_cpu_create(MachineState *machine, + LOONGARCHCPU *cpu, Error **errp) +{ + CPULOONGARCHState *env; + unsigned int id; + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + int smp_cpus = machine->smp.cpus; + id = cpu->id; + env = &cpu->env; + cpu_states[id] = env; + env->CSR_TMID |= id; + + lsms = LoongarchMACHINE(machine); + lsms->reset_info[id] = g_malloc0(sizeof(ResetData)); + lsms->reset_info[id]->cpu = cpu; + lsms->reset_info[id]->vector = env->active_tc.PC; + qemu_register_reset(slave_cpu_reset, lsms->reset_info[id]); + + /* Init CPU internal devices */ + cpu_init_irq(cpu); + cpu_loongarch_clock_init(cpu); + + smp_cpus += 1; + if (lsms->fw_cfg) { + fw_cfg_modify_i16(lsms->fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); + } + cpu_init_ipi(lsms, env->irq[12], id); + cpu_init_apic(lsms, env, id); + + return cpu; +} + +static void fw_cfg_boot_set(void *opaque, const char *boot_device, + Error **errp) +{ + fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); +} + +static FWCfgState *loongarch_fw_cfg_init(ram_addr_t ram_size, + LoongarchMachineState *lsms) +{ + FWCfgState *fw_cfg; + uint64_t *numa_fw_cfg; + int i; + const CPUArchIdList *cpus; + MachineClass *mc = MACHINE_GET_CLASS(lsms); + MachineState *ms = MACHINE(OBJECT(lsms)); + int max_cpus = ms->smp.max_cpus; + int smp_cpus = ms->smp.cpus; + int nb_numa_nodes = ms->numa_state->num_nodes; + NodeInfo *numa_info = ms->numa_state->nodes; + + fw_cfg = fw_cfg_init_mem_wide(FW_CFG_ADDR + 8, FW_CFG_ADDR, 8, 0, NULL); + fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); + fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); + + /* allocate memory for the NUMA channel: one (64bit) word for the number + * of nodes, one word for each VCPU->node and one word for each node to + * hold the amount of memory. + */ + numa_fw_cfg = g_new0(uint64_t, 1 + max_cpus + nb_numa_nodes); + numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes); + cpus = mc->possible_cpu_arch_ids(MACHINE(lsms)); + for (i = 0; i < cpus->len; i++) { + unsigned int apic_id = cpus->cpus[i].arch_id; + assert(apic_id < max_cpus); + numa_fw_cfg[apic_id + 1] = cpu_to_le64(cpus->cpus[i].props.node_id); + } + for (i = 0; i < nb_numa_nodes; i++) { + numa_fw_cfg[max_cpus + 1 + i] = + cpu_to_le64(numa_info[i].node_mem); + } + fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg, + (1 + max_cpus + nb_numa_nodes) * + sizeof(*numa_fw_cfg)); + + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); + return fw_cfg; +} + +static void loongarch_build_smbios(LoongarchMachineState *lsms) +{ + LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + MachineState *ms = MACHINE(OBJECT(lsms)); + uint8_t *smbios_tables, *smbios_anchor; + size_t smbios_tables_len, smbios_anchor_len; + const char *product = "QEMU Virtual Machine"; + ms->smp.cores = 4; + + if (!lsms->fw_cfg) { + return; + } + + if (kvm_enabled()) { + if (strstr(lsmc->cpu_name, "5000")) { + product = "KVM"; + } + } else { + product = "Loongarch-3A5K-7A1000-TCG"; + } + + host_cpufreq = get_host_cpu_freq(); + + smbios_set_defaults("Loongson", product, lsmc->cpu_name, false, + true, NULL, NULL, SMBIOS_ENTRY_POINT_30); + + smbios_get_tables(ms, NULL, 0, &smbios_tables, &smbios_tables_len, + &smbios_anchor, &smbios_anchor_len, &error_fatal); + + if (smbios_anchor) { + fw_cfg_add_file(lsms->fw_cfg, "etc/smbios/smbios-tables", + smbios_tables, smbios_tables_len); + fw_cfg_add_file(lsms->fw_cfg, "etc/smbios/smbios-anchor", + smbios_anchor, smbios_anchor_len); + } +} + +static +void loongarch_machine_done(Notifier *notifier, void *data) +{ + LoongarchMachineState *lsms = container_of(notifier, + LoongarchMachineState, machine_done); + loongarch_acpi_setup(); + loongarch_build_smbios(lsms); +} + +#ifdef CONFIG_TCG +#define FEATURE_REG 0x1fe00008 +#define VENDOR_REG 0x1fe00010 +#define CPUNAME_REG 0x1fe00020 +#define OTHER_FUNC_REG 0x1fe00420 +#define _str(x) #x +#define str(x) _str(x) +#define SIMPLE_OPS(ADDR, SIZE) \ +({\ + MemoryRegion *iomem = g_new(MemoryRegion, 1);\ + memory_region_init_io(iomem, NULL, &loongarch_qemu_ops, \ + (void *)ADDR, str(ADDR) , SIZE);\ + memory_region_add_subregion_overlap(address_space_mem, ADDR, iomem, 1);\ +}) + +static int reg180; + +static void loongarch_qemu_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + addr = ((hwaddr)(long)opaque) + addr; + addr = addr & 0xffffffff; + switch (addr) { + case 0x1fe00180: + reg180 = val; + break; + } +} + +static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size) +{ + uint64_t feature = 0UL; + addr = ((hwaddr)(long)opaque) + addr; + addr = addr & 0xffffffff; + switch (addr) { + case 0x1fe00180: + return reg180; + case 0x1001041c: + return 0xa800; + case FEATURE_REG: + feature |= 1UL << 2 | 1UL << 3 | 1UL << 4 | 1UL << 11; + return feature ; + case VENDOR_REG: + return *(uint64_t *)"Loongson-3A5000"; + case CPUNAME_REG: + return *(uint64_t *)"3A5000"; + case 0x10013ffc: + return 0x80; + } + return 0; +} + +static const MemoryRegionOps loongarch_qemu_ops = { + .read = loongarch_qemu_read, + .write = loongarch_qemu_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 8, + }, + .impl = { + .min_access_size = 4, + .max_access_size = 8, + }, +}; +#endif + + +static void loongarch_system_flash_cleanup_unused(LoongarchMachineState *lsms) +{ + char *prop_name; + int i; + Object *dev_obj; + + for (i = 0; i < ARRAY_SIZE(lsms->flash); i++) { + dev_obj = OBJECT(lsms->flash[i]); + if (!object_property_get_bool(dev_obj, "realized", &error_abort)) { + prop_name = g_strdup_printf("pflash%d", i); + object_property_del(OBJECT(lsms), prop_name); + g_free(prop_name); + object_unparent(dev_obj); + lsms->flash[i] = NULL; + } + } +} + + +static bool loongarch_system_flash_init( LoongarchMachineState *lsms) +{ + int i = 0; + int64_t size = 0; + PFlashCFI01 *pflash = NULL; + BlockBackend *pflash_blk; + + for(i = 0; i < ARRAY_SIZE(lsms->flash); i++) { + pflash_blk = NULL; + pflash = NULL; + + pflash = lsms->flash[i]; + pflash_cfi01_legacy_drive(pflash, + drive_get(IF_PFLASH, 0, i)); + + pflash_blk = pflash_cfi01_get_blk(pflash); + /*The pflash0 must be exist, or not support boot by pflash*/ + if(pflash_blk == NULL) { + if(i == 0) { + return false; + } else { + break; + } + } + + size = blk_getlength(pflash_blk); + if (size == 0 || size % FLASH_SECTOR_SIZE != 0) { + error_report("system firmware block device %s has invalid size " + "%" PRId64, + blk_name(pflash_blk), size); + error_report("its size must be a non-zero multiple of 0x%x", + FLASH_SECTOR_SIZE); + exit(1); + } + qdev_prop_set_uint32(DEVICE(pflash), "num-blocks", + size / FLASH_SECTOR_SIZE); + sysbus_realize_and_unref(SYS_BUS_DEVICE(pflash), &error_fatal); + if(i == 0) { + sysbus_mmio_map(SYS_BUS_DEVICE(pflash), 0, LS_BIOS_BASE); + } else { + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(pflash), 0, LS_BIOS_VAR_BASE, 1); + } + } + + return true; +} +static void ls3a5k_bios_init(LoongarchMachineState *lsms, + ram_addr_t ram_size, + uint64_t highram_size, + uint64_t phyAddr_initrd, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename) +{ + MemoryRegion *bios; + bool fw_cfg_used = false; + LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + char *filename; + int bios_size; + const char *bios_name; + + bios_name = MACHINE(lsms)->firmware; + if (kernel_filename) { + loaderparams.ram_size = ram_size; + loaderparams.kernel_filename = kernel_filename; + loaderparams.kernel_cmdline = kernel_cmdline; + loaderparams.initrd_filename = initrd_filename; + } + + if(loongarch_system_flash_init(lsms)) { + fw_cfg_used = true; + } else { + bios = g_new(MemoryRegion, 1); + memory_region_init_ram(bios, NULL, "loongarch.bios", LS_BIOS_SIZE, &error_fatal); + memory_region_set_readonly(bios, true); + memory_region_add_subregion(get_system_memory(), LS_BIOS_BASE, bios); + + /* BIOS load */ + if (bios_name) { + if (access(bios_name, R_OK) == 0) { + load_image_targphys(bios_name, LS_BIOS_BASE, LS_BIOS_SIZE); + } else { + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + load_image_targphys(filename, LS_BIOS_BASE, LS_BIOS_SIZE); + g_free(filename); + } + fw_cfg_used = true; + } else { + if (strstr(lsmc->cpu_name, "5000")) { + bios_size = sizeof(ls3a5k_aui_boot_code); + rom_add_blob_fixed("bios", ls3a5k_aui_boot_code, bios_size, LS_BIOS_BASE); + } + + if (kernel_filename) { + lsms->reset_info[0]->vector = load_kernel(); + } else { + error_report("Please specify at lease one of -bios and -kernel"); + exit(1); + } + } + } + + loongarch_system_flash_cleanup_unused(lsms); + + if (fw_cfg_used) { + lsms->fw_cfg = loongarch_fw_cfg_init(ram_size, lsms); + rom_set_fw(lsms->fw_cfg); + fw_conf_init(ram_size); + rom_add_blob_fixed("fw_conf", (void *)&fw_config, + sizeof(fw_config), FW_CONF_ADDR); + + if (kernel_filename) { + fw_cfg_add_kernel_info(lsms->fw_cfg, highram_size, phyAddr_initrd); + } + } + + if (lsms->fw_cfg != NULL) { + fw_cfg_add_file(lsms->fw_cfg, "etc/memmap", + la_memmap_table, + sizeof(struct la_memmap_entry) * (la_memmap_entries)); + } + + return ; +} +static void create_fdt(LoongarchMachineState *lsms) +{ + lsms->fdt = create_device_tree(&lsms->fdt_size); + if (!lsms->fdt) { + error_report("create_device_tree() failed"); + exit(1); + } + + /* Header */ + qemu_fdt_setprop_string(lsms->fdt, "/", "compatible", + "linux,dummy-loongson3"); + qemu_fdt_setprop_cell(lsms->fdt, "/", "#address-cells", 0x2); + qemu_fdt_setprop_cell(lsms->fdt, "/", "#size-cells", 0x2); +} + +static void fdt_add_cpu_nodes(const LoongarchMachineState *lsms) +{ + int num; + const MachineState *ms = MACHINE(lsms); + int smp_cpus = ms->smp.cpus; + + qemu_fdt_add_subnode(lsms->fdt, "/cpus"); + qemu_fdt_setprop_cell(lsms->fdt, "/cpus", "#address-cells", 0x1); + qemu_fdt_setprop_cell(lsms->fdt, "/cpus", "#size-cells", 0x0); + + /* cpu nodes */ + for (num = smp_cpus - 1; num >= 0; num--) { + char *nodename = g_strdup_printf("/cpus/cpu@%d", num); + LOONGARCHCPU *cpu = LOONGARCH_CPU(qemu_get_cpu(num)); + + qemu_fdt_add_subnode(lsms->fdt, nodename); + qemu_fdt_setprop_string(lsms->fdt, nodename, "device_type", "cpu"); + qemu_fdt_setprop_string(lsms->fdt, nodename, "compatible", + cpu->dtb_compatible); + qemu_fdt_setprop_cell(lsms->fdt, nodename, "reg", num); + qemu_fdt_setprop_cell(lsms->fdt, nodename, "phandle", + qemu_fdt_alloc_phandle(lsms->fdt)); + g_free(nodename); + } + + /*cpu map */ + qemu_fdt_add_subnode(lsms->fdt, "/cpus/cpu-map"); + + for (num = smp_cpus - 1; num >= 0; num--) { + char *cpu_path = g_strdup_printf("/cpus/cpu@%d", num); + char *map_path; + + if (ms->smp.threads > 1) { + map_path = g_strdup_printf( + "/cpus/cpu-map/socket%d/core%d/thread%d", + num / (ms->smp.cores * ms->smp.threads), + (num / ms->smp.threads) % ms->smp.cores, + num % ms->smp.threads); + } else { + map_path = g_strdup_printf( + "/cpus/cpu-map/socket%d/core%d", + num / ms->smp.cores, + num % ms->smp.cores); + } + qemu_fdt_add_path(lsms->fdt, map_path); + qemu_fdt_setprop_phandle(lsms->fdt, map_path, "cpu", cpu_path); + + g_free(map_path); + g_free(cpu_path); + } +} + +static void fdt_add_fw_cfg_node(const LoongarchMachineState *lsms) +{ + char *nodename; + hwaddr base = FW_CFG_ADDR; + + nodename = g_strdup_printf("/fw_cfg@%" PRIx64, base); + qemu_fdt_add_subnode(lsms->fdt, nodename); + qemu_fdt_setprop_string(lsms->fdt, nodename, + "compatible", "qemu,fw-cfg-mmio"); + qemu_fdt_setprop_sized_cells(lsms->fdt, nodename, "reg", + 2, base, 2, 0x8); + qemu_fdt_setprop(lsms->fdt, nodename, "dma-coherent", NULL, 0); + g_free(nodename); +} + +static void fdt_add_pcie_node(const LoongarchMachineState *lsms) +{ + char *nodename; + hwaddr base_mmio = LS_ISA_MEM_BASE; + hwaddr size_mmio = LS_ISA_MEM_SIZE; + hwaddr base_pio = LS3A5K_ISA_IO_BASE; + hwaddr size_pio = LS_ISA_IO_SIZE; + hwaddr base_pcie = LS_PCIECFG_BASE; + hwaddr size_pcie = LS_PCIECFG_SIZE; + hwaddr base = base_pcie; + + nodename = g_strdup_printf("/pcie@%" PRIx64, base); + qemu_fdt_add_subnode(lsms->fdt, nodename); + qemu_fdt_setprop_string(lsms->fdt, nodename, + "compatible", "pci-host-ecam-generic"); + qemu_fdt_setprop_string(lsms->fdt, nodename, "device_type", "pci"); + qemu_fdt_setprop_cell(lsms->fdt, nodename, "#address-cells", 3); + qemu_fdt_setprop_cell(lsms->fdt, nodename, "#size-cells", 2); + qemu_fdt_setprop_cell(lsms->fdt, nodename, "linux,pci-domain", 0); + qemu_fdt_setprop_cells(lsms->fdt, nodename, "bus-range", 0, + PCIE_MMCFG_BUS(LS_PCIECFG_SIZE - 1)); + qemu_fdt_setprop(lsms->fdt, nodename, "dma-coherent", NULL, 0); + qemu_fdt_setprop_sized_cells(lsms->fdt, nodename, "reg", + 2, base_pcie, 2, size_pcie); + qemu_fdt_setprop_sized_cells(lsms->fdt, nodename, "ranges", + 1, FDT_PCI_RANGE_IOPORT, 2, 0, + 2, base_pio, 2, size_pio, + 1, FDT_PCI_RANGE_MMIO, 2, base_mmio, + 2, base_mmio, 2, size_mmio); + g_free(nodename); + qemu_fdt_dumpdtb(lsms->fdt, lsms->fdt_size); +} + +static void ls3a5k_init(MachineState *args) +{ + int i; + const char *cpu_model = args->cpu_type; + const char *kernel_filename = args->kernel_filename; + const char *kernel_cmdline = args->kernel_cmdline; + const char *initrd_filename = args->initrd_filename; + + ram_addr_t ram_size = args->ram_size; + MemoryRegion *address_space_mem = get_system_memory(); + ram_addr_t offset = 0; + MemoryRegion *isa_io = g_new(MemoryRegion, 1); + MemoryRegion *isa_mem = g_new(MemoryRegion, 1); + MachineState *machine = args; + MachineClass *mc = MACHINE_GET_CLASS(machine); + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + int smp_cpus = machine->smp.cpus; + int nb_numa_nodes = machine->numa_state->num_nodes; + NodeInfo *numa_info = machine->numa_state->nodes; + LOONGARCHCPU *cpu; + CPULOONGARCHState *env; + qemu_irq *ls7a_apic = NULL; + qemu_irq *pirq = NULL; + PCIBus *pci_bus = NULL; + char *ramName = NULL; + uint64_t lowram_size = 0, highram_size = 0, phyAddr = 0, + memmap_size = 0, highram_end_addr = 0; + + CPUArchIdList *possible_cpus; + if (strstr(lsmc->cpu_name, "5000")) { + if (strcmp(cpu_model, LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000")) && + strcmp(cpu_model, LOONGARCH_CPU_TYPE_NAME("host"))) { + error_report("machine type %s does not match cpu type %s", + lsmc->cpu_name, cpu_model); + exit(1); + } + if (kvm_enabled()) { + kvm_vm_ioctl(kvm_state, KVM_LARCH_SET_CPUCFG, ls3a5k_cpucfgs); + } + } + + create_fdt(lsms); + + DPRINTF("isa 0x%lx\n", lsmc->isa_io_base); + DPRINTF("ht1lo 0x%lx\n", lsmc->ht1lo_pcicfg_base); + DPRINTF("cpu_name %s bridge_name %s\n", + lsmc->cpu_name, lsmc->bridge_name); + + /* init CPUs */ + mc->possible_cpu_arch_ids(machine); + possible_cpus = machine->possible_cpus; + + for (i = 0; i < smp_cpus; i++) { + Object *obj = NULL; + Error *local_err = NULL; + + obj = object_new(possible_cpus->cpus[i].type); + + object_property_set_uint(obj, "id", possible_cpus->cpus[i].arch_id, + &local_err); + object_property_set_bool(obj, "realized", true, &local_err); + + object_unref(obj); + error_propagate(&error_fatal, local_err); + + cpu = LOONGARCH_CPU(CPU(obj)); + if (cpu == NULL) { + fprintf(stderr, "Unable to find CPU definition\n"); + exit(1); + } + + env = &cpu->env; + cpu_states[i] = env; + env->CSR_TMID |= i; + + lsms->reset_info[i] = g_malloc0(sizeof(ResetData)); + lsms->reset_info[i]->cpu = cpu; + lsms->reset_info[i]->vector = env->active_tc.PC; + if (i == 0) { + qemu_register_reset(main_cpu_reset, lsms->reset_info[i]); + } else { + qemu_register_reset(slave_cpu_reset, lsms->reset_info[i]); + } + + /* Init CPU internal devices */ + cpu_init_irq(cpu); + cpu_loongarch_clock_init(cpu); + cpu_init_ipi(lsms, env->irq[12], i); + cpu_init_apic(lsms, env, i); + } + + lsms->hotpluged_cpu_num = 0; + fdt_add_cpu_nodes(lsms); + env = cpu_states[0]; + + /* node0 mem*/ + phyAddr = (uint64_t)0; + MemoryRegion *lowmem = g_new(MemoryRegion, 1); + ramName = g_strdup_printf("loongarch_ls3a.node%d.lowram", 0); + + lowram_size = MIN(ram_size, 256 * 0x100000); + memory_region_init_alias(lowmem, NULL, ramName, machine->ram, 0, lowram_size); + memory_region_add_subregion(address_space_mem, phyAddr, lowmem); + + offset += lowram_size; + if (nb_numa_nodes > 0) { + highram_size = numa_info[0].node_mem - S_256MiB; + if (numa_info[0].node_mem > S_1GiB) { + memmap_size = numa_info[0].node_mem - S_1GiB; + la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); + } + } else { + highram_size = ram_size - S_256MiB; + if (ram_size > S_1GiB) { + memmap_size = ram_size - S_1GiB; + la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); + } + } + + phyAddr = (uint64_t)0x90000000; + MemoryRegion *highmem = g_new(MemoryRegion, 1); + ramName = g_strdup_printf("loongarch_ls3a.node%d.highram", 0); + memory_region_init_alias(highmem, NULL, ramName, + machine->ram, offset, highram_size); + memory_region_add_subregion(address_space_mem, + phyAddr, highmem); + offset += highram_size; + phyAddr += highram_size; + + /* initrd address use high mem from high to low */ + highram_end_addr = phyAddr; + /* node1~ nodemax */ + for (i = 1; i < nb_numa_nodes; i++) { + MemoryRegion *nodemem = g_new(MemoryRegion, 1); + ramName = g_strdup_printf("loongarch_ls3a.node%d.ram", i); + memory_region_init_alias(nodemem, NULL, ramName, + machine->ram, offset, numa_info[i].node_mem); + memory_region_add_subregion(address_space_mem, + phyAddr, nodemem); + la_memmap_add_entry(phyAddr, numa_info[i].node_mem, SYSTEM_RAM); + offset += numa_info[i].node_mem; + phyAddr += numa_info[i].node_mem; + } + + fdt_add_fw_cfg_node(lsms); + ls3a5k_bios_init(lsms, ram_size, highram_size, highram_end_addr, + kernel_filename, kernel_cmdline, initrd_filename); + + lsms->machine_done.notify = loongarch_machine_done; + qemu_add_machine_init_done_notifier(&lsms->machine_done); + /*vmstate_register_ram_global(bios);*/ + + /* initialize hotplug memory address space */ + lsms->hotplug_memory_size = 0; + + /* always allocate the device memory information */ + machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); + if (machine->ram_size < machine->maxram_size) { + int max_memslots; + + lsms->hotplug_memory_size = machine->maxram_size - machine->ram_size; + /* + * Limit the number of hotpluggable memory slots to half the number + * slots that KVM supports, leaving the other half for PCI and other + * devices. However ensure that number of slots doesn't drop below 32. + */ + max_memslots = LOONGARCH_MAX_RAM_SLOTS; + if (kvm_enabled()) { + max_memslots = kvm_get_max_memslots() / 2 ; + } + + if (machine->ram_slots == 0) + machine->ram_slots = lsms->hotplug_memory_size / + LOONGARCH_HOTPLUG_MEM_ALIGN; + + if (machine->ram_slots > max_memslots) { + error_report("Specified number of memory slots %" + PRIu64" exceeds max supported %d", + machine->ram_slots, max_memslots); + exit(1); + } + + lsms->ram_slots = machine->ram_slots; + + machine->device_memory->base = get_hotplug_membase(machine->ram_size); + memory_region_init(&machine->device_memory->mr, OBJECT(lsms), + "device-memory", lsms->hotplug_memory_size); + memory_region_add_subregion(get_system_memory(), + machine->device_memory->base, + &machine->device_memory->mr); + } + + memory_region_init_alias(isa_io, NULL, "isa-io", + get_system_io(), 0, LS_ISA_IO_SIZE); + memory_region_init(isa_mem, NULL, "isa-mem", LS_ISA_MEM_SIZE); + memory_region_add_subregion(get_system_memory(), lsmc->isa_io_base, isa_io); + memory_region_add_subregion(get_system_memory(), LS_ISA_MEM_BASE, isa_mem); + + if (!strcmp(lsmc->bridge_name, "ls7a")) { + /*Initialize the 7A IO interrupt subsystem*/ + DeviceState *ls7a_dev; + lsms->apic_xrupt_override = kvm_irqchip_in_kernel(); + ls7a_apic = ls3a_intctl_init(machine, cpu_states); + if (!ls7a_apic) { + perror("Init 7A APIC failed\n"); + exit(1); + } + pci_bus = ls7a_init(machine, ls7a_apic, &ls7a_dev); + + object_property_add_link(OBJECT(machine), + LOONGARCH_MACHINE_ACPI_DEVICE_PROP, + TYPE_HOTPLUG_HANDLER, + (Object **)&lsms->acpi_dev, + object_property_allow_set_link, + OBJ_PROP_LINK_STRONG); + object_property_set_link(OBJECT(machine), LOONGARCH_MACHINE_ACPI_DEVICE_PROP, + OBJECT(ls7a_dev), &error_abort); + +#ifdef CONFIG_KVM + if (kvm_enabled()) { + kvm_direct_msi_allowed = (kvm_check_extension(kvm_state, + KVM_CAP_SIGNAL_MSI) > 0); + } else { + kvm_direct_msi_allowed = 0; + } + msi_nonbroken = kvm_direct_msi_allowed; +#else + msi_nonbroken = true; +#endif + sysbus_create_simple("ls7a_rtc", LS7A_RTC_REG_BASE, + ls7a_apic[LS7A_RTC_IRQ - LOONGARCH_PCH_IRQ_BASE]); + } + + /*Initialize the CPU serial device*/ + + if (serial_hd(0)) { + pirq = qemu_allocate_irqs(legacy_set_irq, ls7a_apic + + (LS7A_UART_IRQ - LOONGARCH_PCH_IRQ_BASE), 1); + serial_mm_init(address_space_mem, LS7A_UART_BASE, 0, pirq[0], + 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN); + } + + /*network card*/ + network_init(pci_bus); + /* VGA setup. Don't bother loading the bios. */ + pci_vga_init(pci_bus); + + sysbus_realize_and_unref(SYS_BUS_DEVICE(qdev_new("iocsr")), &error_fatal); + +#ifdef CONFIG_TCG + int nb_nodes = (smp_cpus - 1) / 4; + for (i = 0; i <= nb_nodes; i++) { + uint64_t off = (uint64_t)i << 44; + SIMPLE_OPS(((hwaddr)0x1fe00180 | off), 0x8); + SIMPLE_OPS(((hwaddr)0x1fe0019c | off), 0x8); + SIMPLE_OPS(((hwaddr)0x1fe001d0 | off), 0x8); + SIMPLE_OPS(((hwaddr)FEATURE_REG | off), 0x8); + SIMPLE_OPS(((hwaddr)VENDOR_REG | off), 0x8); + SIMPLE_OPS(((hwaddr)CPUNAME_REG | off), 0x8); + SIMPLE_OPS(((hwaddr)OTHER_FUNC_REG | off), 0x8); + } + + SIMPLE_OPS(0x1001041c, 0x4); + SIMPLE_OPS(0x10002000, 0x14); + SIMPLE_OPS(0x10013ffc, 0x4); +#endif + + fdt_add_pcie_node(lsms); + + /* load fdt */ + MemoryRegion *fdt_rom = g_new(MemoryRegion, 1); + memory_region_init_rom(fdt_rom, NULL, "fdt", LS_FDT_SIZE, &error_fatal); + memory_region_add_subregion(get_system_memory(), LS_FDT_BASE, fdt_rom); + rom_add_blob_fixed("fdt", lsms->fdt, lsms->fdt_size, LS_FDT_BASE); +} + +static const CPUArchIdList *loongarch_possible_cpu_arch_ids(MachineState *ms) +{ + int i; + int max_cpus = ms->smp.max_cpus; + + if (ms->possible_cpus) { + /* + * make sure that max_cpus hasn't changed since the first use, i.e. + * -smp hasn't been parsed after it + */ + assert(ms->possible_cpus->len == max_cpus); + return ms->possible_cpus; + } + + ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + + sizeof(CPUArchId) * max_cpus); + ms->possible_cpus->len = max_cpus; + for (i = 0; i < ms->possible_cpus->len; i++) { + ms->possible_cpus->cpus[i].type = ms->cpu_type; + ms->possible_cpus->cpus[i].vcpus_count = 1; + ms->possible_cpus->cpus[i].props.has_core_id = true; + ms->possible_cpus->cpus[i].props.core_id = i; + ms->possible_cpus->cpus[i].arch_id = i; + } + return ms->possible_cpus; + +} + +static PFlashCFI01 *loongarch_pflash_create(LoongarchMachineState *lsms, + const char *name, + const char *alias_prop_name) +{ + DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); + + qdev_prop_set_uint64(dev, "sector-length", FLASH_SECTOR_SIZE); + qdev_prop_set_uint8(dev, "width", 1); + qdev_prop_set_string(dev, "name", name); + object_property_add_child(OBJECT(lsms), name, OBJECT(dev)); + object_property_add_alias(OBJECT(lsms), alias_prop_name, + OBJECT(dev), "drive"); + return PFLASH_CFI01(dev); +} + + +static void loongarch_system_flash_create(LoongarchMachineState *lsms) +{ + lsms->flash[0] = loongarch_pflash_create(lsms, "system.flash0", + "pflash0"); + lsms->flash[1] = loongarch_pflash_create(lsms, "system.flash1", + "pflash1"); +} + +static void loongarch_machine_initfn(Object *obj) +{ + LoongarchMachineState *lsms = LoongarchMACHINE(obj); + LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + lsms->acpi_build_enabled = lsmc->has_acpi_build; + loongarch_system_flash_create(lsms); + lsms->oem_id = g_strndup(EFI_ACPI_OEM_ID, 6); + lsms->oem_table_id = g_strndup(EFI_ACPI_OEM_TABLE_ID, 6); +} + +static void ls3a5k_ls7a_machine_options(MachineClass *m) +{ + char *cpu_name = get_host_cpu_model_name(); + LoongarchMachineClass *lsmc = LoongarchMACHINE_CLASS(m); + m->desc = "Loongarch3a5k LS7A1000 machine"; + m->max_cpus = LOONGARCH_MAX_VCPUS; + m->alias = "loongson7a"; + m->is_default = 1; + lsmc->isa_io_base = LS3A5K_ISA_IO_BASE; + lsmc->ht1lo_pcicfg_base = LS3A5K_HT1LO_PCICFG_BASE; + lsmc->pciecfg_base = LS_PCIECFG_BASE; + lsmc->ls7a_ioapic_reg_base = LS3A5K_LS7A_IOAPIC_REG_BASE; + lsmc->node_shift = 44; + strncpy(lsmc->cpu_name, cpu_name, sizeof(lsmc->cpu_name) - 1); + lsmc->cpu_name[sizeof(lsmc->cpu_name) - 1] = 0; + strncpy(lsmc->bridge_name, "ls7a", sizeof(lsmc->bridge_name) - 1); + lsmc->bridge_name[sizeof(lsmc->bridge_name) - 1] = 0; + compat_props_add(m->compat_props, loongarch_compat, loongarch_compat_len); +} + +static void ls3a_board_reset(MachineState *ms) +{ + qemu_devices_reset(); +#ifdef CONFIG_KVM + struct loongarch_kvm_irqchip *chip; + int length; + + if (!kvm_enabled()) { + return; + } + length = sizeof(struct loongarch_kvm_irqchip) + + sizeof(struct loongarch_gipiState); + chip = g_malloc0(length); + memset(chip, 0, length); + chip->chip_id = KVM_IRQCHIP_LS3A_GIPI; + chip->len = length; + kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); + + length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct ls7a_ioapic_state); + chip = g_realloc(chip, length); + memset(chip, 0, length); + chip->chip_id = KVM_IRQCHIP_LS7A_IOAPIC; + chip->len = length; + kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip); + + g_free(chip); +#endif +} + +static CpuInstanceProperties ls3a_cpu_index_to_props(MachineState *ms, unsigned cpu_index) +{ + MachineClass *mc = MACHINE_GET_CLASS(ms); + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); + + assert(cpu_index < possible_cpus->len); + return possible_cpus->cpus[cpu_index].props; +} + +static int64_t ls3a_get_default_cpu_node_id(const MachineState *ms, int idx) +{ + int nb_numa_nodes = ms->numa_state->num_nodes; + int smp_cores = ms->smp.cores; + return idx / smp_cores % nb_numa_nodes; +} + +static void loongarch_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); + LoongarchMachineClass *lsmc = LoongarchMACHINE_CLASS(oc); + + lsmc->get_hotplug_handler = mc->get_hotplug_handler; + lsmc->has_acpi_build = true; + mc->get_hotplug_handler = loongarch_get_hotpug_handler; + mc->has_hotpluggable_cpus = true; + mc->cpu_index_to_instance_props = ls3a_cpu_index_to_props; + mc->possible_cpu_arch_ids = loongarch_possible_cpu_arch_ids; + mc->get_default_cpu_node_id = ls3a_get_default_cpu_node_id; + mc->default_ram_size = 1 * GiB; + mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000"); + mc->default_ram_id = "loongarch_ls3a.ram"; + + mc->reset = ls3a_board_reset; + mc->max_cpus = LOONGARCH_MAX_VCPUS; + hc->pre_plug = loongarch_machine_device_pre_plug; + hc->plug = loongarch_machine_device_plug; + hc->unplug = longson_machine_device_unplug; + hc->unplug_request = loongarch_machine_device_unplug_request; + + object_class_property_add(oc, "acpi", "OnOffAuto", + loongarch_get_acpi, loongarch_set_acpi, + NULL, NULL); + object_class_property_set_description(oc, "acpi", + "Enable ACPI"); +} + +static const TypeInfo loongarch_info = { + .name = TYPE_LOONGARCH_MACHINE, + .parent = TYPE_MACHINE, + .abstract = true, + .instance_size = sizeof(LoongarchMachineState), + .instance_init = loongarch_machine_initfn, + .class_size = sizeof(LoongarchMachineClass), + .class_init = loongarch_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + }, + +}; + +static void loongarch_machine_register_types(void) +{ + type_register_static(&loongarch_info); +} + +type_init(loongarch_machine_register_types) + +DEFINE_LS3A5K_MACHINE(loongson7a_v1_0, "loongson7a_v1.0", + ls3a5k_ls7a_machine_options); diff --git a/hw/loongarch/larch_hotplug.c b/hw/loongarch/larch_hotplug.c new file mode 100644 index 0000000000..7bce957124 --- /dev/null +++ b/hw/loongarch/larch_hotplug.c @@ -0,0 +1,355 @@ +/* + * Hotplug emulation on Loongarch system. + * + * Copyright (c) 2018 Loongarch Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "qemu/queue.h" +#include "qemu/units.h" +#include "qemu/cutils.h" +#include "qemu/bcd.h" +#include "hw/hotplug.h" +#include "hw/loongarch/cpudevs.h" +#include "hw/mem/memory-device.h" +#include "sysemu/numa.h" +#include "sysemu/cpus.h" +#include "hw/loongarch/larch.h" +#include "hw/cpu/core.h" +#include "hw/nvram/fw_cfg.h" + +/* find cpu slot in machine->possible_cpus by core_id */ +static CPUArchId *loongarch_find_cpu_slot(MachineState *ms, uint32_t id, + int *idx) +{ + int index = id; + + if (index >= ms->possible_cpus->len) { + return NULL; + } + if (idx) { + *idx = index; + } + return &ms->possible_cpus->cpus[index]; +} + +static void loongarch_memory_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + Error *local_err = NULL; + LoongarchMachineState *lsms = LoongarchMACHINE(hotplug_dev); + HotplugHandlerClass *hhc; + uint64_t size; + + size = memory_device_get_region_size(MEMORY_DEVICE(dev), &error_abort); + if (size % LOONGARCH_HOTPLUG_MEM_ALIGN) { + error_setg(&local_err, "Hotplugged memory size must be a multiple of " + "%lld MB", LOONGARCH_HOTPLUG_MEM_ALIGN / MiB); + goto out; + } + + pc_dimm_plug(PC_DIMM(dev), MACHINE(lsms)); + + hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); + hhc->plug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &error_abort); +out: + error_propagate(errp, local_err); +} + +static void loongarch_memory_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + Error *local_err = NULL; + HotplugHandlerClass *hhc; + LoongarchMachineState *lsms = LoongarchMACHINE(hotplug_dev); + + if (!lsms->acpi_dev || !loongarch_is_acpi_enabled(lsms)) { + error_setg(&local_err, + "memory hotplug is not enabled: missing acpi device or acpi disabled"); + goto out; + } + hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); + hhc->unplug_request(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); + +out: + error_propagate(errp, local_err); +} + +static void loongarch_cpu_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + CPUArchId *found_cpu; + HotplugHandlerClass *hhc; + Error *local_err = NULL; + LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); + MachineState *machine = MACHINE(OBJECT(hotplug_dev)); + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + + hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); + hhc->unplug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); + + if (local_err) { + goto out; + } + + loongarch_cpu_destroy(machine, cpu); + + found_cpu = loongarch_find_cpu_slot(MACHINE(lsms), cpu->id, NULL); + found_cpu->cpu = NULL; + object_unparent(OBJECT(dev)); + lsms->hotpluged_cpu_num -= 1; +out: + error_propagate(errp, local_err); +} + +static void loongarch_memory_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + Error *local_err = NULL; + HotplugHandlerClass *hhc; + LoongarchMachineState *lsms = LoongarchMACHINE(hotplug_dev); + + hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); + hhc->unplug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); + + if (local_err) { + goto out; + } + + pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev)); + object_unparent(OBJECT(dev)); + +out: + error_propagate(errp, local_err); +} + +static void loongarch_cpu_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + MachineState *ms = MACHINE(OBJECT(hotplug_dev)); + MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); + LoongarchMachineState *lsms = LoongarchMACHINE(ms); + LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); + CPUArchId *cpu_slot; + Error *local_err = NULL; + int index; + int free_index = lsms->hotpluged_cpu_num + ms->smp.cpus; + int max_cpus = ms->smp.max_cpus; + + if (dev->hotplugged && !mc->has_hotpluggable_cpus) { + error_setg(&local_err, "CPU hotplug not supported for this machine"); + goto out; + } + + if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { + error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", + ms->cpu_type); + return; + } + + /* if ID is not set, set it based on core properties */ + if (cpu->id == UNASSIGNED_CPU_ID) { + if ((cpu->core_id) > (max_cpus - 1)) { + error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u", + cpu->core_id, max_cpus - 1); + return; + } + + if (free_index > (max_cpus - 1)) { + error_setg(errp, "The maximum number of CPUs cannot exceed %u.", + max_cpus); + return; + } + + if (cpu->core_id != free_index) { + error_setg(errp, "Invalid CPU core-id: %u must be :%u", + cpu->core_id, free_index); + return; + } + + cpu->id = cpu->core_id; + } + + cpu_slot = loongarch_find_cpu_slot(MACHINE(hotplug_dev), cpu->id, &index); + if (!cpu_slot) { + error_setg(&local_err, "core id %d out of range", cpu->id); + goto out; + } + + if (cpu_slot->cpu) { + error_setg(&local_err, "core %d already populated", cpu->id); + goto out; + } + + numa_cpu_pre_plug(cpu_slot, dev, &local_err); + + return ; +out: + error_propagate(errp, local_err); +} + +static void loongarch_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + MachineState *machine = MACHINE(OBJECT(hotplug_dev)); + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + PCDIMMDevice *dimm = PC_DIMM(dev); + Error *local_err = NULL; + uint64_t size; + + if (!lsms->acpi_dev || !loongarch_is_acpi_enabled(lsms)) { + error_setg(errp, + "memory hotplug is not enabled: missing acpi device or acpi disabled"); + return; + } + + size = memory_device_get_region_size(MEMORY_DEVICE(dimm), &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + if (size % LOONGARCH_HOTPLUG_MEM_ALIGN) { + error_setg(errp, "Hotplugged memory size must be a multiple of " + "%lld MB", LOONGARCH_HOTPLUG_MEM_ALIGN / MiB); + return; + } + + pc_dimm_pre_plug(dimm, MACHINE(hotplug_dev), NULL, errp); +} + +static void loongarch_cpu_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + CPUArchId *found_cpu; + HotplugHandlerClass *hhc; + Error *local_err = NULL; + MachineState *machine = MACHINE(OBJECT(hotplug_dev)); + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); + + if (lsms->acpi_dev) { + loongarch_cpu_create(machine, cpu, errp); + hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); + hhc->plug(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); + if (local_err) { + goto out; + } + } + + found_cpu = loongarch_find_cpu_slot(MACHINE(lsms), cpu->id, NULL); + found_cpu->cpu = OBJECT(dev); + lsms->hotpluged_cpu_num += 1; +out: + error_propagate(errp, local_err); +} + +static void loongarch_cpu_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + MachineState *machine = MACHINE(OBJECT(hotplug_dev)); + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); + Error *local_err = NULL; + HotplugHandlerClass *hhc; + int idx = -1; + + if (!lsms->acpi_dev) { + error_setg(&local_err, "CPU hot unplug not supported without ACPI"); + goto out; + } + + loongarch_find_cpu_slot(MACHINE(lsms), cpu->id, &idx); + assert(idx != -1); + if (idx == 0) { + error_setg(&local_err, "Boot CPU is unpluggable"); + goto out; + } + + hhc = HOTPLUG_HANDLER_GET_CLASS(lsms->acpi_dev); + hhc->unplug_request(HOTPLUG_HANDLER(lsms->acpi_dev), dev, &local_err); + + if (local_err) { + goto out; + } + + out: + error_propagate(errp, local_err); +} + +void longson_machine_device_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); + + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + loongarch_memory_unplug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { + if (!mc->has_hotpluggable_cpus) { + error_setg(errp, "CPU hot unplug not supported on this machine"); + return; + } + loongarch_cpu_unplug(hotplug_dev, dev, errp); + } else { + error_setg(errp, "acpi: device unplug for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); + } + + return; +} + +void loongarch_machine_device_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + loongarch_memory_unplug_request(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { + loongarch_cpu_unplug_request(hotplug_dev, dev, errp); + } +} + +HotplugHandler *loongarch_get_hotpug_handler(MachineState *machine, + DeviceState *dev) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || + object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { + return HOTPLUG_HANDLER(machine); + } + return NULL; +} + +void loongarch_machine_device_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + loongarch_memory_pre_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { + loongarch_cpu_pre_plug(hotplug_dev, dev, errp); + } +} + +void loongarch_machine_device_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + loongarch_memory_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { + loongarch_cpu_plug(hotplug_dev, dev, errp); + } +} + diff --git a/hw/loongarch/larch_int.c b/hw/loongarch/larch_int.c new file mode 100644 index 0000000000..ca073a19cf --- /dev/null +++ b/hw/loongarch/larch_int.c @@ -0,0 +1,91 @@ +/* + * QEMU LOONGARCH interrupt support + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/loongarch/cpudevs.h" +#include "cpu.h" +#include "sysemu/kvm.h" +#include "kvm_larch.h" +#ifdef CONFIG_KVM +#include +#endif + +static void cpu_irq_request(void *opaque, int irq, int level) +{ + LOONGARCHCPU *cpu = opaque; + CPULOONGARCHState *env = &cpu->env; + CPUState *cs = CPU(cpu); + bool locked = false; + + if (irq < 0 || irq > 13) { + return; + } + + /* Make sure locking works even if BQL is already held by the caller */ + if (!qemu_mutex_iothread_locked()) { + locked = true; + qemu_mutex_lock_iothread(); + } + + if (level) { + env->CSR_ESTAT |= 1 << irq; + } else { + env->CSR_ESTAT &= ~(1 << irq); + } + + if (kvm_enabled()) { + if (irq == 2) { + kvm_loongarch_set_interrupt(cpu, irq, level); + } else if (irq == 3) { + kvm_loongarch_set_interrupt(cpu, irq, level); + } else if (irq == 12) { + kvm_loongarch_set_ipi_interrupt(cpu, irq, level); + } + } + + if (env->CSR_ESTAT & CSR_ESTAT_IPMASK) { + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } else { + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } + + if (locked) { + qemu_mutex_unlock_iothread(); + } +} + +void cpu_init_irq(LOONGARCHCPU *cpu) +{ + CPULOONGARCHState *env = &cpu->env; + qemu_irq *qi; + int i; + + qi = qemu_allocate_irqs(cpu_irq_request, loongarch_env_get_cpu(env), N_IRQS); + for (i = 0; i < N_IRQS; i++) { + env->irq[i] = qi[i]; + } +} + + diff --git a/hw/loongarch/ls7a_nb.c b/hw/loongarch/ls7a_nb.c new file mode 100644 index 0000000000..5a500fbd5a --- /dev/null +++ b/hw/loongarch/ls7a_nb.c @@ -0,0 +1,352 @@ +/* + * Loongarch 7A1000 north bridge support + * + * Copyright (c) 2019 Loongarch Technology + * Authors: + * Zhu Chen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" + +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/sysbus.h" +#include "hw/pci/pci.h" +#include "hw/i386/pc.h" +#include "hw/pci/pci_host.h" +#include "hw/pci/pcie_host.h" +#include "sysemu/sysemu.h" +#include "exec/address-spaces.h" +#include "qapi/error.h" +#include "hw/loongarch/cpudevs.h" +#include "hw/acpi/ls7a.h" +#include "hw/i386/pc.h" +#include "hw/isa/isa.h" +#include "hw/boards.h" +#include "qemu/log.h" +#include "hw/loongarch/bios.h" +#include "hw/loader.h" +#include "elf.h" +#include "exec/address-spaces.h" +#include "exec/memory.h" +#include "hw/pci/pci_bridge.h" +#include "hw/pci/pci_bus.h" +#include "linux/kvm.h" +#include "sysemu/kvm.h" +#include "sysemu/runstate.h" +#include "sysemu/reset.h" +#include "migration/vmstate.h" +#include "hw/loongarch/larch.h" +#include "hw/loongarch/ls7a.h" + +#undef DEBUG_LS7A + +#ifdef DEBUG_LS7A +#define DPRINTF(fmt, ...) fprintf(stderr, "%s: " fmt, __func__, ##__VA_ARGS__) +#else +#define DPRINTF(fmt, ...) +#endif + +static void ls7a_reset(void *opaque) +{ + uint64_t wmask; + wmask = ~(-1); + + PCIDevice *dev = opaque; + pci_set_word(dev->config + PCI_VENDOR_ID, 0x0014); + pci_set_word(dev->wmask + PCI_VENDOR_ID, wmask & 0xffff); + pci_set_word(dev->cmask + PCI_VENDOR_ID, 0xffff); + pci_set_word(dev->config + PCI_DEVICE_ID, 0x7a00); + pci_set_word(dev->wmask + PCI_DEVICE_ID, wmask & 0xffff); + pci_set_word(dev->cmask + PCI_DEVICE_ID, 0xffff); + pci_set_word(dev->config + 0x4, 0x0000); + pci_set_word(dev->config + PCI_STATUS, 0x0010); + pci_set_word(dev->wmask + PCI_STATUS, wmask & 0xffff); + pci_set_word(dev->cmask + PCI_STATUS, 0xffff); + pci_set_byte(dev->config + PCI_REVISION_ID, 0x0); + pci_set_byte(dev->wmask + PCI_REVISION_ID, wmask & 0xff); + pci_set_byte(dev->cmask + PCI_REVISION_ID, 0xff); + pci_set_byte(dev->config + 0x9, 0x00); + pci_set_byte(dev->wmask + 0x9, wmask & 0xff); + pci_set_byte(dev->cmask + 0x9, 0xff); + pci_set_byte(dev->config + 0xa, 0x00); + pci_set_byte(dev->wmask + 0xa, wmask & 0xff); + pci_set_byte(dev->cmask + 0xa, 0xff); + pci_set_byte(dev->config + 0xb, 0x06); + pci_set_byte(dev->wmask + 0xb, wmask & 0xff); + pci_set_byte(dev->cmask + 0xb, 0xff); + pci_set_byte(dev->config + 0xc, 0x00); + pci_set_byte(dev->wmask + 0xc, wmask & 0xff); + pci_set_byte(dev->cmask + 0xc, 0xff); + pci_set_byte(dev->config + 0xe, 0x80); + pci_set_byte(dev->wmask + 0xe, wmask & 0xff); + pci_set_byte(dev->cmask + 0xe, 0xff); +} + +static const VMStateDescription vmstate_ls7a_pcie = { + .name = "LS7A_PCIE", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(dev, LS7APCIState), + VMSTATE_STRUCT(pm, LS7APCIState, 0, vmstate_ls7a_pm, LS7APCIPMRegs), + VMSTATE_UINT32_ARRAY(regs, LS7APCIState, LS7A_REGS), + VMSTATE_END_OF_LIST() + } +}; + +static PCIINTxRoute ls7a_route_intx_pin_to_irq(void *opaque, int pin) +{ + PCIINTxRoute route; + + route.irq = pin; + route.mode = PCI_INTX_ENABLED; + return route; +} + +static int pci_ls7a_map_irq(PCIDevice *d, int irq_num) +{ + int irq; + + irq = 16 + ((PCI_SLOT(d->devfn) * 4 + irq_num) & 0xf); + return irq; +} + +static void pci_ls7a_set_irq(void *opaque, int irq_num, int level) +{ + qemu_irq *pic = opaque; + DPRINTF("------ %s irq %d %d\n", __func__, irq_num, level); + qemu_set_irq(pic[irq_num], level); +} + +/* +static int ls7a_pciehost_initfn(SysBusDevice *dev) +{ + return 0; +}*/ + +static void ls7a_pcie_realize(PCIDevice *dev, Error **errp) +{ + LS7APCIState *s = PCIE_LS7A(dev); + /* Ls7a North Bridge, built on FPGA, VENDOR_ID/DEVICE_ID are "undefined" */ + pci_config_set_prog_interface(dev->config, 0x00); + + /* set the default value of north bridge pci config */ + qemu_register_reset(ls7a_reset, s); +} + +static void pci_ls7a_config_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + hwaddr tmp_addr; + tmp_addr = addr & 0xffffff; + + pci_data_write(opaque, tmp_addr, val, size); +} + +static uint64_t pci_ls7a_config_read(void *opaque, + hwaddr addr, unsigned size) +{ + uint64_t val; + hwaddr tmp_addr; + + tmp_addr = addr & 0xffffff; + val = pci_data_read(opaque, tmp_addr, size); + + if (addr & 0x3c) { + DPRINTF(TARGET_FMT_plx" val %lx\n", addr, val); + } + return val; +} + +static const MemoryRegionOps pci_ls7a_config_ops = { + .read = pci_ls7a_config_read, + .write = pci_ls7a_config_write, + /* Set to access 64bits data, because default to 32bits*/ + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, + /* Set to access 64bits data, because default to 32bits*/ + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_NATIVE_ENDIAN, + +}; + +static AddressSpace *ls7a_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) +{ + return &address_space_memory; +} + +static PCIBus *pci_ls7a_init(MachineState *machine, DeviceState *dev, + qemu_irq *pic) +{ + LoongarchMachineState *lsms = LoongarchMACHINE(machine); + LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + PCIExpressHost *e; + SysBusDevice *sysbus; + MemoryRegion *iomem = g_new(MemoryRegion, 1); + PCIHostState *phb; + + e = PCIE_HOST_BRIDGE(dev); + sysbus = SYS_BUS_DEVICE(e); + phb = PCI_HOST_BRIDGE(e); + phb->bus = pci_register_root_bus(dev, "pcie.0", pci_ls7a_set_irq, + pci_ls7a_map_irq, pic, + get_system_memory(), get_system_io(), + (1 << 3), 128, TYPE_PCIE_BUS); + pcie_host_mmcfg_update(e, true, lsmc->pciecfg_base, LS_PCIECFG_SIZE); + DPRINTF("------ %d\n", __LINE__); + + pci_bus_set_route_irq_fn(phb->bus, ls7a_route_intx_pin_to_irq); + memory_region_init_io(iomem, NULL, &pci_ls7a_config_ops, phb->bus, + "ls7a_pci_conf", HT1LO_PCICFG_SIZE); + sysbus_init_mmio(sysbus, iomem); + sysbus_mmio_map(sysbus, 0, lsmc->ht1lo_pcicfg_base); + + return phb->bus; +} + +PCIBus *ls7a_init(MachineState *machine, qemu_irq *pic, DeviceState **ls7a_dev) +{ + DeviceState *dev; + PCIHostState *phb; + LS7APCIState *pbs; + PCIDevice *pcid; + PCIBus *pci_bus; + PCIExpressHost *e; + + /*1. init the HT PCI CFG*/ + DPRINTF("------ %d\n", __LINE__); + dev = qdev_new(TYPE_LS7A_PCIE_HOST_BRIDGE); + e = PCIE_HOST_BRIDGE(dev); + phb = PCI_HOST_BRIDGE(e); + + DPRINTF("------ %d\n", __LINE__); + pci_bus = pci_ls7a_init(machine, dev, pic); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + phb->bus = pci_bus; + /* set the pcihost pointer after rs780_pcihost_initfn is called */ + DPRINTF("------ %d\n", __LINE__); + pcid = pci_new(PCI_DEVFN(0, 0), TYPE_PCIE_LS7A); + pbs = PCIE_LS7A(pcid); + pbs->pciehost = LS7A_PCIE_HOST_BRIDGE(dev); + pbs->pciehost->pci_dev = pbs; + + if (ls7a_dev) { + *ls7a_dev = DEVICE(pcid); + } + + pci_realize_and_unref(pcid, phb->bus, &error_fatal); + + /* IOMMU */ + pci_setup_iommu(phb->bus, ls7a_pci_dma_iommu, NULL); + + ls7a_pm_init(&pbs->pm, pic); + DPRINTF("------ %d\n", __LINE__); + /*3. init the north bridge VGA,not do now*/ + return pci_bus; +} + +LS7APCIState *get_ls7a_type(Object *obj) +{ + LS7APCIState *pbs; + + pbs = PCIE_LS7A(obj); + return pbs; +} + +static void ls7a_pcie_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); + AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(klass); + + k->realize = ls7a_pcie_realize; + k->vendor_id = 0x0014; + k->device_id = 0x7a00; + k->revision = 0x00; + k->class_id = PCI_CLASS_BRIDGE_HOST; + dc->desc = "LS7A1000 PCIE Host bridge"; + dc->vmsd = &vmstate_ls7a_pcie; + /* + * PCI-facing part of the host bridge, not usable without the + * host-facing part, which can't be device_add'ed, yet. + */ + dc->user_creatable = false; + hc->plug = ls7a_pm_device_plug_cb; + hc->unplug_request = ls7a_pm_device_unplug_request_cb; + hc->unplug = ls7a_pm_device_unplug_cb; + adevc->ospm_status = ls7a_pm_ospm_status; + adevc->send_event = ls7a_send_gpe; + adevc->madt_cpu = ls7a_madt_cpu_entry; +} + +static void ls7a_pci_add_properties(LS7APCIState *ls7a) +{ + ls7a_pm_add_properties(OBJECT(ls7a), &ls7a->pm, NULL); +} + +static void ls7a_pci_initfn(Object *obj) +{ + LS7APCIState *ls7a = get_ls7a_type(obj); + + ls7a_pci_add_properties(ls7a); +} + +static const TypeInfo ls7a_pcie_device_info = { + .name = TYPE_PCIE_LS7A, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(LS7APCIState), + .class_init = ls7a_pcie_class_init, + .instance_init = ls7a_pci_initfn, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { TYPE_ACPI_DEVICE_IF }, + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, +}; + +static void ls7a_pciehost_class_init(ObjectClass *klass, void *data) +{ + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + k->parent_class.fw_name = "pci"; +} + +static const TypeInfo ls7a_pciehost_info = { + .name = TYPE_LS7A_PCIE_HOST_BRIDGE, + .parent = TYPE_PCIE_HOST_BRIDGE, + .instance_size = sizeof(LS7APCIEHost), + .class_init = ls7a_pciehost_class_init, +}; + +static void ls7a_register_types(void) +{ + type_register_static(&ls7a_pciehost_info); + type_register_static(&ls7a_pcie_device_info); +} + +type_init(ls7a_register_types) diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build new file mode 100644 index 0000000000..81ee99a028 --- /dev/null +++ b/hw/loongarch/meson.build @@ -0,0 +1,15 @@ +loongarch_ss = ss.source_set() +loongarch_ss.add(files('larch_3a.c'), fdt) +loongarch_ss.add(files( + 'larch_int.c', + 'larch_hotplug.c', + 'ls7a_nb.c', + 'ioapic.c', + 'acpi-build.c', + 'ipi.c', + 'apic.c', + 'iocsr.c', +)) + +hw_arch += {'loongarch64': loongarch_ss} + diff --git a/include/hw/loongarch/bios.h b/include/hw/loongarch/bios.h new file mode 100644 index 0000000000..3677303bfa --- /dev/null +++ b/include/hw/loongarch/bios.h @@ -0,0 +1,5 @@ +#include "qemu/units.h" +#include "cpu.h" + +#define BIOS_SIZE (4 * MiB) +#define BIOS_FILENAME "loongarch_bios.bin" diff --git a/include/hw/loongarch/cpudevs.h b/include/hw/loongarch/cpudevs.h new file mode 100644 index 0000000000..c05ae7a7fc --- /dev/null +++ b/include/hw/loongarch/cpudevs.h @@ -0,0 +1,53 @@ +#ifndef HW_LOONGARCH_CPUDEVS_H +#define HW_LOONGARCH_CPUDEVS_H + +#include "target/loongarch64/cpu-qom.h" + +/* Definitions for LOONGARCH CPU internal devices. */ +#define MAX_GIPI_CORE_NUM 256 +#define MAX_GIPI_MBX_NUM 4 + +#define LS3A_INTC_IP 8 +#define MAX_CORES 256 +#define EXTIOI_IRQS (256) +#define EXTIOI_IRQS_BITMAP_SIZE (256 / 8) +/* map to ipnum per 32 irqs */ +#define EXTIOI_IRQS_IPMAP_SIZE (256 / 32) + +typedef struct gipi_core { + uint32_t status; + uint32_t en; + uint32_t set; + uint32_t clear; + uint64_t buf[MAX_GIPI_MBX_NUM]; + qemu_irq irq; +} gipi_core; + +typedef struct gipiState { + gipi_core core[MAX_GIPI_CORE_NUM]; +} gipiState; + +typedef struct apicState { + /* hardware state */ + uint8_t ext_en[EXTIOI_IRQS_BITMAP_SIZE]; + uint8_t ext_bounce[EXTIOI_IRQS_BITMAP_SIZE]; + uint8_t ext_isr[EXTIOI_IRQS_BITMAP_SIZE]; + uint8_t ext_coreisr[MAX_CORES][EXTIOI_IRQS_BITMAP_SIZE]; + uint8_t ext_ipmap[EXTIOI_IRQS_IPMAP_SIZE]; + uint8_t ext_coremap[EXTIOI_IRQS]; + uint16_t ext_nodetype[16]; + uint64_t ext_control; + + /* software state */ + uint8_t ext_sw_ipmap[EXTIOI_IRQS]; + uint8_t ext_sw_coremap[EXTIOI_IRQS]; + uint8_t ext_ipisr[MAX_CORES * LS3A_INTC_IP][EXTIOI_IRQS_BITMAP_SIZE]; + + qemu_irq parent_irq[MAX_CORES][LS3A_INTC_IP]; + qemu_irq *irq; +} apicState; + +void cpu_init_irq(LOONGARCHCPU *cpu); +void cpu_loongarch_clock_init(LOONGARCHCPU *cpu); + +#endif diff --git a/include/hw/loongarch/larch.h b/include/hw/loongarch/larch.h new file mode 100644 index 0000000000..0886ed52af --- /dev/null +++ b/include/hw/loongarch/larch.h @@ -0,0 +1,163 @@ +/* + * Hotplug emulation on Loongarch system. + * + * Copyright (c) 2018 Loongarch Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef HW_LOONGARCH_H +#define HW_LOONGARCH_H + +#include "target/loongarch64/cpu.h" +#include "qemu-common.h" +#include "exec/memory.h" +#include "hw/mem/pc-dimm.h" +#include "hw/hotplug.h" +#include "hw/boards.h" +#include "hw/acpi/acpi.h" +#include "qemu/notify.h" +#include "qemu/error-report.h" +#include "qemu/queue.h" +#include "hw/acpi/memory_hotplug.h" +#include "hw/loongarch/cpudevs.h" +#include "hw/block/flash.h" + +#define LOONGARCH_MAX_VCPUS 256 +#define LOONGARCH_MAX_PFLASH 2 +/* 256MB alignment for hotplug memory region */ +#define LOONGARCH_HOTPLUG_MEM_ALIGN (1ULL << 28) +#define LOONGARCH_MAX_RAM_SLOTS 10 + +/* Memory types: */ +#define SYSTEM_RAM 1 +#define SYSTEM_RAM_RESERVED 2 +#define ACPI_TABLE 3 +#define ACPI_NVS 4 +#define SYSTEM_PMEM 5 + +#define MAX_MEM_MAP 128 + +typedef struct LoongarchMachineClass { + /*< private >*/ + MachineClass parent_class; + + /* Methods: */ + HotplugHandler *(*get_hotplug_handler)(MachineState *machine, + DeviceState *dev); + + bool has_acpi_build; + + /* save different cpu address*/ + uint64_t isa_io_base; + uint64_t ht_control_regs_base; + uint64_t hpet_mmio_addr; + uint64_t smbus_cfg_base; + uint64_t ht1lo_pcicfg_base; + uint64_t pciecfg_base; + uint64_t ls7a_ioapic_reg_base; + uint32_t node_shift; + char cpu_name[40]; + char bridge_name[16]; + +} LoongarchMachineClass; + +typedef struct ResetData { + LOONGARCHCPU *cpu; + uint64_t vector; +} ResetData; + +typedef struct LoongarchMachineState { + /*< private >*/ + MachineState parent_obj; + + /* */ + ram_addr_t hotplug_memory_size; + + /* State for other subsystems/APIs: */ + Notifier machine_done; + /* Pointers to devices and objects: */ + HotplugHandler *acpi_dev; + int ram_slots; + ResetData *reset_info[LOONGARCH_MAX_VCPUS]; + DeviceState *rtc; + gipiState *gipi; + apicState *apic; + + FWCfgState *fw_cfg; + bool acpi_build_enabled; + bool apic_xrupt_override; + CPUArchIdList *possible_cpus; + PFlashCFI01 *flash[LOONGARCH_MAX_PFLASH]; + void *fdt; + int fdt_size; + unsigned int hotpluged_cpu_num; + OnOffAuto acpi; + char *oem_id; + char *oem_table_id; +} LoongarchMachineState; + +#define LOONGARCH_MACHINE_ACPI_DEVICE_PROP "loongarch-acpi-device" +#define TYPE_LOONGARCH_MACHINE "loongarch-machine" + +#define LoongarchMACHINE(obj) \ + OBJECT_CHECK(LoongarchMachineState, (obj), TYPE_LOONGARCH_MACHINE) +#define LoongarchMACHINE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(LoongarchMachineClass, (obj), TYPE_LOONGARCH_MACHINE) +#define LoongarchMACHINE_CLASS(klass) \ + OBJECT_CLASS_CHECK(LoongarchMachineClass, (klass), TYPE_LOONGARCH_MACHINE) + +#define DEFINE_LOONGARCH_MACHINE(suffix, namestr, initfn, optsfn) \ + static void loongarch_machine_##suffix##_class_init(ObjectClass *oc, void *data) \ + { \ + MachineClass *mc = MACHINE_CLASS(oc); \ + optsfn(mc); \ + mc->init = initfn; \ + } \ + static const TypeInfo loongarch_machine_type_##suffix = { \ + .name = namestr TYPE_MACHINE_SUFFIX, \ + .parent = TYPE_LOONGARCH_MACHINE, \ + .class_init = loongarch_machine_##suffix##_class_init, \ + }; \ + static void loongarch_machine_init_##suffix(void) \ + { \ + type_register(&loongarch_machine_type_##suffix); \ + } \ + type_init(loongarch_machine_init_##suffix) + +void loongarch_machine_device_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +void longson_machine_device_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +HotplugHandler *loongarch_get_hotpug_handler(MachineState *machine, + DeviceState *dev); +void loongarch_machine_device_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); +void loongarch_machine_device_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); + +LOONGARCHCPU *loongarch_cpu_create(MachineState *machine, LOONGARCHCPU *cpu, + Error **errp); +void loongarch_cpu_destroy(MachineState *machine, LOONGARCHCPU *cpu); +int cpu_init_ipi(LoongarchMachineState *ms, qemu_irq parent, int cpu); +int cpu_init_apic(LoongarchMachineState *ms, CPULOONGARCHState *env, int cpu); +int la_memmap_add_entry(uint64_t address, uint64_t length, uint32_t type); +bool loongarch_is_acpi_enabled(LoongarchMachineState *vms); + +/* acpi-build.c */ +void ls7a_madt_cpu_entry(AcpiDeviceIf *adev, int uid, + const CPUArchIdList *apic_ids, GArray *entry, bool force_enabled); +void slave_cpu_reset(void *opaque); +extern uint64_t host_cpufreq; +#endif diff --git a/include/hw/loongarch/ls7a.h b/include/hw/loongarch/ls7a.h new file mode 100644 index 0000000000..686af763a0 --- /dev/null +++ b/include/hw/loongarch/ls7a.h @@ -0,0 +1,152 @@ +#ifndef HW_LS7A_H +#define HW_LS7A_H + +#include "hw/hw.h" +#include "hw/isa/isa.h" +#include "hw/sysbus.h" +#include "hw/isa/apm.h" +#include "hw/pci/pci.h" +#include "hw/pci/pcie_host.h" +#include "hw/pci/pci_bridge.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/ls7a.h" +#include "hw/pci/pci_bus.h" + +/* LS7A PCH Registers (Misc, Confreg) */ +#define LS7A_PCH_REG_BASE 0x10000000UL +#define LS3A5K_LS7A_IOAPIC_REG_BASE (LS7A_PCH_REG_BASE) +#define LS7A_MISC_REG_BASE (LS7A_PCH_REG_BASE + 0x00080000) +#define LS7A_ACPI_REG_BASE (LS7A_MISC_REG_BASE + 0x00050000) + +#define LOONGARCH_PCH_IRQ_BASE 64 +#define LS7A_UART_IRQ (LOONGARCH_PCH_IRQ_BASE + 2) +#define LS7A_RTC_IRQ (LOONGARCH_PCH_IRQ_BASE + 3) +#define LS7A_SCI_IRQ (LOONGARCH_PCH_IRQ_BASE + 4) +#define LS7A_ACPI_IO_BASE 0x800 +#define LS7A_ACPI_IO_SIZE 0x100 +#define LS7A_PM_EVT_BLK (0x0C) /* 4 bytes */ +#define LS7A_PM_CNT_BLK (0x14) /* 2 bytes */ +#define LS7A_GPE0_STS_REG (0x28) /* 4 bytes */ +#define LS7A_GPE0_ENA_REG (0x2C) /* 4 bytes */ +#define LS7A_GPE0_RESET_REG (0x30) /* 4 bytes */ +#define LS7A_PM_TMR_BLK (0x18) /* 4 bytes */ +#define LS7A_GPE0_LEN (8) +#define LS7A_RTC_REG_BASE (LS7A_MISC_REG_BASE + 0x00050100) +#define LS7A_RTC_LEN (0x100) + +#define ACPI_IO_BASE (LS7A_ACPI_REG_BASE) +#define ACPI_GPE0_LEN (LS7A_GPE0_LEN) +#define ACPI_IO_SIZE (LS7A_ACPI_IO_SIZE) +#define ACPI_SCI_IRQ (LS7A_SCI_IRQ) + +#define LS3A5K_ISA_IO_BASE 0x18000000UL +#define LS_ISA_MEM_BASE 0x40000000 +#define LS3A5K_HT1LO_PCICFG_BASE 0x1a000000 +#define HT1LO_PCICFG_SIZE 0x02000000 +#define LS_BIOS_BASE 0x1c000000 +#define LS_BIOS_VAR_BASE 0x1c3a0000 +#define LS_BIOS_SIZE (4 * 1024 * 1024) + +#define FW_CFG_ADDR 0x1e020000 +#define LS7A_REG_BASE 0x1FE00000 +#define LS7A_PCICONFIG_BASE (LS7A_REG_BASE + 0x30) +#define LS7A_PCICONFIG_SIZE (0x100) +#define LS7A_INTERNAL_REG_BASE (LS7A_REG_BASE + 0x100) +#define LS7A_INTERNAL_REG_SIZE (0xE0) +#define LS7A_REGS (0xE0 >> 2) +#define LS7A_UART_BASE 0x1fe001e0 +#define LS7A_UART_LEN 0x8 + +#define LS_FDT_BASE 0x1c400000 +#define LS_FDT_SIZE 0x100000 + +#define LS_PCIECFG_BASE 0x20000000 +#define LS_PCIECFG_SIZE 0x08000000 +#define MSI_ADDR_LOW 0x2FF00000 +#define MSI_ADDR_HI 0x0 + +#define SMP_GIPI_MAILBOX 0x1f000000ULL +#define CORE0_STATUS_OFF 0x000 +#define CORE0_EN_OFF 0x004 +#define CORE0_SET_OFF 0x008 +#define CORE0_CLEAR_OFF 0x00c +#define CORE0_BUF_20 0x020 +#define CORE0_BUF_28 0x028 +#define CORE0_BUF_30 0x030 +#define CORE0_BUF_38 0x038 +#define CORE0_IPI_SEND 0x040 +#define CORE0_MAIL_SEND 0x048 + +#define INT_ROUTER_REGS_BASE 0x1fe01400UL +#define INT_ROUTER_REGS_SIZE 0x100 +#define INT_ROUTER_REGS_SYS_INT0 0x00 +#define INT_ROUTER_REGS_SYS_INT1 0x01 +#define INT_ROUTER_REGS_SYS_INT2 0x02 +#define INT_ROUTER_REGS_SYS_INT3 0x03 +#define INT_ROUTER_REGS_PCI_INT0 0x04 +#define INT_ROUTER_REGS_PCI_INT1 0x05 +#define INT_ROUTER_REGS_PCI_INT2 0x06 +#define INT_ROUTER_REGS_PCI_INT3 0x07 +#define INT_ROUTER_REGS_MATRIX_INT0 0x08 +#define INT_ROUTER_REGS_MATRIX_INT1 0x09 +#define INT_ROUTER_REGS_LPC_INT 0x0a +#define INT_ROUTER_REGS_MC0 0x0b +#define INT_ROUTER_REGS_MC1 0x0c +#define INT_ROUTER_REGS_BARRIER 0x0d +#define INT_ROUTER_REGS_THSENS_INT 0x0e +#define INT_ROUTER_REGS_PCI_PERR 0x0f +#define INT_ROUTER_REGS_HT0_INT0 0x10 +#define INT_ROUTER_REGS_HT0_INT1 0x11 +#define INT_ROUTER_REGS_HT0_INT2 0x12 +#define INT_ROUTER_REGS_HT0_INT3 0x13 +#define INT_ROUTER_REGS_HT0_INT4 0x14 +#define INT_ROUTER_REGS_HT0_INT5 0x15 +#define INT_ROUTER_REGS_HT0_INT6 0x16 +#define INT_ROUTER_REGS_HT0_INT7 0x17 +#define INT_ROUTER_REGS_HT1_INT0 0x18 +#define INT_ROUTER_REGS_HT1_INT1 0x19 +#define INT_ROUTER_REGS_HT1_INT2 0x1a +#define INT_ROUTER_REGS_HT1_INT3 0x1b +#define INT_ROUTER_REGS_HT1_INT4 0x1c +#define INT_ROUTER_REGS_HT1_INT5 0x1d +#define INT_ROUTER_REGS_HT1_INT6 0x1e +#define INT_ROUTER_REGS_HT1_INT7 0x1f +#define INT_ROUTER_REGS_ISR 0x20 +#define INT_ROUTER_REGS_EN 0x24 +#define INT_ROUTER_REGS_EN_SET 0x28 +#define INT_ROUTER_REGS_EN_CLR 0x2c +#define INT_ROUTER_REGS_EDGE 0x38 +#define INT_ROUTER_REGS_CORE0_INTISR 0x40 +#define INT_ROUTER_REGS_CORE1_INTISR 0x48 +#define INT_ROUTER_REGS_CORE2_INTISR 0x50 +#define INT_ROUTER_REGS_CORE3_INTISR 0x58 + +typedef struct LS7APCIState LS7APCIState; +typedef struct LS7APCIEHost { + PCIExpressHost parent_obj; + LS7APCIState *pci_dev; +} LS7APCIEHost; + +struct LS7APCIState { + PCIDevice dev; + + LS7APCIEHost *pciehost; + uint32_t regs[LS7A_REGS]; + + /* LS7A registers */ + MemoryRegion iomem; + LS7APCIPMRegs pm; +}; + +#define TYPE_LS7A_PCIE_HOST_BRIDGE "ls7a1000-pciehost" +#define LS7A_PCIE_HOST_BRIDGE(obj) \ + OBJECT_CHECK(LS7APCIEHost, (obj), TYPE_LS7A_PCIE_HOST_BRIDGE) + +#define TYPE_PCIE_LS7A "ls7a1000_pcie" +#define PCIE_LS7A(obj) \ + OBJECT_CHECK(LS7APCIState, (obj), TYPE_PCIE_LS7A) + +PCIBus *ls7a_init(MachineState *machine, qemu_irq *irq, DeviceState **ls7a_dev); +LS7APCIState *get_ls7a_type(Object *obj); + +#endif /* HW_LS7A_H */ -- Gitee From 1fa9dbf1894810d5ad43b7194c803f009802bcd8 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Fri, 19 Aug 2022 23:44:33 -0400 Subject: [PATCH 04/29] Add target/loongarch64. Change-Id: Idd3ed114968c4a1f1be5fe19dc279028775eb89d Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- target/Kconfig | 1 + target/loongarch64/Kconfig | 2 + target/loongarch64/arch_dump.c | 175 ++ target/loongarch64/cpu-csr.h | 869 ++++++++ target/loongarch64/cpu-param.h | 30 + target/loongarch64/cpu-qom.h | 54 + target/loongarch64/cpu.c | 576 +++++ target/loongarch64/cpu.h | 326 +++ target/loongarch64/csr_helper.c | 704 ++++++ target/loongarch64/fpu.c | 28 + target/loongarch64/fpu_helper.c | 952 ++++++++ target/loongarch64/fpu_helper.h | 129 ++ target/loongarch64/gdbstub.c | 109 + target/loongarch64/helper.c | 727 +++++++ target/loongarch64/helper.h | 168 ++ target/loongarch64/insn.decode | 514 +++++ target/loongarch64/instmap.h | 216 ++ target/loongarch64/internal.h | 184 ++ target/loongarch64/kvm.c | 1622 ++++++++++++++ target/loongarch64/kvm_larch.h | 41 + target/loongarch64/larch-defs.h | 27 + target/loongarch64/machine.c | 416 ++++ target/loongarch64/meson.build | 35 + target/loongarch64/op_helper.c | 533 +++++ target/loongarch64/stabletimer.c | 122 ++ target/loongarch64/tlb_helper.c | 729 +++++++ target/loongarch64/trace-events | 3 + target/loongarch64/trans.inc.c | 3472 ++++++++++++++++++++++++++++++ target/loongarch64/translate.c | 2892 +++++++++++++++++++++++++ target/meson.build | 1 + 30 files changed, 15657 insertions(+) create mode 100644 target/loongarch64/Kconfig create mode 100644 target/loongarch64/arch_dump.c create mode 100644 target/loongarch64/cpu-csr.h create mode 100644 target/loongarch64/cpu-param.h create mode 100644 target/loongarch64/cpu-qom.h create mode 100644 target/loongarch64/cpu.c create mode 100644 target/loongarch64/cpu.h create mode 100644 target/loongarch64/csr_helper.c create mode 100644 target/loongarch64/fpu.c create mode 100644 target/loongarch64/fpu_helper.c create mode 100644 target/loongarch64/fpu_helper.h create mode 100644 target/loongarch64/gdbstub.c create mode 100644 target/loongarch64/helper.c create mode 100644 target/loongarch64/helper.h create mode 100644 target/loongarch64/insn.decode create mode 100644 target/loongarch64/instmap.h create mode 100644 target/loongarch64/internal.h create mode 100644 target/loongarch64/kvm.c create mode 100644 target/loongarch64/kvm_larch.h create mode 100644 target/loongarch64/larch-defs.h create mode 100644 target/loongarch64/machine.c create mode 100644 target/loongarch64/meson.build create mode 100644 target/loongarch64/op_helper.c create mode 100644 target/loongarch64/stabletimer.c create mode 100644 target/loongarch64/tlb_helper.c create mode 100644 target/loongarch64/trace-events create mode 100644 target/loongarch64/trans.inc.c create mode 100644 target/loongarch64/translate.c diff --git a/target/Kconfig b/target/Kconfig index ae7f24fc66..50b46d0487 100644 --- a/target/Kconfig +++ b/target/Kconfig @@ -4,6 +4,7 @@ source avr/Kconfig source cris/Kconfig source hppa/Kconfig source i386/Kconfig +source loongarch64/Kconfig source m68k/Kconfig source microblaze/Kconfig source mips/Kconfig diff --git a/target/loongarch64/Kconfig b/target/loongarch64/Kconfig new file mode 100644 index 0000000000..46b26b1a85 --- /dev/null +++ b/target/loongarch64/Kconfig @@ -0,0 +1,2 @@ +config LOONGARCH64 + bool diff --git a/target/loongarch64/arch_dump.c b/target/loongarch64/arch_dump.c new file mode 100644 index 0000000000..14e9a8ce31 --- /dev/null +++ b/target/loongarch64/arch_dump.c @@ -0,0 +1,175 @@ +/* Support for writing ELF notes for RM architectures + * + * Copyright (C) 2015 Red Hat Inc. + * + * Author: Andrew Jones + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "elf.h" +#include "sysemu/dump.h" +#include "internal.h" + +/* struct user_pt_regs from arch/loongarch/include/uapi/asm/ptrace.h */ +struct loongarch_user_regs { + uint64_t gpr[32]; + uint64_t lo; + uint64_t hi; + uint64_t csr_era; + uint64_t csr_badvaddr; + uint64_t csr_crmd; + uint64_t csr_ecfg; + uint64_t pad[7]; +} QEMU_PACKED; + +QEMU_BUILD_BUG_ON(sizeof(struct loongarch_user_regs) != 360); + +/* struct elf_prstatus from include/uapi/linux/elfcore.h */ +struct loongarch_elf_prstatus { + char pad1[32]; /* 32 == offsetof(struct elf_prstatus, pr_pid) */ + uint32_t pr_pid; + char pad2[76]; /* 76 == offsetof(struct elf_prstatus, pr_reg) - + offsetof(struct elf_prstatus, pr_ppid) */ + struct loongarch_user_regs pr_reg; + uint32_t pr_fpvalid; + char pad3[4]; +} QEMU_PACKED; + +QEMU_BUILD_BUG_ON(sizeof(struct loongarch_elf_prstatus) != 480); + +/* struct user_fpsimd_state from arch/arm64/include/uapi/asm/ptrace.h + * + * While the vregs member of user_fpsimd_state is of type __uint128_t, + * QEMU uses an array of uint64_t, where the high half of the 128-bit + * value is always in the 2n+1'th index. Thus we also break the 128- + * bit values into two halves in this reproduction of user_fpsimd_state. + */ + +struct loongarch_fpu_struct { + uint64_t fpr[32]; + unsigned int fir; + unsigned int fcsr; +} QEMU_PACKED; + +QEMU_BUILD_BUG_ON(sizeof(struct loongarch_fpu_struct) != 264); + +struct loongarch_note { + Elf64_Nhdr hdr; + char name[8]; /* align_up(sizeof("CORE"), 4) */ + union { + struct loongarch_elf_prstatus prstatus; + struct loongarch_fpu_struct fpu; + }; +} QEMU_PACKED; + +#define LOONGARCH_NOTE_HEADER_SIZE offsetof(struct loongarch_note, prstatus) +#define LOONGARCH_PRSTATUS_NOTE_SIZE (LOONGARCH_NOTE_HEADER_SIZE + \ + sizeof(struct loongarch_elf_prstatus)) +#define LOONGARCH_PRFPREG_NOTE_SIZE (LOONGARCH_NOTE_HEADER_SIZE + \ + sizeof(struct loongarch_fpu_struct)) + +static void loongarch_note_init(struct loongarch_note *note, DumpState *s, + const char *name, Elf64_Word namesz, + Elf64_Word type, Elf64_Word descsz) +{ + memset(note, 0, sizeof(*note)); + + note->hdr.n_namesz = cpu_to_dump32(s, namesz); + note->hdr.n_descsz = cpu_to_dump32(s, descsz); + note->hdr.n_type = cpu_to_dump32(s, type); + + memcpy(note->name, name, namesz); +} + +static int loongarch_write_elf64_fprpreg(WriteCoreDumpFunction f, + CPULOONGARCHState *env, int cpuid, + DumpState *s) +{ + struct loongarch_note note; + int ret, i; + + loongarch_note_init(¬e, s, "CORE", 5, NT_PRFPREG, sizeof(note.fpu)); + + note.fpu.fcsr = cpu_to_dump64(s, env->active_fpu.fcsr0); + + for (i = 0; i < 32; ++i) { + note.fpu.fpr[i] = cpu_to_dump64(s, env->active_fpu.fpr[i].fd); + } + + ret = f(¬e, LOONGARCH_PRFPREG_NOTE_SIZE, s); + if (ret < 0) { + return -1; + } + + return 0; +} + +int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, + int cpuid, DumpState *opaque) +{ + struct loongarch_note note; + CPULOONGARCHState *env = &LOONGARCH_CPU(cs)->env; + DumpState *s = opaque; + int ret, i; + + loongarch_note_init(¬e, s, "CORE", 5, NT_PRSTATUS, sizeof(note.prstatus)); + + note.prstatus.pr_pid = cpu_to_dump32(s, cpuid); + note.prstatus.pr_fpvalid = cpu_to_dump32(s, 1); + + for (i = 0; i < 32; ++i) { + note.prstatus.pr_reg.gpr[i] = cpu_to_dump64(s, env->active_tc.gpr[i]); + } + note.prstatus.pr_reg.csr_era = cpu_to_dump64(s, env->CSR_ERA); + note.prstatus.pr_reg.csr_badvaddr = cpu_to_dump64(s, env->CSR_BADV); + note.prstatus.pr_reg.csr_crmd = cpu_to_dump64(s, env->CSR_CRMD); + note.prstatus.pr_reg.csr_ecfg = cpu_to_dump64(s, env->CSR_ECFG); + + ret = f(¬e, LOONGARCH_PRSTATUS_NOTE_SIZE, s); + if (ret < 0) { + return -1; + } + + ret = loongarch_write_elf64_fprpreg(f, env, cpuid, s); + if (ret < 0) { + return -1; + } + + return ret; +} + +int cpu_get_dump_info(ArchDumpInfo *info, + const GuestPhysBlockList *guest_phys_blocks) +{ + info->d_machine = EM_LOONGARCH; + info->d_endian = ELFDATA2LSB; + info->d_class = ELFCLASS64; + + return 0; +} + +ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) +{ + size_t note_size = 0; + + if (class == ELFCLASS64) { + note_size = LOONGARCH_PRSTATUS_NOTE_SIZE + LOONGARCH_PRFPREG_NOTE_SIZE; + } + + return note_size * nr_cpus; +} + diff --git a/target/loongarch64/cpu-csr.h b/target/loongarch64/cpu-csr.h new file mode 100644 index 0000000000..e549bb46b6 --- /dev/null +++ b/target/loongarch64/cpu-csr.h @@ -0,0 +1,869 @@ +#ifndef _CPU_CSR_H_ +#define _CPU_CSR_H_ + +/* basic CSR register */ +#define LOONGARCH_CSR_CRMD 0x0 /* 32 current mode info */ +#define CSR_CRMD_DACM_SHIFT 7 +#define CSR_CRMD_DACM_WIDTH 2 +#define CSR_CRMD_DACM (0x3UL << CSR_CRMD_DACM_SHIFT) +#define CSR_CRMD_DACF_SHIFT 5 +#define CSR_CRMD_DACF_WIDTH 2 +#define CSR_CRMD_DACF (0x3UL << CSR_CRMD_DACF_SHIFT) +#define CSR_CRMD_PG_SHIFT 4 +#define CSR_CRMD_PG (0x1UL << CSR_CRMD_PG_SHIFT) +#define CSR_CRMD_DA_SHIFT 3 +#define CSR_CRMD_DA (0x1UL << CSR_CRMD_DA_SHIFT) +#define CSR_CRMD_IE_SHIFT 2 +#define CSR_CRMD_IE (0x1UL << CSR_CRMD_IE_SHIFT) +#define CSR_CRMD_PLV_SHIFT 0 +#define CSR_CRMD_PLV_WIDTH 2 +#define CSR_CRMD_PLV (0x3UL << CSR_CRMD_PLV_SHIFT) + +#define PLV_USER 3 +#define PLV_KERN 0 +#define PLV_MASK 0x3 + +#define LOONGARCH_CSR_PRMD 0x1 /* 32 prev-exception mode info */ +#define CSR_PRMD_PIE_SHIFT 2 +#define CSR_PRMD_PIE (0x1UL << CSR_PRMD_PIE_SHIFT) +#define CSR_PRMD_PPLV_SHIFT 0 +#define CSR_PRMD_PPLV_WIDTH 2 +#define CSR_PRMD_PPLV (0x3UL << CSR_PRMD_PPLV_SHIFT) + +#define LOONGARCH_CSR_EUEN 0x2 /* 32 coprocessor enable */ +#define CSR_EUEN_LBTEN_SHIFT 3 +#define CSR_EUEN_LBTEN (0x1UL << CSR_EUEN_LBTEN_SHIFT) +#define CSR_EUEN_LASXEN_SHIFT 2 +#define CSR_EUEN_LASXEN (0x1UL << CSR_EUEN_LASXEN_SHIFT) +#define CSR_EUEN_LSXEN_SHIFT 1 +#define CSR_EUEN_LSXEN (0x1UL << CSR_EUEN_LSXEN_SHIFT) +#define CSR_EUEN_FPEN_SHIFT 0 +#define CSR_EUEN_FPEN (0x1UL << CSR_EUEN_FPEN_SHIFT) + +#define LOONGARCH_CSR_MISC 0x3 /* 32 misc config */ + +#define LOONGARCH_CSR_ECFG 0x4 /* 32 exception config */ +#define CSR_ECFG_VS_SHIFT 16 +#define CSR_ECFG_VS_WIDTH 3 +#define CSR_ECFG_VS (0x7UL << CSR_ECFG_VS_SHIFT) +#define CSR_ECFG_IM_SHIFT 0 +#define CSR_ECFG_IM_WIDTH 13 +#define CSR_ECFG_IM (0x1fffUL << CSR_ECFG_IM_SHIFT) + +#define CSR_ECFG_IPMASK 0x00001fff + +#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */ +#define CSR_ESTAT_ESUBCODE_SHIFT 22 +#define CSR_ESTAT_ESUBCODE_WIDTH 9 +#define CSR_ESTAT_ESUBCODE (0x1ffULL << CSR_ESTAT_ESUBCODE_SHIFT) +#define CSR_ESTAT_EXC_SH 16 +#define CSR_ESTAT_EXC_WIDTH 5 +#define CSR_ESTAT_EXC (0x1fULL << CSR_ESTAT_EXC_SH) +#define CSR_ESTAT_IS_SHIFT 0 +#define CSR_ESTAT_IS_WIDTH 15 +#define CSR_ESTAT_IS (0x7fffULL << CSR_ESTAT_IS_SHIFT) + +#define CSR_ESTAT_IPMASK 0x00001fff + +#define EXCODE_IP 64 +#define EXCCODE_RSV 0 +#define EXCCODE_TLBL 1 +#define EXCCODE_TLBS 2 +#define EXCCODE_TLBI 3 +#define EXCCODE_MOD 4 +#define EXCCODE_TLBRI 5 +#define EXCCODE_TLBXI 6 +#define EXCCODE_TLBPE 7 +#define EXCCODE_ADE 8 +#define EXCCODE_UNALIGN 9 +#define EXCCODE_OOB 10 +#define EXCCODE_SYS 11 +#define EXCCODE_BP 12 +#define EXCCODE_RI 13 +#define EXCCODE_IPE 14 +#define EXCCODE_FPDIS 15 +#define EXCCODE_LSXDIS 16 +#define EXCCODE_LASXDIS 17 +#define EXCCODE_FPE 18 +#define EXCCODE_WATCH 19 +#define EXCCODE_BTDIS 20 +#define EXCCODE_BTE 21 +#define EXCCODE_PSI 22 +#define EXCCODE_HYP 23 +#define EXCCODE_FC 24 +#define EXCCODE_SE 25 + +#define LOONGARCH_CSR_ERA 0x6 /* 64 error PC */ + +#define LOONGARCH_CSR_BADV 0x7 /* 64 bad virtual address */ + +#define LOONGARCH_CSR_BADI 0x8 /* 32 bad instruction */ + +#define LOONGARCH_CSR_EEPN 0xc /* 64 exception enter base address */ +#define LOONGARCH_EEPN_CPUID (0x3ffULL << 0) + +#define CU_FPE 1 +#define CU_LSXE (1 << 1) +#define CU_LASXE (1 << 2) +#define CU_LBTE (1 << 3) + +/* TLB related CSR register : start with TLB if no pagewalk */ +/* 32 TLB Index, EHINV, PageSize, is_gtlb */ +#define LOONGARCH_CSR_TLBIDX 0x10 +#define CSR_TLBIDX_EHINV_SHIFT 31 +#define CSR_TLBIDX_EHINV (0x1ULL << CSR_TLBIDX_EHINV_SHIFT) +#define CSR_TLBIDX_PS_SHIFT 24 +#define CSR_TLBIDX_PS_WIDTH 6 +#define CSR_TLBIDX_PS (0x3fULL << CSR_TLBIDX_PS_SHIFT) +#define CSR_TLBIDX_IDX_SHIFT 0 +#define CSR_TLBIDX_IDX_WIDTH 12 +#define CSR_TLBIDX_IDX (0xfffULL << CSR_TLBIDX_IDX_SHIFT) +#define CSR_TLBIDX_SIZEM 0x3f000000 +#define CSR_TLBIDX_SIZE CSR_TLBIDX_PS_SHIFT +#define CSR_TLBIDX_IDXM 0xfff + +#define LOONGARCH_CSR_TLBEHI 0x11 /* 64 TLB EntryHi without ASID */ + +#define LOONGARCH_CSR_TLBELO0 0x12 /* 64 TLB EntryLo0 */ +#define CSR_TLBLO0_RPLV_SHIFT 63 +#define CSR_TLBLO0_RPLV (0x1ULL << CSR_TLBLO0_RPLV_SHIFT) +#define CSR_TLBLO0_XI_SHIFT 62 +#define CSR_TLBLO0_XI (0x1ULL << CSR_TLBLO0_XI_SHIFT) +#define CSR_TLBLO0_RI_SHIFT 61 +#define CSR_TLBLO0_RI (0x1ULL << CSR_TLBLO0_RI_SHIFT) +#define CSR_TLBLO0_PPN_SHIFT 12 +#define CSR_TLBLO0_PPN_WIDTH 36 /* ignore lower 12bits */ +#define CSR_TLBLO0_PPN (0xfffffffffULL << CSR_TLBLO0_PPN_SHIFT) +#define CSR_TLBLO0_GLOBAL_SHIFT 6 +#define CSR_TLBLO0_GLOBAL (0x1ULL << CSR_TLBLO0_GLOBAL_SHIFT) +#define CSR_TLBLO0_CCA_SHIFT 4 +#define CSR_TLBLO0_CCA_WIDTH 2 +#define CSR_TLBLO0_CCA (0x3ULL << CSR_TLBLO0_CCA_SHIFT) +#define CSR_TLBLO0_PLV_SHIFT 2 +#define CSR_TLBLO0_PLV_WIDTH 2 +#define CSR_TLBLO0_PLV (0x3ULL << CSR_TLBLO0_PLV_SHIFT) +#define CSR_TLBLO0_WE_SHIFT 1 +#define CSR_TLBLO0_WE (0x1ULL << CSR_TLBLO0_WE_SHIFT) +#define CSR_TLBLO0_V_SHIFT 0 +#define CSR_TLBLO0_V (0x1ULL << CSR_TLBLO0_V_SHIFT) + +#define LOONGARCH_CSR_TLBELO1 0x13 /* 64 TLB EntryLo1 */ +#define CSR_TLBLO1_RPLV_SHIFT 63 +#define CSR_TLBLO1_RPLV (0x1ULL << CSR_TLBLO1_RPLV_SHIFT) +#define CSR_TLBLO1_XI_SHIFT 62 +#define CSR_TLBLO1_XI (0x1ULL << CSR_TLBLO1_XI_SHIFT) +#define CSR_TLBLO1_RI_SHIFT 61 +#define CSR_TLBLO1_RI (0x1ULL << CSR_TLBLO1_RI_SHIFT) +#define CSR_TLBLO1_PPN_SHIFT 12 +#define CSR_TLBLO1_PPN_WIDTH 36 /* ignore lower 12bits */ +#define CSR_TLBLO1_PPN (0xfffffffffULL << CSR_TLBLO1_PPN_SHIFT) +#define CSR_TLBLO1_GLOBAL_SHIFT 6 +#define CSR_TLBLO1_GLOBAL (0x1ULL << CSR_TLBLO1_GLOBAL_SHIFT) +#define CSR_TLBLO1_CCA_SHIFT 4 +#define CSR_TLBLO1_CCA_WIDTH 2 +#define CSR_TLBLO1_CCA (0x3ULL << CSR_TLBLO1_CCA_SHIFT) +#define CSR_TLBLO1_PLV_SHIFT 2 +#define CSR_TLBLO1_PLV_WIDTH 2 +#define CSR_TLBLO1_PLV (0x3ULL << CSR_TLBLO1_PLV_SHIFT) +#define CSR_TLBLO1_WE_SHIFT 1 +#define CSR_TLBLO1_WE (0x1ULL << CSR_TLBLO1_WE_SHIFT) +#define CSR_TLBLO1_V_SHIFT 0 +#define CSR_TLBLO1_V (0x1ULL << CSR_TLBLO1_V_SHIFT) + +#define LOONGARCH_ENTRYLO_RI (1ULL << 61) +#define LOONGARCH_ENTRYLO_XI (1ULL << 62) + +#define LOONGARCH_CSR_TLBWIRED 0x14 /* 32 TLB wired */ +#define LOONGARCH_CSR_GTLBC 0x15 /* guest-related TLB */ +#define CSR_GTLBC_RID_SHIFT 16 +#define CSR_GTLBC_RID_WIDTH 8 +#define CSR_GTLBC_RID (0xffULL << CSR_GTLBC_RID_SHIFT) +#define CSR_GTLBC_TOTI_SHIFT 13 +#define CSR_GTLBC_TOTI (0x1ULL << CSR_GTLBC_TOTI_SHIFT) +#define CSR_GTLBC_USERID_SHIFT 12 +#define CSR_GTLBC_USERID (0x1ULL << CSR_GTLBC_USERID_SHIFT) +#define CSR_GTLBC_GMTLBSZ_SHIFT 0 +#define CSR_GTLBC_GMTLBSZ_WIDTH 6 +#define CSR_GTLBC_GMTLBSZ (0x3fULL << CSR_GTLBC_GVTLBSZ_SHIFT) + +#define LOONGARCH_CSR_TRGP 0x16 /* guest-related TLB */ +#define CSR_TRGP_RID_SHIFT 16 +#define CSR_TRGP_RID_WIDTH 8 +#define CSR_TRGP_RID (0xffULL << CSR_TRGP_RID_SHIFT) +#define CSR_TRGP_GTLB_SHIFT 0 +#define CSR_TRGP_GTLB (1 << CSR_TRGP_GTLB_SHIFT) + +#define LOONGARCH_CSR_ASID 0x18 /* 64 ASID */ +#define CSR_ASID_BIT_SHIFT 16 /* ASIDBits */ +#define CSR_ASID_BIT_WIDTH 8 +#define CSR_ASID_BIT (0xffULL << CSR_ASID_BIT_SHIFT) +#define CSR_ASID_ASID_SHIFT 0 +#define CSR_ASID_ASID_WIDTH 10 +#define CSR_ASID_ASID (0x3ffULL << CSR_ASID_ASID_SHIFT) + +/* 64 page table base address when badv[47] = 0 */ +#define LOONGARCH_CSR_PGDL 0x19 +/* 64 page table base address when badv[47] = 1 */ +#define LOONGARCH_CSR_PGDH 0x1a + +#define LOONGARCH_CSR_PGD 0x1b /* 64 page table base */ + +#define LOONGARCH_CSR_PWCTL0 0x1c /* 64 PWCtl0 */ +#define CSR_PWCTL0_PTEW_SHIFT 30 +#define CSR_PWCTL0_PTEW_WIDTH 2 +#define CSR_PWCTL0_PTEW (0x3ULL << CSR_PWCTL0_PTEW_SHIFT) +#define CSR_PWCTL0_DIR1WIDTH_SHIFT 25 +#define CSR_PWCTL0_DIR1WIDTH_WIDTH 5 +#define CSR_PWCTL0_DIR1WIDTH (0x1fULL << CSR_PWCTL0_DIR1WIDTH_SHIFT) +#define CSR_PWCTL0_DIR1BASE_SHIFT 20 +#define CSR_PWCTL0_DIR1BASE_WIDTH 5 +#define CSR_PWCTL0_DIR1BASE (0x1fULL << CSR_PWCTL0_DIR1BASE_SHIFT) +#define CSR_PWCTL0_DIR0WIDTH_SHIFT 15 +#define CSR_PWCTL0_DIR0WIDTH_WIDTH 5 +#define CSR_PWCTL0_DIR0WIDTH (0x1fULL << CSR_PWCTL0_DIR0WIDTH_SHIFT) +#define CSR_PWCTL0_DIR0BASE_SHIFT 10 +#define CSR_PWCTL0_DIR0BASE_WIDTH 5 +#define CSR_PWCTL0_DIR0BASE (0x1fULL << CSR_PWCTL0_DIR0BASE_SHIFT) +#define CSR_PWCTL0_PTWIDTH_SHIFT 5 +#define CSR_PWCTL0_PTWIDTH_WIDTH 5 +#define CSR_PWCTL0_PTWIDTH (0x1fULL << CSR_PWCTL0_PTWIDTH_SHIFT) +#define CSR_PWCTL0_PTBASE_SHIFT 0 +#define CSR_PWCTL0_PTBASE_WIDTH 5 +#define CSR_PWCTL0_PTBASE (0x1fULL << CSR_PWCTL0_PTBASE_SHIFT) + +#define LOONGARCH_CSR_PWCTL1 0x1d /* 64 PWCtl1 */ +#define CSR_PWCTL1_DIR3WIDTH_SHIFT 18 +#define CSR_PWCTL1_DIR3WIDTH_WIDTH 5 +#define CSR_PWCTL1_DIR3WIDTH (0x1fULL << CSR_PWCTL1_DIR3WIDTH_SHIFT) +#define CSR_PWCTL1_DIR3BASE_SHIFT 12 +#define CSR_PWCTL1_DIR3BASE_WIDTH 5 +#define CSR_PWCTL1_DIR3BASE (0x1fULL << CSR_PWCTL0_DIR3BASE_SHIFT) +#define CSR_PWCTL1_DIR2WIDTH_SHIFT 6 +#define CSR_PWCTL1_DIR2WIDTH_WIDTH 5 +#define CSR_PWCTL1_DIR2WIDTH (0x1fULL << CSR_PWCTL1_DIR2WIDTH_SHIFT) +#define CSR_PWCTL1_DIR2BASE_SHIFT 0 +#define CSR_PWCTL1_DIR2BASE_WIDTH 5 +#define CSR_PWCTL1_DIR2BASE (0x1fULL << CSR_PWCTL0_DIR2BASE_SHIFT) + +#define LOONGARCH_CSR_STLBPGSIZE 0x1e /* 64 */ +#define CSR_STLBPGSIZE_PS_WIDTH 6 +#define CSR_STLBPGSIZE_PS (0x3f) + +#define LOONGARCH_CSR_RVACFG 0x1f +#define CSR_RVACFG_RDVA_WIDTH 4 +#define CSR_RVACFG_RDVA (0xf) + +/* read only CSR register : start with CPU */ +#define LOONGARCH_CSR_CPUID 0x20 /* 32 CPU core number */ +#define CSR_CPUID_CID_WIDTH 9 +#define CSR_CPUID_CID (0x1ff) + +#define LOONGARCH_CSR_PRCFG1 0x21 /* 32 CPU info */ +#define CSR_CONF1_VSMAX_SHIFT 12 +#define CSR_CONF1_VSMAX_WIDTH 3 +#define CSR_CONF1_VSMAX (7ULL << CSR_CONF1_VSMAX_SHIFT) +/* stable timer bits - 1, 0x2f = 47*/ +#define CSR_CONF1_TMRBITS_SHIFT 4 +#define CSR_CONF1_TMRBITS_WIDTH 8 +#define CSR_CONF1_TMRBITS (0xffULL << CSR_CONF1_TMRBITS_SHIFT) +#define CSR_CONF1_KSNUM_SHIFT 0 +#define CSR_CONF1_KSNUM_WIDTH 4 +#define CSR_CONF1_KSNUM (0x8) + +#define LOONGARCH_CSR_PRCFG2 0x22 +#define CSR_CONF2_PGMASK_SUPP 0x3ffff000 + +#define LOONGARCH_CSR_PRCFG3 0x23 +#define CSR_CONF3_STLBIDX_SHIFT 20 +#define CSR_CONF3_STLBIDX_WIDTH 6 +#define CSR_CONF3_STLBIDX (0x3fULL << CSR_CONF3_STLBIDX_SHIFT) +#define CSR_STLB_SETS 256 +#define CSR_CONF3_STLBWAYS_SHIFT 12 +#define CSR_CONF3_STLBWAYS_WIDTH 8 +#define CSR_CONF3_STLBWAYS (0xffULL << CSR_CONF3_STLBWAYS_SHIFT) +#define CSR_STLBWAYS_SIZE 8 +#define CSR_CONF3_MTLBSIZE_SHIFT 4 +#define CSR_CONF3_MTLBSIZE_WIDTH 8 +#define CSR_CONF3_MTLBSIZE (0xffULL << CSR_CONF3_MTLBSIZE_SHIFT) +/* mean VTLB 64 index */ +#define CSR_MTLB_SIZE 64 +#define CSR_CONF3_TLBORG_SHIFT 0 +#define CSR_CONF3_TLBORG_WIDTH 4 +#define CSR_CONF3_TLBORG (0xfULL << CSR_CONF3_TLBORG_SHIFT) +/* mean use MTLB+STLB */ +#define TLB_ORG 2 + +/* Kscratch : start with KS */ +#define LOONGARCH_CSR_KS0 0x30 /* 64 */ +#define LOONGARCH_CSR_KS1 0x31 /* 64 */ +#define LOONGARCH_CSR_KS2 0x32 /* 64 */ +#define LOONGARCH_CSR_KS3 0x33 /* 64 */ +#define LOONGARCH_CSR_KS4 0x34 /* 64 */ +#define LOONGARCH_CSR_KS5 0x35 /* 64 */ +#define LOONGARCH_CSR_KS6 0x36 /* 64 */ +#define LOONGARCH_CSR_KS7 0x37 /* 64 */ +#define LOONGARCH_CSR_KS8 0x38 /* 64 */ + +/* timer : start with TM */ +#define LOONGARCH_CSR_TMID 0x40 /* 32 timer ID */ + +#define LOONGARCH_CSR_TCFG 0x41 /* 64 timer config */ +#define CSR_TCFG_VAL_SHIFT 2 +#define CSR_TCFG_VAL_WIDTH 48 +#define CSR_TCFG_VAL (0x3fffffffffffULL << CSR_TCFG_VAL_SHIFT) +#define CSR_TCFG_PERIOD_SHIFT 1 +#define CSR_TCFG_PERIOD (0x1ULL << CSR_TCFG_PERIOD_SHIFT) +#define CSR_TCFG_EN (0x1) + +#define LOONGARCH_CSR_TVAL 0x42 /* 64 timer ticks remain */ + +#define LOONGARCH_CSR_CNTC 0x43 /* 64 timer offset */ + +#define LOONGARCH_CSR_TINTCLR 0x44 /* 64 timer interrupt clear */ +#define CSR_TINTCLR_TI_SHIFT 0 +#define CSR_TINTCLR_TI (1 << CSR_TINTCLR_TI_SHIFT) + +/* guest : start with GST */ +#define LOONGARCH_CSR_GSTAT 0x50 /* 32 basic guest info */ +#define CSR_GSTAT_GID_SHIFT 16 +#define CSR_GSTAT_GID_WIDTH 8 +#define CSR_GSTAT_GID (0xffULL << CSR_GSTAT_GID_SHIFT) +#define CSR_GSTAT_GIDBIT_SHIFT 4 +#define CSR_GSTAT_GIDBIT_WIDTH 6 +#define CSR_GSTAT_GIDBIT (0x3fULL << CSR_GSTAT_GIDBIT_SHIFT) +#define CSR_GSTAT_PVM_SHIFT 1 +#define CSR_GSTAT_PVM (0x1ULL << CSR_GSTAT_PVM_SHIFT) +#define CSR_GSTAT_VM_SHIFT 0 +#define CSR_GSTAT_VM (0x1ULL << CSR_GSTAT_VM_SHIFT) + +#define LOONGARCH_CSR_GCFG 0x51 /* 32 guest config */ +#define CSR_GCFG_GPERF_SHIFT 24 +#define CSR_GCFG_GPERF_WIDTH 3 +#define CSR_GCFG_GPERF (0x7ULL << CSR_GCFG_GPERF_SHIFT) +#define CSR_GCFG_GCI_SHIFT 20 +#define CSR_GCFG_GCI_WIDTH 2 +#define CSR_GCFG_GCI (0x3ULL << CSR_GCFG_GCI_SHIFT) +#define CSR_GCFG_GCI_ALL (0x0ULL << CSR_GCFG_GCI_SHIFT) +#define CSR_GCFG_GCI_HIT (0x1ULL << CSR_GCFG_GCI_SHIFT) +#define CSR_GCFG_GCI_SECURE (0x2ULL << CSR_GCFG_GCI_SHIFT) +#define CSR_GCFG_GCIP_SHIFT 16 +#define CSR_GCFG_GCIP (0xfULL << CSR_GCFG_GCIP_SHIFT) +#define CSR_GCFG_GCIP_ALL (0x1ULL << CSR_GCFG_GCIP_SHIFT) +#define CSR_GCFG_GCIP_HIT (0x1ULL << (CSR_GCFG_GCIP_SHIFT + 1)) +#define CSR_GCFG_GCIP_SECURE (0x1ULL << (CSR_GCFG_GCIP_SHIFT + 2)) +#define CSR_GCFG_TORU_SHIFT 15 +#define CSR_GCFG_TORU (0x1ULL << CSR_GCFG_TORU_SHIFT) +#define CSR_GCFG_TORUP_SHIFT 14 +#define CSR_GCFG_TORUP (0x1ULL << CSR_GCFG_TORUP_SHIFT) +#define CSR_GCFG_TOP_SHIFT 13 +#define CSR_GCFG_TOP (0x1ULL << CSR_GCFG_TOP_SHIFT) +#define CSR_GCFG_TOPP_SHIFT 12 +#define CSR_GCFG_TOPP (0x1ULL << CSR_GCFG_TOPP_SHIFT) +#define CSR_GCFG_TOE_SHIFT 11 +#define CSR_GCFG_TOE (0x1ULL << CSR_GCFG_TOE_SHIFT) +#define CSR_GCFG_TOEP_SHIFT 10 +#define CSR_GCFG_TOEP (0x1ULL << CSR_GCFG_TOEP_SHIFT) +#define CSR_GCFG_TIT_SHIFT 9 +#define CSR_GCFG_TIT (0x1ULL << CSR_GCFG_TIT_SHIFT) +#define CSR_GCFG_TITP_SHIFT 8 +#define CSR_GCFG_TITP (0x1ULL << CSR_GCFG_TITP_SHIFT) +#define CSR_GCFG_SIT_SHIFT 7 +#define CSR_GCFG_SIT (0x1ULL << CSR_GCFG_SIT_SHIFT) +#define CSR_GCFG_SITP_SHIFT 6 +#define CSR_GCFG_SITP (0x1ULL << CSR_GCFG_SITP_SHIFT) +#define CSR_GCFG_CACTRL_SHIFT 4 +#define CSR_GCFG_CACTRL_WIDTH 2 +#define CSR_GCFG_CACTRL (0x3ULL << CSR_GCFG_CACTRL_SHIFT) +#define CSR_GCFG_CACTRL_GUEST (0x0ULL << CSR_GCFG_CACTRL_SHIFT) +#define CSR_GCFG_CACTRL_ROOT (0x1ULL << CSR_GCFG_CACTRL_SHIFT) +#define CSR_GCFG_CACTRL_NEST (0x2ULL << CSR_GCFG_CACTRL_SHIFT) +#define CSR_GCFG_CCCP_WIDTH 4 +#define CSR_GCFG_CCCP (0xf) +#define CSR_GCFG_CCCP_GUEST (0x1ULL << 0) +#define CSR_GCFG_CCCP_ROOT (0x1ULL << 1) +#define CSR_GCFG_CCCP_NEST (0x1ULL << 2) + +#define LOONGARCH_CSR_GINTC 0x52 /* 64 guest exception control */ +#define CSR_GINTC_HC_SHIFT 16 +#define CSR_GINTC_HC_WIDTH 8 +#define CSR_GINTC_HC (0xffULL << CSR_GINTC_HC_SHIFT) +#define CSR_GINTC_PIP_SHIFT 8 +#define CSR_GINTC_PIP_WIDTH 8 +#define CSR_GINTC_PIP (0xffULL << CSR_GINTC_PIP_SHIFT) +#define CSR_GINTC_VIP_SHIFT 0 +#define CSR_GINTC_VIP_WIDTH 8 +#define CSR_GINTC_VIP (0xff) + +#define LOONGARCH_CSR_GCNTC 0x53 /* 64 guest timer offset */ + +/* LLBCTL */ +#define LOONGARCH_CSR_LLBCTL 0x60 /* 32 csr number to be changed */ +#define CSR_LLBCTL_ROLLB_SHIFT 0 +#define CSR_LLBCTL_ROLLB (1ULL << CSR_LLBCTL_ROLLB_SHIFT) +#define CSR_LLBCTL_WCLLB_SHIFT 1 +#define CSR_LLBCTL_WCLLB (1ULL << CSR_LLBCTL_WCLLB_SHIFT) +#define CSR_LLBCTL_KLO_SHIFT 2 +#define CSR_LLBCTL_KLO (1ULL << CSR_LLBCTL_KLO_SHIFT) + +/* implement dependent */ +#define LOONGARCH_CSR_IMPCTL1 0x80 /* 32 loongarch config */ +#define CSR_MISPEC_SHIFT 20 +#define CSR_MISPEC_WIDTH 8 +#define CSR_MISPEC (0xffULL << CSR_MISPEC_SHIFT) +#define CSR_SSEN_SHIFT 18 +#define CSR_SSEN (1ULL << CSR_SSEN_SHIFT) +#define CSR_SCRAND_SHIFT 17 +#define CSR_SCRAND (1ULL << CSR_SCRAND_SHIFT) +#define CSR_LLEXCL_SHIFT 16 +#define CSR_LLEXCL (1ULL << CSR_LLEXCL_SHIFT) +#define CSR_DISVC_SHIFT 15 +#define CSR_DISVC (1ULL << CSR_DISVC_SHIFT) +#define CSR_VCLRU_SHIFT 14 +#define CSR_VCLRU (1ULL << CSR_VCLRU_SHIFT) +#define CSR_DCLRU_SHIFT 13 +#define CSR_DCLRU (1ULL << CSR_DCLRU_SHIFT) +#define CSR_FASTLDQ_SHIFT 12 +#define CSR_FASTLDQ (1ULL << CSR_FASTLDQ_SHIFT) +#define CSR_USERCAC_SHIFT 11 +#define CSR_USERCAC (1ULL << CSR_USERCAC_SHIFT) +#define CSR_ANTI_MISPEC_SHIFT 10 +#define CSR_ANTI_MISPEC (1ULL << CSR_ANTI_MISPEC_SHIFT) +#define CSR_ANTI_FLUSHSFB_SHIFT 9 +#define CSR_ANTI_FLUSHSFB (1ULL << CSR_ANTI_FLUSHSFB_SHIFT) +#define CSR_STFILL_SHIFT 8 +#define CSR_STFILL (1ULL << CSR_STFILL_SHIFT) +#define CSR_LIFEP_SHIFT 7 +#define CSR_LIFEP (1ULL << CSR_LIFEP_SHIFT) +#define CSR_LLSYNC_SHIFT 6 +#define CSR_LLSYNC (1ULL << CSR_LLSYNC_SHIFT) +#define CSR_BRBTDIS_SHIFT 5 +#define CSR_BRBTDIS (1ULL << CSR_BRBTDIS_SHIFT) +#define CSR_RASDIS_SHIFT 4 +#define CSR_RASDIS (1ULL << CSR_RASDIS_SHIFT) +#define CSR_STPRE_SHIFT 2 +#define CSR_STPRE_WIDTH 2 +#define CSR_STPRE (3ULL << CSR_STPRE_SHIFT) +#define CSR_INSTPRE_SHIFT 1 +#define CSR_INSTPRE (1ULL << CSR_INSTPRE_SHIFT) +#define CSR_DATAPRE_SHIFT 0 +#define CSR_DATAPRE (1ULL << CSR_DATAPRE_SHIFT) + +#define LOONGARCH_CSR_IMPCTL2 0x81 /* 32 Flush */ +#define CSR_IMPCTL2_MTLB_SHIFT 0 +#define CSR_IMPCTL2_MTLB (1ULL << CSR_IMPCTL2_MTLB_SHIFT) +#define CSR_IMPCTL2_STLB_SHIFT 1 +#define CSR_IMPCTL2_STLB (1ULL << CSR_IMPCTL2_STLB_SHIFT) +#define CSR_IMPCTL2_DTLB_SHIFT 2 +#define CSR_IMPCTL2_DTLB (1ULL << CSR_IMPCTL2_DTLB_SHIFT) +#define CSR_IMPCTL2_ITLB_SHIFT 3 +#define CSR_IMPCTL2_ITLB (1ULL << CSR_IMPCTL2_ITLB_SHIFT) +#define CSR_IMPCTL2_BTAC_SHIFT 4 +#define CSR_IMPCTL2_BTAC (1ULL << CSR_IMPCTL2_BTAC_SHIFT) + +#define LOONGARCH_FLUSH_VTLB 1 +#define LOONGARCH_FLUSH_FTLB (1 << 1) +#define LOONGARCH_FLUSH_DTLB (1 << 2) +#define LOONGARCH_FLUSH_ITLB (1 << 3) +#define LOONGARCH_FLUSH_BTAC (1 << 4) + +#define LOONGARCH_CSR_GNMI 0x82 + +/* TLB Refill Only */ +#define LOONGARCH_CSR_TLBRENT 0x88 /* 64 TLB refill exception address */ +#define LOONGARCH_CSR_TLBRBADV 0x89 /* 64 TLB refill badvaddr */ +#define LOONGARCH_CSR_TLBRERA 0x8a /* 64 TLB refill ERA */ +#define LOONGARCH_CSR_TLBRSAVE 0x8b /* 64 KScratch for TLB refill */ +#define LOONGARCH_CSR_TLBRELO0 0x8c /* 64 TLB refill entrylo0 */ +#define LOONGARCH_CSR_TLBRELO1 0x8d /* 64 TLB refill entrylo1 */ +#define LOONGARCH_CSR_TLBREHI 0x8e /* 64 TLB refill entryhi */ +#define LOONGARCH_CSR_TLBRPRMD 0x8f /* 64 TLB refill mode info */ + +/* error related */ +#define LOONGARCH_CSR_ERRCTL 0x90 /* 32 ERRCTL */ +#define LOONGARCH_CSR_ERRINFO 0x91 +#define LOONGARCH_CSR_ERRINFO1 0x92 +#define LOONGARCH_CSR_ERRENT 0x93 /* 64 error exception base */ +#define LOONGARCH_CSR_ERRERA 0x94 /* 64 error exception PC */ +#define LOONGARCH_CSR_ERRSAVE 0x95 /* 64 KScratch for error exception */ + +#define LOONGARCH_CSR_CTAG 0x98 /* 64 TagLo + TagHi */ + +/* direct map windows */ +#define LOONGARCH_CSR_DMWIN0 0x180 /* 64 direct map win0: MEM & IF */ +#define LOONGARCH_CSR_DMWIN1 0x181 /* 64 direct map win1: MEM & IF */ +#define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */ +#define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */ +#define CSR_DMW_PLV0 0x1 +#define CSR_DMW_PLV1 0x2 +#define CSR_DMW_PLV2 0x4 +#define CSR_DMW_PLV3 0x8 +#define CSR_DMW_BASE_SH 48 +#define dmwin_va2pa(va) \ + (va & (((unsigned long)1 << CSR_DMW_BASE_SH) - 1)) + +/* performance counter */ +#define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ +#define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ +#define LOONGARCH_CSR_PERFCTRL1 0x202 /* 32 perf event 1 config */ +#define LOONGARCH_CSR_PERFCNTR1 0x203 /* 64 perf event 1 count value */ +#define LOONGARCH_CSR_PERFCTRL2 0x204 /* 32 perf event 2 config */ +#define LOONGARCH_CSR_PERFCNTR2 0x205 /* 64 perf event 2 count value */ +#define LOONGARCH_CSR_PERFCTRL3 0x206 /* 32 perf event 3 config */ +#define LOONGARCH_CSR_PERFCNTR3 0x207 /* 64 perf event 3 count value */ +#define CSR_PERFCTRL_PLV0 (1ULL << 16) +#define CSR_PERFCTRL_PLV1 (1ULL << 17) +#define CSR_PERFCTRL_PLV2 (1ULL << 18) +#define CSR_PERFCTRL_PLV3 (1ULL << 19) +#define CSR_PERFCTRL_IE (1ULL << 20) +#define CSR_PERFCTRL_EVENT 0x3ff + +/* debug */ +#define LOONGARCH_CSR_MWPC 0x300 /* data breakpoint config */ +#define LOONGARCH_CSR_MWPS 0x301 /* data breakpoint status */ + +#define LOONGARCH_CSR_DB0ADDR 0x310 /* data breakpoint 0 address */ +#define LOONGARCH_CSR_DB0MASK 0x311 /* data breakpoint 0 mask */ +#define LOONGARCH_CSR_DB0CTL 0x312 /* data breakpoint 0 control */ +#define LOONGARCH_CSR_DB0ASID 0x313 /* data breakpoint 0 asid */ + +#define LOONGARCH_CSR_DB1ADDR 0x318 /* data breakpoint 1 address */ +#define LOONGARCH_CSR_DB1MASK 0x319 /* data breakpoint 1 mask */ +#define LOONGARCH_CSR_DB1CTL 0x31a /* data breakpoint 1 control */ +#define LOONGARCH_CSR_DB1ASID 0x31b /* data breakpoint 1 asid */ + +#define LOONGARCH_CSR_DB2ADDR 0x320 /* data breakpoint 2 address */ +#define LOONGARCH_CSR_DB2MASK 0x321 /* data breakpoint 2 mask */ +#define LOONGARCH_CSR_DB2CTL 0x322 /* data breakpoint 2 control */ +#define LOONGARCH_CSR_DB2ASID 0x323 /* data breakpoint 2 asid */ + +#define LOONGARCH_CSR_DB3ADDR 0x328 /* data breakpoint 3 address */ +#define LOONGARCH_CSR_DB3MASK 0x329 /* data breakpoint 3 mask */ +#define LOONGARCH_CSR_DB3CTL 0x32a /* data breakpoint 3 control */ +#define LOONGARCH_CSR_DB3ASID 0x32b /* data breakpoint 3 asid */ + +#define LOONGARCH_CSR_FWPC 0x380 /* instruction breakpoint config */ +#define LOONGARCH_CSR_FWPS 0x381 /* instruction breakpoint status */ + +#define LOONGARCH_CSR_IB0ADDR 0x390 /* inst breakpoint 0 address */ +#define LOONGARCH_CSR_IB0MASK 0x391 /* inst breakpoint 0 mask */ +#define LOONGARCH_CSR_IB0CTL 0x392 /* inst breakpoint 0 control */ +#define LOONGARCH_CSR_IB0ASID 0x393 /* inst breakpoint 0 asid */ +#define LOONGARCH_CSR_IB1ADDR 0x398 /* inst breakpoint 1 address */ +#define LOONGARCH_CSR_IB1MASK 0x399 /* inst breakpoint 1 mask */ +#define LOONGARCH_CSR_IB1CTL 0x39a /* inst breakpoint 1 control */ +#define LOONGARCH_CSR_IB1ASID 0x39b /* inst breakpoint 1 asid */ + +#define LOONGARCH_CSR_IB2ADDR 0x3a0 /* inst breakpoint 2 address */ +#define LOONGARCH_CSR_IB2MASK 0x3a1 /* inst breakpoint 2 mask */ +#define LOONGARCH_CSR_IB2CTL 0x3a2 /* inst breakpoint 2 control */ +#define LOONGARCH_CSR_IB2ASID 0x3a3 /* inst breakpoint 2 asid */ + +#define LOONGARCH_CSR_IB3ADDR 0x3a8 /* inst breakpoint 3 address */ +#define LOONGARCH_CSR_IB3MASK 0x3a9 /* inst breakpoint 3 mask */ +#define LOONGARCH_CSR_IB3CTL 0x3aa /* inst breakpoint 3 control */ +#define LOONGARCH_CSR_IB3ASID 0x3ab /* inst breakpoint 3 asid */ + +#define LOONGARCH_CSR_IB4ADDR 0x3b0 /* inst breakpoint 4 address */ +#define LOONGARCH_CSR_IB4MASK 0x3b1 /* inst breakpoint 4 mask */ +#define LOONGARCH_CSR_IB4CTL 0x3b2 /* inst breakpoint 4 control */ +#define LOONGARCH_CSR_IB4ASID 0x3b3 /* inst breakpoint 4 asid */ + +#define LOONGARCH_CSR_IB5ADDR 0x3b8 /* inst breakpoint 5 address */ +#define LOONGARCH_CSR_IB5MASK 0x3b9 /* inst breakpoint 5 mask */ +#define LOONGARCH_CSR_IB5CTL 0x3ba /* inst breakpoint 5 control */ +#define LOONGARCH_CSR_IB5ASID 0x3bb /* inst breakpoint 5 asid */ + +#define LOONGARCH_CSR_IB6ADDR 0x3c0 /* inst breakpoint 6 address */ +#define LOONGARCH_CSR_IB6MASK 0x3c1 /* inst breakpoint 6 mask */ +#define LOONGARCH_CSR_IB6CTL 0x3c2 /* inst breakpoint 6 control */ +#define LOONGARCH_CSR_IB6ASID 0x3c3 /* inst breakpoint 6 asid */ + +#define LOONGARCH_CSR_IB7ADDR 0x3c8 /* inst breakpoint 7 address */ +#define LOONGARCH_CSR_IB7MASK 0x3c9 /* inst breakpoint 7 mask */ +#define LOONGARCH_CSR_IB7CTL 0x3ca /* inst breakpoint 7 control */ +#define LOONGARCH_CSR_IB7ASID 0x3cb /* inst breakpoint 7 asid */ + +#define LOONGARCH_CSR_DEBUG 0x500 /* debug config */ +#define CSR_DEBUG_DM 0 +#define CSR_DEBUG_DMVER 1 +#define CSR_DEBUG_DINT 8 +#define CSR_DEBUG_DBP 9 +#define CSR_DEBUG_DIB 10 +#define CSR_DEBUG_DDB 11 + +#define LOONGARCH_CSR_DERA 0x501 /* debug era */ +#define LOONGARCH_CSR_DESAVE 0x502 /* debug save */ + +#define LOONGARCH_CSR_PRID 0xc0 /* 32 LOONGARCH CP0 PRID */ + +#define LOONGARCH_CPUCFG0 0x0 +#define CPUCFG0_3A5000_PRID 0x0014c010 + +#define LOONGARCH_CPUCFG1 0x1 +#define CPUCFG1_ISGR32 BIT(0) +#define CPUCFG1_ISGR64 BIT(1) +#define CPUCFG1_PAGING BIT(2) +#define CPUCFG1_IOCSR BIT(3) +#define CPUCFG1_PABITS (47 << 4) +#define CPUCFG1_VABITS (47 << 12) +#define CPUCFG1_UAL BIT(20) +#define CPUCFG1_RI BIT(21) +#define CPUCFG1_XI BIT(22) +#define CPUCFG1_RPLV BIT(23) +#define CPUCFG1_HUGEPG BIT(24) +#define CPUCFG1_IOCSRBRD BIT(25) +#define CPUCFG1_MSGINT BIT(26) + +#define LOONGARCH_CPUCFG2 0x2 +#define CPUCFG2_FP BIT(0) +#define CPUCFG2_FPSP BIT(1) +#define CPUCFG2_FPDP BIT(2) +#define CPUCFG2_FPVERS (0 << 3) +#define CPUCFG2_LSX BIT(6) +#define CPUCFG2_LASX BIT(7) +#define CPUCFG2_COMPLEX BIT(8) +#define CPUCFG2_CRYPTO BIT(9) +#define CPUCFG2_LVZP BIT(10) +#define CPUCFG2_LVZVER (0 << 11) +#define CPUCFG2_LLFTP BIT(14) +#define CPUCFG2_LLFTPREV (1 << 15) +#define CPUCFG2_X86BT BIT(18) +#define CPUCFG2_ARMBT BIT(19) +#define CPUCFG2_MIPSBT BIT(20) +#define CPUCFG2_LSPW BIT(21) +#define CPUCFG2_LAM BIT(22) + +#define LOONGARCH_CPUCFG3 0x3 +#define CPUCFG3_CCDMA BIT(0) +#define CPUCFG3_SFB BIT(1) +#define CPUCFG3_UCACC BIT(2) +#define CPUCFG3_LLEXC BIT(3) +#define CPUCFG3_SCDLY BIT(4) +#define CPUCFG3_LLDBAR BIT(5) +#define CPUCFG3_ITLBT BIT(6) +#define CPUCFG3_ICACHET BIT(7) +#define CPUCFG3_SPW_LVL (4 << 8) +#define CPUCFG3_SPW_HG_HF BIT(11) +#define CPUCFG3_RVA BIT(12) +#define CPUCFG3_RVAMAX (7 << 13) + +#define LOONGARCH_CPUCFG4 0x4 +#define CCFREQ_100M 100000000 /* 100M */ + +#define LOONGARCH_CPUCFG5 0x5 +#define CPUCFG5_CCMUL 1 +#define CPUCFG5_CCDIV (1 << 16) + +#define LOONGARCH_CPUCFG6 0x6 +#define CPUCFG6_PMP BIT(0) +#define CPUCFG6_PAMVER (1 << 1) +#define CPUCFG6_PMNUM (3 << 4) +#define CPUCFG6_PMBITS (63 << 8) +#define CPUCFG6_UPM BIT(14) + +#define LOONGARCH_CPUCFG16 0x10 +#define CPUCFG16_L1_IUPRE BIT(0) +#define CPUCFG16_L1_UNIFY BIT(1) +#define CPUCFG16_L1_DPRE BIT(2) +#define CPUCFG16_L2_IUPRE BIT(3) +#define CPUCFG16_L2_IUUNIFY BIT(4) +#define CPUCFG16_L2_IUPRIV BIT(5) +#define CPUCFG16_L2_IUINCL BIT(6) +#define CPUCFG16_L2_DPRE BIT(7) +#define CPUCFG16_L2_DPRIV BIT(8) +#define CPUCFG16_L2_DINCL BIT(9) +#define CPUCFG16_L3_IUPRE BIT(10) +#define CPUCFG16_L3_IUUNIFY BIT(11) +#define CPUCFG16_L3_IUPRIV BIT(12) +#define CPUCFG16_L3_IUINCL BIT(13) +#define CPUCFG16_L3_DPRE BIT(14) +#define CPUCFG16_L3_DPRIV BIT(15) +#define CPUCFG16_L3_DINCL BIT(16) + +#define LOONGARCH_CPUCFG17 0x11 +#define CPUCFG17_L1I_WAYS_M (3 << 0) +#define CPUCFG17_L1I_SETS_M (8 << 16) +#define CPUCFG17_L1I_SIZE_M (6 << 24) + +#define LOONGARCH_CPUCFG18 0x12 +#define CPUCFG18_L1D_WAYS_M (3 << 0) +#define CPUCFG18_L1D_SETS_M (8 << 16) +#define CPUCFG18_L1D_SIZE_M (6 << 24) + +#define LOONGARCH_CPUCFG19 0x13 +#define CPUCFG19_L2_WAYS_M (0xf << 0) +#define CPUCFG19_L2_SETS_M (8 << 16) +#define CPUCFG19_L2_SIZE_M (6 << 24) + +#define LOONGARCH_CPUCFG20 0x14 +#define CPUCFG20_L3_WAYS_M (0xf << 0) +#define CPUCFG20_L3_SETS_M (0xe << 16) +#define CPUCFG20_L3_SIZE_M (0x6 << 24) + +#define LOONGARCH_PAGE_HUGE 0x40 +#define LOONGARCH_HUGE_GLOBAL 0x1000 +#define LOONGARCH_HUGE_GLOBAL_SH 12 + +/* All CSR register + * + * default value in target/loongarch/cpu.c + * reset function in target/loongarch/translate.c:cpu_state_reset() + * + * This macro will be used only twice. + * > In target/loongarch/cpu.h:CPULOONGARCHState + * > In target/loongarch/internal.h:loongarch_def_t + * + * helper_function to rd/wr: + * > declare in target/loongarch/helper.h + * > realize in target/loongarch/op_helper.c + * + * during translate: + * > gen_csr_rdl() + * > gen_csr_wrl() + * > gen_csr_rdq() + * > gen_csr_wrq() + */ +#define CPU_LOONGARCH_CSR \ + uint64_t CSR_CRMD; \ + uint64_t CSR_PRMD; \ + uint64_t CSR_EUEN; \ + uint64_t CSR_MISC; \ + uint64_t CSR_ECFG; \ + uint64_t CSR_ESTAT; \ + uint64_t CSR_ERA; \ + uint64_t CSR_BADV; \ + uint64_t CSR_BADI; \ + uint64_t CSR_EEPN; \ + uint64_t CSR_TLBIDX; \ + uint64_t CSR_TLBEHI; \ + uint64_t CSR_TLBELO0; \ + uint64_t CSR_TLBELO1; \ + uint64_t CSR_TLBWIRED; \ + uint64_t CSR_GTLBC; \ + uint64_t CSR_TRGP; \ + uint64_t CSR_ASID; \ + uint64_t CSR_PGDL; \ + uint64_t CSR_PGDH; \ + uint64_t CSR_PGD; \ + uint64_t CSR_PWCTL0; \ + uint64_t CSR_PWCTL1; \ + uint64_t CSR_STLBPGSIZE; \ + uint64_t CSR_RVACFG; \ + uint64_t CSR_CPUID; \ + uint64_t CSR_PRCFG1; \ + uint64_t CSR_PRCFG2; \ + uint64_t CSR_PRCFG3; \ + uint64_t CSR_KS0; \ + uint64_t CSR_KS1; \ + uint64_t CSR_KS2; \ + uint64_t CSR_KS3; \ + uint64_t CSR_KS4; \ + uint64_t CSR_KS5; \ + uint64_t CSR_KS6; \ + uint64_t CSR_KS7; \ + uint64_t CSR_KS8; \ + uint64_t CSR_TMID; \ + uint64_t CSR_TCFG; \ + uint64_t CSR_TVAL; \ + uint64_t CSR_CNTC; \ + uint64_t CSR_TINTCLR; \ + uint64_t CSR_GSTAT; \ + uint64_t CSR_GCFG; \ + uint64_t CSR_GINTC; \ + uint64_t CSR_GCNTC; \ + uint64_t CSR_LLBCTL; \ + uint64_t CSR_IMPCTL1; \ + uint64_t CSR_IMPCTL2; \ + uint64_t CSR_GNMI; \ + uint64_t CSR_TLBRENT; \ + uint64_t CSR_TLBRBADV; \ + uint64_t CSR_TLBRERA; \ + uint64_t CSR_TLBRSAVE; \ + uint64_t CSR_TLBRELO0; \ + uint64_t CSR_TLBRELO1; \ + uint64_t CSR_TLBREHI; \ + uint64_t CSR_TLBRPRMD; \ + uint64_t CSR_ERRCTL; \ + uint64_t CSR_ERRINFO; \ + uint64_t CSR_ERRINFO1; \ + uint64_t CSR_ERRENT; \ + uint64_t CSR_ERRERA; \ + uint64_t CSR_ERRSAVE; \ + uint64_t CSR_CTAG; \ + uint64_t CSR_DMWIN0; \ + uint64_t CSR_DMWIN1; \ + uint64_t CSR_DMWIN2; \ + uint64_t CSR_DMWIN3; \ + uint64_t CSR_PERFCTRL0; \ + uint64_t CSR_PERFCNTR0; \ + uint64_t CSR_PERFCTRL1; \ + uint64_t CSR_PERFCNTR1; \ + uint64_t CSR_PERFCTRL2; \ + uint64_t CSR_PERFCNTR2; \ + uint64_t CSR_PERFCTRL3; \ + uint64_t CSR_PERFCNTR3; \ + uint64_t CSR_MWPC; \ + uint64_t CSR_MWPS; \ + uint64_t CSR_DB0ADDR; \ + uint64_t CSR_DB0MASK; \ + uint64_t CSR_DB0CTL; \ + uint64_t CSR_DB0ASID; \ + uint64_t CSR_DB1ADDR; \ + uint64_t CSR_DB1MASK; \ + uint64_t CSR_DB1CTL; \ + uint64_t CSR_DB1ASID; \ + uint64_t CSR_DB2ADDR; \ + uint64_t CSR_DB2MASK; \ + uint64_t CSR_DB2CTL; \ + uint64_t CSR_DB2ASID; \ + uint64_t CSR_DB3ADDR; \ + uint64_t CSR_DB3MASK; \ + uint64_t CSR_DB3CTL; \ + uint64_t CSR_DB3ASID; \ + uint64_t CSR_FWPC; \ + uint64_t CSR_FWPS; \ + uint64_t CSR_IB0ADDR; \ + uint64_t CSR_IB0MASK; \ + uint64_t CSR_IB0CTL; \ + uint64_t CSR_IB0ASID; \ + uint64_t CSR_IB1ADDR; \ + uint64_t CSR_IB1MASK; \ + uint64_t CSR_IB1CTL; \ + uint64_t CSR_IB1ASID; \ + uint64_t CSR_IB2ADDR; \ + uint64_t CSR_IB2MASK; \ + uint64_t CSR_IB2CTL; \ + uint64_t CSR_IB2ASID; \ + uint64_t CSR_IB3ADDR; \ + uint64_t CSR_IB3MASK; \ + uint64_t CSR_IB3CTL; \ + uint64_t CSR_IB3ASID; \ + uint64_t CSR_IB4ADDR; \ + uint64_t CSR_IB4MASK; \ + uint64_t CSR_IB4CTL; \ + uint64_t CSR_IB4ASID; \ + uint64_t CSR_IB5ADDR; \ + uint64_t CSR_IB5MASK; \ + uint64_t CSR_IB5CTL; \ + uint64_t CSR_IB5ASID; \ + uint64_t CSR_IB6ADDR; \ + uint64_t CSR_IB6MASK; \ + uint64_t CSR_IB6CTL; \ + uint64_t CSR_IB6ASID; \ + uint64_t CSR_IB7ADDR; \ + uint64_t CSR_IB7MASK; \ + uint64_t CSR_IB7CTL; \ + uint64_t CSR_IB7ASID; \ + uint64_t CSR_DEBUG; \ + uint64_t CSR_DERA; \ + uint64_t CSR_DESAVE; \ + +#define LOONGARCH_CSR_32(_R, _S) \ + (KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U32 | (8 * (_R) + (_S))) + +#define LOONGARCH_CSR_64(_R, _S) \ + (KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U64 | (8 * (_R) + (_S))) + +#define KVM_IOC_CSRID(id) LOONGARCH_CSR_64(id, 0) + +#endif diff --git a/target/loongarch64/cpu-param.h b/target/loongarch64/cpu-param.h new file mode 100644 index 0000000000..24ca458af0 --- /dev/null +++ b/target/loongarch64/cpu-param.h @@ -0,0 +1,30 @@ +#ifndef CPU_PARAM_H +#define CPU_PARAM_H + +/* If we want to use host float regs... */ +/* #define USE_HOST_FLOAT_REGS */ + +/* Real pages are variable size... */ +#define TARGET_PAGE_BITS 14 + +#define LOONGARCH_TLB_MAX 2112 + +#define TARGET_LONG_BITS 64 +#define TARGET_PHYS_ADDR_SPACE_BITS 48 +#define TARGET_VIRT_ADDR_SPACE_BITS 48 + +/* + * bit definitions for insn_flags (ISAs/ASEs flags) + * ------------------------------------------------ + */ +#define ISA_LARCH32 0x00000001ULL +#define ISA_LARCH64 0x00000002ULL +#define INSN_LOONGARCH 0x00010000ULL + +#define CPU_LARCH32 (ISA_LARCH32) +#define CPU_LARCH64 (ISA_LARCH32 | ISA_LARCH64) + +#define NB_MMU_MODES 4 + +#endif /* QEMU_LOONGARCH_DEFS_H */ + diff --git a/target/loongarch64/cpu-qom.h b/target/loongarch64/cpu-qom.h new file mode 100644 index 0000000000..ee9c1de571 --- /dev/null +++ b/target/loongarch64/cpu-qom.h @@ -0,0 +1,54 @@ +/* + * QEMU LOONGARCH CPU + * + * Copyright (c) 2012 SUSE LINUX Products GmbH + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ +#ifndef QEMU_LOONGARCH_CPU_QOM_H +#define QEMU_LOONGARCH_CPU_QOM_H + +#include "hw/core/cpu.h" + +#define TYPE_LOONGARCH_CPU "loongarch-cpu" + +#define LOONGARCH_CPU_CLASS(klass) \ + OBJECT_CLASS_CHECK(LOONGARCHCPUClass, (klass), TYPE_LOONGARCH_CPU) +#define LOONGARCH_CPU(obj) \ + OBJECT_CHECK(LOONGARCHCPU, (obj), TYPE_LOONGARCH_CPU) +#define LOONGARCH_CPU_GET_CLASS(obj) \ + OBJECT_GET_CLASS(LOONGARCHCPUClass, (obj), TYPE_LOONGARCH_CPU) + +/** + * LOONGARCHCPUClass: + * @parent_realize: The parent class' realize handler. + * @parent_reset: The parent class' reset handler. + * + * A LOONGARCH CPU model. + */ +typedef struct LOONGARCHCPUClass { + /*< private >*/ + CPUClass parent_class; + /*< public >*/ + + DeviceRealize parent_realize; + DeviceUnrealize parent_unrealize; + DeviceReset parent_reset; + const struct loongarch_def_t *cpu_def; +} LOONGARCHCPUClass; + +typedef struct LOONGARCHCPU LOONGARCHCPU; + +#endif diff --git a/target/loongarch64/cpu.c b/target/loongarch64/cpu.c new file mode 100644 index 0000000000..a4535d34a6 --- /dev/null +++ b/target/loongarch64/cpu.c @@ -0,0 +1,576 @@ +/* + * QEMU LOONGARCH CPU + * + * Copyright (c) 2012 SUSE LINUX Products GmbH + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "cpu.h" +#include "internal.h" +#include "kvm_larch.h" +#include "qemu-common.h" +#include "hw/qdev-properties.h" +#include "sysemu/kvm.h" +#include "exec/exec-all.h" +#include "sysemu/arch_init.h" +#include "cpu-csr.h" +#include "qemu/qemu-print.h" +#include "qapi/qapi-commands-machine-target.h" +#ifdef CONFIG_TCG +#include "hw/core/tcg-cpu-ops.h" +#endif /* CONFIG_TCG */ + +#define LOONGARCH_CONFIG1 \ +((0x8 << CSR_CONF1_KSNUM_SHIFT) | (0x2f << CSR_CONF1_TMRBITS_SHIFT) | \ + (0x7 << CSR_CONF1_VSMAX_SHIFT)) + +#define LOONGARCH_CONFIG3 \ +((0x2 << CSR_CONF3_TLBORG_SHIFT) | (0x3f << CSR_CONF3_MTLBSIZE_SHIFT) | \ + (0x7 << CSR_CONF3_STLBWAYS_SHIFT) | (0x8 << CSR_CONF3_STLBIDX_SHIFT)) + +/*****************************************************************************/ +/* LOONGARCH CPU definitions */ +const loongarch_def_t loongarch_defs[] = { + { + .name = "Loongson-3A5000", + + /* for LoongISA CSR */ + .CSR_PRCFG1 = LOONGARCH_CONFIG1, + .CSR_PRCFG2 = 0x3ffff000, + .CSR_PRCFG3 = LOONGARCH_CONFIG3, + .CSR_CRMD = (0 << CSR_CRMD_PLV_SHIFT) | (0 << CSR_CRMD_IE_SHIFT) | + (1 << CSR_CRMD_DA_SHIFT) | (0 << CSR_CRMD_PG_SHIFT) | + (1 << CSR_CRMD_DACF_SHIFT) | (1 << CSR_CRMD_DACM_SHIFT) , + .CSR_ECFG = 0x7 << 16, + .CSR_STLBPGSIZE = 0xe, + .CSR_RVACFG = 0x0, + .CSR_ASID = 0xa0000, + .FCSR0 = 0x0, + .FCSR0_rw_bitmask = 0x1f1f03df, + .PABITS = 48, + .insn_flags = CPU_LARCH64 | INSN_LOONGARCH, + .mmu_type = MMU_TYPE_LS3A5K, + }, + { + .name = "host", + + /* for LoongISA CSR */ + .CSR_PRCFG1 = LOONGARCH_CONFIG1, + .CSR_PRCFG2 = 0x3ffff000, + .CSR_PRCFG3 = LOONGARCH_CONFIG3, + .CSR_CRMD = (0 << CSR_CRMD_PLV_SHIFT) | (0 << CSR_CRMD_IE_SHIFT) | + (1 << CSR_CRMD_DA_SHIFT) | (0 << CSR_CRMD_PG_SHIFT) | + (1 << CSR_CRMD_DACF_SHIFT) | (1 << CSR_CRMD_DACM_SHIFT) , + .CSR_ECFG = 0x7 << 16, + .CSR_STLBPGSIZE = 0xe, + .CSR_RVACFG = 0x0, + .FCSR0 = 0x0, + .FCSR0_rw_bitmask = 0x1f1f03df, + .PABITS = 48, + .insn_flags = CPU_LARCH64 | INSN_LOONGARCH, + .mmu_type = MMU_TYPE_LS3A5K, + }, +}; +const int loongarch_defs_number = ARRAY_SIZE(loongarch_defs); + +void loongarch_cpu_list(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(loongarch_defs); i++) { + qemu_printf("LOONGARCH '%s'\n", + loongarch_defs[i].name); + } +} + +CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) +{ + CpuDefinitionInfoList *cpu_list = NULL; + const loongarch_def_t *def; + int i; + + for (i = 0; i < ARRAY_SIZE(loongarch_defs); i++) { + CpuDefinitionInfoList *entry; + CpuDefinitionInfo *info; + + def = &loongarch_defs[i]; + info = g_malloc0(sizeof(*info)); + info->name = g_strdup(def->name); + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = cpu_list; + cpu_list = entry; + } + + return cpu_list; +} + +static void loongarch_cpu_set_pc(CPUState *cs, vaddr value) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + + env->active_tc.PC = value & ~(target_ulong)1; +} + +static bool loongarch_cpu_has_work(CPUState *cs) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + bool has_work = false; + + /* It is implementation dependent if non-enabled + interrupts wake-up the CPU, however most of the implementations only + check for interrupts that can be taken. */ + if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && + cpu_loongarch_hw_interrupts_pending(env)) { + has_work = true; + } + + return has_work; +} + +const char * const regnames[] = { + "r0", "ra", "tp", "sp", "a0", "a1", "a2", "a3", + "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", + "t4", "t5", "t6", "t7", "t8", "x0", "fp", "s0", + "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", +}; + +const char * const fregnames[] = { + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", +}; + +static void fpu_dump_state(CPULOONGARCHState *env, FILE *f, + fprintf_function fpu_fprintf, int flags) +{ + int i; + int is_fpu64 = 1; + +#define printfpr(fp) \ + do { \ + if (is_fpu64) \ + fpu_fprintf(f, "w:%08x d:%016" PRIx64 \ + " fd:%13g fs:%13g psu: %13g\n", \ + (fp)->w[FP_ENDIAN_IDX], (fp)->d, \ + (double)(fp)->fd, \ + (double)(fp)->fs[FP_ENDIAN_IDX], \ + (double)(fp)->fs[!FP_ENDIAN_IDX]); \ + else { \ + fpr_t tmp; \ + tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \ + tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \ + fpu_fprintf(f, "w:%08x d:%016" PRIx64 \ + " fd:%13g fs:%13g psu:%13g\n", \ + tmp.w[FP_ENDIAN_IDX], tmp.d, \ + (double)tmp.fd, \ + (double)tmp.fs[FP_ENDIAN_IDX], \ + (double)tmp.fs[!FP_ENDIAN_IDX]); \ + } \ + } while (0) + + + fpu_fprintf(f, "FCSR0 0x%08x SR.FR %d fp_status 0x%02x\n", + env->active_fpu.fcsr0, is_fpu64, + get_float_exception_flags(&env->active_fpu.fp_status)); + for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) { + fpu_fprintf(f, "%3s: ", fregnames[i]); + printfpr(&env->active_fpu.fpr[i]); + } + +#undef printfpr +} + +void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + int i; + + qemu_fprintf(f, "pc:\t %lx\n", env->active_tc.PC); + for (i = 0; i < 32; i++) { + if ((i & 3) == 0) { + qemu_fprintf(f, "GPR%02d:", i); + } + qemu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], + env->active_tc.gpr[i]); + if ((i & 3) == 3) { + qemu_fprintf(f, "\n"); + } + } + qemu_fprintf(f, "EUEN 0x%lx\n", env->CSR_EUEN); + qemu_fprintf(f, "ESTAT 0x%lx\n", env->CSR_ESTAT); + qemu_fprintf(f, "ERA 0x%lx\n", env->CSR_ERA); + qemu_fprintf(f, "CRMD 0x%lx\n", env->CSR_CRMD); + qemu_fprintf(f, "PRMD 0x%lx\n", env->CSR_PRMD); + qemu_fprintf(f, "BadVAddr 0x%lx\n", env->CSR_BADV); + qemu_fprintf(f, "TLB refill ERA 0x%lx\n", env->CSR_TLBRERA); + qemu_fprintf(f, "TLB refill BadV 0x%lx\n", env->CSR_TLBRBADV); + qemu_fprintf(f, "EEPN 0x%lx\n", env->CSR_EEPN); + qemu_fprintf(f, "BadInstr 0x%lx\n", env->CSR_BADI); + qemu_fprintf(f, "PRCFG1 0x%lx\nPRCFG2 0x%lx\nPRCFG3 0x%lx\n", + env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3); + if ((flags & CPU_DUMP_FPU) && (env->hflags & LARCH_HFLAG_FPU)) { + fpu_dump_state(env, f, qemu_fprintf, flags); + } +} + +void cpu_state_reset(CPULOONGARCHState *env) +{ + LOONGARCHCPU *cpu = loongarch_env_get_cpu(env); + CPUState *cs = CPU(cpu); + + /* Reset registers to their default values */ + env->CSR_PRCFG1 = env->cpu_model->CSR_PRCFG1; + env->CSR_PRCFG2 = env->cpu_model->CSR_PRCFG2; + env->CSR_PRCFG3 = env->cpu_model->CSR_PRCFG3; + env->CSR_CRMD = env->cpu_model->CSR_CRMD; + env->CSR_ECFG = env->cpu_model->CSR_ECFG; + env->CSR_STLBPGSIZE = env->cpu_model->CSR_STLBPGSIZE; + env->CSR_RVACFG = env->cpu_model->CSR_RVACFG; + env->CSR_ASID = env->cpu_model->CSR_ASID; + + env->current_tc = 0; + env->active_fpu.fcsr0_rw_bitmask = env->cpu_model->FCSR0_rw_bitmask; + env->active_fpu.fcsr0 = env->cpu_model->FCSR0; + env->insn_flags = env->cpu_model->insn_flags; + +#if !defined(CONFIG_USER_ONLY) + env->CSR_ERA = env->active_tc.PC; + env->active_tc.PC = env->exception_base; +#ifdef CONFIG_TCG + env->tlb->tlb_in_use = env->tlb->nb_tlb; +#endif + env->CSR_TLBWIRED = 0; + env->CSR_TMID = cs->cpu_index; + env->CSR_CPUID = (cs->cpu_index & 0x1ff); + env->CSR_EEPN |= (uint64_t)0x80000000; + env->CSR_TLBRENT |= (uint64_t)0x80000000; +#endif + + /* Count register increments in debug mode, EJTAG version 1 */ + env->CSR_DEBUG = (1 << CSR_DEBUG_DINT) | (0x1 << CSR_DEBUG_DMVER); + + compute_hflags(env); + restore_fp_status(env); + cs->exception_index = EXCP_NONE; +} + +/* CPUClass::reset() */ +static void loongarch_cpu_reset(DeviceState *dev) +{ + CPUState *s = CPU(dev); + LOONGARCHCPU *cpu = LOONGARCH_CPU(s); + LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(cpu); + CPULOONGARCHState *env = &cpu->env; + + mcc->parent_reset(dev); + + memset(env, 0, offsetof(CPULOONGARCHState, end_reset_fields)); + + cpu_state_reset(env); + +#ifndef CONFIG_USER_ONLY + if (kvm_enabled()) { + kvm_loongarch_reset_vcpu(cpu); + } +#endif +} + +static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info) +{ + info->print_insn = print_insn_loongarch; +} + +static void fpu_init(CPULOONGARCHState *env, const loongarch_def_t *def) +{ + memcpy(&env->active_fpu, &env->fpus[0], sizeof(env->active_fpu)); +} + +void cpu_loongarch_realize_env(CPULOONGARCHState *env) +{ + env->exception_base = 0x1C000000; + +#ifdef CONFIG_TCG +#ifndef CONFIG_USER_ONLY + mmu_init(env, env->cpu_model); +#endif +#endif + fpu_init(env, env->cpu_model); +} + +static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp) +{ + CPUState *cs = CPU(dev); + LOONGARCHCPU *cpu = LOONGARCH_CPU(dev); + LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(dev); + Error *local_err = NULL; + + cpu_exec_realizefn(cs, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + + cpu_loongarch_realize_env(&cpu->env); + + loongarch_cpu_register_gdb_regs_for_features(cs); + + cpu_reset(cs); + qemu_init_vcpu(cs); + + mcc->parent_realize(dev, errp); + cpu->hotplugged = 1; +} + +static void loongarch_cpu_unrealizefn(DeviceState *dev) +{ + LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(dev); + +#ifndef CONFIG_USER_ONLY + cpu_remove_sync(CPU(dev)); +#endif + + mcc->parent_unrealize(dev); +} +static void loongarch_cpu_initfn(Object *obj) +{ + CPUState *cs = CPU(obj); + LOONGARCHCPU *cpu = LOONGARCH_CPU(obj); + CPULOONGARCHState *env = &cpu->env; + LOONGARCHCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(obj); + cpu_set_cpustate_pointers(cpu); + cs->env_ptr = env; + env->cpu_model = mcc->cpu_def; + cs->halted = 1; + cpu->dtb_compatible = "loongarch,Loongson-3A5000"; +} + +static char *loongarch_cpu_type_name(const char *cpu_model) +{ + return g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model); +} + +static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model) +{ + ObjectClass *oc; + char *typename; + + typename = loongarch_cpu_type_name(cpu_model); + oc = object_class_by_name(typename); + g_free(typename); + return oc; +} + +static int64_t loongarch_cpu_get_arch_id(CPUState *cs) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + + return cpu->id; +} + +static Property loongarch_cpu_properties[] = { + DEFINE_PROP_INT32("core-id", LOONGARCHCPU, core_id, -1), + DEFINE_PROP_INT32("id", LOONGARCHCPU, id, UNASSIGNED_CPU_ID), + DEFINE_PROP_INT32("node-id", LOONGARCHCPU, node_id, CPU_UNSET_NUMA_NODE_ID), + + DEFINE_PROP_END_OF_LIST() +}; + +#ifdef CONFIG_TCG +static void loongarch_cpu_synchronize_from_tb(CPUState *cs,const TranslationBlock *tb) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + + env->active_tc.PC = tb->pc; + env->hflags &= ~LARCH_HFLAG_BMASK; + env->hflags |= tb->flags & LARCH_HFLAG_BMASK; +} + +static const struct TCGCPUOps loongarch_tcg_ops = { + .initialize = loongarch_tcg_init, + .synchronize_from_tb = loongarch_cpu_synchronize_from_tb, + + .tlb_fill = loongarch_cpu_tlb_fill, + .cpu_exec_interrupt = loongarch_cpu_exec_interrupt, + .do_interrupt = loongarch_cpu_do_interrupt, + +#ifndef CONFIG_USER_ONLY + .do_unaligned_access = loongarch_cpu_do_unaligned_access, +#endif /* !CONFIG_USER_ONLY */ +}; +#endif /* CONFIG_TCG */ + + +#if !defined(CONFIG_USER_ONLY) +static int get_physical_address(CPULOONGARCHState *env, hwaddr *physical, + int *prot, target_ulong real_address, + int rw, int access_type, int mmu_idx) +{ + int user_mode = mmu_idx == LARCH_HFLAG_UM; + int kernel_mode = !user_mode; + unsigned plv, base_c, base_v, tmp; + + /* effective address (modified for KVM T&E kernel segments) */ + target_ulong address = real_address; + + /* Check PG */ + if (!(env->CSR_CRMD & CSR_CRMD_PG)) { + /* DA mode */ + *physical = address & 0xffffffffffffUL; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + return TLBRET_MATCH; + } + + plv = kernel_mode | (user_mode << 3); + base_v = address >> CSR_DMW_BASE_SH; + /* Check direct map window 0 */ + base_c = env->CSR_DMWIN0 >> CSR_DMW_BASE_SH; + if ((plv & env->CSR_DMWIN0) && (base_c == base_v)) { + *physical = dmwin_va2pa(address); + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + return TLBRET_MATCH; + } + /* Check direct map window 1 */ + base_c = env->CSR_DMWIN1 >> CSR_DMW_BASE_SH; + if ((plv & env->CSR_DMWIN1) && (base_c == base_v)) { + *physical = dmwin_va2pa(address); + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + return TLBRET_MATCH; + } + /* Check valid extension */ + tmp = address >> 47; + if (!(tmp == 0 || tmp == 0x1ffff)) { + return TLBRET_BADADDR; + } + /* mapped address */ + return env->tlb->map_address(env, physical, prot, real_address, rw, + access_type); +} + +hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + hwaddr phys_addr; + int prot; + + if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT, + cpu_mmu_index(env, false)) != 0) { + return -1; + } + return phys_addr; +} +#endif + + +#ifndef CONFIG_USER_ONLY +#include "hw/core/sysemu-cpu-ops.h" + +static const struct SysemuCPUOps loongarch_sysemu_ops = { + .write_elf64_note = loongarch_cpu_write_elf64_note, + .get_phys_page_debug = loongarch_cpu_get_phys_page_debug, + .legacy_vmsd = &vmstate_loongarch_cpu, +}; +#endif + + +static void loongarch_cpu_class_init(ObjectClass *c, void *data) +{ + LOONGARCHCPUClass *mcc = LOONGARCH_CPU_CLASS(c); + CPUClass *cc = CPU_CLASS(c); + DeviceClass *dc = DEVICE_CLASS(c); + + device_class_set_props(dc, loongarch_cpu_properties); + device_class_set_parent_realize(dc, loongarch_cpu_realizefn, + &mcc->parent_realize); + + device_class_set_parent_unrealize(dc, loongarch_cpu_unrealizefn, + &mcc->parent_unrealize); + + device_class_set_parent_reset(dc, loongarch_cpu_reset, &mcc->parent_reset); + cc->get_arch_id = loongarch_cpu_get_arch_id; + + cc->class_by_name = loongarch_cpu_class_by_name; + cc->has_work = loongarch_cpu_has_work; + cc->dump_state = loongarch_cpu_dump_state; + cc->set_pc = loongarch_cpu_set_pc; + cc->gdb_read_register = loongarch_cpu_gdb_read_register; + cc->gdb_write_register = loongarch_cpu_gdb_write_register; + cc->disas_set_info = loongarch_cpu_disas_set_info; +#ifndef CONFIG_USER_ONLY + cc->sysemu_ops = &loongarch_sysemu_ops; +#endif /* !CONFIG_USER_ONLY */ + + cc->gdb_num_core_regs = 33; + cc->gdb_core_xml_file = "loongarch-base64.xml"; + cc->gdb_stop_before_watchpoint = true; + + dc->user_creatable = true; +#ifdef CONFIG_TCG + cc->tcg_ops = &loongarch_tcg_ops; +#endif /* CONFIG_TCG */ +} + +static const TypeInfo loongarch_cpu_type_info = { + .name = TYPE_LOONGARCH_CPU, + .parent = TYPE_CPU, + .instance_size = sizeof(LOONGARCHCPU), + .instance_init = loongarch_cpu_initfn, + .abstract = true, + .class_size = sizeof(LOONGARCHCPUClass), + .class_init = loongarch_cpu_class_init, +}; + +static void loongarch_cpu_cpudef_class_init(ObjectClass *oc, void *data) +{ + LOONGARCHCPUClass *mcc = LOONGARCH_CPU_CLASS(oc); + mcc->cpu_def = data; +} + +static void loongarch_register_cpudef_type(const struct loongarch_def_t *def) +{ + char *typename = loongarch_cpu_type_name(def->name); + TypeInfo ti = { + .name = typename, + .parent = TYPE_LOONGARCH_CPU, + .class_init = loongarch_cpu_cpudef_class_init, + .class_data = (void *)def, + }; + + type_register(&ti); + g_free(typename); +} + +static void loongarch_cpu_register_types(void) +{ + int i; + + type_register_static(&loongarch_cpu_type_info); + for (i = 0; i < loongarch_defs_number; i++) { + loongarch_register_cpudef_type(&loongarch_defs[i]); + } +} + +type_init(loongarch_cpu_register_types) diff --git a/target/loongarch64/cpu.h b/target/loongarch64/cpu.h new file mode 100644 index 0000000000..10facb3b73 --- /dev/null +++ b/target/loongarch64/cpu.h @@ -0,0 +1,326 @@ +#ifndef LOONGARCH_CPU_H +#define LOONGARCH_CPU_H + + +#define CPUArchState struct CPULOONGARCHState + +#include "qemu-common.h" +#include "cpu-qom.h" +#include "larch-defs.h" +#include "exec/cpu-defs.h" +#include "fpu/softfloat.h" +#include "sysemu/sysemu.h" +#include "cpu-csr.h" + +#define TCG_GUEST_DEFAULT_MO (0) + +struct CPULOONGARCHState; +typedef LOONGARCHCPU ArchCPU; +typedef struct CPULOONGARCHTLBContext CPULOONGARCHTLBContext; + +#define LASX_REG_WIDTH (256) +typedef union lasx_reg_t lasx_reg_t; +union lasx_reg_t { + int64_t val64[LASX_REG_WIDTH / 64]; +}; + +typedef union fpr_t fpr_t; +union fpr_t { + float64 fd; /* ieee double precision */ + float32 fs[2];/* ieee single precision */ + uint64_t d; /* binary double fixed-point */ + uint32_t w[2]; /* binary single fixed-point */ +/* FPU/LASX register mapping is not tested on big-endian hosts. */ + lasx_reg_t lasx; /* vector data */ +}; +/* define FP_ENDIAN_IDX to access the same location + * in the fpr_t union regardless of the host endianness + */ +#if defined(HOST_WORDS_BIGENDIAN) +# define FP_ENDIAN_IDX 1 +#else +# define FP_ENDIAN_IDX 0 +#endif + +typedef struct CPULOONGARCHFPUContext { + /* Floating point registers */ + fpr_t fpr[32]; + float_status fp_status; + + bool cf[8]; + /* fcsr0 + * 31:29 |28:24 |23:21 |20:16 |15:10 |9:8 |7 |6 |5 |4:0 + * Cause Flags RM DAE TM Enables + */ + uint32_t fcsr0; + uint32_t fcsr0_rw_bitmask; + uint32_t vcsr16; +} CPULOONGARCHFPUContext; + +/* fp control and status register definition */ +#define FCSR0_M1 0xdf /* DAE, TM and Enables */ +#define FCSR0_M2 0x1f1f0000 /* Cause and Flags */ +#define FCSR0_M3 0x300 /* Round Mode */ +#define FCSR0_RM 8 /* Round Mode bit num on fcsr0 */ +#define GET_FP_CAUSE(reg) (((reg) >> 24) & 0x1f) +#define GET_FP_ENABLE(reg) (((reg) >> 0) & 0x1f) +#define GET_FP_FLAGS(reg) (((reg) >> 16) & 0x1f) +#define SET_FP_CAUSE(reg, v) do { (reg) = ((reg) & ~(0x1f << 24)) | \ + ((v & 0x1f) << 24); \ + } while (0) +#define SET_FP_ENABLE(reg, v) do { (reg) = ((reg) & ~(0x1f << 0)) | \ + ((v & 0x1f) << 0); \ + } while (0) +#define SET_FP_FLAGS(reg, v) do { (reg) = ((reg) & ~(0x1f << 16)) | \ + ((v & 0x1f) << 16); \ + } while (0) +#define UPDATE_FP_FLAGS(reg, v) do { (reg) |= ((v & 0x1f) << 16); } while (0) +#define FP_INEXACT 1 +#define FP_UNDERFLOW 2 +#define FP_OVERFLOW 4 +#define FP_DIV0 8 +#define FP_INVALID 16 + +#define TARGET_INSN_START_EXTRA_WORDS 2 + +typedef struct loongarch_def_t loongarch_def_t; + +#define LOONGARCH_FPU_MAX 1 +#define LOONGARCH_KSCRATCH_NUM 8 + +typedef struct TCState TCState; +struct TCState { + target_ulong gpr[32]; + target_ulong PC; +}; + +#define N_IRQS 14 +#define IRQ_TIMER 11 +#define IRQ_IPI 12 +#define IRQ_UART 2 + +typedef struct CPULOONGARCHState CPULOONGARCHState; +struct CPULOONGARCHState { + TCState active_tc; + CPULOONGARCHFPUContext active_fpu; + + uint32_t current_tc; + uint64_t scr[4]; + uint32_t PABITS; + + /* LoongISA CSR register */ + CPU_LOONGARCH_CSR + uint64_t lladdr; + target_ulong llval; + uint64_t llval_wp; + uint32_t llnewval_wp; + + CPULOONGARCHFPUContext fpus[LOONGARCH_FPU_MAX]; + /* QEMU */ + int error_code; +#define EXCP_TLB_NOMATCH 0x1 +#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */ + uint32_t hflags; /* CPU State */ + /* TMASK defines different execution modes */ +#define LARCH_HFLAG_TMASK 0x5F5807FF + /* + * The KSU flags must be the lowest bits in hflags. The flag order + * must be the same as defined for CP0 Status. This allows to use + * the bits as the value of mmu_idx. + */ +#define LARCH_HFLAG_KSU 0x00003 /* kernel/user mode mask */ +#define LARCH_HFLAG_UM 0x00003 /* user mode flag */ +#define LARCH_HFLAG_KM 0x00000 /* kernel mode flag */ +#define LARCH_HFLAG_64 0x00008 /* 64-bit instructions enabled */ +#define LARCH_HFLAG_FPU 0x00020 /* FPU enabled */ +#define LARCH_HFLAG_AWRAP 0x00200 /* 32-bit compatibility address wrapping */ + /* If translation is interrupted between the branch instruction and + * the delay slot, record what type of branch it is so that we can + * resume translation properly. It might be possible to reduce + * this from three bits to two. */ +#define LARCH_HFLAG_BMASK 0x03800 +#define LARCH_HFLAG_B 0x00800 /* Unconditional branch */ +#define LARCH_HFLAG_BC 0x01000 /* Conditional branch */ +#define LARCH_HFLAG_BR 0x02000 /* branch to register (can't link TB) */ +#define LARCH_HFLAG_LSX 0x1000000 +#define LARCH_HFLAG_LASX 0x2000000 +#define LARCH_HFLAG_LBT 0x40000000 + target_ulong btarget; /* Jump / branch target */ + target_ulong bcond; /* Branch condition (if needed) */ + + uint64_t insn_flags; /* Supported instruction set */ + int cpu_cfg[64]; + + /* Fields up to this point are cleared by a CPU reset */ + struct {} end_reset_fields; + + /* Fields from here on are preserved across CPU reset. */ +#if !defined(CONFIG_USER_ONLY) + CPULOONGARCHTLBContext *tlb; +#endif + + const loongarch_def_t *cpu_model; + void *irq[N_IRQS]; + QEMUTimer *timer; /* Internal timer */ + MemoryRegion *itc_tag; /* ITC Configuration Tags */ + target_ulong exception_base; /* ExceptionBase input to the core */ + struct { + uint64_t guest_addr; + } st; +}; + + +/* CPU can't have 0xFFFFFFFF APIC ID, use that value to distinguish + * that ID hasn't been set yet + */ +#define UNASSIGNED_CPU_ID 0xFFFFFFFF + +/** + * LOONGARCHCPU: + * @env: #CPULOONGARCHState + * + * A LOONGARCH CPU. + */ +struct LOONGARCHCPU { + /*< private >*/ + CPUState parent_obj; + /*< public >*/ + CPUNegativeOffsetState neg; + CPULOONGARCHState env; + int32_t id; + int hotplugged; + uint8_t online_vcpus; + uint8_t is_migrate; + uint64_t counter_value; + uint32_t cpu_freq; + uint32_t count_ctl; + uint64_t pending_exceptions; + uint64_t pending_exceptions_clr; + uint64_t core_ext_ioisr[4]; + VMChangeStateEntry *cpuStateEntry; + int32_t node_id; /* NUMA node this CPU belongs to */ + int32_t core_id; + struct kvm_msrs *kvm_msr_buf; + /* 'compatible' string for this CPU for Linux device trees */ + const char *dtb_compatible; +}; + +static inline LOONGARCHCPU *loongarch_env_get_cpu(CPULOONGARCHState *env) +{ + return container_of(env, LOONGARCHCPU, env); +} + +#define ENV_GET_CPU(e) CPU(loongarch_env_get_cpu(e)) + +#define ENV_OFFSET offsetof(LOONGARCHCPU, env) + +void loongarch_cpu_list(void); + +#define cpu_signal_handler cpu_loongarch_signal_handler +#define cpu_list loongarch_cpu_list + +/* MMU modes definitions. We carefully match the indices with our + hflags layout. */ +#define MMU_MODE0_SUFFIX _kernel +#define MMU_MODE1_SUFFIX _super +#define MMU_MODE2_SUFFIX _user +#define MMU_MODE3_SUFFIX _error +#define MMU_USER_IDX 3 + +static inline int hflags_mmu_index(uint32_t hflags) +{ + return hflags & LARCH_HFLAG_KSU; +} + +static inline int cpu_mmu_index(CPULOONGARCHState *env, bool ifetch) +{ + return hflags_mmu_index(env->hflags); +} + +#include "exec/cpu-all.h" + +/* Memory access type : + * may be needed for precise access rights control and precise exceptions. + */ +enum { + /* 1 bit to define user level / supervisor access */ + ACCESS_USER = 0x00, + ACCESS_SUPER = 0x01, + /* 1 bit to indicate direction */ + ACCESS_STORE = 0x02, + /* Type of instruction that generated the access */ + ACCESS_CODE = 0x10, /* Code fetch access */ + ACCESS_INT = 0x20, /* Integer load/store access */ + ACCESS_FLOAT = 0x30, /* floating point load/store access */ +}; + +/* Exceptions */ +enum { + EXCP_NONE = -1, + EXCP_RESET = 0, + EXCP_SRESET, + EXCP_DINT, + EXCP_NMI, + EXCP_EXT_INTERRUPT, /* 7 */ + EXCP_AdEL, + EXCP_AdES, + EXCP_TLBF, + EXCP_IBE, + EXCP_SYSCALL, + EXCP_BREAK, + EXCP_FPDIS, + EXCP_LSXDIS, + EXCP_LASXDIS, + EXCP_RI, + EXCP_OVERFLOW, + EXCP_TRAP, + EXCP_FPE, + EXCP_LTLBL, + EXCP_TLBL, + EXCP_TLBS, + EXCP_DBE, + EXCP_TLBXI, + EXCP_TLBRI, + EXCP_TLBPE, + EXCP_BTDIS, + + EXCP_LAST = EXCP_BTDIS, +}; + +/* + * This is an internally generated WAKE request line. + * It is driven by the CPU itself. Raised when the MT + * block wants to wake a VPE from an inactive state and + * cleared when VPE goes from active to inactive. + */ +#define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0 + +int cpu_loongarch_signal_handler(int host_signum, void *pinfo, void *puc); + +#define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU +#define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX +#define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU + +/* helper.c */ +target_ulong exception_resume_pc(CPULOONGARCHState *env); + +/* gdbstub.c */ +void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs); +void mmu_init(CPULOONGARCHState *env, const loongarch_def_t *def); + +static inline void cpu_get_tb_cpu_state(CPULOONGARCHState *env, target_ulong *pc, + target_ulong *cs_base, uint32_t *flags) +{ + *pc = env->active_tc.PC; + *cs_base = 0; + *flags = env->hflags & (LARCH_HFLAG_TMASK | LARCH_HFLAG_BMASK); +} + +static inline bool cpu_refill_state(CPULOONGARCHState *env) +{ + return env->CSR_TLBRERA & 0x1; +} + +extern const char * const regnames[]; +extern const char * const fregnames[]; +#endif /* LOONGARCH_CPU_H */ diff --git a/target/loongarch64/csr_helper.c b/target/loongarch64/csr_helper.c new file mode 100644 index 0000000000..182e59e925 --- /dev/null +++ b/target/loongarch64/csr_helper.c @@ -0,0 +1,704 @@ +/* + * loongarch tlb emulation helpers for qemu. + * + * Copyright (c) 2020 - 2021 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "cpu.h" +#include "internal.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "sysemu/kvm.h" +#include "hw/irq.h" +#include "cpu-csr.h" +#include "instmap.h" + +#ifndef CONFIG_USER_ONLY +target_ulong helper_csr_rdq(CPULOONGARCHState *env, uint64_t csr) +{ + int64_t v; + +#define CASE_CSR_RDQ(csr) \ + case LOONGARCH_CSR_ ## csr: \ + { \ + v = env->CSR_ ## csr; \ + break; \ + }; \ + + switch (csr) { + CASE_CSR_RDQ(CRMD) + CASE_CSR_RDQ(PRMD) + CASE_CSR_RDQ(EUEN) + CASE_CSR_RDQ(MISC) + CASE_CSR_RDQ(ECFG) + CASE_CSR_RDQ(ESTAT) + CASE_CSR_RDQ(ERA) + CASE_CSR_RDQ(BADV) + CASE_CSR_RDQ(BADI) + CASE_CSR_RDQ(EEPN) + CASE_CSR_RDQ(TLBIDX) + CASE_CSR_RDQ(TLBEHI) + CASE_CSR_RDQ(TLBELO0) + CASE_CSR_RDQ(TLBELO1) + CASE_CSR_RDQ(TLBWIRED) + CASE_CSR_RDQ(GTLBC) + CASE_CSR_RDQ(TRGP) + CASE_CSR_RDQ(ASID) + CASE_CSR_RDQ(PGDL) + CASE_CSR_RDQ(PGDH) + CASE_CSR_RDQ(PGD) + CASE_CSR_RDQ(PWCTL0) + CASE_CSR_RDQ(PWCTL1) + CASE_CSR_RDQ(STLBPGSIZE) + CASE_CSR_RDQ(RVACFG) + CASE_CSR_RDQ(CPUID) + CASE_CSR_RDQ(PRCFG1) + CASE_CSR_RDQ(PRCFG2) + CASE_CSR_RDQ(PRCFG3) + CASE_CSR_RDQ(KS0) + CASE_CSR_RDQ(KS1) + CASE_CSR_RDQ(KS2) + CASE_CSR_RDQ(KS3) + CASE_CSR_RDQ(KS4) + CASE_CSR_RDQ(KS5) + CASE_CSR_RDQ(KS6) + CASE_CSR_RDQ(KS7) + CASE_CSR_RDQ(KS8) + CASE_CSR_RDQ(TMID) + CASE_CSR_RDQ(TCFG) + case LOONGARCH_CSR_TVAL: + v = cpu_loongarch_get_stable_timer_ticks(env); + break; + CASE_CSR_RDQ(CNTC) + CASE_CSR_RDQ(TINTCLR) + CASE_CSR_RDQ(GSTAT) + CASE_CSR_RDQ(GCFG) + CASE_CSR_RDQ(GINTC) + CASE_CSR_RDQ(GCNTC) + CASE_CSR_RDQ(LLBCTL) + CASE_CSR_RDQ(IMPCTL1) + CASE_CSR_RDQ(IMPCTL2) + CASE_CSR_RDQ(GNMI) + CASE_CSR_RDQ(TLBRENT) + CASE_CSR_RDQ(TLBRBADV) + CASE_CSR_RDQ(TLBRERA) + CASE_CSR_RDQ(TLBRSAVE) + CASE_CSR_RDQ(TLBRELO0) + CASE_CSR_RDQ(TLBRELO1) + CASE_CSR_RDQ(TLBREHI) + CASE_CSR_RDQ(TLBRPRMD) + CASE_CSR_RDQ(ERRCTL) + CASE_CSR_RDQ(ERRINFO) + CASE_CSR_RDQ(ERRINFO1) + CASE_CSR_RDQ(ERRENT) + CASE_CSR_RDQ(ERRERA) + CASE_CSR_RDQ(ERRSAVE) + CASE_CSR_RDQ(CTAG) + CASE_CSR_RDQ(DMWIN0) + CASE_CSR_RDQ(DMWIN1) + CASE_CSR_RDQ(DMWIN2) + CASE_CSR_RDQ(DMWIN3) + CASE_CSR_RDQ(PERFCTRL0) + CASE_CSR_RDQ(PERFCNTR0) + CASE_CSR_RDQ(PERFCTRL1) + CASE_CSR_RDQ(PERFCNTR1) + CASE_CSR_RDQ(PERFCTRL2) + CASE_CSR_RDQ(PERFCNTR2) + CASE_CSR_RDQ(PERFCTRL3) + CASE_CSR_RDQ(PERFCNTR3) + /* debug */ + CASE_CSR_RDQ(MWPC) + CASE_CSR_RDQ(MWPS) + CASE_CSR_RDQ(DB0ADDR) + CASE_CSR_RDQ(DB0MASK) + CASE_CSR_RDQ(DB0CTL) + CASE_CSR_RDQ(DB0ASID) + CASE_CSR_RDQ(DB1ADDR) + CASE_CSR_RDQ(DB1MASK) + CASE_CSR_RDQ(DB1CTL) + CASE_CSR_RDQ(DB1ASID) + CASE_CSR_RDQ(DB2ADDR) + CASE_CSR_RDQ(DB2MASK) + CASE_CSR_RDQ(DB2CTL) + CASE_CSR_RDQ(DB2ASID) + CASE_CSR_RDQ(DB3ADDR) + CASE_CSR_RDQ(DB3MASK) + CASE_CSR_RDQ(DB3CTL) + CASE_CSR_RDQ(DB3ASID) + CASE_CSR_RDQ(FWPC) + CASE_CSR_RDQ(FWPS) + CASE_CSR_RDQ(IB0ADDR) + CASE_CSR_RDQ(IB0MASK) + CASE_CSR_RDQ(IB0CTL) + CASE_CSR_RDQ(IB0ASID) + CASE_CSR_RDQ(IB1ADDR) + CASE_CSR_RDQ(IB1MASK) + CASE_CSR_RDQ(IB1CTL) + CASE_CSR_RDQ(IB1ASID) + CASE_CSR_RDQ(IB2ADDR) + CASE_CSR_RDQ(IB2MASK) + CASE_CSR_RDQ(IB2CTL) + CASE_CSR_RDQ(IB2ASID) + CASE_CSR_RDQ(IB3ADDR) + CASE_CSR_RDQ(IB3MASK) + CASE_CSR_RDQ(IB3CTL) + CASE_CSR_RDQ(IB3ASID) + CASE_CSR_RDQ(IB4ADDR) + CASE_CSR_RDQ(IB4MASK) + CASE_CSR_RDQ(IB4CTL) + CASE_CSR_RDQ(IB4ASID) + CASE_CSR_RDQ(IB5ADDR) + CASE_CSR_RDQ(IB5MASK) + CASE_CSR_RDQ(IB5CTL) + CASE_CSR_RDQ(IB5ASID) + CASE_CSR_RDQ(IB6ADDR) + CASE_CSR_RDQ(IB6MASK) + CASE_CSR_RDQ(IB6CTL) + CASE_CSR_RDQ(IB6ASID) + CASE_CSR_RDQ(IB7ADDR) + CASE_CSR_RDQ(IB7MASK) + CASE_CSR_RDQ(IB7CTL) + CASE_CSR_RDQ(IB7ASID) + CASE_CSR_RDQ(DEBUG) + CASE_CSR_RDQ(DERA) + CASE_CSR_RDQ(DESAVE) + default : + assert(0); + } + +#undef CASE_CSR_RDQ + compute_hflags(env); + return v; +} + +target_ulong helper_csr_wrq(CPULOONGARCHState *env, target_ulong val, + uint64_t csr) +{ + int64_t old_v, v; + old_v = -1; + v = val; + +#define CASE_CSR_WRQ(csr) \ + case LOONGARCH_CSR_ ## csr: \ + { \ + old_v = env->CSR_ ## csr; \ + env->CSR_ ## csr = v; \ + break; \ + }; \ + + switch (csr) { + CASE_CSR_WRQ(CRMD) + CASE_CSR_WRQ(PRMD) + CASE_CSR_WRQ(EUEN) + CASE_CSR_WRQ(MISC) + CASE_CSR_WRQ(ECFG) + CASE_CSR_WRQ(ESTAT) + CASE_CSR_WRQ(ERA) + CASE_CSR_WRQ(BADV) + CASE_CSR_WRQ(BADI) + CASE_CSR_WRQ(EEPN) + CASE_CSR_WRQ(TLBIDX) + CASE_CSR_WRQ(TLBEHI) + CASE_CSR_WRQ(TLBELO0) + CASE_CSR_WRQ(TLBELO1) + CASE_CSR_WRQ(TLBWIRED) + CASE_CSR_WRQ(GTLBC) + CASE_CSR_WRQ(TRGP) + CASE_CSR_WRQ(ASID) + CASE_CSR_WRQ(PGDL) + CASE_CSR_WRQ(PGDH) + CASE_CSR_WRQ(PGD) + CASE_CSR_WRQ(PWCTL0) + CASE_CSR_WRQ(PWCTL1) + CASE_CSR_WRQ(STLBPGSIZE) + CASE_CSR_WRQ(RVACFG) + CASE_CSR_WRQ(CPUID) + CASE_CSR_WRQ(PRCFG1) + CASE_CSR_WRQ(PRCFG2) + CASE_CSR_WRQ(PRCFG3) + CASE_CSR_WRQ(KS0) + CASE_CSR_WRQ(KS1) + CASE_CSR_WRQ(KS2) + CASE_CSR_WRQ(KS3) + CASE_CSR_WRQ(KS4) + CASE_CSR_WRQ(KS5) + CASE_CSR_WRQ(KS6) + CASE_CSR_WRQ(KS7) + CASE_CSR_WRQ(KS8) + CASE_CSR_WRQ(TMID) + case LOONGARCH_CSR_TCFG: + old_v = env->CSR_TCFG; + cpu_loongarch_store_stable_timer_config(env, v); + break; + CASE_CSR_WRQ(TVAL) + CASE_CSR_WRQ(CNTC) + case LOONGARCH_CSR_TINTCLR: + old_v = 0; + qemu_irq_lower(env->irq[IRQ_TIMER]); + break; + CASE_CSR_WRQ(GSTAT) + CASE_CSR_WRQ(GCFG) + CASE_CSR_WRQ(GINTC) + CASE_CSR_WRQ(GCNTC) + CASE_CSR_WRQ(LLBCTL) + CASE_CSR_WRQ(IMPCTL1) + case LOONGARCH_CSR_IMPCTL2: + if (v & CSR_IMPCTL2_MTLB) { + ls3a5k_flush_vtlb(env); + } + if (v & CSR_IMPCTL2_STLB) { + ls3a5k_flush_ftlb(env); + } + break; + CASE_CSR_WRQ(GNMI) + CASE_CSR_WRQ(TLBRENT) + CASE_CSR_WRQ(TLBRBADV) + CASE_CSR_WRQ(TLBRERA) + CASE_CSR_WRQ(TLBRSAVE) + CASE_CSR_WRQ(TLBRELO0) + CASE_CSR_WRQ(TLBRELO1) + CASE_CSR_WRQ(TLBREHI) + CASE_CSR_WRQ(TLBRPRMD) + CASE_CSR_WRQ(ERRCTL) + CASE_CSR_WRQ(ERRINFO) + CASE_CSR_WRQ(ERRINFO1) + CASE_CSR_WRQ(ERRENT) + CASE_CSR_WRQ(ERRERA) + CASE_CSR_WRQ(ERRSAVE) + CASE_CSR_WRQ(CTAG) + CASE_CSR_WRQ(DMWIN0) + CASE_CSR_WRQ(DMWIN1) + CASE_CSR_WRQ(DMWIN2) + CASE_CSR_WRQ(DMWIN3) + CASE_CSR_WRQ(PERFCTRL0) + CASE_CSR_WRQ(PERFCNTR0) + CASE_CSR_WRQ(PERFCTRL1) + CASE_CSR_WRQ(PERFCNTR1) + CASE_CSR_WRQ(PERFCTRL2) + CASE_CSR_WRQ(PERFCNTR2) + CASE_CSR_WRQ(PERFCTRL3) + CASE_CSR_WRQ(PERFCNTR3) + /* debug */ + CASE_CSR_WRQ(MWPC) + CASE_CSR_WRQ(MWPS) + CASE_CSR_WRQ(DB0ADDR) + CASE_CSR_WRQ(DB0MASK) + CASE_CSR_WRQ(DB0CTL) + CASE_CSR_WRQ(DB0ASID) + CASE_CSR_WRQ(DB1ADDR) + CASE_CSR_WRQ(DB1MASK) + CASE_CSR_WRQ(DB1CTL) + CASE_CSR_WRQ(DB1ASID) + CASE_CSR_WRQ(DB2ADDR) + CASE_CSR_WRQ(DB2MASK) + CASE_CSR_WRQ(DB2CTL) + CASE_CSR_WRQ(DB2ASID) + CASE_CSR_WRQ(DB3ADDR) + CASE_CSR_WRQ(DB3MASK) + CASE_CSR_WRQ(DB3CTL) + CASE_CSR_WRQ(DB3ASID) + CASE_CSR_WRQ(FWPC) + CASE_CSR_WRQ(FWPS) + CASE_CSR_WRQ(IB0ADDR) + CASE_CSR_WRQ(IB0MASK) + CASE_CSR_WRQ(IB0CTL) + CASE_CSR_WRQ(IB0ASID) + CASE_CSR_WRQ(IB1ADDR) + CASE_CSR_WRQ(IB1MASK) + CASE_CSR_WRQ(IB1CTL) + CASE_CSR_WRQ(IB1ASID) + CASE_CSR_WRQ(IB2ADDR) + CASE_CSR_WRQ(IB2MASK) + CASE_CSR_WRQ(IB2CTL) + CASE_CSR_WRQ(IB2ASID) + CASE_CSR_WRQ(IB3ADDR) + CASE_CSR_WRQ(IB3MASK) + CASE_CSR_WRQ(IB3CTL) + CASE_CSR_WRQ(IB3ASID) + CASE_CSR_WRQ(IB4ADDR) + CASE_CSR_WRQ(IB4MASK) + CASE_CSR_WRQ(IB4CTL) + CASE_CSR_WRQ(IB4ASID) + CASE_CSR_WRQ(IB5ADDR) + CASE_CSR_WRQ(IB5MASK) + CASE_CSR_WRQ(IB5CTL) + CASE_CSR_WRQ(IB5ASID) + CASE_CSR_WRQ(IB6ADDR) + CASE_CSR_WRQ(IB6MASK) + CASE_CSR_WRQ(IB6CTL) + CASE_CSR_WRQ(IB6ASID) + CASE_CSR_WRQ(IB7ADDR) + CASE_CSR_WRQ(IB7MASK) + CASE_CSR_WRQ(IB7CTL) + CASE_CSR_WRQ(IB7ASID) + CASE_CSR_WRQ(DEBUG) + CASE_CSR_WRQ(DERA) + CASE_CSR_WRQ(DESAVE) + default : + assert(0); + } + + if (csr == LOONGARCH_CSR_ASID) { + if (old_v != v) { + tlb_flush(CPU(loongarch_env_get_cpu(env))); + } + } + +#undef CASE_CSR_WRQ + compute_hflags(env); + return old_v; +} + +target_ulong helper_csr_xchgq(CPULOONGARCHState *env, target_ulong val, + target_ulong mask, uint64_t csr) +{ + target_ulong v, tmp; + v = val & mask; + +#define CASE_CSR_XCHGQ(csr) \ + case LOONGARCH_CSR_ ## csr: \ + { \ + val = env->CSR_ ## csr; \ + env->CSR_ ## csr = (env->CSR_ ## csr) & (~mask); \ + env->CSR_ ## csr = (env->CSR_ ## csr) | v; \ + break; \ + }; \ + + switch (csr) { + CASE_CSR_XCHGQ(CRMD) + CASE_CSR_XCHGQ(PRMD) + CASE_CSR_XCHGQ(EUEN) + CASE_CSR_XCHGQ(MISC) + CASE_CSR_XCHGQ(ECFG) + case LOONGARCH_CSR_ESTAT: + val = env->CSR_ESTAT; + qatomic_and(&env->CSR_ESTAT, ~mask); + qatomic_or(&env->CSR_ESTAT, v); + break; + CASE_CSR_XCHGQ(ERA) + CASE_CSR_XCHGQ(BADV) + CASE_CSR_XCHGQ(BADI) + CASE_CSR_XCHGQ(EEPN) + CASE_CSR_XCHGQ(TLBIDX) + CASE_CSR_XCHGQ(TLBEHI) + CASE_CSR_XCHGQ(TLBELO0) + CASE_CSR_XCHGQ(TLBELO1) + CASE_CSR_XCHGQ(TLBWIRED) + CASE_CSR_XCHGQ(GTLBC) + CASE_CSR_XCHGQ(TRGP) + CASE_CSR_XCHGQ(ASID) + CASE_CSR_XCHGQ(PGDL) + CASE_CSR_XCHGQ(PGDH) + CASE_CSR_XCHGQ(PGD) + CASE_CSR_XCHGQ(PWCTL0) + CASE_CSR_XCHGQ(PWCTL1) + CASE_CSR_XCHGQ(STLBPGSIZE) + CASE_CSR_XCHGQ(RVACFG) + CASE_CSR_XCHGQ(CPUID) + CASE_CSR_XCHGQ(PRCFG1) + CASE_CSR_XCHGQ(PRCFG2) + CASE_CSR_XCHGQ(PRCFG3) + CASE_CSR_XCHGQ(KS0) + CASE_CSR_XCHGQ(KS1) + CASE_CSR_XCHGQ(KS2) + CASE_CSR_XCHGQ(KS3) + CASE_CSR_XCHGQ(KS4) + CASE_CSR_XCHGQ(KS5) + CASE_CSR_XCHGQ(KS6) + CASE_CSR_XCHGQ(KS7) + CASE_CSR_XCHGQ(KS8) + CASE_CSR_XCHGQ(TMID) + case LOONGARCH_CSR_TCFG: + val = env->CSR_TCFG; + tmp = val & ~mask; + tmp |= v; + cpu_loongarch_store_stable_timer_config(env, tmp); + break; + CASE_CSR_XCHGQ(TVAL) + CASE_CSR_XCHGQ(CNTC) + CASE_CSR_XCHGQ(TINTCLR) + CASE_CSR_XCHGQ(GSTAT) + CASE_CSR_XCHGQ(GCFG) + CASE_CSR_XCHGQ(GINTC) + CASE_CSR_XCHGQ(GCNTC) + CASE_CSR_XCHGQ(LLBCTL) + CASE_CSR_XCHGQ(IMPCTL1) + CASE_CSR_XCHGQ(IMPCTL2) + CASE_CSR_XCHGQ(GNMI) + CASE_CSR_XCHGQ(TLBRENT) + CASE_CSR_XCHGQ(TLBRBADV) + CASE_CSR_XCHGQ(TLBRERA) + CASE_CSR_XCHGQ(TLBRSAVE) + CASE_CSR_XCHGQ(TLBRELO0) + CASE_CSR_XCHGQ(TLBRELO1) + CASE_CSR_XCHGQ(TLBREHI) + CASE_CSR_XCHGQ(TLBRPRMD) + CASE_CSR_XCHGQ(ERRCTL) + CASE_CSR_XCHGQ(ERRINFO) + CASE_CSR_XCHGQ(ERRINFO1) + CASE_CSR_XCHGQ(ERRENT) + CASE_CSR_XCHGQ(ERRERA) + CASE_CSR_XCHGQ(ERRSAVE) + CASE_CSR_XCHGQ(CTAG) + CASE_CSR_XCHGQ(DMWIN0) + CASE_CSR_XCHGQ(DMWIN1) + CASE_CSR_XCHGQ(DMWIN2) + CASE_CSR_XCHGQ(DMWIN3) + CASE_CSR_XCHGQ(PERFCTRL0) + CASE_CSR_XCHGQ(PERFCNTR0) + CASE_CSR_XCHGQ(PERFCTRL1) + CASE_CSR_XCHGQ(PERFCNTR1) + CASE_CSR_XCHGQ(PERFCTRL2) + CASE_CSR_XCHGQ(PERFCNTR2) + CASE_CSR_XCHGQ(PERFCTRL3) + CASE_CSR_XCHGQ(PERFCNTR3) + /* debug */ + CASE_CSR_XCHGQ(MWPC) + CASE_CSR_XCHGQ(MWPS) + CASE_CSR_XCHGQ(DB0ADDR) + CASE_CSR_XCHGQ(DB0MASK) + CASE_CSR_XCHGQ(DB0CTL) + CASE_CSR_XCHGQ(DB0ASID) + CASE_CSR_XCHGQ(DB1ADDR) + CASE_CSR_XCHGQ(DB1MASK) + CASE_CSR_XCHGQ(DB1CTL) + CASE_CSR_XCHGQ(DB1ASID) + CASE_CSR_XCHGQ(DB2ADDR) + CASE_CSR_XCHGQ(DB2MASK) + CASE_CSR_XCHGQ(DB2CTL) + CASE_CSR_XCHGQ(DB2ASID) + CASE_CSR_XCHGQ(DB3ADDR) + CASE_CSR_XCHGQ(DB3MASK) + CASE_CSR_XCHGQ(DB3CTL) + CASE_CSR_XCHGQ(DB3ASID) + CASE_CSR_XCHGQ(FWPC) + CASE_CSR_XCHGQ(FWPS) + CASE_CSR_XCHGQ(IB0ADDR) + CASE_CSR_XCHGQ(IB0MASK) + CASE_CSR_XCHGQ(IB0CTL) + CASE_CSR_XCHGQ(IB0ASID) + CASE_CSR_XCHGQ(IB1ADDR) + CASE_CSR_XCHGQ(IB1MASK) + CASE_CSR_XCHGQ(IB1CTL) + CASE_CSR_XCHGQ(IB1ASID) + CASE_CSR_XCHGQ(IB2ADDR) + CASE_CSR_XCHGQ(IB2MASK) + CASE_CSR_XCHGQ(IB2CTL) + CASE_CSR_XCHGQ(IB2ASID) + CASE_CSR_XCHGQ(IB3ADDR) + CASE_CSR_XCHGQ(IB3MASK) + CASE_CSR_XCHGQ(IB3CTL) + CASE_CSR_XCHGQ(IB3ASID) + CASE_CSR_XCHGQ(IB4ADDR) + CASE_CSR_XCHGQ(IB4MASK) + CASE_CSR_XCHGQ(IB4CTL) + CASE_CSR_XCHGQ(IB4ASID) + CASE_CSR_XCHGQ(IB5ADDR) + CASE_CSR_XCHGQ(IB5MASK) + CASE_CSR_XCHGQ(IB5CTL) + CASE_CSR_XCHGQ(IB5ASID) + CASE_CSR_XCHGQ(IB6ADDR) + CASE_CSR_XCHGQ(IB6MASK) + CASE_CSR_XCHGQ(IB6CTL) + CASE_CSR_XCHGQ(IB6ASID) + CASE_CSR_XCHGQ(IB7ADDR) + CASE_CSR_XCHGQ(IB7MASK) + CASE_CSR_XCHGQ(IB7CTL) + CASE_CSR_XCHGQ(IB7ASID) + CASE_CSR_XCHGQ(DEBUG) + CASE_CSR_XCHGQ(DERA) + CASE_CSR_XCHGQ(DESAVE) + default : + assert(0); + } + +#undef CASE_CSR_XCHGQ + compute_hflags(env); + return val; +} + +static target_ulong confbus_addr(CPULOONGARCHState *env, int cpuid, + target_ulong csr_addr) +{ + target_ulong addr; + target_ulong node_addr; + int cores_per_node = ((0x60018 >> 3) & 0xff) + 1; + + switch (cores_per_node) { + case 4: + assert(cpuid < 64); + node_addr = ((target_ulong)(cpuid & 0x3c) << 42); + break; + case 8: + assert(cpuid < 128); + node_addr = ((target_ulong)(cpuid & 0x78) << 41) + + ((target_ulong)(cpuid & 0x4) << 14); + break; + case 16: + assert(cpuid < 256); + node_addr = ((target_ulong)(cpuid & 0xf0) << 40) + + ((target_ulong)(cpuid & 0xc) << 14); + break; + default: + assert(0); + break; + } + + /* + * per core address + *0x10xx => ipi + * 0x18xx => extioi isr + */ + if (((csr_addr & 0xff00) == 0x1000)) { + addr = (csr_addr & 0xff) + (target_ulong)(cpuid << 8); + addr = 0x800000001f000000UL + addr; + return addr; + } else if ((csr_addr & 0xff00) == 0x1800) { + addr = (csr_addr & 0xff) + ((target_ulong)(cpuid << 8)); + addr = 0x800000001f020000UL + addr; + return addr; + } else if ((csr_addr & 0xff00) >= 0x1400 && (csr_addr & 0xff00) < 0x1d00) { + addr = 0x800000001f010000UL + ((csr_addr & 0xfff) - 0x400); + return addr; + } else if (csr_addr == 0x408) { + addr = csr_addr; + } else { + addr = csr_addr + node_addr; + } + + addr = 0x800000001fe00000UL + addr; + return addr; +} + +void helper_iocsr(CPULOONGARCHState *env, target_ulong r_addr, + target_ulong r_val, uint32_t op) +{ + target_ulong addr; + target_ulong val = env->active_tc.gpr[r_val]; + int mask; + + addr = confbus_addr(env, CPU(loongarch_env_get_cpu(env))->cpu_index, + env->active_tc.gpr[r_addr]); + + switch (env->active_tc.gpr[r_addr]) { + /* IPI send */ + case 0x1040: + if (op != OPC_LARCH_ST_W) { + return; + } + op = OPC_LARCH_ST_W; + break; + + /* Mail send */ + case 0x1048: + if (op != OPC_LARCH_ST_D) { + return; + } + op = OPC_LARCH_ST_D; + break; + + /* ANY send */ + case 0x1158: + if (op != OPC_LARCH_ST_D) { + return; + } + addr = confbus_addr(env, (val >> 16) & 0x3ff, val & 0xffff); + mask = (val >> 27) & 0xf; + val = (val >> 32); + switch (mask) { + case 0: + op = OPC_LARCH_ST_W; + break; + case 0x7: + op = OPC_LARCH_ST_B; + addr += 3; + val >>= 24; + break; + case 0xb: + op = OPC_LARCH_ST_B; + addr += 2; + val >>= 16; + break; + case 0xd: + op = OPC_LARCH_ST_B; + addr += 1; + val >>= 8; + break; + case 0xe: + op = OPC_LARCH_ST_B; + break; + case 0xc: + op = OPC_LARCH_ST_H; + break; + case 0x3: + op = OPC_LARCH_ST_H; + addr += 2; + val >>= 16; + break; + default: + qemu_log("Unsupported any_send mask0x%x\n", mask); + break; + } + break; + + default: + break; + } + + switch (op) { + case OPC_LARCH_LD_D: + env->active_tc.gpr[r_val] = cpu_ldq_data_ra(env, addr, + GETPC()); + break; + case OPC_LARCH_LD_W: + env->active_tc.gpr[r_val] = cpu_ldl_data_ra(env, addr, + GETPC()); + break; + case OPC_LARCH_LD_H: + assert(0); + break; + case OPC_LARCH_LD_B: + assert(0); + break; + case OPC_LARCH_ST_D: + cpu_stq_data_ra(env, addr, val, GETPC()); + break; + case OPC_LARCH_ST_W: + cpu_stl_data_ra(env, addr, val, GETPC()); + break; + case OPC_LARCH_ST_H: + cpu_stb_data_ra(env, addr, val, GETPC()); + break; + case OPC_LARCH_ST_B: + cpu_stb_data_ra(env, addr, val, GETPC()); + break; + default: + qemu_log("Unknown op 0x%x", op); + assert(0); + } +} +#endif + +target_ulong helper_cpucfg(CPULOONGARCHState *env, target_ulong rj) +{ + return 0; +} + + diff --git a/target/loongarch64/fpu.c b/target/loongarch64/fpu.c new file mode 100644 index 0000000000..795458205b --- /dev/null +++ b/target/loongarch64/fpu.c @@ -0,0 +1,28 @@ +/* + * loongarch float point emulation helpers for qemu. + * + * Copyright (c) 2020-2021 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#include "qemu/osdep.h" +#include "fpu/softfloat.h" + +/* convert loongarch rounding mode in fcsr0 to IEEE library */ +unsigned int ieee_rm[] = { + float_round_nearest_even, + float_round_to_zero, + float_round_up, + float_round_down +}; diff --git a/target/loongarch64/fpu_helper.c b/target/loongarch64/fpu_helper.c new file mode 100644 index 0000000000..42d7f05ca2 --- /dev/null +++ b/target/loongarch64/fpu_helper.c @@ -0,0 +1,952 @@ +/* + * loongarch float point emulation helpers for qemu. + * + * Copyright (c) 2020-2021 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#include "qemu/osdep.h" +#include "cpu.h" +#include "internal.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "exec/exec-all.h" +#include "fpu/softfloat.h" + +#define FP_TO_INT32_OVERFLOW 0x7fffffff +#define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL + +#define FLOAT_CLASS_SIGNALING_NAN 0x001 +#define FLOAT_CLASS_QUIET_NAN 0x002 +#define FLOAT_CLASS_NEGATIVE_INFINITY 0x004 +#define FLOAT_CLASS_NEGATIVE_NORMAL 0x008 +#define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010 +#define FLOAT_CLASS_NEGATIVE_ZERO 0x020 +#define FLOAT_CLASS_POSITIVE_INFINITY 0x040 +#define FLOAT_CLASS_POSITIVE_NORMAL 0x080 +#define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100 +#define FLOAT_CLASS_POSITIVE_ZERO 0x200 + +target_ulong helper_movfcsr2gr(CPULOONGARCHState *env, uint32_t reg) +{ + target_ulong r = 0; + + switch (reg) { + case 0: + r = (uint32_t)env->active_fpu.fcsr0; + break; + case 1: + r = (env->active_fpu.fcsr0 & FCSR0_M1); + break; + case 2: + r = (env->active_fpu.fcsr0 & FCSR0_M2); + break; + case 3: + r = (env->active_fpu.fcsr0 & FCSR0_M3); + break; + case 16: + r = (uint32_t)env->active_fpu.vcsr16; + break; + default: + printf("%s: warning, fcsr '%d' not supported\n", __func__, reg); + assert(0); + break; + } + + return r; +} + +void helper_movgr2fcsr(CPULOONGARCHState *env, target_ulong arg1, + uint32_t fcsr, uint32_t rj) +{ + switch (fcsr) { + case 0: + env->active_fpu.fcsr0 = arg1; + break; + case 1: + env->active_fpu.fcsr0 = (arg1 & FCSR0_M1) | + (env->active_fpu.fcsr0 & ~FCSR0_M1); + break; + case 2: + env->active_fpu.fcsr0 = (arg1 & FCSR0_M2) | + (env->active_fpu.fcsr0 & ~FCSR0_M2); + break; + case 3: + env->active_fpu.fcsr0 = (arg1 & FCSR0_M3) | + (env->active_fpu.fcsr0 & ~FCSR0_M3); + break; + case 16: + env->active_fpu.vcsr16 = arg1; + break; + default: + printf("%s: warning, fcsr '%d' not supported\n", __func__, fcsr); + assert(0); + break; + } + restore_fp_status(env); + set_float_exception_flags(0, &env->active_fpu.fp_status); +} + +void helper_movreg2cf(CPULOONGARCHState *env, uint32_t cd, target_ulong src) +{ + env->active_fpu.cf[cd & 0x7] = src & 0x1; +} + +void helper_movreg2cf_i32(CPULOONGARCHState *env, uint32_t cd, uint32_t src) +{ + env->active_fpu.cf[cd & 0x7] = src & 0x1; +} + +void helper_movreg2cf_i64(CPULOONGARCHState *env, uint32_t cd, uint64_t src) +{ + env->active_fpu.cf[cd & 0x7] = src & 0x1; +} + +target_ulong helper_movcf2reg(CPULOONGARCHState *env, uint32_t cj) +{ + return (target_ulong)env->active_fpu.cf[cj & 0x7]; +} + +int ieee_ex_to_loongarch(int xcpt) +{ + int ret = 0; + if (xcpt) { + if (xcpt & float_flag_invalid) { + ret |= FP_INVALID; + } + if (xcpt & float_flag_overflow) { + ret |= FP_OVERFLOW; + } + if (xcpt & float_flag_underflow) { + ret |= FP_UNDERFLOW; + } + if (xcpt & float_flag_divbyzero) { + ret |= FP_DIV0; + } + if (xcpt & float_flag_inexact) { + ret |= FP_INEXACT; + } + } + return ret; +} + +static inline void update_fcsr0(CPULOONGARCHState *env, uintptr_t pc) +{ + int tmp = ieee_ex_to_loongarch(get_float_exception_flags( + &env->active_fpu.fp_status)); + + SET_FP_CAUSE(env->active_fpu.fcsr0, tmp); + if (tmp) { + set_float_exception_flags(0, &env->active_fpu.fp_status); + + if (GET_FP_ENABLE(env->active_fpu.fcsr0) & tmp) { + do_raise_exception(env, EXCP_FPE, pc); + } else { + UPDATE_FP_FLAGS(env->active_fpu.fcsr0, tmp); + } + } +} + +/* unary operations, modifying fp status */ +uint64_t helper_float_sqrt_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fdt0; +} + +uint32_t helper_float_sqrt_s(CPULOONGARCHState *env, uint32_t fst0) +{ + fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fst0; +} + +uint64_t helper_float_cvtd_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint64_t fdt2; + + fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fdt2; +} + +uint64_t helper_float_cvtd_w(CPULOONGARCHState *env, uint32_t wt0) +{ + uint64_t fdt2; + + fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fdt2; +} + +uint64_t helper_float_cvtd_l(CPULOONGARCHState *env, uint64_t dt0) +{ + uint64_t fdt2; + + fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fdt2; +} + +uint64_t helper_float_cvt_l_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint64_t dt2; + + dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + dt2 = FP_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return dt2; +} + +uint64_t helper_float_cvt_l_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint64_t dt2; + + dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + dt2 = FP_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return dt2; +} + +uint32_t helper_float_cvts_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint32_t fst2; + + fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fst2; +} + +uint32_t helper_float_cvts_w(CPULOONGARCHState *env, uint32_t wt0) +{ + uint32_t fst2; + + fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fst2; +} + +uint32_t helper_float_cvts_l(CPULOONGARCHState *env, uint64_t dt0) +{ + uint32_t fst2; + + fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fst2; +} + +uint32_t helper_float_cvt_w_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint32_t wt2; + + wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + wt2 = FP_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return wt2; +} + +uint32_t helper_float_cvt_w_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint32_t wt2; + + wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + wt2 = FP_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return wt2; +} + +uint64_t helper_float_round_l_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint64_t dt2; + + set_float_rounding_mode(float_round_nearest_even, + &env->active_fpu.fp_status); + dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + dt2 = FP_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return dt2; +} + +uint64_t helper_float_round_l_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint64_t dt2; + + set_float_rounding_mode(float_round_nearest_even, + &env->active_fpu.fp_status); + dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + dt2 = FP_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return dt2; +} + +uint32_t helper_float_round_w_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint32_t wt2; + + set_float_rounding_mode(float_round_nearest_even, + &env->active_fpu.fp_status); + wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + wt2 = FP_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return wt2; +} + +uint32_t helper_float_round_w_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint32_t wt2; + + set_float_rounding_mode(float_round_nearest_even, + &env->active_fpu.fp_status); + wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + wt2 = FP_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return wt2; +} + +uint64_t helper_float_trunc_l_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint64_t dt2; + + dt2 = float64_to_int64_round_to_zero(fdt0, + &env->active_fpu.fp_status); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + dt2 = FP_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return dt2; +} + +uint64_t helper_float_trunc_l_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint64_t dt2; + + dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + dt2 = FP_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return dt2; +} + +uint32_t helper_float_trunc_w_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint32_t wt2; + + wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + wt2 = FP_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return wt2; +} + +uint32_t helper_float_trunc_w_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint32_t wt2; + + wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + wt2 = FP_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return wt2; +} + +uint64_t helper_float_ceil_l_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint64_t dt2; + + set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); + dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + dt2 = FP_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return dt2; +} + +uint64_t helper_float_ceil_l_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint64_t dt2; + + set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); + dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + dt2 = FP_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return dt2; +} + +uint32_t helper_float_ceil_w_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint32_t wt2; + + set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); + wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + wt2 = FP_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return wt2; +} + +uint32_t helper_float_ceil_w_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint32_t wt2; + + set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); + wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + wt2 = FP_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return wt2; +} + +uint64_t helper_float_floor_l_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint64_t dt2; + + set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); + dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + dt2 = FP_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return dt2; +} + +uint64_t helper_float_floor_l_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint64_t dt2; + + set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); + dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + dt2 = FP_TO_INT64_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return dt2; +} + +uint32_t helper_float_floor_w_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint32_t wt2; + + set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); + wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + wt2 = FP_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return wt2; +} + +uint32_t helper_float_floor_w_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint32_t wt2; + + set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); + wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); + restore_rounding_mode(env); + if (get_float_exception_flags(&env->active_fpu.fp_status) + & (float_flag_invalid | float_flag_overflow)) { + wt2 = FP_TO_INT32_OVERFLOW; + } + update_fcsr0(env, GETPC()); + return wt2; +} + +/* unary operations, not modifying fp status */ +#define FLOAT_UNOP(name) \ +uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \ +{ \ + return float64_ ## name(fdt0); \ +} \ +uint32_t helper_float_ ## name ## _s(uint32_t fst0) \ +{ \ + return float32_ ## name(fst0); \ +} + +FLOAT_UNOP(abs) +FLOAT_UNOP(chs) +#undef FLOAT_UNOP + +uint64_t helper_float_recip_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint64_t fdt2; + + fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fdt2; +} + +uint32_t helper_float_recip_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint32_t fst2; + + fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fst2; +} + +uint64_t helper_float_rsqrt_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint64_t fdt2; + + fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); + fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fdt2; +} + +uint32_t helper_float_rsqrt_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint32_t fst2; + + fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); + fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fst2; +} + +uint32_t helper_float_rint_s(CPULOONGARCHState *env, uint32_t fs) +{ + uint32_t fdret; + + fdret = float32_round_to_int(fs, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fdret; +} + +uint64_t helper_float_rint_d(CPULOONGARCHState *env, uint64_t fs) +{ + uint64_t fdret; + + fdret = float64_round_to_int(fs, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return fdret; +} + +#define FLOAT_CLASS(name, bits) \ +uint ## bits ## _t float_ ## name(uint ## bits ## _t arg, \ + float_status *status) \ +{ \ + if (float ## bits ## _is_signaling_nan(arg, status)) { \ + return FLOAT_CLASS_SIGNALING_NAN; \ + } else if (float ## bits ## _is_quiet_nan(arg, status)) { \ + return FLOAT_CLASS_QUIET_NAN; \ + } else if (float ## bits ## _is_neg(arg)) { \ + if (float ## bits ## _is_infinity(arg)) { \ + return FLOAT_CLASS_NEGATIVE_INFINITY; \ + } else if (float ## bits ## _is_zero(arg)) { \ + return FLOAT_CLASS_NEGATIVE_ZERO; \ + } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ + return FLOAT_CLASS_NEGATIVE_SUBNORMAL; \ + } else { \ + return FLOAT_CLASS_NEGATIVE_NORMAL; \ + } \ + } else { \ + if (float ## bits ## _is_infinity(arg)) { \ + return FLOAT_CLASS_POSITIVE_INFINITY; \ + } else if (float ## bits ## _is_zero(arg)) { \ + return FLOAT_CLASS_POSITIVE_ZERO; \ + } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ + return FLOAT_CLASS_POSITIVE_SUBNORMAL; \ + } else { \ + return FLOAT_CLASS_POSITIVE_NORMAL; \ + } \ + } \ +} \ + \ +uint ## bits ## _t helper_float_ ## name(CPULOONGARCHState *env, \ + uint ## bits ## _t arg) \ +{ \ + return float_ ## name(arg, &env->active_fpu.fp_status); \ +} + +FLOAT_CLASS(class_s, 32) +FLOAT_CLASS(class_d, 64) +#undef FLOAT_CLASS + +/* binary operations */ +#define FLOAT_BINOP(name) \ +uint64_t helper_float_ ## name ## _d(CPULOONGARCHState *env, \ + uint64_t fdt0, uint64_t fdt1) \ +{ \ + uint64_t dt2; \ + \ + dt2 = float64_ ## name(fdt0, fdt1, &env->active_fpu.fp_status);\ + update_fcsr0(env, GETPC()); \ + return dt2; \ +} \ + \ +uint32_t helper_float_ ## name ## _s(CPULOONGARCHState *env, \ + uint32_t fst0, uint32_t fst1) \ +{ \ + uint32_t wt2; \ + \ + wt2 = float32_ ## name(fst0, fst1, &env->active_fpu.fp_status);\ + update_fcsr0(env, GETPC()); \ + return wt2; \ +} + +FLOAT_BINOP(add) +FLOAT_BINOP(sub) +FLOAT_BINOP(mul) +FLOAT_BINOP(div) +#undef FLOAT_BINOP + +uint64_t helper_float_exp2_d(CPULOONGARCHState *env, + uint64_t fdt0, uint64_t fdt1) +{ + uint64_t dt2; + int64_t n = (int64_t)fdt1; + + dt2 = float64_scalbn(fdt0, + n > 0x1000 ? 0x1000 : + n < -0x1000 ? -0x1000 : n, + &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return dt2; +} + +uint32_t helper_float_exp2_s(CPULOONGARCHState *env, + uint32_t fst0, uint32_t fst1) +{ + uint32_t wt2; + int32_t n = (int32_t)fst1; + + wt2 = float32_scalbn(fst0, + n > 0x200 ? 0x200 : + n < -0x200 ? -0x200 : n, + &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return wt2; +} + +#define FLOAT_MINMAX(name, bits, minmaxfunc) \ +uint ## bits ## _t helper_float_ ## name(CPULOONGARCHState *env, \ + uint ## bits ## _t fs, \ + uint ## bits ## _t ft) \ +{ \ + uint ## bits ## _t fdret; \ + \ + fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \ + &env->active_fpu.fp_status); \ + update_fcsr0(env, GETPC()); \ + return fdret; \ +} + +FLOAT_MINMAX(max_s, 32, maxnum) +FLOAT_MINMAX(max_d, 64, maxnum) +FLOAT_MINMAX(maxa_s, 32, maxnummag) +FLOAT_MINMAX(maxa_d, 64, maxnummag) + +FLOAT_MINMAX(min_s, 32, minnum) +FLOAT_MINMAX(min_d, 64, minnum) +FLOAT_MINMAX(mina_s, 32, minnummag) +FLOAT_MINMAX(mina_d, 64, minnummag) +#undef FLOAT_MINMAX + +#define FLOAT_FMADDSUB(name, bits, muladd_arg) \ +uint ## bits ## _t helper_float_ ## name(CPULOONGARCHState *env, \ + uint ## bits ## _t fs, \ + uint ## bits ## _t ft, \ + uint ## bits ## _t fd) \ +{ \ + uint ## bits ## _t fdret; \ + \ + fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \ + &env->active_fpu.fp_status); \ + update_fcsr0(env, GETPC()); \ + return fdret; \ +} + +FLOAT_FMADDSUB(maddf_s, 32, 0) +FLOAT_FMADDSUB(maddf_d, 64, 0) +FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_c) +FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_c) +FLOAT_FMADDSUB(nmaddf_s, 32, float_muladd_negate_result) +FLOAT_FMADDSUB(nmaddf_d, 64, float_muladd_negate_result) +FLOAT_FMADDSUB(nmsubf_s, 32, float_muladd_negate_result | float_muladd_negate_c) +FLOAT_FMADDSUB(nmsubf_d, 64, float_muladd_negate_result | float_muladd_negate_c) +#undef FLOAT_FMADDSUB + +/* compare operations */ +#define FOP_CONDN_D(op, cond) \ +uint64_t helper_cmp_d_ ## op(CPULOONGARCHState *env, uint64_t fdt0, \ + uint64_t fdt1) \ +{ \ + uint64_t c; \ + c = cond; \ + update_fcsr0(env, GETPC()); \ + if (c) { \ + return -1; \ + } else { \ + return 0; \ + } \ +} + +/* + * NOTE: the comma operator will make "cond" to eval to false, + * but float64_unordered_quiet() is still called. + */ +FOP_CONDN_D(af, (float64_unordered_quiet(fdt1, fdt0, + &env->active_fpu.fp_status), 0)) +FOP_CONDN_D(un, (float64_unordered_quiet(fdt1, fdt0, + &env->active_fpu.fp_status))) +FOP_CONDN_D(eq, (float64_eq_quiet(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(ueq, (float64_unordered_quiet(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_eq_quiet(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(lt, (float64_lt_quiet(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(ult, (float64_unordered_quiet(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_lt_quiet(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(le, (float64_le_quiet(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(ule, (float64_unordered_quiet(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_le_quiet(fdt0, fdt1, + &env->active_fpu.fp_status))) +/* + * NOTE: the comma operator will make "cond" to eval to false, + * but float64_unordered() is still called. + */ +FOP_CONDN_D(saf, (float64_unordered(fdt1, fdt0, + &env->active_fpu.fp_status), 0)) +FOP_CONDN_D(sun, (float64_unordered(fdt1, fdt0, + &env->active_fpu.fp_status))) +FOP_CONDN_D(seq, (float64_eq(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_eq(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(slt, (float64_lt(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_lt(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(sle, (float64_le(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_le(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(or, (float64_le_quiet(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_le_quiet(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(une, (float64_unordered_quiet(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_lt_quiet(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_lt_quiet(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(ne, (float64_lt_quiet(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_lt_quiet(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(sor, (float64_le(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_le(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(sune, (float64_unordered(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_lt(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_lt(fdt0, fdt1, + &env->active_fpu.fp_status))) +FOP_CONDN_D(sne, (float64_lt(fdt1, fdt0, + &env->active_fpu.fp_status) + || float64_lt(fdt0, fdt1, + &env->active_fpu.fp_status))) + +#define FOP_CONDN_S(op, cond) \ +uint32_t helper_cmp_s_ ## op(CPULOONGARCHState *env, uint32_t fst0, \ + uint32_t fst1) \ +{ \ + uint64_t c; \ + c = cond; \ + update_fcsr0(env, GETPC()); \ + if (c) { \ + return -1; \ + } else { \ + return 0; \ + } \ +} + +/* + * NOTE: the comma operator will make "cond" to eval to false, + * but float32_unordered_quiet() is still called. + */ +FOP_CONDN_S(af, (float32_unordered_quiet(fst1, fst0, + &env->active_fpu.fp_status), 0)) +FOP_CONDN_S(un, (float32_unordered_quiet(fst1, fst0, + &env->active_fpu.fp_status))) +FOP_CONDN_S(eq, (float32_eq_quiet(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(ueq, (float32_unordered_quiet(fst1, fst0, + &env->active_fpu.fp_status) + || float32_eq_quiet(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(lt, (float32_lt_quiet(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(ult, (float32_unordered_quiet(fst1, fst0, + &env->active_fpu.fp_status) + || float32_lt_quiet(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(le, (float32_le_quiet(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(ule, (float32_unordered_quiet(fst1, fst0, + &env->active_fpu.fp_status) + || float32_le_quiet(fst0, fst1, + &env->active_fpu.fp_status))) +/* + * NOTE: the comma operator will make "cond" to eval to false, + * but float32_unordered() is still called. + */ +FOP_CONDN_S(saf, (float32_unordered(fst1, fst0, + &env->active_fpu.fp_status), 0)) +FOP_CONDN_S(sun, (float32_unordered(fst1, fst0, + &env->active_fpu.fp_status))) +FOP_CONDN_S(seq, (float32_eq(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0, + &env->active_fpu.fp_status) + || float32_eq(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(slt, (float32_lt(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(sult, (float32_unordered(fst1, fst0, + &env->active_fpu.fp_status) + || float32_lt(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(sle, (float32_le(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(sule, (float32_unordered(fst1, fst0, + &env->active_fpu.fp_status) + || float32_le(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(or, (float32_le_quiet(fst1, fst0, + &env->active_fpu.fp_status) + || float32_le_quiet(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(une, (float32_unordered_quiet(fst1, fst0, + &env->active_fpu.fp_status) + || float32_lt_quiet(fst1, fst0, + &env->active_fpu.fp_status) + || float32_lt_quiet(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(ne, (float32_lt_quiet(fst1, fst0, + &env->active_fpu.fp_status) + || float32_lt_quiet(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(sor, (float32_le(fst1, fst0, + &env->active_fpu.fp_status) + || float32_le(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, + &env->active_fpu.fp_status) + || float32_lt(fst1, fst0, + &env->active_fpu.fp_status) + || float32_lt(fst0, fst1, + &env->active_fpu.fp_status))) +FOP_CONDN_S(sne, (float32_lt(fst1, fst0, + &env->active_fpu.fp_status) + || float32_lt(fst0, fst1, + &env->active_fpu.fp_status))) + +uint32_t helper_float_logb_s(CPULOONGARCHState *env, uint32_t fst0) +{ + uint32_t wt2; + + wt2 = float32_log2(fst0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return wt2; +} + +uint64_t helper_float_logb_d(CPULOONGARCHState *env, uint64_t fdt0) +{ + uint64_t dt2; + + dt2 = float64_log2(fdt0, &env->active_fpu.fp_status); + update_fcsr0(env, GETPC()); + return dt2; +} + +target_ulong helper_fsel(CPULOONGARCHState *env, target_ulong fj, + target_ulong fk, uint32_t ca) +{ + if (env->active_fpu.cf[ca & 0x7]) { + return fk; + } else { + return fj; + } +} diff --git a/target/loongarch64/fpu_helper.h b/target/loongarch64/fpu_helper.h new file mode 100644 index 0000000000..b6898c2e91 --- /dev/null +++ b/target/loongarch64/fpu_helper.h @@ -0,0 +1,129 @@ +/* loongarch internal definitions and helpers + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef LOONGARCH_FPU_H +#define LOONGARCH_FPU_H + +#include "cpu-csr.h" + + +extern const struct loongarch_def_t loongarch_defs[]; +extern const int loongarch_defs_number; + +enum CPULSXDataFormat { + DF_BYTE = 0, + DF_HALF, + DF_WORD, + DF_DOUBLE, + DF_QUAD +}; + +void loongarch_cpu_do_interrupt(CPUState *cpu); +bool loongarch_cpu_exec_interrupt(CPUState *cpu, int int_req); +void loongarch_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, + MMUAccessType access_type, + int mmu_idx, uintptr_t retaddr) QEMU_NORETURN; + +#if !defined(CONFIG_USER_ONLY) + +typedef struct r4k_tlb_t r4k_tlb_t; +struct r4k_tlb_t { + target_ulong VPN; + uint32_t PageMask; + uint16_t ASID; + unsigned int G:1; + unsigned int C0:3; + unsigned int C1:3; + unsigned int V0:1; + unsigned int V1:1; + unsigned int D0:1; + unsigned int D1:1; + unsigned int XI0:1; + unsigned int XI1:1; + unsigned int RI0:1; + unsigned int RI1:1; + unsigned int EHINV:1; + uint64_t PPN[2]; +}; + +int no_mmu_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, + target_ulong address, int rw, int access_type); +int fixed_mmu_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, + target_ulong address, int rw, int access_type); +int r4k_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, + target_ulong address, int rw, int access_type); + +/* loongarch 3a5000 tlb helper function : lisa csr */ +int ls3a5k_map_address(CPULOONGARCHState *env, hwaddr *physical, + int *prot, target_ulong address, + int rw, int access_type); +void ls3a5k_helper_tlbwr(CPULOONGARCHState *env); +void ls3a5k_helper_tlbfill(CPULOONGARCHState *env); +void ls3a5k_helper_tlbsrch(CPULOONGARCHState *env); +void ls3a5k_helper_tlbrd(CPULOONGARCHState *env); +void ls3a5k_helper_tlbclr(CPULOONGARCHState *env); +void ls3a5k_helper_tlbflush(CPULOONGARCHState *env); +void ls3a5k_invalidate_tlb(CPULOONGARCHState *env, int idx); +void ls3a5k_helper_invtlb(CPULOONGARCHState *env, target_ulong addr, + target_ulong info, int op); +void ls3a5k_flush_vtlb(CPULOONGARCHState *env); +void ls3a5k_flush_ftlb(CPULOONGARCHState *env); +/*void loongarch_cpu_unassigned_access(CPUState *cpu, hwaddr addr, + bool is_write, bool is_exec, int unused, + unsigned size); +*/ +hwaddr cpu_loongarch_translate_address(CPULOONGARCHState *env, target_ulong address, + int rw); +#endif + +#define cpu_signal_handler cpu_loongarch_signal_handler + + +static inline bool cpu_loongarch_hw_interrupts_enabled(CPULOONGARCHState *env) +{ + bool ret = 0; + + ret = env->CSR_CRMD & (1 << CSR_CRMD_IE_SHIFT); + + return ret; +} + + +void loongarch_tcg_init(void); + + +/* helper.c */ +bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); + +/* op_helper.c */ +uint32_t float_class_s(uint32_t arg, float_status *fst); +uint64_t float_class_d(uint64_t arg, float_status *fst); + +int ieee_ex_to_loongarch(int xcpt); +void update_pagemask(CPULOONGARCHState *env, target_ulong arg1, int32_t *pagemask); + +void cpu_loongarch_tlb_flush(CPULOONGARCHState *env); +void sync_c0_status(CPULOONGARCHState *env, CPULOONGARCHState *cpu, int tc); + +void QEMU_NORETURN do_raise_exception_err(CPULOONGARCHState *env, uint32_t exception, + int error_code, uintptr_t pc); +int loongarch_read_qxfer(CPUState *cs, const char *annex, + uint8_t *read_buf, + unsigned long offset, unsigned long len); +int loongarch_write_qxfer(CPUState *cs, const char *annex, + const uint8_t *write_buf, + unsigned long offset, unsigned long len); + +static inline void QEMU_NORETURN do_raise_exception(CPULOONGARCHState *env, + uint32_t exception, + uintptr_t pc) +{ + do_raise_exception_err(env, exception, 0, pc); +} + +#endif diff --git a/target/loongarch64/gdbstub.c b/target/loongarch64/gdbstub.c new file mode 100644 index 0000000000..4013178f45 --- /dev/null +++ b/target/loongarch64/gdbstub.c @@ -0,0 +1,109 @@ +/* + * LOONGARCH gdb server stub + * + * Copyright (c) 2003-2005 Fabrice Bellard + * Copyright (c) 2013 SUSE LINUX Products GmbH + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "internal.h" +#include "exec/gdbstub.h" +#ifdef CONFIG_TCG +#include "exec/helper-proto.h" +#endif +int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + + if (0 <= n && n < 32) { + return gdb_get_regl(mem_buf, env->active_tc.gpr[n]); + } else if (n == 32) { + return gdb_get_regl(mem_buf, env->active_tc.PC); + } + return 0; +} + +int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + target_ulong tmp = ldtul_p(mem_buf); + + if (0 <= n && n < 32) { + return env->active_tc.gpr[n] = tmp, sizeof(target_ulong); + } else if (n == 32) { + return env->active_tc.PC = tmp, sizeof(target_ulong); + } + return 0; +} + +static int loongarch_gdb_get_fpu(CPULOONGARCHState *env, GByteArray *mem_buf, int n) +{ + if (0 <= n && n < 32) { + return gdb_get_reg64(mem_buf, env->active_fpu.fpr[n].d); + } else if (32 <= n && n < 40) { + return gdb_get_reg8(mem_buf, env->active_fpu.cf[n - 32]); + } else if (n == 40) { + return gdb_get_reg32(mem_buf, env->active_fpu.fcsr0); + } + return 0; +} + +static int loongarch_gdb_set_fpu(CPULOONGARCHState *env, uint8_t *mem_buf, int n) +{ + if (0 <= n && n < 32) { + return env->active_fpu.fpr[n].d = ldq_p(mem_buf), 8; + } else if (32 <= n && n < 40) { + return env->active_fpu.cf[n - 32] = ldub_p(mem_buf), 1; + } else if (n == 40) { + return env->active_fpu.fcsr0 = ldl_p(mem_buf), 4; + } + return 0; +} + +void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs) +{ + gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu, + 41, "loongarch-fpu64.xml", 0); +} + +#ifdef CONFIG_TCG +int loongarch_read_qxfer(CPUState *cs, const char *annex, uint8_t *read_buf, + unsigned long offset, unsigned long len) +{ + if (strncmp(annex, "cpucfg", sizeof("cpucfg") - 1) == 0) { + if (offset % 4 != 0 || len % 4 != 0) { + return 0; + } + + size_t i; + for (i = offset; i < offset + len; i += 4) + ((uint32_t *)read_buf)[(i - offset) / 4] = + helper_cpucfg(&(LOONGARCH_CPU(cs)->env), i / 4); + return 32 * 4; + } + return 0; +} + +int loongarch_write_qxfer(CPUState *cs, const char *annex, + const uint8_t *write_buf, unsigned long offset, + unsigned long len) +{ + return 0; +} +#endif diff --git a/target/loongarch64/helper.c b/target/loongarch64/helper.c new file mode 100644 index 0000000000..841240e57b --- /dev/null +++ b/target/loongarch64/helper.c @@ -0,0 +1,727 @@ +/* + * LOONGARCH emulation helpers for qemu. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#include "qemu/osdep.h" +#include "cpu.h" +#include "internal.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "exec/log.h" +#include "hw/loongarch/cpudevs.h" + + +#if !defined(CONFIG_USER_ONLY) + +static int ls3a5k_map_address_tlb_entry( + CPULOONGARCHState *env, + hwaddr *physical, + int *prot, + target_ulong address, + int rw, + int access_type, + ls3a5k_tlb_t *tlb) +{ + uint64_t mask = tlb->PageMask; + int n = !!(address & mask & ~(mask >> 1)); + uint32_t plv = env->CSR_CRMD & CSR_CRMD_PLV; + + /* Check access rights */ + if (!(n ? tlb->V1 : tlb->V0)) { + return TLBRET_INVALID; + } + + if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) { + return TLBRET_XI; + } + + if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) { + return TLBRET_RI; + } + + if (plv > (n ? tlb->PLV1 : tlb->PLV0)) { + return TLBRET_PE; + } + + if (rw != MMU_DATA_STORE || (n ? tlb->WE1 : tlb->WE0)) { + /* PPN address + * 4 KB: [47:13] [12;0] + * 16 KB: [47:15] [14:0] + */ + if (n) { + *physical = tlb->PPN1 | (address & (mask >> 1)); + } else { + *physical = tlb->PPN0 | (address & (mask >> 1)); + } + *prot = PAGE_READ; + if (n ? tlb->WE1 : tlb->WE0) { + *prot |= PAGE_WRITE; + } + if (!(n ? tlb->XI1 : tlb->XI0)) { + *prot |= PAGE_EXEC; + } + return TLBRET_MATCH; + } + + return TLBRET_DIRTY; +} + +/* Loongarch 3A5K -style MMU emulation */ +int ls3a5k_map_address(CPULOONGARCHState *env, hwaddr *physical, int *prot, + target_ulong address, int rw, int access_type) +{ + uint16_t asid = env->CSR_ASID & 0x3ff; + int i; + ls3a5k_tlb_t *tlb; + + int ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; + int vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; + + int ftlb_idx; + + uint64_t mask; + uint64_t vpn; /* address to map */ + uint64_t tag; /* address in TLB entry */ + + /* search VTLB */ + for (i = ftlb_size; i < ftlb_size + vtlb_size; ++i) { + tlb = &env->tlb->mmu.ls3a5k.tlb[i]; + mask = tlb->PageMask; + + vpn = address & 0xffffffffe000 & ~mask; + tag = tlb->VPN & ~mask; + + if ((tlb->G == 1 || tlb->ASID == asid) + && vpn == tag + && tlb->EHINV != 1) + { + return ls3a5k_map_address_tlb_entry(env, physical, prot, + address, rw, access_type, tlb); + } + } + + if (ftlb_size == 0) { + return TLBRET_NOMATCH; + } + + /* search FTLB */ + mask = env->tlb->mmu.ls3a5k.ftlb_mask; + vpn = address & 0xffffffffe000 & ~mask; + + ftlb_idx = (address & 0xffffffffc000) >> 15; /* 16 KB */ + ftlb_idx = ftlb_idx & 0xff; /* [0,255] */ + + for (i = 0; i < 8; ++i) { + /* ---------- set 0 1 2 ... 7 + * ftlb_idx ----------------------------------- + * 0 | 0 1 2 ... 7 + * 1 | 8 9 10 ... 15 + * 2 | 16 17 18 ... 23 + * ... | + * 255 | 2040 2041 2042 ... 2047 + */ + tlb = &env->tlb->mmu.ls3a5k.tlb[ftlb_idx * 8 + i]; + tag = tlb->VPN & ~mask; + + if ((tlb->G == 1 || tlb->ASID == asid) + && vpn == tag + && tlb->EHINV != 1) + { + return ls3a5k_map_address_tlb_entry(env, physical, prot, + address, rw, access_type, tlb); + } + } + + return TLBRET_NOMATCH; +} + +static int get_physical_address(CPULOONGARCHState *env, hwaddr *physical, + int *prot, target_ulong real_address, + int rw, int access_type, int mmu_idx) +{ + int user_mode = mmu_idx == LARCH_HFLAG_UM; + int kernel_mode = !user_mode; + unsigned plv, base_c, base_v, tmp; + + /* effective address (modified for KVM T&E kernel segments) */ + target_ulong address = real_address; + + /* Check PG */ + if (!(env->CSR_CRMD & CSR_CRMD_PG)) { + /* DA mode */ + *physical = address & 0xffffffffffffUL; + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + return TLBRET_MATCH; + } + + plv = kernel_mode | (user_mode << 3); + base_v = address >> CSR_DMW_BASE_SH; + /* Check direct map window 0 */ + base_c = env->CSR_DMWIN0 >> CSR_DMW_BASE_SH; + if ((plv & env->CSR_DMWIN0) && (base_c == base_v)) { + *physical = dmwin_va2pa(address); + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + return TLBRET_MATCH; + } + /* Check direct map window 1 */ + base_c = env->CSR_DMWIN1 >> CSR_DMW_BASE_SH; + if ((plv & env->CSR_DMWIN1) && (base_c == base_v)) { + *physical = dmwin_va2pa(address); + *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + return TLBRET_MATCH; + } + /* Check valid extension */ + tmp = address >> 47; + if (!(tmp == 0 || tmp == 0x1ffff)) { + return TLBRET_BADADDR; + } + /* mapped address */ + return env->tlb->map_address(env, physical, prot, real_address, rw, + access_type); +} + +void cpu_loongarch_tlb_flush(CPULOONGARCHState *env) +{ + LOONGARCHCPU *cpu = loongarch_env_get_cpu(env); + + /* Flush qemu's TLB and discard all shadowed entries. */ + tlb_flush(CPU(cpu)); + env->tlb->tlb_in_use = env->tlb->nb_tlb; +} +#endif + +static void raise_mmu_exception(CPULOONGARCHState *env, target_ulong address, + int rw, int tlb_error) +{ + CPUState *cs = CPU(loongarch_env_get_cpu(env)); + int exception = 0, error_code = 0; + + if (rw == MMU_INST_FETCH) { + error_code |= EXCP_INST_NOTAVAIL; + } + + switch (tlb_error) { + default: + case TLBRET_BADADDR: + /* Reference to kernel address from user mode or supervisor mode */ + /* Reference to supervisor address from user mode */ + if (rw == MMU_DATA_STORE) { + exception = EXCP_AdES; + } else { + exception = EXCP_AdEL; + } + break; + case TLBRET_NOMATCH: + /* No TLB match for a mapped address */ + if (rw == MMU_DATA_STORE) { + exception = EXCP_TLBS; + } else { + exception = EXCP_TLBL; + } + error_code |= EXCP_TLB_NOMATCH; + break; + case TLBRET_INVALID: + /* TLB match with no valid bit */ + if (rw == MMU_DATA_STORE) { + exception = EXCP_TLBS; + } else { + exception = EXCP_TLBL; + } + break; + case TLBRET_DIRTY: + /* TLB match but 'D' bit is cleared */ + exception = EXCP_LTLBL; + break; + case TLBRET_XI: + /* Execute-Inhibit Exception */ + exception = EXCP_TLBXI; + break; + case TLBRET_RI: + /* Read-Inhibit Exception */ + exception = EXCP_TLBRI; + break; + case TLBRET_PE: + /* Privileged Exception */ + exception = EXCP_TLBPE; + break; + } + + if (env->insn_flags & INSN_LOONGARCH) { + if (tlb_error == TLBRET_NOMATCH) { + env->CSR_TLBRBADV = address; + env->CSR_TLBREHI = address & (TARGET_PAGE_MASK << 1); + cs->exception_index = exception; + env->error_code = error_code; + return; + } + } + + /* Raise exception */ + env->CSR_BADV = address; + cs->exception_index = exception; + env->error_code = error_code; + + if (env->insn_flags & INSN_LOONGARCH) { + env->CSR_TLBEHI = address & (TARGET_PAGE_MASK << 1); + } +} + +bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; +#if !defined(CONFIG_USER_ONLY) + hwaddr physical; + int prot; + int loongarch_access_type; +#endif + int ret = TLBRET_BADADDR; + + qemu_log_mask(CPU_LOG_MMU, + "%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " mmu_idx %d\n", + __func__, env->active_tc.PC, address, mmu_idx); + + /* data access */ +#if !defined(CONFIG_USER_ONLY) + /* XXX: put correct access by using cpu_restore_state() correctly */ + loongarch_access_type = ACCESS_INT; + ret = get_physical_address(env, &physical, &prot, address, + access_type, loongarch_access_type, mmu_idx); + switch (ret) { + case TLBRET_MATCH: + qemu_log_mask(CPU_LOG_MMU, + "%s address=%" VADDR_PRIx " physical " TARGET_FMT_plx + " prot %d asid %ld pc 0x%lx\n", + __func__, address, physical, prot, + env->CSR_ASID, env->active_tc.PC); + break; + default: + qemu_log_mask(CPU_LOG_MMU, + "%s address=%" VADDR_PRIx " ret %d asid %ld pc 0x%lx\n", + __func__, address, ret, env->CSR_ASID, env->active_tc.PC); + break; + } + if (ret == TLBRET_MATCH) { + tlb_set_page(cs, address & TARGET_PAGE_MASK, + physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, + mmu_idx, TARGET_PAGE_SIZE); + ret = true; + } + if (probe) { + return false; + } +#endif + + raise_mmu_exception(env, address, access_type, ret); + do_raise_exception_err(env, cs->exception_index, env->error_code, retaddr); +} + +#if !defined(CONFIG_USER_ONLY) +hwaddr cpu_loongarch_translate_address(CPULOONGARCHState *env, + target_ulong address, int rw) +{ + hwaddr physical; + int prot; + int access_type; + int ret = 0; + + /* data access */ + access_type = ACCESS_INT; + ret = get_physical_address(env, &physical, &prot, address, rw, access_type, + cpu_mmu_index(env, false)); + if (ret != TLBRET_MATCH) { + raise_mmu_exception(env, address, rw, ret); + return -1LL; + } else { + return physical; + } +} + +static const char * const excp_names[EXCP_LAST + 1] = { + [EXCP_RESET] = "reset", + [EXCP_SRESET] = "soft reset", + [EXCP_NMI] = "non-maskable interrupt", + [EXCP_EXT_INTERRUPT] = "interrupt", + [EXCP_AdEL] = "address error load", + [EXCP_AdES] = "address error store", + [EXCP_TLBF] = "TLB refill", + [EXCP_IBE] = "instruction bus error", + [EXCP_SYSCALL] = "syscall", + [EXCP_BREAK] = "break", + [EXCP_FPDIS] = "float unit unusable", + [EXCP_LSXDIS] = "vector128 unusable", + [EXCP_LASXDIS] = "vector256 unusable", + [EXCP_RI] = "reserved instruction", + [EXCP_OVERFLOW] = "arithmetic overflow", + [EXCP_TRAP] = "trap", + [EXCP_FPE] = "floating point", + [EXCP_LTLBL] = "TLB modify", + [EXCP_TLBL] = "TLB load", + [EXCP_TLBS] = "TLB store", + [EXCP_DBE] = "data bus error", + [EXCP_TLBXI] = "TLB execute-inhibit", + [EXCP_TLBRI] = "TLB read-inhibit", + [EXCP_TLBPE] = "TLB priviledged error", +}; +#endif + +target_ulong exception_resume_pc(CPULOONGARCHState *env) +{ + target_ulong bad_pc; + + bad_pc = env->active_tc.PC; + if (env->hflags & LARCH_HFLAG_BMASK) { + /* If the exception was raised from a delay slot, come back to + the jump. */ + bad_pc -= 4; + } + + return bad_pc; +} + +#if !defined(CONFIG_USER_ONLY) +static void set_hflags_for_handler (CPULOONGARCHState *env) +{ + /* Exception handlers are entered in 32-bit mode. */ +} + +static inline void set_badinstr_registers(CPULOONGARCHState *env) +{ + if ((env->insn_flags & INSN_LOONGARCH)) { + env->CSR_BADI = cpu_ldl_code(env, env->active_tc.PC); + return; + } +} +#endif + +static inline unsigned int get_vint_size(CPULOONGARCHState *env) +{ + unsigned int size = 0; + + switch ((env->CSR_ECFG >> 16) & 0x7) { + case 0: + break; + case 1: + size = 2 * 4; /* #Insts * inst_size */ + break; + case 2: + size = 4 * 4; + break; + case 3: + size = 8 * 4; + break; + case 4: + size = 16 * 4; + break; + case 5: + size = 32 * 4; + break; + case 6: + size = 64 * 4; + break; + case 7: + size = 128 * 4; + break; + default: + printf("%s: unexpected value", __func__); + assert(0); + } + + return size; +} + +#define is_refill(cs, env) (((cs->exception_index == EXCP_TLBL) \ + || (cs->exception_index == EXCP_TLBS)) \ + && (env->error_code & EXCP_TLB_NOMATCH)) + +void loongarch_cpu_do_interrupt(CPUState *cs) +{ +#if !defined(CONFIG_USER_ONLY) + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + bool update_badinstr = 0; + int cause = -1; + const char *name; + + if (qemu_loglevel_mask(CPU_LOG_INT) + && cs->exception_index != EXCP_EXT_INTERRUPT) { + if (cs->exception_index < 0 || cs->exception_index > EXCP_LAST) { + name = "unknown"; + } else { + name = excp_names[cs->exception_index]; + } + + qemu_log("%s enter: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx + " TLBRERA 0x%016lx" " %s exception\n", __func__, + env->active_tc.PC, env->CSR_ERA, env->CSR_TLBRERA, name); + } + + switch (cs->exception_index) { + case EXCP_RESET: + cpu_reset(CPU(cpu)); + break; + case EXCP_NMI: + env->CSR_ERRERA = exception_resume_pc(env); + env->hflags &= ~LARCH_HFLAG_BMASK; + env->hflags |= LARCH_HFLAG_64; + env->hflags &= ~LARCH_HFLAG_AWRAP; + env->hflags &= ~(LARCH_HFLAG_KSU); + env->active_tc.PC = env->exception_base; + set_hflags_for_handler(env); + break; + case EXCP_EXT_INTERRUPT: + cause = 0; + goto set_ERA; + case EXCP_LTLBL: + cause = 1; + update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); + goto set_ERA; + case EXCP_TLBL: + cause = 2; + update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); + goto set_ERA; + case EXCP_TLBS: + cause = 3; + update_badinstr = 1; + goto set_ERA; + case EXCP_AdEL: + cause = 4; + update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); + goto set_ERA; + case EXCP_AdES: + cause = 5; + update_badinstr = 1; + goto set_ERA; + case EXCP_IBE: + cause = 6; + goto set_ERA; + case EXCP_DBE: + cause = 7; + goto set_ERA; + case EXCP_SYSCALL: + cause = 8; + update_badinstr = 1; + goto set_ERA; + case EXCP_BREAK: + cause = 9; + update_badinstr = 1; + goto set_ERA; + case EXCP_RI: + cause = 10; + update_badinstr = 1; + goto set_ERA; + case EXCP_FPDIS: + case EXCP_LSXDIS: + case EXCP_LASXDIS: + cause = 11; + update_badinstr = 1; + goto set_ERA; + case EXCP_OVERFLOW: + cause = 12; + update_badinstr = 1; + goto set_ERA; + case EXCP_TRAP: + cause = 13; + update_badinstr = 1; + goto set_ERA; + case EXCP_FPE: + cause = 15; + update_badinstr = 1; + goto set_ERA; + case EXCP_TLBRI: + cause = 19; + update_badinstr = 1; + goto set_ERA; + case EXCP_TLBXI: + case EXCP_TLBPE: + cause = 20; + goto set_ERA; + set_ERA: + if (is_refill(cs, env)) { + env->CSR_TLBRERA = exception_resume_pc(env); + env->CSR_TLBRERA |= 1; + } else { + env->CSR_ERA = exception_resume_pc(env); + } + + if (update_badinstr) { + set_badinstr_registers(env); + } + env->hflags &= ~(LARCH_HFLAG_KSU); + + env->hflags &= ~LARCH_HFLAG_BMASK; + if (env->insn_flags & INSN_LOONGARCH) { + /* save PLV and IE */ + if (is_refill(cs, env)) { + env->CSR_TLBRPRMD &= (~0x7); + env->CSR_TLBRPRMD |= (env->CSR_CRMD & 0x7); + } else { + env->CSR_PRMD &= (~0x7); + env->CSR_PRMD |= (env->CSR_CRMD & 0x7); + } + + env->CSR_CRMD &= ~(0x7); + + switch (cs->exception_index) { + case EXCP_EXT_INTERRUPT: + break; + case EXCP_TLBL: + if (env->error_code & EXCP_INST_NOTAVAIL) { + cause = EXCCODE_TLBI; + } else { + cause = EXCCODE_TLBL; + } + break; + case EXCP_TLBS: + cause = EXCCODE_TLBS; + break; + case EXCP_LTLBL: + cause = EXCCODE_MOD; + break; + case EXCP_TLBRI: + cause = EXCCODE_TLBRI; + break; + case EXCP_TLBXI: + cause = EXCCODE_TLBXI; + break; + case EXCP_TLBPE: + cause = EXCCODE_TLBPE; + break; + case EXCP_AdEL: + case EXCP_AdES: + case EXCP_IBE: + case EXCP_DBE: + cause = EXCCODE_ADE; + break; + case EXCP_SYSCALL: + cause = EXCCODE_SYS; + break; + case EXCP_BREAK: + cause = EXCCODE_BP; + break; + case EXCP_RI: + cause = EXCCODE_RI; + break; + case EXCP_FPDIS: + cause = EXCCODE_FPDIS; + break; + case EXCP_LSXDIS: + cause = EXCCODE_LSXDIS; + break; + case EXCP_LASXDIS: + cause = EXCCODE_LASXDIS; + break; + case EXCP_FPE: + cause = EXCCODE_FPE; + break; + default: + printf("Error: exception(%d) '%s' has not been supported\n", + cs->exception_index, excp_names[cs->exception_index]); + abort(); + } + + uint32_t vec_size = get_vint_size(env); + env->active_tc.PC = env->CSR_EEPN; + env->active_tc.PC += cause * vec_size; + if (is_refill(cs, env)) { + /* TLB Refill */ + env->active_tc.PC = env->CSR_TLBRENT; + break; /* Do not modify excode */ + } + if (cs->exception_index == EXCP_EXT_INTERRUPT) { + /* Interrupt */ + uint32_t vector = 0; + uint32_t pending = env->CSR_ESTAT & CSR_ESTAT_IPMASK; + pending &= env->CSR_ECFG & CSR_ECFG_IPMASK; + + /* Find the highest-priority interrupt. */ + while (pending >>= 1) { + vector++; + } + env->active_tc.PC = env->CSR_EEPN + + (EXCODE_IP + vector) * vec_size; + if (qemu_loglevel_mask(CPU_LOG_INT)) { + qemu_log("%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx + " cause %d\n" " A " TARGET_FMT_lx " D " + TARGET_FMT_lx " vector = %d ExC %08lx ExS %08lx\n", + __func__, env->active_tc.PC, env->CSR_ERA, + cause, env->CSR_BADV, env->CSR_DERA, vector, + env->CSR_ECFG, env->CSR_ESTAT); + } + } + /* Excode */ + env->CSR_ESTAT = (env->CSR_ESTAT & ~(0x1f << CSR_ESTAT_EXC_SH)) | + (cause << CSR_ESTAT_EXC_SH); + } + set_hflags_for_handler(env); + break; + default: + abort(); + } + if (qemu_loglevel_mask(CPU_LOG_INT) + && cs->exception_index != EXCP_EXT_INTERRUPT) { + qemu_log("%s: PC " TARGET_FMT_lx " ERA 0x%08lx" " cause %d%s\n" + " ESTAT %08lx EXCFG 0x%08lx BADVA 0x%08lx BADI 0x%08lx \ + SYS_NUM %lu cpu %d asid 0x%lx" "\n", + __func__, env->active_tc.PC, + is_refill(cs, env) ? env->CSR_TLBRERA : env->CSR_ERA, + cause, + is_refill(cs, env) ? "(refill)" : "", + env->CSR_ESTAT, env->CSR_ECFG, + is_refill(cs, env) ? env->CSR_TLBRBADV : env->CSR_BADV, + env->CSR_BADI, env->active_tc.gpr[11], cs->cpu_index, + env->CSR_ASID + ); + } +#endif + cs->exception_index = EXCP_NONE; +} + +bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + if (interrupt_request & CPU_INTERRUPT_HARD) { + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + + if (cpu_loongarch_hw_interrupts_enabled(env) && + cpu_loongarch_hw_interrupts_pending(env)) { + /* Raise it */ + cs->exception_index = EXCP_EXT_INTERRUPT; + env->error_code = 0; + loongarch_cpu_do_interrupt(cs); + return true; + } + } + return false; +} + +void QEMU_NORETURN do_raise_exception_err(CPULOONGARCHState *env, + uint32_t exception, + int error_code, + uintptr_t pc) +{ + CPUState *cs = CPU(loongarch_env_get_cpu(env)); + + qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n", + __func__, exception, error_code); + cs->exception_index = exception; + env->error_code = error_code; + + cpu_loop_exit_restore(cs, pc); +} diff --git a/target/loongarch64/helper.h b/target/loongarch64/helper.h new file mode 100644 index 0000000000..ff2026ed82 --- /dev/null +++ b/target/loongarch64/helper.h @@ -0,0 +1,168 @@ +DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) +DEF_HELPER_2(raise_exception, noreturn, env, i32) +DEF_HELPER_1(raise_exception_debug, noreturn, env) + +#if 0 +#ifndef CONFIG_USER_ONLY +DEF_HELPER_3(ll, tl, env, tl, int) +DEF_HELPER_3(lld, tl, env, tl, int) +#endif +#endif + +DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl) + +DEF_HELPER_3(crc32, tl, tl, tl, i32) +DEF_HELPER_3(crc32c, tl, tl, tl, i32) + +#ifndef CONFIG_USER_ONLY +/* LoongISA CSR register */ +DEF_HELPER_2(csr_rdq, tl, env, i64) +DEF_HELPER_3(csr_wrq, tl, env, tl, i64) +DEF_HELPER_4(csr_xchgq, tl, env, tl, tl, i64) + +#endif /* !CONFIG_USER_ONLY */ + +/* CP1 functions */ +DEF_HELPER_2(movfcsr2gr, tl, env, i32) +DEF_HELPER_4(movgr2fcsr, void, env, tl, i32, i32) + +DEF_HELPER_2(float_cvtd_s, i64, env, i32) +DEF_HELPER_2(float_cvtd_w, i64, env, i32) +DEF_HELPER_2(float_cvtd_l, i64, env, i64) +DEF_HELPER_2(float_cvts_d, i32, env, i64) +DEF_HELPER_2(float_cvts_w, i32, env, i32) +DEF_HELPER_2(float_cvts_l, i32, env, i64) + +DEF_HELPER_FLAGS_2(float_class_s, TCG_CALL_NO_RWG_SE, i32, env, i32) +DEF_HELPER_FLAGS_2(float_class_d, TCG_CALL_NO_RWG_SE, i64, env, i64) + +#define FOP_PROTO(op) \ +DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \ +DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64) +FOP_PROTO(maddf) +FOP_PROTO(msubf) +FOP_PROTO(nmaddf) +FOP_PROTO(nmsubf) +#undef FOP_PROTO + +#define FOP_PROTO(op) \ +DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \ +DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64) +FOP_PROTO(max) +FOP_PROTO(maxa) +FOP_PROTO(min) +FOP_PROTO(mina) +#undef FOP_PROTO + +#define FOP_PROTO(op) \ +DEF_HELPER_2(float_ ## op ## _l_s, i64, env, i32) \ +DEF_HELPER_2(float_ ## op ## _l_d, i64, env, i64) \ +DEF_HELPER_2(float_ ## op ## _w_s, i32, env, i32) \ +DEF_HELPER_2(float_ ## op ## _w_d, i32, env, i64) +FOP_PROTO(cvt) +FOP_PROTO(round) +FOP_PROTO(trunc) +FOP_PROTO(ceil) +FOP_PROTO(floor) +#undef FOP_PROTO + +#define FOP_PROTO(op) \ +DEF_HELPER_2(float_ ## op ## _s, i32, env, i32) \ +DEF_HELPER_2(float_ ## op ## _d, i64, env, i64) +FOP_PROTO(sqrt) +FOP_PROTO(rsqrt) +FOP_PROTO(recip) +FOP_PROTO(rint) +#undef FOP_PROTO + +#define FOP_PROTO(op) \ +DEF_HELPER_1(float_ ## op ## _s, i32, i32) \ +DEF_HELPER_1(float_ ## op ## _d, i64, i64) +FOP_PROTO(abs) +FOP_PROTO(chs) +#undef FOP_PROTO + +#define FOP_PROTO(op) \ +DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \ +DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64) +FOP_PROTO(add) +FOP_PROTO(sub) +FOP_PROTO(mul) +FOP_PROTO(div) +#undef FOP_PROTO + +#define FOP_PROTO(op) \ +DEF_HELPER_3(cmp_d_ ## op, i64, env, i64, i64) \ +DEF_HELPER_3(cmp_s_ ## op, i32, env, i32, i32) +FOP_PROTO(af) +FOP_PROTO(un) +FOP_PROTO(eq) +FOP_PROTO(ueq) +FOP_PROTO(lt) +FOP_PROTO(ult) +FOP_PROTO(le) +FOP_PROTO(ule) +FOP_PROTO(saf) +FOP_PROTO(sun) +FOP_PROTO(seq) +FOP_PROTO(sueq) +FOP_PROTO(slt) +FOP_PROTO(sult) +FOP_PROTO(sle) +FOP_PROTO(sule) +FOP_PROTO(or) +FOP_PROTO(une) +FOP_PROTO(ne) +FOP_PROTO(sor) +FOP_PROTO(sune) +FOP_PROTO(sne) +#undef FOP_PROTO + +/* Special functions */ +#ifndef CONFIG_USER_ONLY +DEF_HELPER_1(tlbwr, void, env) +DEF_HELPER_1(tlbfill, void, env) +DEF_HELPER_1(tlbsrch, void, env) +DEF_HELPER_1(tlbrd, void, env) +DEF_HELPER_1(tlbclr, void, env) +DEF_HELPER_1(tlbflush, void, env) +DEF_HELPER_4(invtlb, void, env, tl, tl, tl) +DEF_HELPER_1(ertn, void, env) +DEF_HELPER_5(lddir, void, env, tl, tl, tl, i32) +DEF_HELPER_4(ldpte, void, env, tl, tl, i32) +DEF_HELPER_3(drdtime, void, env, tl, tl) +DEF_HELPER_1(read_pgd, tl, env) +#endif /* !CONFIG_USER_ONLY */ +DEF_HELPER_2(cpucfg, tl, env, tl) +DEF_HELPER_1(idle, void, env) + +DEF_HELPER_3(float_exp2_s, i32, env, i32, i32) +DEF_HELPER_3(float_exp2_d, i64, env, i64, i64) +DEF_HELPER_2(float_logb_s, i32, env, i32) +DEF_HELPER_2(float_logb_d, i64, env, i64) +DEF_HELPER_3(movreg2cf, void, env, i32, tl) +DEF_HELPER_2(movcf2reg, tl, env, i32) +DEF_HELPER_3(movreg2cf_i32, void, env, i32, i32) +DEF_HELPER_3(movreg2cf_i64, void, env, i32, i64) + +DEF_HELPER_2(cto_w, tl, env, tl) +DEF_HELPER_2(ctz_w, tl, env, tl) +DEF_HELPER_2(cto_d, tl, env, tl) +DEF_HELPER_2(ctz_d, tl, env, tl) +DEF_HELPER_2(bitrev_w, tl, env, tl) +DEF_HELPER_2(bitrev_d, tl, env, tl) + +DEF_HELPER_2(load_scr, i64, env, i32) +DEF_HELPER_3(store_scr, void, env, i32, i64) + +DEF_HELPER_3(asrtle_d, void, env, tl, tl) +DEF_HELPER_3(asrtgt_d, void, env, tl, tl) + +DEF_HELPER_4(fsel, i64, env, i64, i64, i32) + +#ifndef CONFIG_USER_ONLY +DEF_HELPER_4(iocsr, void, env, tl, tl, i32) +#endif +DEF_HELPER_3(memtrace_addr, void, env, tl, i32) +DEF_HELPER_2(memtrace_val, void, env, tl) diff --git a/target/loongarch64/insn.decode b/target/loongarch64/insn.decode new file mode 100644 index 0000000000..f194f70116 --- /dev/null +++ b/target/loongarch64/insn.decode @@ -0,0 +1,514 @@ +# Fields +%sd 0:2 +%rj 5:5 +%rd 0:5 +%sj 5:2 +%ptr 5:3 +%rk 10:5 +%sa2 15:2 +%sa3 15:3 +%si5 10:s5 +%code 0:15 +%cond 10:4 +%cond2 0:4 +%ui5 10:5 +%ui6 10:6 +%ui3 10:3 +%ui4 10:4 +%op 5:5 +%ui8 10:8 +%msbw 16:5 +%lsbw 10:5 +%msbd 16:6 +%lsbd 10:6 +%fd 0:5 +%fj 5:5 +%fk 10:5 +%fcsrd 0:5 +%fcsrs 5:5 +%cd 0:3 +%cj 5:3 +%si12 10:s12 +%ui12 10:12 +%csr 10:14 +%cop 0:5 +%level 10:8 +%seq 10:8 +%whint 0:15 +%addr 10:5 +%info 5:5 +%invop 0:5 +%fa 15:5 +%vd 0:5 +%vj 5:5 +%vk 10:5 +%va 15:5 +%xd 0:5 +%xj 5:5 +%xk 10:5 +%xa 15:5 +%fcond 15:5 +%ca 15:3 +%vui5 15:5 +%si16 10:s16 +%si20 5:s20 +%si14 10:s14 +%hint 0:5 +%si9 10:s9 +%si10 10:s10 +%si11 10:s11 +%si8 10:s8 +%idx1 18:1 +%idx2 18:2 +%idx3 18:3 +%idx4 18:4 +%idx 18:5 +%offs21 0:s5 10:16 +%offs16 10:s16 +%offs 0:s10 10:16 +%mode 5:5 +%ui2 10:2 +%ui1 10:1 +%ui7 10:7 +%i13 5:13 + +# Argument sets +&fmt_sdrj sd rj +&fmt_rdsj rd sj +&fmt_rdrj rd rj +&fmt_empty +&fmt_rjrk rj rk +&fmt_rdrjrksa2 rd rj rk sa2 +&fmt_rdrjrksa3 rd rj rk sa3 +&fmt_rdrjrk rd rj rk +&fmt_code code +&fmt_rdrjui5 rd rj ui5 +&fmt_rdrjui6 rd rj ui6 +&fmt_rdrjmsbwlsbw rd rj msbw lsbw +&fmt_rdrjmsbdlsbd rd rj msbd lsbd +&fmt_fdfjfk fd fj fk +&fmt_fdfj fd fj +&fmt_fdrj fd rj +&fmt_rdfj rd fj +&fmt_fcsrdrj fcsrd rj +&fmt_rdfcsrs rd fcsrs +&fmt_cdfj cd fj +&fmt_fdcj fd cj +&fmt_cdrj cd rj +&fmt_rdcj rd cj +&fmt_rdrjsi12 rd rj si12 +&fmt_rdrjui12 rd rj ui12 +&fmt_rdrjcsr rd rj csr +&fmt_coprjsi12 cop rj si12 +&fmt_rdrjlevel rd rj level +&fmt_rjseq rj seq +&fmt_whint whint +&fmt_invtlb addr info invop +&fmt_fdfjfkfa fd fj fk fa +&fmt_cdfjfkfcond cd fj fk fcond +&fmt_fdfjfkca fd fj fk ca +&fmt_rdrjsi16 rd rj si16 +&fmt_rdsi20 rd si20 +&fmt_rdrjsi14 rd rj si14 +&fmt_hintrjsi12 hint rj si12 +&fmt_fdrjsi12 fd rj si12 +&fmt_fdrjrk fd rj rk +&fmt_rjoffs21 rj offs21 +&fmt_cjoffs21 cj offs21 +&fmt_rdrjoffs16 rd rj offs16 +&fmt_offs offs +&fmt_rjrdoffs16 rj rd offs16 + +# Formats +@fmt_sdrj .... ........ ..... ..... ..... ... .. &fmt_sdrj %sd %rj +@fmt_rdsj .... ........ ..... ..... ... .. ..... &fmt_rdsj %rd %sj +@fmt_rdrj .... ........ ..... ..... ..... ..... &fmt_rdrj %rd %rj +@fmt_empty .... ........ ..... ..... ..... ..... &fmt_empty +@fmt_rjrk .... ........ ..... ..... ..... ..... &fmt_rjrk %rj %rk +@fmt_rdrjrksa2 .... ........ ... .. ..... ..... ..... &fmt_rdrjrksa2 %rd %rj %rk %sa2 +@fmt_rdrjrksa3 .... ........ .. ... ..... ..... ..... &fmt_rdrjrksa3 %rd %rj %rk %sa3 +@fmt_rdrjrk .... ........ ..... ..... ..... ..... &fmt_rdrjrk %rd %rj %rk +@fmt_code .... ........ ..... ............... &fmt_code %code +@fmt_rdrjui5 .... ........ ..... ..... ..... ..... &fmt_rdrjui5 %rd %rj %ui5 +@fmt_rdrjui6 .... ........ .... ...... ..... ..... &fmt_rdrjui6 %rd %rj %ui6 +@fmt_rdrjmsbwlsbw .... ....... ..... . ..... ..... ..... &fmt_rdrjmsbwlsbw %rd %rj %msbw %lsbw +@fmt_rdrjmsbdlsbd .... ...... ...... ...... ..... ..... &fmt_rdrjmsbdlsbd %rd %rj %msbd %lsbd +@fmt_fdfjfk .... ........ ..... ..... ..... ..... &fmt_fdfjfk %fd %fj %fk +@fmt_fdfj .... ........ ..... ..... ..... ..... &fmt_fdfj %fd %fj +@fmt_fdrj .... ........ ..... ..... ..... ..... &fmt_fdrj %fd %rj +@fmt_rdfj .... ........ ..... ..... ..... ..... &fmt_rdfj %rd %fj +@fmt_fcsrdrj .... ........ ..... ..... ..... ..... &fmt_fcsrdrj %fcsrd %rj +@fmt_rdfcsrs .... ........ ..... ..... ..... ..... &fmt_rdfcsrs %rd %fcsrs +@fmt_cdfj .... ........ ..... ..... ..... .. ... &fmt_cdfj %cd %fj +@fmt_fdcj .... ........ ..... ..... .. ... ..... &fmt_fdcj %fd %cj +@fmt_cdrj .... ........ ..... ..... ..... .. ... &fmt_cdrj %cd %rj +@fmt_rdcj .... ........ ..... ..... .. ... ..... &fmt_rdcj %rd %cj +@fmt_rdrjsi12 .... ...... ............ ..... ..... &fmt_rdrjsi12 %rd %rj %si12 +@fmt_rdrjui12 .... ...... ............ ..... ..... &fmt_rdrjui12 %rd %rj %ui12 +@fmt_rdrjcsr .... .... .............. ..... ..... &fmt_rdrjcsr %rd %rj %csr +@fmt_coprjsi12 .... ...... ............ ..... ..... &fmt_coprjsi12 %cop %rj %si12 +@fmt_rdrjlevel .... ........ .. ........ ..... ..... &fmt_rdrjlevel %rd %rj %level +@fmt_rjseq .... ........ .. ........ ..... ..... &fmt_rjseq %rj %seq +@fmt_whint .... ........ ..... ............... &fmt_whint %whint +@fmt_invtlb ...... ...... ..... ..... ..... ..... &fmt_invtlb %addr %info %invop +@fmt_fdfjfkfa .... ........ ..... ..... ..... ..... &fmt_fdfjfkfa %fd %fj %fk %fa +@fmt_cdfjfkfcond .... ........ ..... ..... ..... .. ... &fmt_cdfjfkfcond %cd %fj %fk %fcond +@fmt_fdfjfkca .... ........ .. ... ..... ..... ..... &fmt_fdfjfkca %fd %fj %fk %ca +@fmt_rdrjsi16 .... .. ................ ..... ..... &fmt_rdrjsi16 %rd %rj %si16 +@fmt_rdsi20 .... ... .................... ..... &fmt_rdsi20 %rd %si20 +@fmt_rdrjsi14 .... .... .............. ..... ..... &fmt_rdrjsi14 %rd %rj %si14 +@fmt_hintrjsi12 .... ...... ............ ..... ..... &fmt_hintrjsi12 %hint %rj %si12 +@fmt_fdrjsi12 .... ...... ............ ..... ..... &fmt_fdrjsi12 %fd %rj %si12 +@fmt_fdrjrk .... ........ ..... ..... ..... ..... &fmt_fdrjrk %fd %rj %rk +@fmt_rjoffs21 .... .. ................ ..... ..... &fmt_rjoffs21 %rj %offs21 +@fmt_cjoffs21 .... .. ................ .. ... ..... &fmt_cjoffs21 %cj %offs21 +@fmt_rdrjoffs16 .... .. ................ ..... ..... &fmt_rdrjoffs16 %rd %rj %offs16 +@fmt_offs .... .. .......................... &fmt_offs %offs +@fmt_rjrdoffs16 .... .. ................ ..... ..... &fmt_rjrdoffs16 %rj %rd %offs16 + +# Instructions + +# Fiexd point arithmetic Instructions +gr2scr 0000 00000000 00000 00010 ..... 000 .. @fmt_sdrj +scr2gr 0000 00000000 00000 00011 000 .. ..... @fmt_rdsj +clo_w 0000 00000000 00000 00100 ..... ..... @fmt_rdrj +clz_w 0000 00000000 00000 00101 ..... ..... @fmt_rdrj +cto_w 0000 00000000 00000 00110 ..... ..... @fmt_rdrj +ctz_w 0000 00000000 00000 00111 ..... ..... @fmt_rdrj +clo_d 0000 00000000 00000 01000 ..... ..... @fmt_rdrj +clz_d 0000 00000000 00000 01001 ..... ..... @fmt_rdrj +cto_d 0000 00000000 00000 01010 ..... ..... @fmt_rdrj +ctz_d 0000 00000000 00000 01011 ..... ..... @fmt_rdrj +revb_2h 0000 00000000 00000 01100 ..... ..... @fmt_rdrj +revb_4h 0000 00000000 00000 01101 ..... ..... @fmt_rdrj +revb_2w 0000 00000000 00000 01110 ..... ..... @fmt_rdrj +revb_d 0000 00000000 00000 01111 ..... ..... @fmt_rdrj +revh_2w 0000 00000000 00000 10000 ..... ..... @fmt_rdrj +revh_d 0000 00000000 00000 10001 ..... ..... @fmt_rdrj +bitrev_4b 0000 00000000 00000 10010 ..... ..... @fmt_rdrj +bitrev_8b 0000 00000000 00000 10011 ..... ..... @fmt_rdrj +bitrev_w 0000 00000000 00000 10100 ..... ..... @fmt_rdrj +bitrev_d 0000 00000000 00000 10101 ..... ..... @fmt_rdrj +ext_w_h 0000 00000000 00000 10110 ..... ..... @fmt_rdrj +ext_w_b 0000 00000000 00000 10111 ..... ..... @fmt_rdrj +rdtime_d 0000 00000000 00000 11010 ..... ..... @fmt_rdrj +cpucfg 0000 00000000 00000 11011 ..... ..... @fmt_rdrj +asrtle_d 0000 00000000 00010 ..... ..... 00000 @fmt_rjrk +asrtgt_d 0000 00000000 00011 ..... ..... 00000 @fmt_rjrk +alsl_w 0000 00000000 010 .. ..... ..... ..... @fmt_rdrjrksa2 +alsl_wu 0000 00000000 011 .. ..... ..... ..... @fmt_rdrjrksa2 +bytepick_w 0000 00000000 100 .. ..... ..... ..... @fmt_rdrjrksa2 +bytepick_d 0000 00000000 11 ... ..... ..... ..... @fmt_rdrjrksa3 +add_w 0000 00000001 00000 ..... ..... ..... @fmt_rdrjrk +add_d 0000 00000001 00001 ..... ..... ..... @fmt_rdrjrk +sub_w 0000 00000001 00010 ..... ..... ..... @fmt_rdrjrk +sub_d 0000 00000001 00011 ..... ..... ..... @fmt_rdrjrk +slt 0000 00000001 00100 ..... ..... ..... @fmt_rdrjrk +sltu 0000 00000001 00101 ..... ..... ..... @fmt_rdrjrk +maskeqz 0000 00000001 00110 ..... ..... ..... @fmt_rdrjrk +masknez 0000 00000001 00111 ..... ..... ..... @fmt_rdrjrk +nor 0000 00000001 01000 ..... ..... ..... @fmt_rdrjrk +and 0000 00000001 01001 ..... ..... ..... @fmt_rdrjrk +or 0000 00000001 01010 ..... ..... ..... @fmt_rdrjrk +xor 0000 00000001 01011 ..... ..... ..... @fmt_rdrjrk +orn 0000 00000001 01100 ..... ..... ..... @fmt_rdrjrk +andn 0000 00000001 01101 ..... ..... ..... @fmt_rdrjrk +sll_w 0000 00000001 01110 ..... ..... ..... @fmt_rdrjrk +srl_w 0000 00000001 01111 ..... ..... ..... @fmt_rdrjrk +sra_w 0000 00000001 10000 ..... ..... ..... @fmt_rdrjrk +sll_d 0000 00000001 10001 ..... ..... ..... @fmt_rdrjrk +srl_d 0000 00000001 10010 ..... ..... ..... @fmt_rdrjrk +sra_d 0000 00000001 10011 ..... ..... ..... @fmt_rdrjrk +rotr_w 0000 00000001 10110 ..... ..... ..... @fmt_rdrjrk +rotr_d 0000 00000001 10111 ..... ..... ..... @fmt_rdrjrk +mul_w 0000 00000001 11000 ..... ..... ..... @fmt_rdrjrk +mulh_w 0000 00000001 11001 ..... ..... ..... @fmt_rdrjrk +mulh_wu 0000 00000001 11010 ..... ..... ..... @fmt_rdrjrk +mul_d 0000 00000001 11011 ..... ..... ..... @fmt_rdrjrk +mulh_d 0000 00000001 11100 ..... ..... ..... @fmt_rdrjrk +mulh_du 0000 00000001 11101 ..... ..... ..... @fmt_rdrjrk +mulw_d_w 0000 00000001 11110 ..... ..... ..... @fmt_rdrjrk +mulw_d_wu 0000 00000001 11111 ..... ..... ..... @fmt_rdrjrk +div_w 0000 00000010 00000 ..... ..... ..... @fmt_rdrjrk +mod_w 0000 00000010 00001 ..... ..... ..... @fmt_rdrjrk +div_wu 0000 00000010 00010 ..... ..... ..... @fmt_rdrjrk +mod_wu 0000 00000010 00011 ..... ..... ..... @fmt_rdrjrk +div_d 0000 00000010 00100 ..... ..... ..... @fmt_rdrjrk +mod_d 0000 00000010 00101 ..... ..... ..... @fmt_rdrjrk +div_du 0000 00000010 00110 ..... ..... ..... @fmt_rdrjrk +mod_du 0000 00000010 00111 ..... ..... ..... @fmt_rdrjrk +crc_w_b_w 0000 00000010 01000 ..... ..... ..... @fmt_rdrjrk +crc_w_h_w 0000 00000010 01001 ..... ..... ..... @fmt_rdrjrk +crc_w_w_w 0000 00000010 01010 ..... ..... ..... @fmt_rdrjrk +crc_w_d_w 0000 00000010 01011 ..... ..... ..... @fmt_rdrjrk +crcc_w_b_w 0000 00000010 01100 ..... ..... ..... @fmt_rdrjrk +crcc_w_h_w 0000 00000010 01101 ..... ..... ..... @fmt_rdrjrk +crcc_w_w_w 0000 00000010 01110 ..... ..... ..... @fmt_rdrjrk +crcc_w_d_w 0000 00000010 01111 ..... ..... ..... @fmt_rdrjrk +break 0000 00000010 10100 ............... @fmt_code +dbcl 0000 00000010 10101 ............... @fmt_code +syscall 0000 00000010 10110 ............... @fmt_code +alsl_d 0000 00000010 110 .. ..... ..... ..... @fmt_rdrjrksa2 +slli_w 0000 00000100 00001 ..... ..... ..... @fmt_rdrjui5 +slli_d 0000 00000100 0001 ...... ..... ..... @fmt_rdrjui6 +srli_w 0000 00000100 01001 ..... ..... ..... @fmt_rdrjui5 +srli_d 0000 00000100 0101 ...... ..... ..... @fmt_rdrjui6 +srai_w 0000 00000100 10001 ..... ..... ..... @fmt_rdrjui5 +srai_d 0000 00000100 1001 ...... ..... ..... @fmt_rdrjui6 +rotri_w 0000 00000100 11001 ..... ..... ..... @fmt_rdrjui5 +rotri_d 0000 00000100 1101 ...... ..... ..... @fmt_rdrjui6 +bstrins_w 0000 0000011 ..... 0 ..... ..... ..... @fmt_rdrjmsbwlsbw +bstrpick_w 0000 0000011 ..... 1 ..... ..... ..... @fmt_rdrjmsbwlsbw +bstrins_d 0000 000010 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd +bstrpick_d 0000 000011 ...... ...... ..... ..... @fmt_rdrjmsbdlsbd + +# float Instructions +fadd_s 0000 00010000 00001 ..... ..... ..... @fmt_fdfjfk +fadd_d 0000 00010000 00010 ..... ..... ..... @fmt_fdfjfk +fsub_s 0000 00010000 00101 ..... ..... ..... @fmt_fdfjfk +fsub_d 0000 00010000 00110 ..... ..... ..... @fmt_fdfjfk +fmul_s 0000 00010000 01001 ..... ..... ..... @fmt_fdfjfk +fmul_d 0000 00010000 01010 ..... ..... ..... @fmt_fdfjfk +fdiv_s 0000 00010000 01101 ..... ..... ..... @fmt_fdfjfk +fdiv_d 0000 00010000 01110 ..... ..... ..... @fmt_fdfjfk +fmax_s 0000 00010000 10001 ..... ..... ..... @fmt_fdfjfk +fmax_d 0000 00010000 10010 ..... ..... ..... @fmt_fdfjfk +fmin_s 0000 00010000 10101 ..... ..... ..... @fmt_fdfjfk +fmin_d 0000 00010000 10110 ..... ..... ..... @fmt_fdfjfk +fmaxa_s 0000 00010000 11001 ..... ..... ..... @fmt_fdfjfk +fmaxa_d 0000 00010000 11010 ..... ..... ..... @fmt_fdfjfk +fmina_s 0000 00010000 11101 ..... ..... ..... @fmt_fdfjfk +fmina_d 0000 00010000 11110 ..... ..... ..... @fmt_fdfjfk +fscaleb_s 0000 00010001 00001 ..... ..... ..... @fmt_fdfjfk +fscaleb_d 0000 00010001 00010 ..... ..... ..... @fmt_fdfjfk +fcopysign_s 0000 00010001 00101 ..... ..... ..... @fmt_fdfjfk +fcopysign_d 0000 00010001 00110 ..... ..... ..... @fmt_fdfjfk +fabs_s 0000 00010001 01000 00001 ..... ..... @fmt_fdfj +fabs_d 0000 00010001 01000 00010 ..... ..... @fmt_fdfj +fneg_s 0000 00010001 01000 00101 ..... ..... @fmt_fdfj +fneg_d 0000 00010001 01000 00110 ..... ..... @fmt_fdfj +flogb_s 0000 00010001 01000 01001 ..... ..... @fmt_fdfj +flogb_d 0000 00010001 01000 01010 ..... ..... @fmt_fdfj +fclass_s 0000 00010001 01000 01101 ..... ..... @fmt_fdfj +fclass_d 0000 00010001 01000 01110 ..... ..... @fmt_fdfj +fsqrt_s 0000 00010001 01000 10001 ..... ..... @fmt_fdfj +fsqrt_d 0000 00010001 01000 10010 ..... ..... @fmt_fdfj +frecip_s 0000 00010001 01000 10101 ..... ..... @fmt_fdfj +frecip_d 0000 00010001 01000 10110 ..... ..... @fmt_fdfj +frsqrt_s 0000 00010001 01000 11001 ..... ..... @fmt_fdfj +frsqrt_d 0000 00010001 01000 11010 ..... ..... @fmt_fdfj +fmov_s 0000 00010001 01001 00101 ..... ..... @fmt_fdfj +fmov_d 0000 00010001 01001 00110 ..... ..... @fmt_fdfj +movgr2fr_w 0000 00010001 01001 01001 ..... ..... @fmt_fdrj +movgr2fr_d 0000 00010001 01001 01010 ..... ..... @fmt_fdrj +movgr2frh_w 0000 00010001 01001 01011 ..... ..... @fmt_fdrj +movfr2gr_s 0000 00010001 01001 01101 ..... ..... @fmt_rdfj +movfr2gr_d 0000 00010001 01001 01110 ..... ..... @fmt_rdfj +movfrh2gr_s 0000 00010001 01001 01111 ..... ..... @fmt_rdfj +movgr2fcsr 0000 00010001 01001 10000 ..... ..... @fmt_fcsrdrj +movfcsr2gr 0000 00010001 01001 10010 ..... ..... @fmt_rdfcsrs +movfr2cf 0000 00010001 01001 10100 ..... 00 ... @fmt_cdfj +movcf2fr 0000 00010001 01001 10101 00 ... ..... @fmt_fdcj +movgr2cf 0000 00010001 01001 10110 ..... 00 ... @fmt_cdrj +movcf2gr 0000 00010001 01001 10111 00 ... ..... @fmt_rdcj +fcvt_s_d 0000 00010001 10010 00110 ..... ..... @fmt_fdfj +fcvt_d_s 0000 00010001 10010 01001 ..... ..... @fmt_fdfj +ftintrm_w_s 0000 00010001 10100 00001 ..... ..... @fmt_fdfj +ftintrm_w_d 0000 00010001 10100 00010 ..... ..... @fmt_fdfj +ftintrm_l_s 0000 00010001 10100 01001 ..... ..... @fmt_fdfj +ftintrm_l_d 0000 00010001 10100 01010 ..... ..... @fmt_fdfj +ftintrp_w_s 0000 00010001 10100 10001 ..... ..... @fmt_fdfj +ftintrp_w_d 0000 00010001 10100 10010 ..... ..... @fmt_fdfj +ftintrp_l_s 0000 00010001 10100 11001 ..... ..... @fmt_fdfj +ftintrp_l_d 0000 00010001 10100 11010 ..... ..... @fmt_fdfj +ftintrz_w_s 0000 00010001 10101 00001 ..... ..... @fmt_fdfj +ftintrz_w_d 0000 00010001 10101 00010 ..... ..... @fmt_fdfj +ftintrz_l_s 0000 00010001 10101 01001 ..... ..... @fmt_fdfj +ftintrz_l_d 0000 00010001 10101 01010 ..... ..... @fmt_fdfj +ftintrne_w_s 0000 00010001 10101 10001 ..... ..... @fmt_fdfj +ftintrne_w_d 0000 00010001 10101 10010 ..... ..... @fmt_fdfj +ftintrne_l_s 0000 00010001 10101 11001 ..... ..... @fmt_fdfj +ftintrne_l_d 0000 00010001 10101 11010 ..... ..... @fmt_fdfj +ftint_w_s 0000 00010001 10110 00001 ..... ..... @fmt_fdfj +ftint_w_d 0000 00010001 10110 00010 ..... ..... @fmt_fdfj +ftint_l_s 0000 00010001 10110 01001 ..... ..... @fmt_fdfj +ftint_l_d 0000 00010001 10110 01010 ..... ..... @fmt_fdfj +ffint_s_w 0000 00010001 11010 00100 ..... ..... @fmt_fdfj +ffint_s_l 0000 00010001 11010 00110 ..... ..... @fmt_fdfj +ffint_d_w 0000 00010001 11010 01000 ..... ..... @fmt_fdfj +ffint_d_l 0000 00010001 11010 01010 ..... ..... @fmt_fdfj +frint_s 0000 00010001 11100 10001 ..... ..... @fmt_fdfj +frint_d 0000 00010001 11100 10010 ..... ..... @fmt_fdfj + +# 12 bit immediate Instructions +slti 0000 001000 ............ ..... ..... @fmt_rdrjsi12 +sltui 0000 001001 ............ ..... ..... @fmt_rdrjsi12 +addi_w 0000 001010 ............ ..... ..... @fmt_rdrjsi12 +addi_d 0000 001011 ............ ..... ..... @fmt_rdrjsi12 +lu52i_d 0000 001100 ............ ..... ..... @fmt_rdrjsi12 +andi 0000 001101 ............ ..... ..... @fmt_rdrjui12 +ori 0000 001110 ............ ..... ..... @fmt_rdrjui12 +xori 0000 001111 ............ ..... ..... @fmt_rdrjui12 + +# core Instructions +csrxchg 0000 0100 .............. ..... ..... @fmt_rdrjcsr +cacop 0000 011000 ............ ..... ..... @fmt_coprjsi12 +lddir 0000 01100100 00 ........ ..... ..... @fmt_rdrjlevel +ldpte 0000 01100100 01 ........ ..... 00000 @fmt_rjseq +iocsrrd_b 0000 01100100 10000 00000 ..... ..... @fmt_rdrj +iocsrrd_h 0000 01100100 10000 00001 ..... ..... @fmt_rdrj +iocsrrd_w 0000 01100100 10000 00010 ..... ..... @fmt_rdrj +iocsrrd_d 0000 01100100 10000 00011 ..... ..... @fmt_rdrj +iocsrwr_b 0000 01100100 10000 00100 ..... ..... @fmt_rdrj +iocsrwr_h 0000 01100100 10000 00101 ..... ..... @fmt_rdrj +iocsrwr_w 0000 01100100 10000 00110 ..... ..... @fmt_rdrj +iocsrwr_d 0000 01100100 10000 00111 ..... ..... @fmt_rdrj +tlbclr 0000 01100100 10000 01000 00000 00000 @fmt_empty +tlbflush 0000 01100100 10000 01001 00000 00000 @fmt_empty +tlbsrch 0000 01100100 10000 01010 00000 00000 @fmt_empty +tlbrd 0000 01100100 10000 01011 00000 00000 @fmt_empty +tlbwr 0000 01100100 10000 01100 00000 00000 @fmt_empty +tlbfill 0000 01100100 10000 01101 00000 00000 @fmt_empty +ertn 0000 01100100 10000 01110 00000 00000 @fmt_empty +idle 0000 01100100 10001 ............... @fmt_whint +invtlb 0000 01100100 10011 ..... ..... ..... @fmt_invtlb + +# foure Op Instructions +fmadd_s 0000 10000001 ..... ..... ..... ..... @fmt_fdfjfkfa +fmadd_d 0000 10000010 ..... ..... ..... ..... @fmt_fdfjfkfa +fmsub_s 0000 10000101 ..... ..... ..... ..... @fmt_fdfjfkfa +fmsub_d 0000 10000110 ..... ..... ..... ..... @fmt_fdfjfkfa +fnmadd_s 0000 10001001 ..... ..... ..... ..... @fmt_fdfjfkfa +fnmadd_d 0000 10001010 ..... ..... ..... ..... @fmt_fdfjfkfa +fnmsub_s 0000 10001101 ..... ..... ..... ..... @fmt_fdfjfkfa +fnmsub_d 0000 10001110 ..... ..... ..... ..... @fmt_fdfjfkfa +fcmp_cond_s 0000 11000001 ..... ..... ..... 00 ... @fmt_cdfjfkfcond +fcmp_cond_d 0000 11000010 ..... ..... ..... 00 ... @fmt_cdfjfkfcond +fsel 0000 11010000 00 ... ..... ..... ..... @fmt_fdfjfkca + +# loog immediate Instructions +addu16i_d 0001 00 ................ ..... ..... @fmt_rdrjsi16 +lu12i_w 0001 010 .................... ..... @fmt_rdsi20 +lu32i_d 0001 011 .................... ..... @fmt_rdsi20 +pcaddi 0001 100 .................... ..... @fmt_rdsi20 +pcalau12i 0001 101 .................... ..... @fmt_rdsi20 +pcaddu12i 0001 110 .................... ..... @fmt_rdsi20 +pcaddu18i 0001 111 .................... ..... @fmt_rdsi20 + +# load/store Instructions +ll_w 0010 0000 .............. ..... ..... @fmt_rdrjsi14 +sc_w 0010 0001 .............. ..... ..... @fmt_rdrjsi14 +ll_d 0010 0010 .............. ..... ..... @fmt_rdrjsi14 +sc_d 0010 0011 .............. ..... ..... @fmt_rdrjsi14 +ldptr_w 0010 0100 .............. ..... ..... @fmt_rdrjsi14 +stptr_w 0010 0101 .............. ..... ..... @fmt_rdrjsi14 +ldptr_d 0010 0110 .............. ..... ..... @fmt_rdrjsi14 +stptr_d 0010 0111 .............. ..... ..... @fmt_rdrjsi14 +ld_b 0010 100000 ............ ..... ..... @fmt_rdrjsi12 +ld_h 0010 100001 ............ ..... ..... @fmt_rdrjsi12 +ld_w 0010 100010 ............ ..... ..... @fmt_rdrjsi12 +ld_d 0010 100011 ............ ..... ..... @fmt_rdrjsi12 +st_b 0010 100100 ............ ..... ..... @fmt_rdrjsi12 +st_h 0010 100101 ............ ..... ..... @fmt_rdrjsi12 +st_w 0010 100110 ............ ..... ..... @fmt_rdrjsi12 +st_d 0010 100111 ............ ..... ..... @fmt_rdrjsi12 +ld_bu 0010 101000 ............ ..... ..... @fmt_rdrjsi12 +ld_hu 0010 101001 ............ ..... ..... @fmt_rdrjsi12 +ld_wu 0010 101010 ............ ..... ..... @fmt_rdrjsi12 +preld 0010 101011 ............ ..... ..... @fmt_hintrjsi12 +fld_s 0010 101100 ............ ..... ..... @fmt_fdrjsi12 +fst_s 0010 101101 ............ ..... ..... @fmt_fdrjsi12 +fld_d 0010 101110 ............ ..... ..... @fmt_fdrjsi12 +fst_d 0010 101111 ............ ..... ..... @fmt_fdrjsi12 +ldx_b 0011 10000000 00000 ..... ..... ..... @fmt_rdrjrk +ldx_h 0011 10000000 01000 ..... ..... ..... @fmt_rdrjrk +ldx_w 0011 10000000 10000 ..... ..... ..... @fmt_rdrjrk +ldx_d 0011 10000000 11000 ..... ..... ..... @fmt_rdrjrk +stx_b 0011 10000001 00000 ..... ..... ..... @fmt_rdrjrk +stx_h 0011 10000001 01000 ..... ..... ..... @fmt_rdrjrk +stx_w 0011 10000001 10000 ..... ..... ..... @fmt_rdrjrk +stx_d 0011 10000001 11000 ..... ..... ..... @fmt_rdrjrk +ldx_bu 0011 10000010 00000 ..... ..... ..... @fmt_rdrjrk +ldx_hu 0011 10000010 01000 ..... ..... ..... @fmt_rdrjrk +ldx_wu 0011 10000010 10000 ..... ..... ..... @fmt_rdrjrk +fldx_s 0011 10000011 00000 ..... ..... ..... @fmt_fdrjrk +fldx_d 0011 10000011 01000 ..... ..... ..... @fmt_fdrjrk +fstx_s 0011 10000011 10000 ..... ..... ..... @fmt_fdrjrk +fstx_d 0011 10000011 11000 ..... ..... ..... @fmt_fdrjrk +amswap_w 0011 10000110 00000 ..... ..... ..... @fmt_rdrjrk +amswap_d 0011 10000110 00001 ..... ..... ..... @fmt_rdrjrk +amadd_w 0011 10000110 00010 ..... ..... ..... @fmt_rdrjrk +amadd_d 0011 10000110 00011 ..... ..... ..... @fmt_rdrjrk +amand_w 0011 10000110 00100 ..... ..... ..... @fmt_rdrjrk +amand_d 0011 10000110 00101 ..... ..... ..... @fmt_rdrjrk +amor_w 0011 10000110 00110 ..... ..... ..... @fmt_rdrjrk +amor_d 0011 10000110 00111 ..... ..... ..... @fmt_rdrjrk +amxor_w 0011 10000110 01000 ..... ..... ..... @fmt_rdrjrk +amxor_d 0011 10000110 01001 ..... ..... ..... @fmt_rdrjrk +ammax_w 0011 10000110 01010 ..... ..... ..... @fmt_rdrjrk +ammax_d 0011 10000110 01011 ..... ..... ..... @fmt_rdrjrk +ammin_w 0011 10000110 01100 ..... ..... ..... @fmt_rdrjrk +ammin_d 0011 10000110 01101 ..... ..... ..... @fmt_rdrjrk +ammax_wu 0011 10000110 01110 ..... ..... ..... @fmt_rdrjrk +ammax_du 0011 10000110 01111 ..... ..... ..... @fmt_rdrjrk +ammin_wu 0011 10000110 10000 ..... ..... ..... @fmt_rdrjrk +ammin_du 0011 10000110 10001 ..... ..... ..... @fmt_rdrjrk +amswap_db_w 0011 10000110 10010 ..... ..... ..... @fmt_rdrjrk +amswap_db_d 0011 10000110 10011 ..... ..... ..... @fmt_rdrjrk +amadd_db_w 0011 10000110 10100 ..... ..... ..... @fmt_rdrjrk +amadd_db_d 0011 10000110 10101 ..... ..... ..... @fmt_rdrjrk +amand_db_w 0011 10000110 10110 ..... ..... ..... @fmt_rdrjrk +amand_db_d 0011 10000110 10111 ..... ..... ..... @fmt_rdrjrk +amor_db_w 0011 10000110 11000 ..... ..... ..... @fmt_rdrjrk +amor_db_d 0011 10000110 11001 ..... ..... ..... @fmt_rdrjrk +amxor_db_w 0011 10000110 11010 ..... ..... ..... @fmt_rdrjrk +amxor_db_d 0011 10000110 11011 ..... ..... ..... @fmt_rdrjrk +ammax_db_w 0011 10000110 11100 ..... ..... ..... @fmt_rdrjrk +ammax_db_d 0011 10000110 11101 ..... ..... ..... @fmt_rdrjrk +ammin_db_w 0011 10000110 11110 ..... ..... ..... @fmt_rdrjrk +ammin_db_d 0011 10000110 11111 ..... ..... ..... @fmt_rdrjrk +ammax_db_wu 0011 10000111 00000 ..... ..... ..... @fmt_rdrjrk +ammax_db_du 0011 10000111 00001 ..... ..... ..... @fmt_rdrjrk +ammin_db_wu 0011 10000111 00010 ..... ..... ..... @fmt_rdrjrk +ammin_db_du 0011 10000111 00011 ..... ..... ..... @fmt_rdrjrk +dbar 0011 10000111 00100 ............... @fmt_whint +ibar 0011 10000111 00101 ............... @fmt_whint +fldgt_s 0011 10000111 01000 ..... ..... ..... @fmt_fdrjrk +fldgt_d 0011 10000111 01001 ..... ..... ..... @fmt_fdrjrk +fldle_s 0011 10000111 01010 ..... ..... ..... @fmt_fdrjrk +fldle_d 0011 10000111 01011 ..... ..... ..... @fmt_fdrjrk +fstgt_s 0011 10000111 01100 ..... ..... ..... @fmt_fdrjrk +fstgt_d 0011 10000111 01101 ..... ..... ..... @fmt_fdrjrk +fstle_s 0011 10000111 01110 ..... ..... ..... @fmt_fdrjrk +fstle_d 0011 10000111 01111 ..... ..... ..... @fmt_fdrjrk +ldgt_b 0011 10000111 10000 ..... ..... ..... @fmt_rdrjrk +ldgt_h 0011 10000111 10001 ..... ..... ..... @fmt_rdrjrk +ldgt_w 0011 10000111 10010 ..... ..... ..... @fmt_rdrjrk +ldgt_d 0011 10000111 10011 ..... ..... ..... @fmt_rdrjrk +ldle_b 0011 10000111 10100 ..... ..... ..... @fmt_rdrjrk +ldle_h 0011 10000111 10101 ..... ..... ..... @fmt_rdrjrk +ldle_w 0011 10000111 10110 ..... ..... ..... @fmt_rdrjrk +ldle_d 0011 10000111 10111 ..... ..... ..... @fmt_rdrjrk +stgt_b 0011 10000111 11000 ..... ..... ..... @fmt_rdrjrk +stgt_h 0011 10000111 11001 ..... ..... ..... @fmt_rdrjrk +stgt_w 0011 10000111 11010 ..... ..... ..... @fmt_rdrjrk +stgt_d 0011 10000111 11011 ..... ..... ..... @fmt_rdrjrk +stle_b 0011 10000111 11100 ..... ..... ..... @fmt_rdrjrk +stle_h 0011 10000111 11101 ..... ..... ..... @fmt_rdrjrk +stle_w 0011 10000111 11110 ..... ..... ..... @fmt_rdrjrk +stle_d 0011 10000111 11111 ..... ..... ..... @fmt_rdrjrk + +# jump Instructions +beqz 0100 00 ................ ..... ..... @fmt_rjoffs21 +bnez 0100 01 ................ ..... ..... @fmt_rjoffs21 +bceqz 0100 10 ................ 00 ... ..... @fmt_cjoffs21 +bcnez 0100 10 ................ 01 ... ..... @fmt_cjoffs21 +jirl 0100 11 ................ ..... ..... @fmt_rdrjoffs16 +b 0101 00 .......................... @fmt_offs +bl 0101 01 .......................... @fmt_offs +beq 0101 10 ................ ..... ..... @fmt_rjrdoffs16 +bne 0101 11 ................ ..... ..... @fmt_rjrdoffs16 +blt 0110 00 ................ ..... ..... @fmt_rjrdoffs16 +bge 0110 01 ................ ..... ..... @fmt_rjrdoffs16 +bltu 0110 10 ................ ..... ..... @fmt_rjrdoffs16 +bgeu 0110 11 ................ ..... ..... @fmt_rjrdoffs16 diff --git a/target/loongarch64/instmap.h b/target/loongarch64/instmap.h new file mode 100644 index 0000000000..6e85847f8a --- /dev/null +++ b/target/loongarch64/instmap.h @@ -0,0 +1,216 @@ +/* + * Loongarch emulation for qemu: instruction opcode + * + * Copyright (c) 2020-2021 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef TARGET_LARCH_INSTMAP_H +#define TARGET_LARCH_INSTMAP_H + +enum { + /* fix opcodes */ + OPC_LARCH_CLO_W = (0x000004 << 10), + OPC_LARCH_CLZ_W = (0x000005 << 10), + OPC_LARCH_CLO_D = (0x000008 << 10), + OPC_LARCH_CLZ_D = (0x000009 << 10), + OPC_LARCH_REVB_2H = (0x00000C << 10), + OPC_LARCH_REVB_4H = (0x00000D << 10), + OPC_LARCH_REVH_D = (0x000011 << 10), + OPC_LARCH_BREV_4B = (0x000012 << 10), + OPC_LARCH_BREV_8B = (0x000013 << 10), + OPC_LARCH_EXT_WH = (0x000016 << 10), + OPC_LARCH_EXT_WB = (0x000017 << 10), + + OPC_LARCH_ADD_W = (0x00020 << 15), + OPC_LARCH_ADD_D = (0x00021 << 15), + OPC_LARCH_SUB_W = (0x00022 << 15), + OPC_LARCH_SUB_D = (0x00023 << 15), + OPC_LARCH_SLT = (0x00024 << 15), + OPC_LARCH_SLTU = (0x00025 << 15), + OPC_LARCH_MASKEQZ = (0x00026 << 15), + OPC_LARCH_MASKNEZ = (0x00027 << 15), + OPC_LARCH_NOR = (0x00028 << 15), + OPC_LARCH_AND = (0x00029 << 15), + OPC_LARCH_OR = (0x0002A << 15), + OPC_LARCH_XOR = (0x0002B << 15), + OPC_LARCH_SLL_W = (0x0002E << 15), + OPC_LARCH_SRL_W = (0x0002F << 15), + OPC_LARCH_SRA_W = (0x00030 << 15), + OPC_LARCH_SLL_D = (0x00031 << 15), + OPC_LARCH_SRL_D = (0x00032 << 15), + OPC_LARCH_SRA_D = (0x00033 << 15), + OPC_LARCH_ROTR_W = (0x00036 << 15), + OPC_LARCH_ROTR_D = (0x00037 << 15), + OPC_LARCH_MUL_W = (0x00038 << 15), + OPC_LARCH_MULH_W = (0x00039 << 15), + OPC_LARCH_MULH_WU = (0x0003A << 15), + OPC_LARCH_MUL_D = (0x0003B << 15), + OPC_LARCH_MULH_D = (0x0003C << 15), + OPC_LARCH_MULH_DU = (0x0003D << 15), + OPC_LARCH_DIV_W = (0x00040 << 15), + OPC_LARCH_MOD_W = (0x00041 << 15), + OPC_LARCH_DIV_WU = (0x00042 << 15), + OPC_LARCH_MOD_WU = (0x00043 << 15), + OPC_LARCH_DIV_D = (0x00044 << 15), + OPC_LARCH_MOD_D = (0x00045 << 15), + OPC_LARCH_DIV_DU = (0x00046 << 15), + OPC_LARCH_MOD_DU = (0x00047 << 15), + OPC_LARCH_SRLI_W = (0x00089 << 15), + OPC_LARCH_SRAI_W = (0x00091 << 15), + OPC_LARCH_ROTRI_W = (0x00099 << 15), + + OPC_LARCH_ALSL_W = (0x0002 << 17), + OPC_LARCH_ALSL_D = (0x0016 << 17), + + OPC_LARCH_TRINS_W = (0x003 << 21) | (0x0 << 15), + OPC_LARCH_TRPICK_W = (0x003 << 21) | (0x1 << 15), +}; + +enum { + /* float opcodes */ + OPC_LARCH_FABS_S = (0x004501 << 10), + OPC_LARCH_FABS_D = (0x004502 << 10), + OPC_LARCH_FNEG_S = (0x004505 << 10), + OPC_LARCH_FNEG_D = (0x004506 << 10), + OPC_LARCH_FCLASS_S = (0x00450D << 10), + OPC_LARCH_FCLASS_D = (0x00450E << 10), + OPC_LARCH_FSQRT_S = (0x004511 << 10), + OPC_LARCH_FSQRT_D = (0x004512 << 10), + OPC_LARCH_FRECIP_S = (0x004515 << 10), + OPC_LARCH_FRECIP_D = (0x004516 << 10), + OPC_LARCH_FRSQRT_S = (0x004519 << 10), + OPC_LARCH_FRSQRT_D = (0x00451A << 10), + OPC_LARCH_FMOV_S = (0x004525 << 10), + OPC_LARCH_FMOV_D = (0x004526 << 10), + OPC_LARCH_GR2FR_W = (0x004529 << 10), + OPC_LARCH_GR2FR_D = (0x00452A << 10), + OPC_LARCH_GR2FRH_W = (0x00452B << 10), + OPC_LARCH_FR2GR_S = (0x00452D << 10), + OPC_LARCH_FR2GR_D = (0x00452E << 10), + OPC_LARCH_FRH2GR_S = (0x00452F << 10), + + OPC_LARCH_FCVT_S_D = (0x004646 << 10), + OPC_LARCH_FCVT_D_S = (0x004649 << 10), + OPC_LARCH_FTINTRM_W_S = (0x004681 << 10), + OPC_LARCH_FTINTRM_W_D = (0x004682 << 10), + OPC_LARCH_FTINTRM_L_S = (0x004689 << 10), + OPC_LARCH_FTINTRM_L_D = (0x00468A << 10), + OPC_LARCH_FTINTRP_W_S = (0x004691 << 10), + OPC_LARCH_FTINTRP_W_D = (0x004692 << 10), + OPC_LARCH_FTINTRP_L_S = (0x004699 << 10), + OPC_LARCH_FTINTRP_L_D = (0x00469A << 10), + OPC_LARCH_FTINTRZ_W_S = (0x0046A1 << 10), + OPC_LARCH_FTINTRZ_W_D = (0x0046A2 << 10), + OPC_LARCH_FTINTRZ_L_S = (0x0046A9 << 10), + OPC_LARCH_FTINTRZ_L_D = (0x0046AA << 10), + OPC_LARCH_FTINTRNE_W_S = (0x0046B1 << 10), + OPC_LARCH_FTINTRNE_W_D = (0x0046B2 << 10), + OPC_LARCH_FTINTRNE_L_S = (0x0046B9 << 10), + OPC_LARCH_FTINTRNE_L_D = (0x0046BA << 10), + OPC_LARCH_FTINT_W_S = (0x0046C1 << 10), + OPC_LARCH_FTINT_W_D = (0x0046C2 << 10), + OPC_LARCH_FTINT_L_S = (0x0046C9 << 10), + OPC_LARCH_FTINT_L_D = (0x0046CA << 10), + OPC_LARCH_FFINT_S_W = (0x004744 << 10), + OPC_LARCH_FFINT_S_L = (0x004746 << 10), + OPC_LARCH_FFINT_D_W = (0x004748 << 10), + OPC_LARCH_FFINT_D_L = (0x00474A << 10), + OPC_LARCH_FRINT_S = (0x004791 << 10), + OPC_LARCH_FRINT_D = (0x004792 << 10), + + OPC_LARCH_FADD_S = (0x00201 << 15), + OPC_LARCH_FADD_D = (0x00202 << 15), + OPC_LARCH_FSUB_S = (0x00205 << 15), + OPC_LARCH_FSUB_D = (0x00206 << 15), + OPC_LARCH_FMUL_S = (0x00209 << 15), + OPC_LARCH_FMUL_D = (0x0020A << 15), + OPC_LARCH_FDIV_S = (0x0020D << 15), + OPC_LARCH_FDIV_D = (0x0020E << 15), + OPC_LARCH_FMAX_S = (0x00211 << 15), + OPC_LARCH_FMAX_D = (0x00212 << 15), + OPC_LARCH_FMIN_S = (0x00215 << 15), + OPC_LARCH_FMIN_D = (0x00216 << 15), + OPC_LARCH_FMAXA_S = (0x00219 << 15), + OPC_LARCH_FMAXA_D = (0x0021A << 15), + OPC_LARCH_FMINA_S = (0x0021D << 15), + OPC_LARCH_FMINA_D = (0x0021E << 15), +}; + +enum { + /* 12 bit immediate opcodes */ + OPC_LARCH_SLTI = (0x008 << 22), + OPC_LARCH_SLTIU = (0x009 << 22), + OPC_LARCH_ADDI_W = (0x00A << 22), + OPC_LARCH_ADDI_D = (0x00B << 22), + OPC_LARCH_ANDI = (0x00D << 22), + OPC_LARCH_ORI = (0x00E << 22), + OPC_LARCH_XORI = (0x00F << 22), +}; + +enum { + /* load/store opcodes */ + OPC_LARCH_FLDX_S = (0x07060 << 15), + OPC_LARCH_FLDX_D = (0x07068 << 15), + OPC_LARCH_FSTX_S = (0x07070 << 15), + OPC_LARCH_FSTX_D = (0x07078 << 15), + OPC_LARCH_FLDGT_S = (0x070E8 << 15), + OPC_LARCH_FLDGT_D = (0x070E9 << 15), + OPC_LARCH_FLDLE_S = (0x070EA << 15), + OPC_LARCH_FLDLE_D = (0x070EB << 15), + OPC_LARCH_FSTGT_S = (0x070EC << 15), + OPC_LARCH_FSTGT_D = (0x070ED << 15), + OPC_LARCH_FSTLE_S = (0x070EE << 15), + OPC_LARCH_FSTLE_D = (0x070EF << 15), + + OPC_LARCH_LD_B = (0x0A0 << 22), + OPC_LARCH_LD_H = (0x0A1 << 22), + OPC_LARCH_LD_W = (0x0A2 << 22), + OPC_LARCH_LD_D = (0x0A3 << 22), + OPC_LARCH_ST_B = (0x0A4 << 22), + OPC_LARCH_ST_H = (0x0A5 << 22), + OPC_LARCH_ST_W = (0x0A6 << 22), + OPC_LARCH_ST_D = (0x0A7 << 22), + OPC_LARCH_LD_BU = (0x0A8 << 22), + OPC_LARCH_LD_HU = (0x0A9 << 22), + OPC_LARCH_LD_WU = (0x0AA << 22), + OPC_LARCH_FLD_S = (0x0AC << 22), + OPC_LARCH_FST_S = (0x0AD << 22), + OPC_LARCH_FLD_D = (0x0AE << 22), + OPC_LARCH_FST_D = (0x0AF << 22), + + OPC_LARCH_LL_W = (0x20 << 24), + OPC_LARCH_SC_W = (0x21 << 24), + OPC_LARCH_LL_D = (0x22 << 24), + OPC_LARCH_SC_D = (0x23 << 24), + OPC_LARCH_LDPTR_W = (0x24 << 24), + OPC_LARCH_STPTR_W = (0x25 << 24), + OPC_LARCH_LDPTR_D = (0x26 << 24), + OPC_LARCH_STPTR_D = (0x27 << 24), +}; + +enum { + /* jump opcodes */ + OPC_LARCH_BEQZ = (0x10 << 26), + OPC_LARCH_BNEZ = (0x11 << 26), + OPC_LARCH_B = (0x14 << 26), + OPC_LARCH_BEQ = (0x16 << 26), + OPC_LARCH_BNE = (0x17 << 26), + OPC_LARCH_BLT = (0x18 << 26), + OPC_LARCH_BGE = (0x19 << 26), + OPC_LARCH_BLTU = (0x1A << 26), + OPC_LARCH_BGEU = (0x1B << 26), +}; + +#endif diff --git a/target/loongarch64/internal.h b/target/loongarch64/internal.h new file mode 100644 index 0000000000..274916d7a9 --- /dev/null +++ b/target/loongarch64/internal.h @@ -0,0 +1,184 @@ +#ifndef LOONGARCH_INTERNAL_H +#define LOONGARCH_INTERNAL_H + +#include "cpu-csr.h" + +/* MMU types, the first four entries have the same layout as the + CP0C0_MT field. */ +enum loongarch_mmu_types { + MMU_TYPE_NONE, + MMU_TYPE_LS3A5K, /* LISA CSR */ +}; + + + +struct loongarch_def_t { + const char *name; + int32_t CSR_PRid; + int32_t FCSR0; + int32_t FCSR0_rw_bitmask; + int32_t PABITS; + CPU_LOONGARCH_CSR + uint64_t insn_flags; + enum loongarch_mmu_types mmu_type; + int cpu_cfg[64]; +}; + +/* loongarch 3a5000 TLB entry */ +struct ls3a5k_tlb_t { + target_ulong VPN; + uint64_t PageMask; /* CSR_TLBIDX[29:24] */ + uint32_t PageSize; + uint16_t ASID; + unsigned int G:1; /* CSR_TLBLO[6] */ + + unsigned int C0:3; /* CSR_TLBLO[5:4] */ + unsigned int C1:3; + + unsigned int V0:1; /* CSR_TLBLO[0] */ + unsigned int V1:1; + + unsigned int WE0:1; /* CSR_TLBLO[1] */ + unsigned int WE1:1; + + unsigned int XI0:1; /* CSR_TLBLO[62] */ + unsigned int XI1:1; + + unsigned int RI0:1; /* CSR_TLBLO[61] */ + unsigned int RI1:1; + + unsigned int EHINV:1;/* CSR_TLBIDX[31] */ + + unsigned int PLV0:2; /* CSR_TLBLO[3:2] */ + unsigned int PLV1:2; + + unsigned int RPLV0:1; + unsigned int RPLV1:1; /* CSR_TLBLO[63] */ + + uint64_t PPN0; /* CSR_TLBLO[47:12] */ + uint64_t PPN1; /* CSR_TLBLO[47:12] */ +}; +typedef struct ls3a5k_tlb_t ls3a5k_tlb_t; + + +struct CPULOONGARCHTLBContext { + uint32_t nb_tlb; + uint32_t tlb_in_use; + int (*map_address)(struct CPULOONGARCHState *env, hwaddr *physical, int *prot, + target_ulong address, int rw, int access_type); + void (*helper_tlbwr)(struct CPULOONGARCHState *env); + void (*helper_tlbfill)(struct CPULOONGARCHState *env); + void (*helper_tlbsrch)(struct CPULOONGARCHState *env); + void (*helper_tlbrd)(struct CPULOONGARCHState *env); + void (*helper_tlbclr)(struct CPULOONGARCHState *env); + void (*helper_tlbflush)(struct CPULOONGARCHState *env); + void (*helper_invtlb)(struct CPULOONGARCHState *env, target_ulong addr, + target_ulong info, int op); + union { + struct { + uint64_t ftlb_mask; + uint32_t ftlb_size; /* at most : 8 * 256 = 2048 */ + uint32_t vtlb_size; /* at most : 64 */ + ls3a5k_tlb_t tlb[2048 + 64]; /* at most : 2048 FTLB + 64 VTLB */ + } ls3a5k; + } mmu; +}; + +enum { + TLBRET_PE = -7, + TLBRET_XI = -6, + TLBRET_RI = -5, + TLBRET_DIRTY = -4, + TLBRET_INVALID = -3, + TLBRET_NOMATCH = -2, + TLBRET_BADADDR = -1, + TLBRET_MATCH = 0 +}; + + +extern unsigned int ieee_rm[]; + +static inline void restore_rounding_mode(CPULOONGARCHState *env) +{ + set_float_rounding_mode(ieee_rm[(env->active_fpu.fcsr0 >> FCSR0_RM) & 0x3], + &env->active_fpu.fp_status); +} + +static inline void restore_flush_mode(CPULOONGARCHState *env) +{ + set_flush_to_zero(0, &env->active_fpu.fp_status); +} + +static inline void restore_fp_status(CPULOONGARCHState *env) +{ + restore_rounding_mode(env); + restore_flush_mode(env); +} +static inline void compute_hflags(CPULOONGARCHState *env) +{ + env->hflags &= ~(LARCH_HFLAG_64 | LARCH_HFLAG_FPU | LARCH_HFLAG_KSU | + LARCH_HFLAG_AWRAP | LARCH_HFLAG_LSX | LARCH_HFLAG_LASX); + + env->hflags |= (env->CSR_CRMD & CSR_CRMD_PLV); + env->hflags |= LARCH_HFLAG_64; + + if (env->CSR_EUEN & CSR_EUEN_FPEN) { + env->hflags |= LARCH_HFLAG_FPU; + } + if (env->CSR_EUEN & CSR_EUEN_LSXEN) { + env->hflags |= LARCH_HFLAG_LSX; + } + if (env->CSR_EUEN & CSR_EUEN_LASXEN) { + env->hflags |= LARCH_HFLAG_LASX; + } + if (env->CSR_EUEN & CSR_EUEN_LBTEN) { + env->hflags |= LARCH_HFLAG_LBT; + } +} + +/* Check if there is pending and not masked out interrupt */ +static inline bool cpu_loongarch_hw_interrupts_pending(CPULOONGARCHState *env) +{ + int32_t pending; + int32_t status; + bool r; + + pending = env->CSR_ESTAT & CSR_ESTAT_IPMASK; + status = env->CSR_ECFG & CSR_ECFG_IPMASK; + + /* Configured with compatibility or VInt (Vectored Interrupts) + treats the pending lines as individual interrupt lines, the status + lines are individual masks. */ + r = (pending & status) != 0; + + return r; +} + + +/* stabletimer.c */ +uint32_t cpu_loongarch_get_random_ls3a5k_tlb(uint32_t low, uint32_t high); +uint64_t cpu_loongarch_get_stable_counter(CPULOONGARCHState *env); +uint64_t cpu_loongarch_get_stable_timer_ticks(CPULOONGARCHState *env); +void cpu_loongarch_store_stable_timer_config(CPULOONGARCHState *env, uint64_t value); +int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu, + int cpuid, DumpState *opaque); + +void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags); + +/* TODO QOM'ify CPU reset and remove */ +void cpu_state_reset(CPULOONGARCHState *s); +void cpu_loongarch_realize_env(CPULOONGARCHState *env); + +int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n); +int loongarch_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); + +#ifdef CONFIG_TCG +#include "fpu_helper.h" +#endif + +#ifndef CONFIG_USER_ONLY +extern const struct VMStateDescription vmstate_loongarch_cpu; +hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); +#endif + +#endif diff --git a/target/loongarch64/kvm.c b/target/loongarch64/kvm.c new file mode 100644 index 0000000000..404a605eb6 --- /dev/null +++ b/target/loongarch64/kvm.c @@ -0,0 +1,1622 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * KVM/LOONGARCH: LOONGARCH specific KVM APIs + * + * Copyright (C) 2012-2014 Imagination Technologies Ltd. + * Authors: Sanjay Lal +*/ + +#include "qemu/osdep.h" +#include + +#include + +#include "qemu-common.h" +#include "cpu.h" +#include "internal.h" +#include "qemu/error-report.h" +#include "qemu/timer.h" +#include "qemu/main-loop.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" +#include "sysemu/runstate.h" +#include "sysemu/cpus.h" +#include "kvm_larch.h" +#include "exec/memattrs.h" +#include "exec/gdbstub.h" + +#define DEBUG_KVM 0 +/* A 16384-byte buffer can hold the 8-byte kvm_msrs header, plus + * 2047 kvm_msr_entry structs */ +#define MSR_BUF_SIZE 16384 + +#define DPRINTF(fmt, ...) \ + do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) + +/* + * Define loongarch kvm version. + * Add version number when + * qemu/kvm interface changed + */ +#define KVM_LOONGARCH_VERSION 1 + +static struct { + target_ulong addr; + int len; + int type; +} inst_breakpoint[8], data_breakpoint[8]; + +int nb_data_breakpoint = 0, nb_inst_breakpoint = 0; +static int kvm_loongarch_version_cap; + +/* Hardware breakpoint control register + * 4:1 plv0-plv3 enable + * 6:5 config virtualization mode + * 9:8 load store */ +static const int type_code[] = { + [GDB_BREAKPOINT_HW] = 0x5e, + [GDB_WATCHPOINT_READ] = (0x5e | 1 << 8), + [GDB_WATCHPOINT_WRITE] = (0x5e | 1 << 9), + [GDB_WATCHPOINT_ACCESS] = (0x5e | 1 << 8 | 1 << 9) +}; + +const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO +}; + +static void kvm_loongarch_update_state(void *opaque, bool running, RunState state); +static inline int kvm_larch_putq(CPUState *cs, uint64_t reg_id, uint64_t *addr); + +unsigned long kvm_arch_vcpu_id(CPUState *cs) +{ + return cs->cpu_index; +} + +int kvm_arch_init(MachineState *ms, KVMState *s) +{ + /* LOONGARCH has 128 signals */ + kvm_set_sigmask_len(s, 16); + + kvm_loongarch_version_cap = kvm_check_extension(s, KVM_CAP_LOONGARCH_VZ); + + if (kvm_loongarch_version_cap != KVM_LOONGARCH_VERSION) { + warn_report("QEMU/KVM version not match, qemu_la_version: lvz-%d,\ + kvm_la_version: lvz-%d \n", + KVM_LOONGARCH_VERSION, kvm_loongarch_version_cap); + } + return 0; +} + +int kvm_arch_irqchip_create(KVMState *s) +{ + return 0; +} + +int kvm_arch_init_vcpu(CPUState *cs) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + int ret = 0; + + cpu->cpuStateEntry = qemu_add_vm_change_state_handler(kvm_loongarch_update_state, cs); + cpu->kvm_msr_buf = g_malloc0(MSR_BUF_SIZE); + DPRINTF("%s\n", __func__); + return ret; +} + +int kvm_arch_destroy_vcpu(CPUState *cs) +{ + return 0; +} + +static void kvm_msr_buf_reset(LOONGARCHCPU *cpu) +{ + memset(cpu->kvm_msr_buf, 0, MSR_BUF_SIZE); +} + +static void kvm_msr_entry_add(LOONGARCHCPU *cpu, uint32_t index, uint64_t value) +{ + struct kvm_msrs *msrs = cpu->kvm_msr_buf; + void *limit = ((void *)msrs) + MSR_BUF_SIZE; + struct kvm_csr_entry *entry = &msrs->entries[msrs->ncsrs]; + + assert((void *)(entry + 1) <= limit); + + entry->index = index; + entry->reserved = 0; + entry->data = value; + msrs->ncsrs++; +} + +void kvm_loongarch_reset_vcpu(LOONGARCHCPU *cpu) +{ + int ret = 0; + uint64_t reset = 1; + + if (CPU(cpu)->kvm_fd > 0) { + ret = kvm_larch_putq(CPU(cpu), KVM_REG_LOONGARCH_VCPU_RESET, &reset); + if (ret < 0) { + error_report("%s reset vcpu failed:%d", __func__, ret); + } + } + + DPRINTF("%s\n", __func__); +} + +void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg) +{ + int n; + if (kvm_sw_breakpoints_active(cpu)) { + dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; + } + if (nb_data_breakpoint > 0) { + dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; + for (n = 0; n < nb_data_breakpoint; n++) { + dbg->arch.data_breakpoint[n].addr = data_breakpoint[n].addr; + dbg->arch.data_breakpoint[n].mask = 0; + dbg->arch.data_breakpoint[n].asid = 0; + dbg->arch.data_breakpoint[n].ctrl = type_code[data_breakpoint[n].type]; + } + dbg->arch.data_bp_nums = nb_data_breakpoint; + } else { + dbg->arch.data_bp_nums = 0; + } + if (nb_inst_breakpoint > 0) { + dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; + for (n = 0; n < nb_inst_breakpoint; n++) { + dbg->arch.inst_breakpoint[n].addr = inst_breakpoint[n].addr; + dbg->arch.inst_breakpoint[n].mask = 0; + dbg->arch.inst_breakpoint[n].asid = 0; + dbg->arch.inst_breakpoint[n].ctrl = type_code[inst_breakpoint[n].type]; + } + dbg->arch.inst_bp_nums = nb_inst_breakpoint; + } else { + dbg->arch.inst_bp_nums = 0; + } +} + +static const unsigned int brk_insn = 0x002b8005; + +int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) +{ + DPRINTF("%s\n", __func__); + if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) || + cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk_insn, 4, 1)) { + error_report("%s failed", __func__); + return -EINVAL; + } + return 0; +} + +int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) +{ + static uint32_t brk; + + DPRINTF("%s\n", __func__); + if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk, 4, 0) || + brk != brk_insn || + cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 1)) { + error_report("%s failed", __func__); + return -EINVAL; + } + return 0; +} + +static int find_hw_breakpoint(uint64_t addr, int len, int type) +{ + int n; + switch (type) { + case GDB_BREAKPOINT_HW: + if (nb_inst_breakpoint == 0) { + return -1; + } + for (n = 0; n < nb_inst_breakpoint; n++) { + if (inst_breakpoint[n].addr == addr && inst_breakpoint[n].type == type) { + return n; + } + } + break; + case GDB_WATCHPOINT_WRITE: + case GDB_WATCHPOINT_READ: + case GDB_WATCHPOINT_ACCESS: + if (nb_data_breakpoint == 0) { + return -1; + } + for (n = 0; n < nb_data_breakpoint; n++) { + if (data_breakpoint[n].addr == addr && data_breakpoint[n].type == type && + data_breakpoint[n].len == len) { + return n; + } + } + break; + default: + return -1; + } + return -1; +} + +int kvm_arch_insert_hw_breakpoint(target_ulong addr, + target_ulong len, int type) +{ + switch (type) { + case GDB_BREAKPOINT_HW: + len = 1; + if (nb_inst_breakpoint == 8) { + return -ENOBUFS; + } + if (find_hw_breakpoint(addr, len, type) >= 0) { + return -EEXIST; + } + inst_breakpoint[nb_inst_breakpoint].addr = addr; + inst_breakpoint[nb_inst_breakpoint].len = len; + inst_breakpoint[nb_inst_breakpoint].type = type; + nb_inst_breakpoint++; + break; + case GDB_WATCHPOINT_WRITE: + case GDB_WATCHPOINT_READ: + case GDB_WATCHPOINT_ACCESS: + switch (len) { + case 1: + case 2: + case 4: + case 8: + if (addr & (len - 1)) { + return -EINVAL; + } + if (nb_data_breakpoint == 8) { + return -ENOBUFS; + } + if (find_hw_breakpoint(addr, len, type) >= 0) { + return -EEXIST; + } + data_breakpoint[nb_data_breakpoint].addr = addr; + data_breakpoint[nb_data_breakpoint].len = len; + data_breakpoint[nb_data_breakpoint].type = type; + nb_data_breakpoint++; + break; + default: + return -EINVAL; + } + break; + default: + return -ENOSYS; + } + return 0; +} + +int kvm_arch_remove_hw_breakpoint(target_ulong addr, + target_ulong len, int type) +{ + int n; + n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type); + if (n < 0) { + printf("err not find remove target\n"); + return -ENOENT; + } + switch (type) { + case GDB_BREAKPOINT_HW: + nb_inst_breakpoint--; + inst_breakpoint[n] = inst_breakpoint[nb_inst_breakpoint]; + break; + case GDB_WATCHPOINT_WRITE: + case GDB_WATCHPOINT_READ: + case GDB_WATCHPOINT_ACCESS: + nb_data_breakpoint--; + data_breakpoint[n] = data_breakpoint[nb_data_breakpoint]; + break; + default: + return -1; + } + return 0; +} + +void kvm_arch_remove_all_hw_breakpoints(void) +{ + DPRINTF("%s\n", __func__); + nb_data_breakpoint = 0; + nb_inst_breakpoint = 0; +} + +static inline int cpu_loongarch_io_interrupts_pending(LOONGARCHCPU *cpu) +{ + CPULOONGARCHState *env = &cpu->env; + + return env->CSR_ESTAT & (0x1 << 2); +} + +void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + int r; + struct kvm_loongarch_interrupt intr; + + qemu_mutex_lock_iothread(); + + if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && + cpu_loongarch_io_interrupts_pending(cpu)) { + intr.cpu = -1; + intr.irq = 2; + r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); + if (r < 0) { + error_report("%s: cpu %d: failed to inject IRQ %x", + __func__, cs->cpu_index, intr.irq); + } + } + + qemu_mutex_unlock_iothread(); +} + +MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) +{ + return MEMTXATTRS_UNSPECIFIED; +} + +int kvm_arch_process_async_events(CPUState *cs) +{ + return cs->halted; +} + +static CPUWatchpoint hw_watchpoint; + +static bool kvm_loongarch_handle_debug(CPUState *cs, struct kvm_run *run) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + int i; + bool ret = false; + kvm_cpu_synchronize_state(cs); + if (cs->singlestep_enabled) { + return true; + } + if (kvm_find_sw_breakpoint(cs, env->active_tc.PC)) { + return true; + } + /* hw breakpoint */ + if (run->debug.arch.exception == EXCCODE_WATCH) { + for (i = 0; i < 8; i++) { + if (run->debug.arch.fwps & (1 << i)) { + ret = true; + break; + } + } + for (i = 0; i < 8; i++) { + if (run->debug.arch.mwps & (1 << i)) { + cs->watchpoint_hit = &hw_watchpoint; + hw_watchpoint.vaddr = data_breakpoint[i].addr; + switch (data_breakpoint[i].type) { + case GDB_WATCHPOINT_READ: + ret = true; + hw_watchpoint.flags = BP_MEM_READ; + break; + case GDB_WATCHPOINT_WRITE: + ret = true; + hw_watchpoint.flags = BP_MEM_WRITE; + break; + case GDB_WATCHPOINT_ACCESS: + ret = true; + hw_watchpoint.flags = BP_MEM_ACCESS; + break; + } + } + } + run->debug.arch.exception = 0; + run->debug.arch.fwps = 0; + run->debug.arch.mwps = 0; + } + return ret; +} + +int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) +{ + int ret; + + DPRINTF("%s\n", __func__); + switch (run->exit_reason) { + case KVM_EXIT_HYPERCALL: + DPRINTF("handle LOONGARCH hypercall\n"); + ret = 0; + run->hypercall.ret = ret; + break; + + case KVM_EXIT_DEBUG: + ret = 0; + if (kvm_loongarch_handle_debug(cs, run)) { + ret = EXCP_DEBUG; + } + break; + default: + error_report("%s: unknown exit reason %d", + __func__, run->exit_reason); + ret = -1; + break; + } + + return ret; +} + +bool kvm_arch_stop_on_emulation_error(CPUState *cs) +{ + DPRINTF("%s\n", __func__); + return true; +} +/* +#if 0 +int kvmloongarch_load_kernel(CPUState *env, void *ram_base) +{ + int ret; + + ret = kvm_vcpu_ioctl(env, KVM_LOAD_KERNEL, ram_base); + + return ret; +} +#endif +*/ +void kvm_arch_init_irq_routing(KVMState *s) +{ +} + +int kvm_loongarch_set_interrupt(LOONGARCHCPU *cpu, int irq, int level) +{ + CPUState *cs = CPU(cpu); + struct kvm_loongarch_interrupt intr; + + if (!kvm_enabled()) { + return 0; + } + + intr.cpu = -1; + + if (level) { + intr.irq = irq; + } else { + intr.irq = -irq; + } + + kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); + + return 0; +} + +int kvm_loongarch_set_ipi_interrupt(LOONGARCHCPU *cpu, int irq, int level) +{ + CPUState *cs = current_cpu; + CPUState *dest_cs = CPU(cpu); + struct kvm_loongarch_interrupt intr; + + if (!kvm_enabled()) { + return 0; + } + + intr.cpu = dest_cs->cpu_index; + + if (level) { + intr.irq = irq; + } else { + intr.irq = -irq; + } + + DPRINTF("%s: IRQ: %d\n", __func__, intr.irq); + if (!current_cpu) { + cs = dest_cs; + } + kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr); + + return 0; +} + +static inline int kvm_loongarch_put_one_reg(CPUState *cs, uint64_t reg_id, + int32_t *addr) +{ + struct kvm_one_reg csrreg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); +} + +static inline int kvm_loongarch_put_one_ureg(CPUState *cs, uint64_t reg_id, + uint32_t *addr) +{ + struct kvm_one_reg csrreg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); +} + +static inline int kvm_loongarch_put_one_ulreg(CPUState *cs, uint64_t reg_id, + target_ulong *addr) +{ + uint64_t val64 = *addr; + struct kvm_one_reg csrreg = { + .id = reg_id, + .addr = (uintptr_t)&val64 + }; + + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); +} + +static inline int kvm_loongarch_put_one_reg64(CPUState *cs, int64_t reg_id, + int64_t *addr) +{ + struct kvm_one_reg csrreg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); +} + +static inline int kvm_larch_putq(CPUState *cs, uint64_t reg_id, + uint64_t *addr) +{ + struct kvm_one_reg csrreg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); +} + +static inline int kvm_loongarch_get_one_reg(CPUState *cs, uint64_t reg_id, + int32_t *addr) +{ + struct kvm_one_reg csrreg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); +} + +static inline int kvm_loongarch_get_one_ureg(CPUState *cs, uint64_t reg_id, + uint32_t *addr) +{ + struct kvm_one_reg csrreg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); +} + +static inline int kvm_loongarch_get_one_ulreg(CPUState *cs, uint64_t reg_id, + target_ulong *addr) +{ + int ret; + uint64_t val64 = 0; + struct kvm_one_reg csrreg = { + .id = reg_id, + .addr = (uintptr_t)&val64 + }; + + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); + if (ret >= 0) { + *addr = val64; + } + return ret; +} + +static inline int kvm_loongarch_get_one_reg64(CPUState *cs, int64_t reg_id, + int64_t *addr) +{ + struct kvm_one_reg csrreg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); +} + +static inline int kvm_larch_getq(CPUState *cs, uint64_t reg_id, + uint64_t *addr) +{ + struct kvm_one_reg csrreg = { + .id = reg_id, + .addr = (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); +} + +static inline int kvm_loongarch_change_one_reg(CPUState *cs, uint64_t reg_id, + int32_t *addr, int32_t mask) +{ + int err; + int32_t tmp, change; + + err = kvm_loongarch_get_one_reg(cs, reg_id, &tmp); + if (err < 0) { + return err; + } + + /* only change bits in mask */ + change = (*addr ^ tmp) & mask; + if (!change) { + return 0; + } + + tmp = tmp ^ change; + return kvm_loongarch_put_one_reg(cs, reg_id, &tmp); +} + +static inline int kvm_loongarch_change_one_reg64(CPUState *cs, uint64_t reg_id, + int64_t *addr, int64_t mask) +{ + int err; + int64_t tmp, change; + + err = kvm_loongarch_get_one_reg64(cs, reg_id, &tmp); + if (err < 0) { + DPRINTF("%s: Failed to get CSR_CONFIG7 (%d)\n", __func__, err); + return err; + } + + /* only change bits in mask */ + change = (*addr ^ tmp) & mask; + if (!change) { + return 0; + } + + tmp = tmp ^ change; + return kvm_loongarch_put_one_reg64(cs, reg_id, &tmp); +} +/* + * Handle the VM clock being started or stopped + */ +static void kvm_loongarch_update_state(void *opaque, bool running, RunState state) +{ + CPUState *cs = opaque; + int ret; + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + + /* + * If state is already dirty (synced to QEMU) then the KVM timer state is + * already saved and can be restored when it is synced back to KVM. + */ + if (!running) { + ret = kvm_larch_getq(cs, + KVM_REG_LOONGARCH_COUNTER, &cpu->counter_value); + if (ret < 0) { + printf("%s: Failed to get counter_value (%d)\n", __func__, ret); + } + + } else { + ret = kvm_larch_putq(cs, KVM_REG_LOONGARCH_COUNTER, + &(LOONGARCH_CPU(cs))->counter_value); + if (ret < 0) { + printf("%s: Failed to put counter_value (%d)\n", __func__, ret); + } + } +} + +static int kvm_loongarch_put_fpu_registers(CPUState *cs, int level) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + int err, ret = 0; + unsigned int i; + struct kvm_fpu fpu; + + fpu.fcsr = env->active_fpu.fcsr0; + for (i = 0; i < 32; i++) { + memcpy(&fpu.fpr[i], &env->active_fpu.fpr[i], sizeof(struct kvm_fpureg)); + } + for (i = 0; i < 8; i++) { + ((char *)&fpu.fcc)[i] = env->active_fpu.cf[i]; + } + fpu.vcsr = env->active_fpu.vcsr16; + + err = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu); + if (err < 0) { + DPRINTF("%s: Failed to get FPU (%d)\n", __func__, err); + ret = err; + } + + return ret; +} + +static int kvm_loongarch_get_fpu_registers(CPUState *cs) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + int err, ret = 0; + unsigned int i; + struct kvm_fpu fpu; + + err = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu); + if (err < 0) { + DPRINTF("%s: Failed to get FPU (%d)\n", __func__, err); + ret = err; + } else { + env->active_fpu.fcsr0 = fpu.fcsr; + for (i = 0; i < 32; i++) { + memcpy(&env->active_fpu.fpr[i], &fpu.fpr[i], sizeof(struct kvm_fpureg)); + } + for (i = 0; i < 8; i++) { + env->active_fpu.cf[i] = ((char *)&fpu.fcc)[i]; + } + env->active_fpu.vcsr16 = fpu.vcsr; + } + + return ret; +} + +#define KVM_PUT_ONE_UREG64(cs, regidx, addr) \ + ({ \ + int err; \ + uint64_t csrid = 0; \ + csrid = (KVM_IOC_CSRID(regidx)); \ + err = kvm_larch_putq(cs, csrid, addr); \ + if (err < 0) { \ + DPRINTF("%s: Failed to put regidx 0x%x err:%d\n", __func__, regidx, err); \ + } \ + err; \ + }) + + +static int kvm_loongarch_put_csr_registers(CPUState *cs, int level) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + int ret = 0; + + (void)level; + + kvm_msr_buf_reset(cpu); + + kvm_msr_entry_add(cpu, LOONGARCH_CSR_CRMD, env->CSR_CRMD); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRMD, env->CSR_PRMD); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_EUEN, env->CSR_EUEN); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_MISC, env->CSR_MISC); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ECFG, env->CSR_ECFG); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ESTAT, env->CSR_ESTAT); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERA, env->CSR_ERA); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADV, env->CSR_BADV); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADI, env->CSR_BADI); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_EEPN, env->CSR_EEPN); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBIDX, env->CSR_TLBIDX); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBEHI, env->CSR_TLBEHI); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO0, env->CSR_TLBELO0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO1, env->CSR_TLBELO1); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GTLBC, env->CSR_GTLBC); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TRGP, env->CSR_TRGP); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ASID, env->CSR_ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDL, env->CSR_PGDL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDH, env->CSR_PGDH); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGD, env->CSR_PGD); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL0, env->CSR_PWCTL0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL1, env->CSR_PWCTL1); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_STLBPGSIZE, env->CSR_STLBPGSIZE); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_RVACFG, env->CSR_RVACFG); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_CPUID, env->CSR_CPUID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG1, env->CSR_PRCFG1); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG2, env->CSR_PRCFG2); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG3, env->CSR_PRCFG3); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS0, env->CSR_KS0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS1, env->CSR_KS1); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS2, env->CSR_KS2); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS3, env->CSR_KS3); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS4, env->CSR_KS4); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS5, env->CSR_KS5); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS6, env->CSR_KS6); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS7, env->CSR_KS7); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TMID, env->CSR_TMID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_CNTC, env->CSR_CNTC); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TINTCLR, env->CSR_TINTCLR); + + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GSTAT, env->CSR_GSTAT); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCFG, env->CSR_GCFG); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GINTC, env->CSR_GINTC); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCNTC, env->CSR_GCNTC); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_LLBCTL, env->CSR_LLBCTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL1, env->CSR_IMPCTL1); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL2, env->CSR_IMPCTL2); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GNMI, env->CSR_GNMI); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRENT, env->CSR_TLBRENT); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRBADV, env->CSR_TLBRBADV); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRERA, env->CSR_TLBRERA); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRSAVE, env->CSR_TLBRSAVE); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO0, env->CSR_TLBRELO0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO1, env->CSR_TLBRELO1); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBREHI, env->CSR_TLBREHI); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRPRMD, env->CSR_TLBRPRMD); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRCTL, env->CSR_ERRCTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO, env->CSR_ERRINFO); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO1, env->CSR_ERRINFO1); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRENT, env->CSR_ERRENT); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRERA, env->CSR_ERRERA); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRSAVE, env->CSR_ERRSAVE); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_CTAG, env->CSR_CTAG); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN0, env->CSR_DMWIN0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN1, env->CSR_DMWIN1); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN2, env->CSR_DMWIN2); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN3, env->CSR_DMWIN3); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL0, env->CSR_PERFCTRL0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR0, env->CSR_PERFCNTR0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL1, env->CSR_PERFCTRL1); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR1, env->CSR_PERFCNTR1); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL2, env->CSR_PERFCTRL2); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR2, env->CSR_PERFCNTR2); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL3, env->CSR_PERFCTRL3); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR3, env->CSR_PERFCNTR3); + + /* debug */ + kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPC, env->CSR_MWPC); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPS, env->CSR_MWPS); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ADDR, env->CSR_DB0ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0MASK, env->CSR_DB0MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0CTL, env->CSR_DB0CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ASID, env->CSR_DB0ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ADDR, env->CSR_DB1ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1MASK, env->CSR_DB1MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1CTL, env->CSR_DB1CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ASID, env->CSR_DB1ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ADDR, env->CSR_DB2ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2MASK, env->CSR_DB2MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2CTL, env->CSR_DB2CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ASID, env->CSR_DB2ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ADDR, env->CSR_DB3ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3MASK, env->CSR_DB3MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3CTL, env->CSR_DB3CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ASID, env->CSR_DB3ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPC, env->CSR_FWPC); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPS, env->CSR_FWPS); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ADDR, env->CSR_IB0ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0MASK, env->CSR_IB0MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0CTL, env->CSR_IB0CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ASID, env->CSR_IB0ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ADDR, env->CSR_IB1ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1MASK, env->CSR_IB1MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1CTL, env->CSR_IB1CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ASID, env->CSR_IB1ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ADDR, env->CSR_IB2ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2MASK, env->CSR_IB2MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2CTL, env->CSR_IB2CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ASID, env->CSR_IB2ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ADDR, env->CSR_IB3ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3MASK, env->CSR_IB3MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3CTL, env->CSR_IB3CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ASID, env->CSR_IB3ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ADDR, env->CSR_IB4ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4MASK, env->CSR_IB4MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4CTL, env->CSR_IB4CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ASID, env->CSR_IB4ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ADDR, env->CSR_IB5ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5MASK, env->CSR_IB5MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5CTL, env->CSR_IB5CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ASID, env->CSR_IB5ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ADDR, env->CSR_IB6ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6MASK, env->CSR_IB6MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6CTL, env->CSR_IB6CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ASID, env->CSR_IB6ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ADDR, env->CSR_IB7ADDR); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7MASK, env->CSR_IB7MASK); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7CTL, env->CSR_IB7CTL); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ASID, env->CSR_IB7ASID); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DEBUG, env->CSR_DEBUG); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DERA, env->CSR_DERA); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DESAVE, env->CSR_DESAVE); + + ret = kvm_vcpu_ioctl(cs, KVM_SET_MSRS, cpu->kvm_msr_buf); + if (ret < cpu->kvm_msr_buf->ncsrs) { + struct kvm_csr_entry *e = &cpu->kvm_msr_buf->entries[ret]; + printf("error: failed to set CSR 0x%" PRIx32 " to 0x%" PRIx64"\n", + (uint32_t)e->index, (uint64_t)e->data); + } + + /* + * timer cfg must be put at last since it is used to enable + * guest timer + */ + ret |= KVM_PUT_ONE_UREG64(cs, LOONGARCH_CSR_TVAL, &env->CSR_TVAL); + ret |= KVM_PUT_ONE_UREG64(cs, LOONGARCH_CSR_TCFG, &env->CSR_TCFG); + return ret; +} + +#define KVM_GET_ONE_UREG64(cs, regidx, addr) \ + ({ \ + int err; \ + uint64_t csrid = 0; \ + csrid = (KVM_IOC_CSRID(regidx)); \ + err = kvm_larch_getq(cs, csrid, addr); \ + if (err < 0) { \ + DPRINTF("%s: Failed to put regidx 0x%x err:%d\n", __func__, regidx, err); \ + } \ + err; \ + }) + +static int kvm_loongarch_get_csr_registers(CPUState *cs) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + int ret = 0, i; + struct kvm_csr_entry *csrs = cpu->kvm_msr_buf->entries; + + kvm_msr_buf_reset(cpu); + + kvm_msr_entry_add(cpu, LOONGARCH_CSR_CRMD, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRMD, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_EUEN, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_MISC, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ECFG, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ESTAT, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERA, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADV, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADI, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_EEPN, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBIDX, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBEHI, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO0, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO1, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GTLBC, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TRGP, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDH, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGD, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL0, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL1, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_STLBPGSIZE, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_RVACFG, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_CPUID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG1, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG2, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG3, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS0, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS1, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS2, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS3, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS4, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS5, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS6, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS7, 0); + + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TMID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_CNTC, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TINTCLR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GSTAT, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCFG, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GINTC, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCNTC, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_LLBCTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL1, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL2, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_GNMI, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRENT, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRBADV, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRERA, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRSAVE, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO0, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO1, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBREHI, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRPRMD, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRCTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO1, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRENT, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRERA, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRSAVE, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_CTAG, 0); + + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN0, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN1, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN2, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN3, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL0, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR0, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL1, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR1, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL2, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR2, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL3, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR3, 0); + + /* debug */ + kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPC, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPS, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPC, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPS, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ADDR, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7MASK, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7CTL, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ASID, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DEBUG, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DERA, 0); + kvm_msr_entry_add(cpu, LOONGARCH_CSR_DESAVE, 0); + + ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, cpu->kvm_msr_buf); + if (ret < cpu->kvm_msr_buf->ncsrs) { + struct kvm_csr_entry *e = &cpu->kvm_msr_buf->entries[ret]; + printf("error: failed to get CSR 0x%" PRIx32"\n", + (uint32_t)e->index); + } + + for (i = 0; i < ret; i++) { + uint32_t index = csrs[i].index; + + switch (index) { + case LOONGARCH_CSR_CRMD: + env->CSR_CRMD = csrs[i].data; + break; + case LOONGARCH_CSR_PRMD: + env->CSR_PRMD = csrs[i].data; + break; + case LOONGARCH_CSR_EUEN: + env->CSR_EUEN = csrs[i].data; + break; + case LOONGARCH_CSR_MISC: + env->CSR_MISC = csrs[i].data; + break; + case LOONGARCH_CSR_ECFG: + env->CSR_ECFG = csrs[i].data; + break; + case LOONGARCH_CSR_ESTAT: + env->CSR_ESTAT = csrs[i].data; + break; + case LOONGARCH_CSR_ERA: + env->CSR_ERA = csrs[i].data; + break; + case LOONGARCH_CSR_BADV: + env->CSR_BADV = csrs[i].data; + break; + case LOONGARCH_CSR_BADI: + env->CSR_BADI = csrs[i].data; + break; + case LOONGARCH_CSR_EEPN: + env->CSR_EEPN = csrs[i].data; + break; + case LOONGARCH_CSR_TLBIDX: + env->CSR_TLBIDX = csrs[i].data; + break; + case LOONGARCH_CSR_TLBEHI: + env->CSR_TLBEHI = csrs[i].data; + break; + case LOONGARCH_CSR_TLBELO0: + env->CSR_TLBELO0 = csrs[i].data; + break; + case LOONGARCH_CSR_TLBELO1: + env->CSR_TLBELO1 = csrs[i].data; + break; + case LOONGARCH_CSR_GTLBC: + env->CSR_GTLBC = csrs[i].data; + break; + case LOONGARCH_CSR_TRGP: + env->CSR_TRGP = csrs[i].data; + break; + case LOONGARCH_CSR_ASID: + env->CSR_ASID = csrs[i].data; + break; + case LOONGARCH_CSR_PGDL: + env->CSR_PGDL = csrs[i].data; + break; + case LOONGARCH_CSR_PGDH: + env->CSR_PGDH = csrs[i].data; + break; + case LOONGARCH_CSR_PGD: + env->CSR_PGD = csrs[i].data; + break; + case LOONGARCH_CSR_PWCTL0: + env->CSR_PWCTL0 = csrs[i].data; + break; + case LOONGARCH_CSR_PWCTL1: + env->CSR_PWCTL1 = csrs[i].data; + break; + case LOONGARCH_CSR_STLBPGSIZE: + env->CSR_STLBPGSIZE = csrs[i].data; + break; + case LOONGARCH_CSR_RVACFG: + env->CSR_RVACFG = csrs[i].data; + break; + case LOONGARCH_CSR_CPUID: + env->CSR_CPUID = csrs[i].data; + break; + case LOONGARCH_CSR_PRCFG1: + env->CSR_PRCFG1 = csrs[i].data; + break; + case LOONGARCH_CSR_PRCFG2: + env->CSR_PRCFG2 = csrs[i].data; + break; + case LOONGARCH_CSR_PRCFG3: + env->CSR_PRCFG3 = csrs[i].data; + break; + case LOONGARCH_CSR_KS0: + env->CSR_KS0 = csrs[i].data; + break; + case LOONGARCH_CSR_KS1: + env->CSR_KS1 = csrs[i].data; + break; + case LOONGARCH_CSR_KS2: + env->CSR_KS2 = csrs[i].data; + break; + case LOONGARCH_CSR_KS3: + env->CSR_KS3 = csrs[i].data; + break; + case LOONGARCH_CSR_KS4: + env->CSR_KS4 = csrs[i].data; + break; + case LOONGARCH_CSR_KS5: + env->CSR_KS5 = csrs[i].data; + break; + case LOONGARCH_CSR_KS6: + env->CSR_KS6 = csrs[i].data; + break; + case LOONGARCH_CSR_KS7: + env->CSR_KS7 = csrs[i].data; + break; + + case LOONGARCH_CSR_TMID: + env->CSR_TMID = csrs[i].data; + break; + case LOONGARCH_CSR_CNTC: + env->CSR_CNTC = csrs[i].data; + break; + case LOONGARCH_CSR_TINTCLR: + env->CSR_TINTCLR = csrs[i].data; + break; + case LOONGARCH_CSR_GSTAT: + env->CSR_GSTAT = csrs[i].data; + break; + case LOONGARCH_CSR_GCFG: + env->CSR_GCFG = csrs[i].data; + break; + case LOONGARCH_CSR_GINTC: + env->CSR_GINTC = csrs[i].data; + break; + case LOONGARCH_CSR_GCNTC: + env->CSR_GCNTC = csrs[i].data; + break; + case LOONGARCH_CSR_LLBCTL: + env->CSR_LLBCTL = csrs[i].data; + break; + case LOONGARCH_CSR_IMPCTL1: + env->CSR_IMPCTL1 = csrs[i].data; + break; + case LOONGARCH_CSR_IMPCTL2: + env->CSR_IMPCTL2 = csrs[i].data; + break; + case LOONGARCH_CSR_GNMI: + env->CSR_GNMI = csrs[i].data; + break; + case LOONGARCH_CSR_TLBRENT: + env->CSR_TLBRENT = csrs[i].data; + break; + case LOONGARCH_CSR_TLBRBADV: + env->CSR_TLBRBADV = csrs[i].data; + break; + case LOONGARCH_CSR_TLBRERA: + env->CSR_TLBRERA = csrs[i].data; + break; + case LOONGARCH_CSR_TLBRSAVE: + env->CSR_TLBRSAVE = csrs[i].data; + break; + case LOONGARCH_CSR_TLBRELO0: + env->CSR_TLBRELO0 = csrs[i].data; + break; + case LOONGARCH_CSR_TLBRELO1: + env->CSR_TLBRELO1 = csrs[i].data; + break; + case LOONGARCH_CSR_TLBREHI: + env->CSR_TLBREHI = csrs[i].data; + break; + case LOONGARCH_CSR_TLBRPRMD: + env->CSR_TLBRPRMD = csrs[i].data; + break; + case LOONGARCH_CSR_ERRCTL: + env->CSR_ERRCTL = csrs[i].data; + break; + case LOONGARCH_CSR_ERRINFO: + env->CSR_ERRINFO = csrs[i].data; + break; + case LOONGARCH_CSR_ERRINFO1: + env->CSR_ERRINFO1 = csrs[i].data; + break; + case LOONGARCH_CSR_ERRENT: + env->CSR_ERRENT = csrs[i].data; + break; + case LOONGARCH_CSR_ERRERA: + env->CSR_ERRERA = csrs[i].data; + break; + case LOONGARCH_CSR_ERRSAVE: + env->CSR_ERRSAVE = csrs[i].data; + break; + case LOONGARCH_CSR_CTAG: + env->CSR_CTAG = csrs[i].data; + break; + case LOONGARCH_CSR_DMWIN0: + env->CSR_DMWIN0 = csrs[i].data; + break; + case LOONGARCH_CSR_DMWIN1: + env->CSR_DMWIN1 = csrs[i].data; + break; + case LOONGARCH_CSR_DMWIN2: + env->CSR_DMWIN2 = csrs[i].data; + break; + case LOONGARCH_CSR_DMWIN3: + env->CSR_DMWIN3 = csrs[i].data; + break; + case LOONGARCH_CSR_PERFCTRL0: + env->CSR_PERFCTRL0 = csrs[i].data; + break; + case LOONGARCH_CSR_PERFCNTR0: + env->CSR_PERFCNTR0 = csrs[i].data; + break; + case LOONGARCH_CSR_PERFCTRL1: + env->CSR_PERFCTRL1 = csrs[i].data; + break; + case LOONGARCH_CSR_PERFCNTR1: + env->CSR_PERFCNTR1 = csrs[i].data; + break; + case LOONGARCH_CSR_PERFCTRL2: + env->CSR_PERFCTRL2 = csrs[i].data; + break; + case LOONGARCH_CSR_PERFCNTR2: + env->CSR_PERFCNTR2 = csrs[i].data; + break; + case LOONGARCH_CSR_PERFCTRL3: + env->CSR_PERFCTRL3 = csrs[i].data; + break; + case LOONGARCH_CSR_PERFCNTR3: + env->CSR_PERFCNTR3 = csrs[i].data; + break; + + case LOONGARCH_CSR_MWPC: + env->CSR_MWPC = csrs[i].data; + break; + case LOONGARCH_CSR_MWPS: + env->CSR_MWPS = csrs[i].data; + break; + case LOONGARCH_CSR_DB0ADDR: + env->CSR_DB0ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_DB0MASK: + env->CSR_DB0MASK = csrs[i].data; + break; + case LOONGARCH_CSR_DB0CTL: + env->CSR_DB0CTL = csrs[i].data; + break; + case LOONGARCH_CSR_DB0ASID: + env->CSR_DB0ASID = csrs[i].data; + break; + case LOONGARCH_CSR_DB1ADDR: + env->CSR_DB1ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_DB1MASK: + env->CSR_DB1MASK = csrs[i].data; + break; + case LOONGARCH_CSR_DB1CTL: + env->CSR_DB1CTL = csrs[i].data; + break; + case LOONGARCH_CSR_DB1ASID: + env->CSR_DB1ASID = csrs[i].data; + break; + case LOONGARCH_CSR_DB2ADDR: + env->CSR_DB2ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_DB2MASK: + env->CSR_DB2MASK = csrs[i].data; + break; + case LOONGARCH_CSR_DB2CTL: + env->CSR_DB2CTL = csrs[i].data; + break; + case LOONGARCH_CSR_DB2ASID: + env->CSR_DB2ASID = csrs[i].data; + break; + case LOONGARCH_CSR_DB3ADDR: + env->CSR_DB3ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_DB3MASK: + env->CSR_DB3MASK = csrs[i].data; + break; + case LOONGARCH_CSR_DB3CTL: + env->CSR_DB3CTL = csrs[i].data; + break; + case LOONGARCH_CSR_DB3ASID: + env->CSR_DB3ASID = csrs[i].data; + break; + case LOONGARCH_CSR_FWPC: + env->CSR_FWPC = csrs[i].data; + break; + case LOONGARCH_CSR_FWPS: + env->CSR_FWPS = csrs[i].data; + break; + case LOONGARCH_CSR_IB0ADDR: + env->CSR_IB0ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_IB0MASK: + env->CSR_IB0MASK = csrs[i].data; + break; + case LOONGARCH_CSR_IB0CTL: + env->CSR_IB0CTL = csrs[i].data; + break; + case LOONGARCH_CSR_IB0ASID: + env->CSR_IB0ASID = csrs[i].data; + break; + case LOONGARCH_CSR_IB1ADDR: + env->CSR_IB1ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_IB1MASK: + env->CSR_IB1MASK = csrs[i].data; + break; + case LOONGARCH_CSR_IB1CTL: + env->CSR_IB1CTL = csrs[i].data; + break; + case LOONGARCH_CSR_IB1ASID: + env->CSR_IB1ASID = csrs[i].data; + break; + case LOONGARCH_CSR_IB2ADDR: + env->CSR_IB2ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_IB2MASK: + env->CSR_IB2MASK = csrs[i].data; + break; + case LOONGARCH_CSR_IB2CTL: + env->CSR_IB2CTL = csrs[i].data; + break; + case LOONGARCH_CSR_IB2ASID: + env->CSR_IB2ASID = csrs[i].data; + break; + case LOONGARCH_CSR_IB3ADDR: + env->CSR_IB3ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_IB3MASK: + env->CSR_IB3MASK = csrs[i].data; + break; + case LOONGARCH_CSR_IB3CTL: + env->CSR_IB3CTL = csrs[i].data; + break; + case LOONGARCH_CSR_IB3ASID: + env->CSR_IB3ASID = csrs[i].data; + break; + case LOONGARCH_CSR_IB4ADDR: + env->CSR_IB4ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_IB4MASK: + env->CSR_IB4MASK = csrs[i].data; + break; + case LOONGARCH_CSR_IB4CTL: + env->CSR_IB4CTL = csrs[i].data; + break; + case LOONGARCH_CSR_IB4ASID: + env->CSR_IB4ASID = csrs[i].data; + break; + case LOONGARCH_CSR_IB5ADDR: + env->CSR_IB5ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_IB5MASK: + env->CSR_IB5MASK = csrs[i].data; + break; + case LOONGARCH_CSR_IB5CTL: + env->CSR_IB5CTL = csrs[i].data; + break; + case LOONGARCH_CSR_IB5ASID: + env->CSR_IB5ASID = csrs[i].data; + break; + case LOONGARCH_CSR_IB6ADDR: + env->CSR_IB6ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_IB6MASK: + env->CSR_IB6MASK = csrs[i].data; + break; + case LOONGARCH_CSR_IB6CTL: + env->CSR_IB6CTL = csrs[i].data; + break; + case LOONGARCH_CSR_IB6ASID: + env->CSR_IB6ASID = csrs[i].data; + break; + case LOONGARCH_CSR_IB7ADDR: + env->CSR_IB7ADDR = csrs[i].data; + break; + case LOONGARCH_CSR_IB7MASK: + env->CSR_IB7MASK = csrs[i].data; + break; + case LOONGARCH_CSR_IB7CTL: + env->CSR_IB7CTL = csrs[i].data; + break; + case LOONGARCH_CSR_IB7ASID: + env->CSR_IB7ASID = csrs[i].data; + break; + case LOONGARCH_CSR_DEBUG: + env->CSR_DEBUG = csrs[i].data; + break; + case LOONGARCH_CSR_DERA: + env->CSR_DERA = csrs[i].data; + break; + case LOONGARCH_CSR_DESAVE: + env->CSR_DESAVE = csrs[i].data; + break; + default: + break; + } + } + + ret |= KVM_GET_ONE_UREG64(cs, LOONGARCH_CSR_TVAL, &env->CSR_TVAL); + ret |= KVM_GET_ONE_UREG64(cs, LOONGARCH_CSR_TCFG, &env->CSR_TCFG); + return ret; +} + +int kvm_loongarch_put_pvtime(LOONGARCHCPU *cpu) +{ + CPULOONGARCHState *env = &cpu->env; + int err; + struct kvm_device_attr attr = { + .group = KVM_LARCH_VCPU_PVTIME_CTRL, + .attr = KVM_LARCH_VCPU_PVTIME_IPA, + .addr = (uint64_t)&env->st.guest_addr, + }; + + err = kvm_vcpu_ioctl(CPU(cpu), KVM_HAS_DEVICE_ATTR, attr); + if (err != 0) { + /* It's ok even though kvm has not such attr */ + return 0; + } + + err = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_DEVICE_ATTR, attr); + if (err != 0) { + error_report("PVTIME IPA: KVM_SET_DEVICE_ATTR: %s", strerror(-err)); + return err; + } + + return 0; +} + +int kvm_loongarch_get_pvtime(LOONGARCHCPU *cpu) +{ + CPULOONGARCHState *env = &cpu->env; + int err; + struct kvm_device_attr attr = { + .group = KVM_LARCH_VCPU_PVTIME_CTRL, + .attr = KVM_LARCH_VCPU_PVTIME_IPA, + .addr = (uint64_t)&env->st.guest_addr, + }; + + err = kvm_vcpu_ioctl(CPU(cpu), KVM_HAS_DEVICE_ATTR, attr); + if (err != 0) { + /* It's ok even though kvm has not such attr */ + return 0; + } + + err = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_DEVICE_ATTR, attr); + if (err != 0) { + error_report("PVTIME IPA: KVM_GET_DEVICE_ATTR: %s", strerror(-err)); + return err; + } + + return 0; +} + +int kvm_arch_put_registers(CPUState *cs, int level) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + struct kvm_regs regs; + int ret; + int i; + + /* Set the registers based on QEMU's view of things */ + for (i = 0; i < 32; i++) { + regs.gpr[i] = (int64_t)(target_long)env->active_tc.gpr[i]; + } + + regs.pc = (int64_t)(target_long)env->active_tc.PC; + + ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); + + if (ret < 0) { + return ret; + } + + ret = kvm_loongarch_put_csr_registers(cs, level); + if (ret < 0) { + return ret; + } + + ret = kvm_loongarch_put_fpu_registers(cs, level); + if (ret < 0) { + return ret; + } + + return ret; +} + +int kvm_arch_get_registers(CPUState *cs) +{ + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + int ret = 0; + struct kvm_regs regs; + int i; + + /* Get the current register set as KVM seems it */ + ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); + + if (ret < 0) { + return ret; + } + + for (i = 0; i < 32; i++) { + env->active_tc.gpr[i] = regs.gpr[i]; + } + + env->active_tc.PC = regs.pc; + + kvm_loongarch_get_csr_registers(cs); + kvm_loongarch_get_fpu_registers(cs); + + return ret; +} + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data, PCIDevice *dev) +{ + return 0; +} + +int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, + int vector, PCIDevice *dev) +{ + return 0; +} + +bool kvm_arch_cpu_check_are_resettable(void) +{ + return true; +} + +int kvm_arch_release_virq_post(int virq) +{ + return 0; +} + +int kvm_arch_msi_data_to_gsi(uint32_t data) +{ + abort(); +} diff --git a/target/loongarch64/kvm_larch.h b/target/loongarch64/kvm_larch.h new file mode 100644 index 0000000000..a56026d10c --- /dev/null +++ b/target/loongarch64/kvm_larch.h @@ -0,0 +1,41 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * KVM/LOONGARCH: LOONGARCH specific KVM APIs + * + * Copyright (C) 2012-2014 Imagination Technologies Ltd. + * Authors: Sanjay Lal +*/ + +#ifndef KVM_LOONGARCH_H +#define KVM_LOONGARCH_H + +/** + * kvm_loongarch_reset_vcpu: + * @cpu: LOONGARCHCPU + * + * Called at reset time to set kernel registers to their initial values. + */ +void kvm_loongarch_reset_vcpu(LOONGARCHCPU *cpu); + +int kvm_loongarch_set_interrupt(LOONGARCHCPU *cpu, int irq, int level); +int kvm_loongarch_set_ipi_interrupt(LOONGARCHCPU *cpu, int irq, int level); + +int kvm_loongarch_put_pvtime(LOONGARCHCPU *cpu); +int kvm_loongarch_get_pvtime(LOONGARCHCPU *cpu); + +#ifndef KVM_INTERRUPT_SET +#define KVM_INTERRUPT_SET -1 +#endif + +#ifndef KVM_INTERRUPT_UNSET +#define KVM_INTERRUPT_UNSET -2 +#endif + +#ifndef KVM_INTERRUPT_SET_LEVEL +#define KVM_INTERRUPT_SET_LEVEL -3 +#endif + +#endif /* KVM_LOONGARCH_H */ diff --git a/target/loongarch64/larch-defs.h b/target/loongarch64/larch-defs.h new file mode 100644 index 0000000000..d3a61cf255 --- /dev/null +++ b/target/loongarch64/larch-defs.h @@ -0,0 +1,27 @@ +#ifndef QEMU_LOONGARCH_DEFS_H +#define QEMU_LOONGARCH_DEFS_H + +/* If we want to use host float regs... */ +/* #define USE_HOST_FLOAT_REGS */ + +/* Real pages are variable size... */ +#define TARGET_PAGE_BITS 14 + +#define LOONGARCH_TLB_MAX 2112 + +#define TARGET_LONG_BITS 64 +#define TARGET_PHYS_ADDR_SPACE_BITS 48 +#define TARGET_VIRT_ADDR_SPACE_BITS 48 + +/* + * bit definitions for insn_flags (ISAs/ASEs flags) + * ------------------------------------------------ + */ +#define ISA_LARCH32 0x00000001ULL +#define ISA_LARCH64 0x00000002ULL +#define INSN_LOONGARCH 0x00010000ULL + +#define CPU_LARCH32 (ISA_LARCH32) +#define CPU_LARCH64 (ISA_LARCH32 | ISA_LARCH64) + +#endif /* QEMU_LOONGARCH_DEFS_H */ diff --git a/target/loongarch64/machine.c b/target/loongarch64/machine.c new file mode 100644 index 0000000000..b69bca6a9b --- /dev/null +++ b/target/loongarch64/machine.c @@ -0,0 +1,416 @@ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "internal.h" +#include "hw/hw.h" +#include "kvm_larch.h" +#include "migration/cpu.h" +#include "linux/kvm.h" +#include "sysemu/kvm.h" +#include "qemu/error-report.h" + +static int cpu_post_load(void *opaque, int version_id) +{ + LOONGARCHCPU *cpu = opaque; + CPULOONGARCHState *env = &cpu->env; + int r = 0; + +#ifdef CONFIG_KVM + struct kvm_loongarch_vcpu_state vcpu_state; + int i; + + vcpu_state.online_vcpus = cpu->online_vcpus; + vcpu_state.is_migrate = cpu->is_migrate; + vcpu_state.cpu_freq = cpu->cpu_freq; + vcpu_state.count_ctl = cpu->count_ctl; + vcpu_state.pending_exceptions = cpu->pending_exceptions; + vcpu_state.pending_exceptions_clr = cpu->pending_exceptions_clr; + for (i = 0; i < 4; i++) { + vcpu_state.core_ext_ioisr[i] = cpu->core_ext_ioisr[i]; + } + r = kvm_vcpu_ioctl(CPU(cpu), KVM_LARCH_SET_VCPU_STATE, &vcpu_state); + if (r) { + error_report("set vcpu state failed %d", r); + } + + kvm_loongarch_put_pvtime(cpu); +#endif + + restore_fp_status(env); + compute_hflags(env); + + return r; +} + +static int cpu_pre_save(void *opaque) +{ +#ifdef CONFIG_KVM + LOONGARCHCPU *cpu = opaque; + struct kvm_loongarch_vcpu_state vcpu_state; + int i, r = 0; + + r = kvm_vcpu_ioctl(CPU(cpu), KVM_LARCH_GET_VCPU_STATE, &vcpu_state); + if (r < 0) { + error_report("get vcpu state failed %d", r); + return r; + } + + cpu->online_vcpus = vcpu_state.online_vcpus; + cpu->is_migrate = vcpu_state.is_migrate; + cpu->cpu_freq = vcpu_state.cpu_freq; + cpu->count_ctl = vcpu_state.count_ctl; + cpu->pending_exceptions = vcpu_state.pending_exceptions; + cpu->pending_exceptions_clr = vcpu_state.pending_exceptions_clr; + for (i = 0; i < 4; i++) { + cpu->core_ext_ioisr[i] = vcpu_state.core_ext_ioisr[i]; + } + + kvm_loongarch_get_pvtime(cpu); +#endif + return 0; +} + +/* FPU state */ + +static int get_fpr(QEMUFile *f, void *pv, size_t size, + const VMStateField *field) +{ + fpr_t *v = pv; + qemu_get_be64s(f, &v->d); + return 0; +} + +static int put_fpr(QEMUFile *f, void *pv, size_t size, + const VMStateField *field, JSONWriter *vmdesc) +{ + fpr_t *v = pv; + qemu_put_be64s(f, &v->d); + return 0; +} + +const VMStateInfo vmstate_info_fpr = { + .name = "fpr", + .get = get_fpr, + .put = put_fpr, +}; + +#define VMSTATE_FPR_ARRAY_V(_f, _s, _n, _v) \ + VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_fpr, fpr_t) + +#define VMSTATE_FPR_ARRAY(_f, _s, _n) \ + VMSTATE_FPR_ARRAY_V(_f, _s, _n, 0) + +static VMStateField vmstate_fpu_fields[] = { + VMSTATE_FPR_ARRAY(fpr, CPULOONGARCHFPUContext, 32), + VMSTATE_UINT32(fcsr0, CPULOONGARCHFPUContext), + VMSTATE_END_OF_LIST() +}; + +const VMStateDescription vmstate_fpu = { + .name = "cpu/fpu", + .version_id = 1, + .minimum_version_id = 1, + .fields = vmstate_fpu_fields +}; + +const VMStateDescription vmstate_inactive_fpu = { + .name = "cpu/inactive_fpu", + .version_id = 1, + .minimum_version_id = 1, + .fields = vmstate_fpu_fields +}; + +/* TC state */ + +static VMStateField vmstate_tc_fields[] = { + VMSTATE_UINTTL_ARRAY(gpr, TCState, 32), + VMSTATE_UINTTL(PC, TCState), + VMSTATE_END_OF_LIST() +}; + +const VMStateDescription vmstate_tc = { + .name = "cpu/tc", + .version_id = 1, + .minimum_version_id = 1, + .fields = vmstate_tc_fields +}; + +const VMStateDescription vmstate_inactive_tc = { + .name = "cpu/inactive_tc", + .version_id = 1, + .minimum_version_id = 1, + .fields = vmstate_tc_fields +}; + +/* TLB state */ + +static int get_tlb(QEMUFile *f, void *pv, size_t size, + const VMStateField *field) +{ + ls3a5k_tlb_t *v = pv; + uint32_t flags; + + qemu_get_betls(f, &v->VPN); + qemu_get_be64s(f, &v->PageMask); + qemu_get_be32s(f, &v->PageSize); + qemu_get_be16s(f, &v->ASID); + qemu_get_be32s(f, &flags); + v->RPLV1 = (flags >> 21) & 1; + v->RPLV0 = (flags >> 20) & 1; + v->PLV1 = (flags >> 18) & 3; + v->PLV0 = (flags >> 16) & 3; + v->EHINV = (flags >> 15) & 1; + v->RI1 = (flags >> 14) & 1; + v->RI0 = (flags >> 13) & 1; + v->XI1 = (flags >> 12) & 1; + v->XI0 = (flags >> 11) & 1; + v->WE1 = (flags >> 10) & 1; + v->WE0 = (flags >> 9) & 1; + v->V1 = (flags >> 8) & 1; + v->V0 = (flags >> 7) & 1; + v->C1 = (flags >> 4) & 7; + v->C0 = (flags >> 1) & 7; + v->G = (flags >> 0) & 1; + qemu_get_be64s(f, &v->PPN0); + qemu_get_be64s(f, &v->PPN1); + + return 0; +} + +static int put_tlb(QEMUFile *f, void *pv, size_t size, + const VMStateField *field, JSONWriter *vmdesc) +{ + ls3a5k_tlb_t *v = pv; + + uint16_t asid = v->ASID; + uint32_t flags = ((v->RPLV1 << 21) | + (v->RPLV0 << 20) | + (v->PLV1 << 18) | + (v->PLV0 << 16) | + (v->EHINV << 15) | + (v->RI1 << 14) | + (v->RI0 << 13) | + (v->XI1 << 12) | + (v->XI0 << 11) | + (v->WE1 << 10) | + (v->WE0 << 9) | + (v->V1 << 8) | + (v->V0 << 7) | + (v->C1 << 4) | + (v->C0 << 1) | + (v->G << 0)); + + qemu_put_betls(f, &v->VPN); + qemu_put_be64s(f, &v->PageMask); + qemu_put_be32s(f, &v->PageSize); + qemu_put_be16s(f, &asid); + qemu_put_be32s(f, &flags); + qemu_put_be64s(f, &v->PPN0); + qemu_put_be64s(f, &v->PPN1); + + return 0; +} + +const VMStateInfo vmstate_info_tlb = { + .name = "tlb_entry", + .get = get_tlb, + .put = put_tlb, +}; + +#define VMSTATE_TLB_ARRAY_V(_f, _s, _n, _v) \ + VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_tlb, ls3a5k_tlb_t) + +#define VMSTATE_TLB_ARRAY(_f, _s, _n) \ + VMSTATE_TLB_ARRAY_V(_f, _s, _n, 0) + +const VMStateDescription vmstate_tlb = { + .name = "cpu/tlb", + .version_id = 2, + .minimum_version_id = 2, + .fields = (VMStateField[]) { + VMSTATE_UINT32(nb_tlb, CPULOONGARCHTLBContext), + VMSTATE_UINT32(tlb_in_use, CPULOONGARCHTLBContext), + VMSTATE_TLB_ARRAY(mmu.ls3a5k.tlb, CPULOONGARCHTLBContext, LOONGARCH_TLB_MAX), + VMSTATE_END_OF_LIST() + } +}; + +/* LOONGARCH CPU state */ + +const VMStateDescription vmstate_loongarch_cpu = { + .name = "cpu", + .version_id = 15, + .minimum_version_id = 15, + .post_load = cpu_post_load, + .pre_save = cpu_pre_save, + .fields = (VMStateField[]) { + /* Active TC */ + VMSTATE_STRUCT(env.active_tc, LOONGARCHCPU, 1, vmstate_tc, TCState), + + /* Active FPU */ + VMSTATE_STRUCT(env.active_fpu, LOONGARCHCPU, 1, vmstate_fpu, + CPULOONGARCHFPUContext), + + /* TLB */ + VMSTATE_STRUCT_POINTER(env.tlb, LOONGARCHCPU, vmstate_tlb, + CPULOONGARCHTLBContext), + /* CPU metastate */ + VMSTATE_UINT32(env.current_tc, LOONGARCHCPU), + VMSTATE_INT32(env.error_code, LOONGARCHCPU), + VMSTATE_UINTTL(env.btarget, LOONGARCHCPU), + VMSTATE_UINTTL(env.bcond, LOONGARCHCPU), + + VMSTATE_UINT64(env.lladdr, LOONGARCHCPU), + + /* PV time */ + VMSTATE_UINT64(env.st.guest_addr, LOONGARCHCPU), + + /* Remaining CSR registers */ + VMSTATE_UINT64(env.CSR_CRMD, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PRMD, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_EUEN, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_MISC, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_ECFG, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_ESTAT, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_ERA, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_BADV, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_BADI, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_EEPN, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBIDX, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBEHI, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBELO0, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBELO1, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBWIRED, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_GTLBC, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TRGP, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PGDL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PGDH, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PGD, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PWCTL0, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PWCTL1, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_STLBPGSIZE, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_RVACFG, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_CPUID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PRCFG1, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PRCFG2, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PRCFG3, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_KS0, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_KS1, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_KS2, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_KS3, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_KS4, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_KS5, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_KS6, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_KS7, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TMID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TCFG, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TVAL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_CNTC, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TINTCLR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_GSTAT, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_GCFG, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_GINTC, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_GCNTC, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_LLBCTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IMPCTL1, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IMPCTL2, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_GNMI, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBRENT, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBRBADV, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBRERA, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBRSAVE, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBRELO0, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBRELO1, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBREHI, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_TLBRPRMD, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_ERRCTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_ERRINFO, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_ERRINFO1, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_ERRENT, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_ERRERA, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_ERRSAVE, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_CTAG, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DMWIN0, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DMWIN1, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DMWIN2, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DMWIN3, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PERFCTRL0, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PERFCNTR0, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PERFCTRL1, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PERFCNTR1, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PERFCTRL2, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PERFCNTR2, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PERFCTRL3, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_PERFCNTR3, LOONGARCHCPU), + /* debug */ + VMSTATE_UINT64(env.CSR_MWPC, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_MWPS, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB0ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB0MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB0CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB0ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB1ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB1MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB1CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB1ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB2ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB2MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB2CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB2ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB3ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB3MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB3CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DB3ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_FWPC, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_FWPS, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB0ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB0MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB0CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB0ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB1ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB1MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB1CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB1ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB2ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB2MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB2CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB2ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB3ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB3MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB3CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB3ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB4ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB4MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB4CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB4ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB5ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB5MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB5CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB5ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB6ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB6MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB6CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB6ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB7ADDR, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB7MASK, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB7CTL, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_IB7ASID, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DEBUG, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DERA, LOONGARCHCPU), + VMSTATE_UINT64(env.CSR_DESAVE, LOONGARCHCPU), + + VMSTATE_STRUCT_ARRAY(env.fpus, LOONGARCHCPU, LOONGARCH_FPU_MAX, 1, + vmstate_inactive_fpu, CPULOONGARCHFPUContext), + VMSTATE_UINT8(online_vcpus, LOONGARCHCPU), + VMSTATE_UINT8(is_migrate, LOONGARCHCPU), + VMSTATE_UINT64(counter_value, LOONGARCHCPU), + VMSTATE_UINT32(cpu_freq, LOONGARCHCPU), + VMSTATE_UINT32(count_ctl, LOONGARCHCPU), + VMSTATE_UINT64(pending_exceptions, LOONGARCHCPU), + VMSTATE_UINT64(pending_exceptions_clr, LOONGARCHCPU), + VMSTATE_UINT64_ARRAY(core_ext_ioisr, LOONGARCHCPU, 4), + + VMSTATE_END_OF_LIST() + }, +}; diff --git a/target/loongarch64/meson.build b/target/loongarch64/meson.build new file mode 100644 index 0000000000..6badf4484e --- /dev/null +++ b/target/loongarch64/meson.build @@ -0,0 +1,35 @@ +loongarch_user_ss = ss.source_set() +loongarch_softmmu_ss = ss.source_set() +loongarch_ss = ss.source_set() +loongarch_ss.add(files( + 'cpu.c', + 'fpu.c', + 'gdbstub.c', +)) + +gen = [ + decodetree.process('insn.decode', extra_args: [ '--decode', 'decode_insn', + '--insnwidth', '32' ]) +] + +loongarch_ss.add(gen) +loongarch_ss.add(when: 'CONFIG_TCG', if_true: files( + 'helper.c', + 'translate.c', + 'op_helper.c', + 'fpu_helper.c', + 'tlb_helper.c', + 'csr_helper.c', +)) + +loongarch_softmmu_ss.add(when: 'CONFIG_SOFTMMU', if_true: files( + 'machine.c', + 'stabletimer.c', + 'arch_dump.c', +)) + +loongarch_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) + +target_arch += {'loongarch64': loongarch_ss} +target_softmmu_arch += {'loongarch64': loongarch_softmmu_ss} +target_user_arch += {'loongarch64': loongarch_user_ss} diff --git a/target/loongarch64/op_helper.c b/target/loongarch64/op_helper.c new file mode 100644 index 0000000000..9a34c0d25e --- /dev/null +++ b/target/loongarch64/op_helper.c @@ -0,0 +1,533 @@ +/* + * LOONGARCH emulation helpers for qemu. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "cpu.h" +#include "internal.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "sysemu/kvm.h" +#include "qemu/crc32c.h" +#include +#include "hw/irq.h" +#include "hw/core/cpu.h" +#include "instmap.h" + +/*****************************************************************************/ +/* Exceptions processing helpers */ + +void helper_raise_exception_err(CPULOONGARCHState *env, uint32_t exception, + int error_code) +{ + do_raise_exception_err(env, exception, error_code, 0); +} + +void helper_raise_exception(CPULOONGARCHState *env, uint32_t exception) +{ + do_raise_exception(env, exception, GETPC()); +} + +void helper_raise_exception_debug(CPULOONGARCHState *env) +{ + do_raise_exception(env, EXCP_DEBUG, 0); +} + +static void raise_exception(CPULOONGARCHState *env, uint32_t exception) +{ + do_raise_exception(env, exception, 0); +} + +#if defined(CONFIG_USER_ONLY) +#define HELPER_LD(name, insn, type) \ +static inline type do_##name(CPULOONGARCHState *env, target_ulong addr, \ + int mem_idx, uintptr_t retaddr) \ +{ \ + return (type) cpu_##insn##_data_ra(env, addr, retaddr); \ +} +#else + +#define HF_SMAP_SHIFT 23 /* CR4.SMAP */ +#define HF_SMAP_MASK (1 << HF_SMAP_SHIFT) +#define MMU_KNOSMAP_IDX 2 +#define HF_CPL_SHIFT 0 +#define HF_CPL_MASK (3 << HF_CPL_SHIFT) +#define AC_MASK 0x00040000 +#define MMU_KSMAP_IDX 0 +static inline int cpu_mmu_index_kernel(CPULOONGARCHState *env) +{ + return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX : + ((env->hflags & HF_CPL_MASK) < 3 && (env->hflags & AC_MASK)) + ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX; +} + +#define cpu_ldl_kernel_ra(e, p, r) \ + cpu_ldl_mmuidx_ra(e, p, cpu_mmu_index_kernel(e), r) + +#define HELPER_LD(name, insn, type) \ +static inline type do_##name(CPULOONGARCHState *env, target_ulong addr, \ + int mem_idx, uintptr_t retaddr) \ +{ \ +/* \ + switch (mem_idx) { \ + case 0: return (type) cpu_##insn##_kernel_ra(env, addr, retaddr); \ + case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr); \ + default: \ + case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr); \ + case 3: return (type) cpu_##insn##_error_ra(env, addr, retaddr); \ + } \ +*/ \ +} +#endif +#if 0 +HELPER_LD(lw, ldl, int32_t) +HELPER_LD(ld, ldq, int64_t) +#endif +#undef HELPER_LD + +#if defined(CONFIG_USER_ONLY) +#define HELPER_ST(name, insn, type) \ +static inline void do_##name(CPULOONGARCHState *env, target_ulong addr, \ + type val, int mem_idx, uintptr_t retaddr) \ +{ \ +/* \ + cpu_##insn##_data_ra(env, addr, val, retaddr); \ +*/ \ +} +#else +#define HELPER_ST(name, insn, type) \ +static inline void do_##name(CPULOONGARCHState *env, target_ulong addr, \ + type val, int mem_idx, uintptr_t retaddr) \ +{ \ +/* \ + switch (mem_idx) { \ + case 0: \ + cpu_##insn##_kernel_ra(env, addr, val, retaddr); \ + break; \ + case 1: \ + cpu_##insn##_super_ra(env, addr, val, retaddr); \ + break; \ + default: \ + case 2: \ + cpu_##insn##_user_ra(env, addr, val, retaddr); \ + break; \ + case 3: \ + cpu_##insn##_error_ra(env, addr, val, retaddr); \ + break; \ + } \ +*/ \ +} +#endif +#if 0 +HELPER_ST(sb, stb, uint8_t) +HELPER_ST(sw, stl, uint32_t) +HELPER_ST(sd, stq, uint64_t) +#endif +#undef HELPER_ST + +static inline target_ulong bitswap(target_ulong v) +{ + v = ((v >> 1) & (target_ulong)0x5555555555555555ULL) | + ((v & (target_ulong)0x5555555555555555ULL) << 1); + v = ((v >> 2) & (target_ulong)0x3333333333333333ULL) | + ((v & (target_ulong)0x3333333333333333ULL) << 2); + v = ((v >> 4) & (target_ulong)0x0F0F0F0F0F0F0F0FULL) | + ((v & (target_ulong)0x0F0F0F0F0F0F0F0FULL) << 4); + return v; +} + +target_ulong helper_dbitswap(target_ulong rt) +{ + return bitswap(rt); +} + +target_ulong helper_bitswap(target_ulong rt) +{ + return (int32_t)bitswap(rt); +} + +/* these crc32 functions are based on target/arm/helper-a64.c */ +target_ulong helper_crc32(target_ulong val, target_ulong m, uint32_t sz) +{ + uint8_t buf[8]; + target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1); + + m &= mask; + stq_le_p(buf, m); + return (int32_t) (crc32(val ^ 0xffffffff, buf, sz) ^ 0xffffffff); +} + +target_ulong helper_crc32c(target_ulong val, target_ulong m, uint32_t sz) +{ + uint8_t buf[8]; + target_ulong mask = ((sz * 8) == 64) ? -1ULL : ((1ULL << (sz * 8)) - 1); + m &= mask; + stq_le_p(buf, m); + return (int32_t) (crc32c(val, buf, sz) ^ 0xffffffff); +} + +#ifndef CONFIG_USER_ONLY + +#define HELPER_LD_ATOMIC(name, insn, almask) \ +target_ulong helper_##name(CPULOONGARCHState *env, target_ulong arg, int mem_idx) \ +{ \ +/* \ + if (arg & almask) { \ + env->CSR_BADV = arg; \ + do_raise_exception(env, EXCP_AdEL, GETPC()); \ + } \ + env->lladdr = arg; \ + env->llval = do_##insn(env, arg, mem_idx, GETPC()); \ + return env->llval; \ +*/ \ +} +#if 0 +HELPER_LD_ATOMIC(ll, lw, 0x3) +HELPER_LD_ATOMIC(lld, ld, 0x7) +#endif +#undef HELPER_LD_ATOMIC +#endif + +#ifndef CONFIG_USER_ONLY +void helper_drdtime(CPULOONGARCHState *env, target_ulong rd, target_ulong rs) +{ + env->active_tc.gpr[rd] = cpu_loongarch_get_stable_counter(env); + env->active_tc.gpr[rs] = env->CSR_TMID; +} +#endif + +#ifndef CONFIG_USER_ONLY +static void debug_pre_ertn(CPULOONGARCHState *env) +{ + if (qemu_loglevel_mask(CPU_LOG_EXEC)) { + qemu_log("ERTN: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx, + env->active_tc.PC, env->CSR_ERA); + qemu_log("\n"); + } +} + +static void debug_post_ertn(CPULOONGARCHState *env) +{ + if (qemu_loglevel_mask(CPU_LOG_EXEC)) { + qemu_log("ERTN: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx, + env->active_tc.PC, env->CSR_ERA); + } +} + +static void set_pc(CPULOONGARCHState *env, target_ulong error_pc) +{ + env->active_tc.PC = error_pc & ~(target_ulong)1; +} + +static inline void exception_return(CPULOONGARCHState *env) +{ + debug_pre_ertn(env); + + if (cpu_refill_state(env)) { + env->CSR_CRMD &= (~0x7); + env->CSR_CRMD |= (env->CSR_TLBRPRMD & 0x7); + /* Clear Refill flag and set pc */ + env->CSR_TLBRERA &= (~0x1); + set_pc(env, env->CSR_TLBRERA); + if (qemu_loglevel_mask(CPU_LOG_INT)) { + qemu_log("%s: TLBRERA 0x%lx\n", __func__, env->CSR_TLBRERA); + } + } else { + env->CSR_CRMD &= (~0x7); + env->CSR_CRMD |= (env->CSR_PRMD & 0x7); + /* Clear Refill flag and set pc*/ + set_pc(env, env->CSR_ERA); + if (qemu_loglevel_mask(CPU_LOG_INT)) { + qemu_log("%s: ERA 0x%lx\n", __func__, env->CSR_ERA); + } + } + + compute_hflags(env); + debug_post_ertn(env); +} + +void helper_ertn(CPULOONGARCHState *env) +{ + exception_return(env); + env->lladdr = 1; +} + +#endif /* !CONFIG_USER_ONLY */ + +void helper_idle(CPULOONGARCHState *env) +{ + CPUState *cs = CPU(loongarch_env_get_cpu(env)); + + cs->halted = 1; + cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE); + /* Last instruction in the block, PC was updated before + - no need to recover PC and icount */ + raise_exception(env, EXCP_HLT); +} + +#if !defined(CONFIG_USER_ONLY) + +void loongarch_cpu_do_unaligned_access(CPUState *cs, vaddr addr, + MMUAccessType access_type, + int mmu_idx, uintptr_t retaddr) +{ + while(1); +} + +#endif /* !CONFIG_USER_ONLY */ + +void helper_store_scr(CPULOONGARCHState *env, uint32_t n, target_ulong val) +{ + env->scr[n & 0x3] = val; +} + +target_ulong helper_load_scr(CPULOONGARCHState *env, uint32_t n) +{ + return env->scr[n & 0x3]; +} + +/* loongarch assert op */ +void helper_asrtle_d(CPULOONGARCHState *env, target_ulong rs, target_ulong rt) +{ + if (rs > rt) { + do_raise_exception(env, EXCP_AdEL, GETPC()); + } +} + +void helper_asrtgt_d(CPULOONGARCHState *env, target_ulong rs, target_ulong rt) +{ + if (rs <= rt) { + do_raise_exception(env, EXCP_AdEL, GETPC()); + } +} + +target_ulong helper_cto_w(CPULOONGARCHState *env, target_ulong a0) +{ + uint32_t v = (uint32_t)a0; + int temp = 0; + + while ((v & 0x1) == 1) { + temp++; + v = v >> 1; + } + + return (target_ulong)temp; +} + +target_ulong helper_ctz_w(CPULOONGARCHState *env, target_ulong a0) +{ + uint32_t v = (uint32_t)a0; + + if (v == 0) { + return 32; + } + + int temp = 0; + while ((v & 0x1) == 0) { + temp++; + v = v >> 1; + } + + return (target_ulong)temp; +} + +target_ulong helper_cto_d(CPULOONGARCHState *env, target_ulong a0) +{ + uint64_t v = a0; + int temp = 0; + + while ((v & 0x1) == 1) { + temp++; + v = v >> 1; + } + + return (target_ulong)temp; +} + +target_ulong helper_ctz_d(CPULOONGARCHState *env, target_ulong a0) +{ + uint64_t v = a0; + + if (v == 0) { + return 64; + } + + int temp = 0; + while ((v & 0x1) == 0) { + temp++; + v = v >> 1; + } + + return (target_ulong)temp; +} + +target_ulong helper_bitrev_w(CPULOONGARCHState *env, target_ulong a0) +{ + int32_t v = (int32_t)a0; + const int SIZE = 32; + uint8_t bytes[SIZE]; + + int i; + for (i = 0; i < SIZE; i++) { + bytes[i] = v & 0x1; + v = v >> 1; + } + /* v == 0 */ + for (i = 0; i < SIZE; i++) { + v = v | ((uint32_t)bytes[i] << (SIZE - 1 - i)); + } + + return (target_ulong)(int32_t)v; +} + +target_ulong helper_bitrev_d(CPULOONGARCHState *env, target_ulong a0) +{ + uint64_t v = a0; + const int SIZE = 64; + uint8_t bytes[SIZE]; + + int i; + for (i = 0; i < SIZE; i++) { + bytes[i] = v & 0x1; + v = v >> 1; + } + /* v == 0 */ + for (i = 0; i < SIZE; i++) { + v = v | ((uint64_t)bytes[i] << (SIZE - 1 - i)); + } + + return (target_ulong)v; +} + +void helper_memtrace_addr(CPULOONGARCHState *env, + target_ulong address, uint32_t op) +{ + qemu_log("[cpu %d asid 0x%lx pc 0x%lx] addr 0x%lx op", + CPU(loongarch_env_get_cpu(env))->cpu_index, + env->CSR_ASID, env->active_tc.PC, address); + switch (op) { + case OPC_LARCH_LDPTR_D: + qemu_log("OPC_LARCH_LDPTR_D"); + break; + case OPC_LARCH_LD_D: + qemu_log("OPC_LARCH_LD_D"); + break; + case OPC_LARCH_LDPTR_W: + qemu_log("OPC_LARCH_LDPTR_W"); + break; + case OPC_LARCH_LD_W: + qemu_log("OPC_LARCH_LD_W"); + break; + case OPC_LARCH_LD_H: + qemu_log("OPC_LARCH_LD_H"); + break; + case OPC_LARCH_LD_B: + qemu_log("OPC_LARCH_LD_B"); + break; + case OPC_LARCH_LD_WU: + qemu_log("OPC_LARCH_LD_WU"); + break; + case OPC_LARCH_LD_HU: + qemu_log("OPC_LARCH_LD_HU"); + break; + case OPC_LARCH_LD_BU: + qemu_log("OPC_LARCH_LD_BU"); + break; + case OPC_LARCH_STPTR_D: + qemu_log("OPC_LARCH_STPTR_D"); + break; + case OPC_LARCH_ST_D: + qemu_log("OPC_LARCH_ST_D"); + break; + case OPC_LARCH_STPTR_W: + qemu_log("OPC_LARCH_STPTR_W"); + break; + case OPC_LARCH_ST_W: + qemu_log("OPC_LARCH_ST_W"); + break; + case OPC_LARCH_ST_H: + qemu_log("OPC_LARCH_ST_H"); + break; + case OPC_LARCH_ST_B: + qemu_log("OPC_LARCH_ST_B"); + break; + case OPC_LARCH_FLD_S: + qemu_log("OPC_LARCH_FLD_S"); + break; + case OPC_LARCH_FLD_D: + qemu_log("OPC_LARCH_FLD_D"); + break; + case OPC_LARCH_FST_S: + qemu_log("OPC_LARCH_FST_S"); + break; + case OPC_LARCH_FST_D: + qemu_log("OPC_LARCH_FST_D"); + break; + case OPC_LARCH_FLDX_S: + qemu_log("OPC_LARCH_FLDX_S"); + break; + case OPC_LARCH_FLDGT_S: + qemu_log("OPC_LARCH_FLDGT_S"); + break; + case OPC_LARCH_FLDLE_S: + qemu_log("OPC_LARCH_FLDLE_S"); + break;; + case OPC_LARCH_FSTX_S: + qemu_log("OPC_LARCH_FSTX_S"); + break; + case OPC_LARCH_FSTGT_S: + qemu_log("OPC_LARCH_FSTGT_S"); + break; + case OPC_LARCH_FSTLE_S: + qemu_log("OPC_LARCH_FSTLE_S"); + break; + case OPC_LARCH_FLDX_D: + qemu_log("OPC_LARCH_FLDX_D"); + break; + case OPC_LARCH_FLDGT_D: + qemu_log("OPC_LARCH_FLDGT_D"); + break; + case OPC_LARCH_FLDLE_D: + qemu_log("OPC_LARCH_FLDLE_D"); + break;; + case OPC_LARCH_FSTX_D: + qemu_log("OPC_LARCH_FSTX_D"); + break; + case OPC_LARCH_FSTGT_D: + qemu_log("OPC_LARCH_FSTGT_D"); + break; + case OPC_LARCH_FSTLE_D: + qemu_log("OPC_LARCH_FSTLE_D"); + break; + case OPC_LARCH_LL_W: + qemu_log("OPC_LARCH_LL_W"); + break; + case OPC_LARCH_LL_D: + qemu_log("OPC_LARCH_LL_D"); + break; + default: + qemu_log("0x%x", op); + } +} + +void helper_memtrace_val(CPULOONGARCHState *env, target_ulong val) +{ + qemu_log("val 0x%lx\n", val); +} diff --git a/target/loongarch64/stabletimer.c b/target/loongarch64/stabletimer.c new file mode 100644 index 0000000000..b86fecf899 --- /dev/null +++ b/target/loongarch64/stabletimer.c @@ -0,0 +1,122 @@ +/* + * QEMU LOONGARCH timer support + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "hw/loongarch/cpudevs.h" +#include "qemu/timer.h" +#include "sysemu/kvm.h" +#include "internal.h" +#include "hw/irq.h" + + +#ifdef DEBUG_TIMER +#define debug_timer(fmt, args...) printf("%s(%d)-%s -> " #fmt "\n", \ + __FILE__, __LINE__, __func__, ##args); +#else +#define debug_timer(fmt, args...) +#endif + +#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */ +#define STABLETIMER_TICK_MASK 0xfffffffffffcUL +#define STABLETIMER_ENABLE 0x1UL +#define STABLETIMER_PERIOD 0x2UL + +/* return random value in [low, high] */ +uint32_t cpu_loongarch_get_random_ls3a5k_tlb(uint32_t low, uint32_t high) +{ + static uint32_t seed = 5; + static uint32_t prev_idx; + uint32_t idx; + uint32_t nb_rand_tlb = high - low + 1; + + do { + seed = 1103515245 * seed + 12345; + idx = (seed >> 16) % nb_rand_tlb + low; + } while (idx == prev_idx); + prev_idx = idx; + + return idx; +} + +/* LOONGARCH timer */ +uint64_t cpu_loongarch_get_stable_counter(CPULOONGARCHState *env) +{ + return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD; +} + +uint64_t cpu_loongarch_get_stable_timer_ticks(CPULOONGARCHState *env) +{ + uint64_t now, expire; + + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + expire = timer_expire_time_ns(env->timer); + + return (expire - now) / TIMER_PERIOD; +} + +void cpu_loongarch_store_stable_timer_config(CPULOONGARCHState *env, + uint64_t value) +{ + uint64_t now, next; + + env->CSR_TCFG = value; + if (value & STABLETIMER_ENABLE) { + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + next = now + (value & STABLETIMER_TICK_MASK) * TIMER_PERIOD; + timer_mod(env->timer, next); + } + debug_timer("0x%lx 0x%lx now 0x%lx, next 0x%lx", + value, env->CSR_TCFG, now, next); +} + +static void loongarch_stable_timer_cb(void *opaque) +{ + CPULOONGARCHState *env; + uint64_t now, next; + + env = opaque; + debug_timer(); + if (env->CSR_TCFG & STABLETIMER_PERIOD) { + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + next = now + (env->CSR_TCFG & STABLETIMER_TICK_MASK) * TIMER_PERIOD; + timer_mod(env->timer, next); + } else { + env->CSR_TCFG &= ~STABLETIMER_ENABLE; + } + + qemu_irq_raise(env->irq[IRQ_TIMER]); + +} + +void cpu_loongarch_clock_init(LOONGARCHCPU *cpu) +{ + CPULOONGARCHState *env = &cpu->env; + + /* + * If we're in KVM mode, don't create the periodic timer, that is handled in + * kernel. + */ + if (!kvm_enabled()) { + env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + &loongarch_stable_timer_cb, env); + } +} diff --git a/target/loongarch64/tlb_helper.c b/target/loongarch64/tlb_helper.c new file mode 100644 index 0000000000..f5e68349a9 --- /dev/null +++ b/target/loongarch64/tlb_helper.c @@ -0,0 +1,729 @@ +/* + * loongarch tlb emulation helpers for qemu. + * + * Copyright (c) 2020 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "cpu.h" +#include "internal.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" + +#ifndef CONFIG_USER_ONLY + +#define HELPER_LD(name, insn, type) \ +static inline type do_##name(CPULOONGARCHState *env, target_ulong addr, \ + int mem_idx, uintptr_t retaddr) \ +{ \ +/* \ + switch (mem_idx) { \ + case 0: return (type) cpu_##insn##_kernel_ra(env, addr, retaddr); \ + case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr); \ + default: \ + case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr); \ + case 3: return (type) cpu_##insn##_error_ra(env, addr, retaddr); \ + } \ +*/ \ +} +#if 0 +HELPER_LD(lw, ldl, int32_t) +HELPER_LD(ld, ldq, int64_t) +#endif + +void helper_lddir(CPULOONGARCHState *env, target_ulong base, target_ulong rt, + target_ulong level, uint32_t mem_idx) +{ +#if 0 + target_ulong pointer = env->active_tc.gpr[base]; + target_ulong badvaddr; + target_ulong index; + target_ulong vaddr; + int shift; + + badvaddr = env->CSR_TLBRBADV; + + /* 0:8B, 1:16B, 2:32B, 3:64B */ + shift = (env->CSR_PWCTL0 >> 30) & 0x3; + shift = (shift + 1) * 3; + + switch (level) { + case 1: + index = (badvaddr >> ((env->CSR_PWCTL0 >> 10) & 0x1f)) & \ + ((1 << ((env->CSR_PWCTL0 >> 15) & 0x1f)) - 1); + break; + case 3: + index = (badvaddr >> ((env->CSR_PWCTL1 >> 0) & 0x3f)) & \ + ((1 << ((env->CSR_PWCTL1 >> 6) & 0x3f)) - 1); + break; + default: + do_raise_exception(env, EXCP_RI, GETPC()); + return; + } + + vaddr = pointer | index << shift; + env->active_tc.gpr[rt] = do_ld(env, vaddr, mem_idx, GETPC()); + return; +#endif +} + +void helper_ldpte(CPULOONGARCHState *env, target_ulong base, target_ulong odd, + uint32_t mem_idx) +{ +#if 0 + target_ulong pointer = env->active_tc.gpr[base]; + target_ulong vaddr; + target_ulong tmp0 = 1; + target_ulong ptindex, ptoffset0, ptoffset1; + target_ulong pagesize; + target_ulong badv; + int shift; + bool huge = pointer & LOONGARCH_PAGE_HUGE; + + if (huge) { + /* Huge Page. pointer is paddr */ + tmp0 = pointer ^ LOONGARCH_PAGE_HUGE; + /* move Global bit */ + tmp0 |= ((tmp0 & LOONGARCH_HUGE_GLOBAL) + >> (LOONGARCH_HUGE_GLOBAL_SH - CSR_TLBLO0_GLOBAL_SHIFT)); + pagesize = (env->CSR_PWCTL0 & 0x1f) + + ((env->CSR_PWCTL0 >> 5) & 0x1f) - 1; + if (odd) { + tmp0 += (1 << pagesize); + } + } else { + /* 0:8B, 1:16B, 2:32B, 3:64B */ + shift = (env->CSR_PWCTL0 >> 30) & 0x3; + shift = (shift + 1) * 3; + badv = env->CSR_TLBRBADV; + + ptindex = (badv >> (env->CSR_PWCTL0 & 0x1f)) & + ((1 << ((env->CSR_PWCTL0 >> 5) & 0x1f)) - 1); + ptindex = ptindex & ~0x1; /* clear bit 0 */ + ptoffset0 = ptindex << shift; + ptoffset1 = (ptindex + 1) << shift; + + vaddr = pointer | (odd ? ptoffset1 : ptoffset0); + tmp0 = do_ld(env, vaddr, mem_idx, GETPC()); + pagesize = (env->CSR_PWCTL0 & 0x1f); + } + if (odd) { + env->CSR_TLBRELO1 = tmp0; + } else { + env->CSR_TLBRELO0 = tmp0; + } + env->CSR_TLBREHI = env->CSR_TLBREHI & (~0x3f); + env->CSR_TLBREHI = env->CSR_TLBREHI | pagesize; +#endif + return; +} + +target_ulong helper_read_pgd(CPULOONGARCHState *env) +{ + uint64_t badv; + + assert(env->CSR_TLBRERA & 0x1); + + if (env->CSR_TLBRERA & 0x1) { + badv = env->CSR_TLBRBADV; + } else { + badv = env->CSR_BADV; + } + + if ((badv >> 63) & 0x1) { + return env->CSR_PGDH; + } else { + return env->CSR_PGDL; + } +} + +/* TLB management */ +static uint64_t ls3a5k_pagesize_to_mask(int pagesize) +{ + /* 4KB - 1GB */ + if (pagesize < 12 && pagesize > 30) { + printf("[ERROR] unsupported page size %d\n", pagesize); + exit(-1); + } + + return (1 << (pagesize + 1)) - 1; +} + +static void ls3a5k_fill_tlb_entry(CPULOONGARCHState *env, + ls3a5k_tlb_t *tlb, int is_ftlb) +{ + uint64_t page_mask; /* 0000...00001111...1111 */ + uint32_t page_size; + uint64_t entryhi; + uint64_t lo0, lo1; + + if (env->CSR_TLBRERA & 0x1) { + page_size = env->CSR_TLBREHI & 0x3f; + entryhi = env->CSR_TLBREHI; + lo0 = env->CSR_TLBRELO0; + lo1 = env->CSR_TLBRELO1; + } else { + page_size = (env->CSR_TLBIDX >> CSR_TLBIDX_PS_SHIFT) & 0x3f; + entryhi = env->CSR_TLBEHI; + lo0 = env->CSR_TLBELO0; + lo1 = env->CSR_TLBELO1; + } + + if (page_size == 0) { + printf("Warning: page_size is 0\n"); + } + + /* 15-12 11-8 7-4 3-0 + * 4KB: 0001 1111 1111 1111 // double 4KB mask [12:0] + * 16KB: 0111 1111 1111 1111 // double 16KB mask [14:0] + */ + if (is_ftlb) { + page_mask = env->tlb->mmu.ls3a5k.ftlb_mask; + } else { + page_mask = ls3a5k_pagesize_to_mask(page_size); + } + + tlb->VPN = entryhi & 0xffffffffe000 & ~page_mask; + + tlb->ASID = env->CSR_ASID & 0x3ff; /* CSR_ASID[9:0] */ + tlb->EHINV = 0; + tlb->G = (lo0 >> CSR_TLBLO0_GLOBAL_SHIFT) & /* CSR_TLBLO[6] */ + (lo1 >> CSR_TLBLO1_GLOBAL_SHIFT) & 1; + + tlb->PageMask = page_mask; + tlb->PageSize = page_size; + + tlb->V0 = (lo0 >> CSR_TLBLO0_V_SHIFT) & 0x1; /* [0] */ + tlb->WE0 = (lo0 >> CSR_TLBLO0_WE_SHIFT) & 0x1; /* [1] */ + tlb->PLV0 = (lo0 >> CSR_TLBLO0_PLV_SHIFT) & 0x3; /* [3:2] */ + tlb->C0 = (lo0 >> CSR_TLBLO0_CCA_SHIFT) & 0x3; /* [5:4] */ + tlb->PPN0 = (lo0 & 0xfffffffff000 & ~(page_mask >> 1)); + tlb->RI0 = (lo0 >> CSR_TLBLO0_RI_SHIFT) & 0x1; /* [61] */ + tlb->XI0 = (lo0 >> CSR_TLBLO0_XI_SHIFT) & 0x1; /* [62] */ + tlb->RPLV0 = (lo0 >> CSR_TLBLO0_RPLV_SHIFT) & 0x1; /* [63] */ + + tlb->V1 = (lo1 >> CSR_TLBLO1_V_SHIFT) & 0x1; /* [0] */ + tlb->WE1 = (lo1 >> CSR_TLBLO1_WE_SHIFT) & 0x1; /* [1] */ + tlb->PLV1 = (lo1 >> CSR_TLBLO1_PLV_SHIFT) & 0x3; /* [3:2] */ + tlb->C1 = (lo1 >> CSR_TLBLO1_CCA_SHIFT) & 0x3; /* [5:4] */ + tlb->PPN1 = (lo1 & 0xfffffffff000 & ~(page_mask >> 1)); + tlb->RI1 = (lo1 >> CSR_TLBLO1_RI_SHIFT) & 0x1; /* [61] */ + tlb->XI1 = (lo1 >> CSR_TLBLO1_XI_SHIFT) & 0x1; /* [62] */ + tlb->RPLV1 = (lo1 >> CSR_TLBLO1_RPLV_SHIFT) & 0x1; /* [63] */ +} + +static void ls3a5k_fill_tlb(CPULOONGARCHState *env, int idx, bool tlbwr) +{ + ls3a5k_tlb_t *tlb; + + tlb = &env->tlb->mmu.ls3a5k.tlb[idx]; + if (tlbwr) { + if ((env->CSR_TLBIDX >> CSR_TLBIDX_EHINV_SHIFT) & 0x1) { + tlb->EHINV = 1; + return; + } + } + + if (idx < 2048) { + ls3a5k_fill_tlb_entry(env, tlb, 1); + } else { + ls3a5k_fill_tlb_entry(env, tlb, 0); + } +} + +void ls3a5k_flush_vtlb(CPULOONGARCHState *env) +{ + uint32_t ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; + uint32_t vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; + int i; + + ls3a5k_tlb_t *tlb; + + for (i = ftlb_size; i < ftlb_size + vtlb_size; ++i) { + tlb = &env->tlb->mmu.ls3a5k.tlb[i]; + tlb->EHINV = 1; + } + + cpu_loongarch_tlb_flush(env); +} + +void ls3a5k_flush_ftlb(CPULOONGARCHState *env) +{ + uint32_t ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; + int i; + + ls3a5k_tlb_t *tlb; + + for (i = 0; i < ftlb_size; ++i) { + tlb = &env->tlb->mmu.ls3a5k.tlb[i]; + tlb->EHINV = 1; + } + + cpu_loongarch_tlb_flush(env); +} + +void ls3a5k_helper_tlbclr(CPULOONGARCHState *env) +{ + int i; + uint16_t asid; + int vsize, fsize, index; + int start = 0, end = -1; + + asid = env->CSR_ASID & 0x3ff; + vsize = env->tlb->mmu.ls3a5k.vtlb_size; + fsize = env->tlb->mmu.ls3a5k.ftlb_size; + index = env->CSR_TLBIDX & CSR_TLBIDX_IDX; + + if (index < fsize) { + /* FTLB. One line per operation */ + int set = index % 256; + start = set * 8; + end = start + 7; + } else if (index < (fsize + vsize)) { + /* VTLB. All entries */ + start = fsize; + end = fsize + vsize - 1; + } else { + /* Ignore */ + } + + for (i = start; i <= end; i++) { + ls3a5k_tlb_t *tlb; + tlb = &env->tlb->mmu.ls3a5k.tlb[i]; + if (!tlb->G && tlb->ASID == asid) { + tlb->EHINV = 1; + } + } + + cpu_loongarch_tlb_flush(env); +} + +void ls3a5k_helper_tlbflush(CPULOONGARCHState *env) +{ + int i; + int vsize, fsize, index; + int start = 0, end = -1; + + vsize = env->tlb->mmu.ls3a5k.vtlb_size; + fsize = env->tlb->mmu.ls3a5k.ftlb_size; + index = env->CSR_TLBIDX & CSR_TLBIDX_IDX; + + if (index < fsize) { + /* FTLB. One line per operation */ + int set = index % 256; + start = set * 8; + end = start + 7; + } else if (index < (fsize + vsize)) { + /* VTLB. All entries */ + start = fsize; + end = fsize + vsize - 1; + } else { + /* Ignore */ + } + + for (i = start; i <= end; i++) { + env->tlb->mmu.ls3a5k.tlb[i].EHINV = 1; + } + + cpu_loongarch_tlb_flush(env); +} + +void ls3a5k_helper_invtlb(CPULOONGARCHState *env, target_ulong addr, + target_ulong info, int op) +{ + uint32_t asid = info & 0x3ff; + int i; + + switch (op) { + case 0: + case 1: + for (i = 0; i < env->tlb->nb_tlb; i++) { + env->tlb->mmu.ls3a5k.tlb[i].EHINV = 1; + } + break; + case 4: { + int i; + for (i = 0; i < env->tlb->nb_tlb; i++) { + struct ls3a5k_tlb_t *tlb = &env->tlb->mmu.ls3a5k.tlb[i]; + + if (!tlb->G && tlb->ASID == asid) { + tlb->EHINV = 1; + } + } + break; + } + + case 5: { + int i; + for (i = 0; i < env->tlb->nb_tlb; i++) { + struct ls3a5k_tlb_t *tlb = &env->tlb->mmu.ls3a5k.tlb[i]; + uint64_t vpn = addr & 0xffffffffe000 & ~tlb->PageMask; + + if (!tlb->G && tlb->ASID == asid && vpn == tlb->VPN) { + tlb->EHINV = 1; + } + } + break; + } + case 6: { + int i; + for (i = 0; i < env->tlb->nb_tlb; i++) { + struct ls3a5k_tlb_t *tlb = &env->tlb->mmu.ls3a5k.tlb[i]; + uint64_t vpn = addr & 0xffffffffe000 & ~tlb->PageMask; + + if ((tlb->G || tlb->ASID == asid) && vpn == tlb->VPN) { + tlb->EHINV = 1; + } + } + break; + } + default: + helper_raise_exception(env, EXCP_RI); + } + + cpu_loongarch_tlb_flush(env); +} + +static void ls3a5k_invalidate_tlb_entry(CPULOONGARCHState *env, + ls3a5k_tlb_t *tlb) +{ + LOONGARCHCPU *cpu = loongarch_env_get_cpu(env); + CPUState *cs = CPU(cpu); + target_ulong addr; + target_ulong end; + target_ulong mask; + + mask = tlb->PageMask; /* 000...000111...111 */ + + if (tlb->V0) { + addr = tlb->VPN & ~mask; /* xxx...xxx[0]000..0000 */ + end = addr | (mask >> 1); /* xxx...xxx[0]111..1111 */ + while (addr < end) { + tlb_flush_page(cs, addr); + addr += TARGET_PAGE_SIZE; + } + } + + if (tlb->V1) { + /* xxx...xxx[1]000..0000 */ + addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1); + end = addr | mask; /* xxx...xxx[1]111..1111 */ + while (addr - 1 < end) { + tlb_flush_page(cs, addr); + addr += TARGET_PAGE_SIZE; + } + } +} + +void ls3a5k_invalidate_tlb(CPULOONGARCHState *env, int idx) +{ + ls3a5k_tlb_t *tlb; + int asid = env->CSR_ASID & 0x3ff; + tlb = &env->tlb->mmu.ls3a5k.tlb[idx]; + if (tlb->G == 0 && tlb->ASID != asid) { + return; + } + ls3a5k_invalidate_tlb_entry(env, tlb); +} + +void ls3a5k_helper_tlbwr(CPULOONGARCHState *env) +{ + int idx = env->CSR_TLBIDX & CSR_TLBIDX_IDX; /* [11:0] */ + + /* Convert idx if in FTLB */ + if (idx < env->tlb->mmu.ls3a5k.ftlb_size) { + /* + * 0 3 6 0 1 2 + * 1 4 7 => 3 4 5 + * 2 5 8 6 7 8 + */ + int set = idx % 256; + int way = idx / 256; + idx = set * 8 + way; + } + ls3a5k_invalidate_tlb(env, idx); + ls3a5k_fill_tlb(env, idx, true); +} + +void ls3a5k_helper_tlbfill(CPULOONGARCHState *env) +{ + uint64_t mask; + uint64_t address; + int idx; + int set, ftlb_idx; + + uint64_t entryhi; + uint32_t pagesize; + + if (env->CSR_TLBRERA & 0x1) { + entryhi = env->CSR_TLBREHI & ~0x3f; + pagesize = env->CSR_TLBREHI & 0x3f; + } else { + entryhi = env->CSR_TLBEHI; + pagesize = (env->CSR_TLBIDX >> CSR_TLBIDX_PS_SHIFT) & 0x3f; + } + + uint32_t ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; + uint32_t vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; + + mask = ls3a5k_pagesize_to_mask(pagesize); + + if (mask == env->tlb->mmu.ls3a5k.ftlb_mask && + env->tlb->mmu.ls3a5k.ftlb_size > 0) { + /* only write into FTLB */ + address = entryhi & 0xffffffffe000; /* [47:13] */ + + /* choose one set ramdomly */ + set = cpu_loongarch_get_random_ls3a5k_tlb(0, 7); + + /* index in one set */ + ftlb_idx = (address >> 15) & 0xff; /* [0,255] */ + + /* final idx */ + idx = ftlb_idx * 8 + set; /* max is 7 + 8 * 255 = 2047 */ + } else { + /* only write into VTLB */ + int wired_nr = env->CSR_TLBWIRED & 0x3f; + idx = cpu_loongarch_get_random_ls3a5k_tlb( + ftlb_size + wired_nr, ftlb_size + vtlb_size - 1); + } + + ls3a5k_invalidate_tlb(env, idx); + ls3a5k_fill_tlb(env, idx, false); +} + +void ls3a5k_helper_tlbsrch(CPULOONGARCHState *env) +{ + uint64_t mask; + uint64_t vpn; + uint64_t tag; + uint16_t asid; + + int ftlb_size = env->tlb->mmu.ls3a5k.ftlb_size; + int vtlb_size = env->tlb->mmu.ls3a5k.vtlb_size; + int i; + int ftlb_idx; /* [0,255] 2^8 0xff */ + + ls3a5k_tlb_t *tlb; + + asid = env->CSR_ASID & 0x3ff; + + /* search VTLB */ + for (i = ftlb_size; i < ftlb_size + vtlb_size; ++i) { + tlb = &env->tlb->mmu.ls3a5k.tlb[i]; + mask = tlb->PageMask; + + vpn = env->CSR_TLBEHI & 0xffffffffe000 & ~mask; + tag = tlb->VPN & ~mask; + + if ((tlb->G == 1 || tlb->ASID == asid) && vpn == tag && tlb->EHINV != 1) + { + env->CSR_TLBIDX = (i & 0xfff) | + ((tlb->PageSize & 0x3f) << CSR_TLBIDX_PS_SHIFT); + goto _MATCH_OUT_; + } + } + + if (ftlb_size == 0) { + goto _NO_MATCH_OUT_; + } + + /* search FTLB */ + mask = env->tlb->mmu.ls3a5k.ftlb_mask; + vpn = env->CSR_TLBEHI & 0xffffffffe000 & ~mask; + + ftlb_idx = (env->CSR_TLBEHI & 0xffffffffe000) >> 15; /* 16 KB */ + ftlb_idx = ftlb_idx & 0xff; /* [0,255] */ + + for (i = 0; i < 8; ++i) { + tlb = &env->tlb->mmu.ls3a5k.tlb[ftlb_idx * 8 + i]; + tag = tlb->VPN & ~mask; + + if ((tlb->G == 1 || tlb->ASID == asid) && vpn == tag && tlb->EHINV != 1) + { + env->CSR_TLBIDX = ((i * 256 + ftlb_idx) & 0xfff) | + ((tlb->PageSize & 0x3f) << CSR_TLBIDX_PS_SHIFT); + goto _MATCH_OUT_; + } + } + +_NO_MATCH_OUT_: + env->CSR_TLBIDX = 1 << CSR_TLBIDX_EHINV_SHIFT; +_MATCH_OUT_: + return; +} + +void ls3a5k_helper_tlbrd(CPULOONGARCHState *env) +{ + ls3a5k_tlb_t *tlb; + int idx; + uint16_t asid; + + idx = env->CSR_TLBIDX & CSR_TLBIDX_IDX; + if (idx < env->tlb->mmu.ls3a5k.ftlb_size) { + int set = idx % 256; + int way = idx / 256; + idx = set * 8 + way; + } + + tlb = &env->tlb->mmu.ls3a5k.tlb[idx]; + + asid = env->CSR_ASID & 0x3ff; + + if (asid != tlb->ASID) { + cpu_loongarch_tlb_flush(env); + } + + if (tlb->EHINV) { + /* invalid TLB entry */ + env->CSR_TLBIDX = 1 << CSR_TLBIDX_EHINV_SHIFT; + env->CSR_TLBEHI = 0; + env->CSR_TLBELO0 = 0; + env->CSR_TLBELO1 = 0; + } else { + /* valid TLB entry */ + env->CSR_TLBIDX = (env->CSR_TLBIDX & 0xfff) | + ((tlb->PageSize & 0x3f) << CSR_TLBIDX_PS_SHIFT); + env->CSR_TLBEHI = tlb->VPN; + env->CSR_TLBELO0 = (tlb->V0 << CSR_TLBLO0_V_SHIFT) | + (tlb->WE0 << CSR_TLBLO0_WE_SHIFT) | + (tlb->PLV0 << CSR_TLBLO0_PLV_SHIFT) | + (tlb->C0 << CSR_TLBLO0_CCA_SHIFT) | + (tlb->G << CSR_TLBLO0_GLOBAL_SHIFT) | + (tlb->PPN0 & 0xfffffffff000) | + ((uint64_t)tlb->RI0 << CSR_TLBLO0_RI_SHIFT) | + ((uint64_t)tlb->XI0 << CSR_TLBLO0_XI_SHIFT) | + ((uint64_t)tlb->RPLV0 << CSR_TLBLO0_RPLV_SHIFT); + env->CSR_TLBELO1 = (tlb->V1 << CSR_TLBLO1_V_SHIFT) | + (tlb->WE1 << CSR_TLBLO1_WE_SHIFT) | + (tlb->PLV1 << CSR_TLBLO1_PLV_SHIFT) | + (tlb->C1 << CSR_TLBLO1_CCA_SHIFT) | + (tlb->G << CSR_TLBLO0_GLOBAL_SHIFT) | + (tlb->PPN1 & 0xfffffffff000) | + ((uint64_t)tlb->RI1 << CSR_TLBLO1_RI_SHIFT) | + ((uint64_t)tlb->XI1 << CSR_TLBLO1_XI_SHIFT) | + ((uint64_t)tlb->RPLV1 << CSR_TLBLO1_RPLV_SHIFT); + env->CSR_ASID = (tlb->ASID << CSR_ASID_ASID_SHIFT) | + (env->CSR_ASID & 0xff0000); + } +} + +void helper_tlbwr(CPULOONGARCHState *env) +{ + env->tlb->helper_tlbwr(env); +} + +void helper_tlbfill(CPULOONGARCHState *env) +{ + env->tlb->helper_tlbfill(env); +} + +void helper_tlbsrch(CPULOONGARCHState *env) +{ + env->tlb->helper_tlbsrch(env); +} + +void helper_tlbrd(CPULOONGARCHState *env) +{ + env->tlb->helper_tlbrd(env); +} + +void helper_tlbclr(CPULOONGARCHState *env) +{ + env->tlb->helper_tlbclr(env); +} + +void helper_tlbflush(CPULOONGARCHState *env) +{ + env->tlb->helper_tlbflush(env); +} + +void helper_invtlb(CPULOONGARCHState *env, target_ulong addr, target_ulong info, + target_ulong op) +{ + env->tlb->helper_invtlb(env, addr, info, op); +} + +static void ls3a5k_mmu_init(CPULOONGARCHState *env, const loongarch_def_t *def) +{ + /* number of VTLB */ + env->tlb->nb_tlb = 64; + env->tlb->mmu.ls3a5k.vtlb_size = 64; + + /* number of FTLB */ + env->tlb->nb_tlb += 2048; + env->tlb->mmu.ls3a5k.ftlb_size = 2048; + env->tlb->mmu.ls3a5k.ftlb_mask = (1 << 15) - 1; /* 16 KB */ + /* + * page_size | ftlb_mask | party field + * ---------------------------------------------------------------- + * 4 KB = 12 | ( 1 << 13 ) - 1 = [12:0] | [12] + * 16 KB = 14 | ( 1 << 15 ) - 1 = [14:0] | [14] + * 64 KB = 16 | ( 1 << 17 ) - 1 = [16:0] | [16] + * 256 KB = 18 | ( 1 << 19 ) - 1 = [18:0] | [18] + * 1 MB = 20 | ( 1 << 21 ) - 1 = [20:0] | [20] + * 4 MB = 22 | ( 1 << 23 ) - 1 = [22:0] | [22] + * 16 MB = 24 | ( 1 << 25 ) - 1 = [24:0] | [24] + * 64 MB = 26 | ( 1 << 27 ) - 1 = [26:0] | [26] + * 256 MB = 28 | ( 1 << 29 ) - 1 = [28:0] | [28] + * 1 GB = 30 | ( 1 << 31 ) - 1 = [30:0] | [30] + * ---------------------------------------------------------------- + * take party field index as @n. eg. For 16 KB, n = 14 + * ---------------------------------------------------------------- + * tlb->VPN = TLBEHI & 0xffffffffe000[47:13] & ~mask = [47:n+1] + * tlb->PPN = TLBLO0 & 0xffffffffe000[47:13] & ~mask = [47:n+1] + * tlb->PPN = TLBLO1 & 0xffffffffe000[47:13] & ~mask = [47:n+1] + * ---------------------------------------------------------------- + * On mapping : + * > vpn = address & 0xffffffffe000[47:13] & ~mask = [47:n+1] + * > tag = tlb->VPN & ~mask = [47:n+1] + * ---------------------------------------------------------------- + * physical address = [47:n+1] | [n:0] + * physical address = tlb->PPN0 | (address & mask) + * physical address = tlb->PPN1 | (address & mask) + */ + + int i; + for (i = 0; i < env->tlb->nb_tlb; i++) { + env->tlb->mmu.ls3a5k.tlb[i].EHINV = 1; + } + + /* TLB's helper functions */ + env->tlb->map_address = &ls3a5k_map_address; + env->tlb->helper_tlbwr = ls3a5k_helper_tlbwr; + env->tlb->helper_tlbfill = ls3a5k_helper_tlbfill; + env->tlb->helper_tlbsrch = ls3a5k_helper_tlbsrch; + env->tlb->helper_tlbrd = ls3a5k_helper_tlbrd; + env->tlb->helper_tlbclr = ls3a5k_helper_tlbclr; + env->tlb->helper_tlbflush = ls3a5k_helper_tlbflush; + env->tlb->helper_invtlb = ls3a5k_helper_invtlb; +} + +void mmu_init(CPULOONGARCHState *env, const loongarch_def_t *def) +{ + env->tlb = g_malloc0(sizeof(CPULOONGARCHTLBContext)); + + switch (def->mmu_type) { + case MMU_TYPE_LS3A5K: + ls3a5k_mmu_init(env, def); + break; + default: + cpu_abort(CPU(loongarch_env_get_cpu(env)), "MMU type not supported\n"); + } +} +#endif /* !CONFIG_USER_ONLY */ diff --git a/target/loongarch64/trace-events b/target/loongarch64/trace-events new file mode 100644 index 0000000000..e0bca4f82e --- /dev/null +++ b/target/loongarch64/trace-events @@ -0,0 +1,3 @@ +# See docs/devel/tracing.txt for syntax documentation. + +# target/loongarch/translate.c diff --git a/target/loongarch64/trans.inc.c b/target/loongarch64/trans.inc.c new file mode 100644 index 0000000000..e50670be47 --- /dev/null +++ b/target/loongarch64/trans.inc.c @@ -0,0 +1,3472 @@ +static bool trans_syscall(DisasContext *ctx, arg_syscall *a) +{ + generate_exception_end(ctx, EXCP_SYSCALL); + return true; +} + +static bool trans_break(DisasContext *ctx, arg_break *a) +{ + generate_exception_end(ctx, EXCP_BREAK); + return true; +} + +static bool trans_dbcl(DisasContext *ctx, arg_dbcl *a) +{ + /* + * dbcl instruction is not support in tcg + */ + generate_exception_end(ctx, EXCP_RI); + return true; +} + +static bool trans_addi_w(DisasContext *ctx, arg_addi_w *a) +{ + gen_arith_imm(ctx, OPC_LARCH_ADDI_W, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_addi_d(DisasContext *ctx, arg_addi_d *a) +{ + gen_arith_imm(ctx, OPC_LARCH_ADDI_D, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_slli_d(DisasContext *ctx, arg_slli_d *a) +{ + if (a->rd == 0) { + /* Nop */ + return true; + } + + TCGv t0 = tcg_temp_new(); + + gen_load_gpr(t0, a->rj); + tcg_gen_shli_tl(cpu_gpr[a->rd], t0, a->ui6); + + tcg_temp_free(t0); + return true; +} + +static bool trans_andi(DisasContext *ctx, arg_andi *a) +{ + gen_logic_imm(ctx, OPC_LARCH_ANDI, a->rd, a->rj, a->ui12); + return true; +} + +static bool trans_srli_d(DisasContext *ctx, arg_srli_d *a) +{ + TCGv t0 = tcg_temp_new(); + + gen_load_gpr(t0, a->rj); + tcg_gen_shri_tl(cpu_gpr[a->rd], t0, a->ui6); + + tcg_temp_free(t0); + return true; +} + +static bool trans_slli_w(DisasContext *ctx, arg_slli_w *a) +{ + if (a->rd == 0) { + /* Nop */ + return true; + } + + TCGv t0 = tcg_temp_new(); + + gen_load_gpr(t0, a->rj); + tcg_gen_shli_tl(t0, t0, a->ui5); + tcg_gen_ext32s_tl(cpu_gpr[a->rd], t0); + + tcg_temp_free(t0); + return true; +} + +static bool trans_addu16i_d(DisasContext *ctx, arg_addu16i_d *a) +{ + if (a->rj != 0) { + tcg_gen_addi_tl(cpu_gpr[a->rd], cpu_gpr[a->rj], a->si16 << 16); + } else { + tcg_gen_movi_tl(cpu_gpr[a->rd], a->si16 << 16); + } + return true; +} + +static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a) +{ + tcg_gen_movi_tl(cpu_gpr[a->rd], a->si20 << 12); + return true; +} + +static bool trans_lu32i_d(DisasContext *ctx, arg_lu32i_d *a) +{ + TCGv_i64 t0, t1; + t0 = tcg_temp_new_i64(); + t1 = tcg_temp_new_i64(); + + tcg_gen_movi_tl(t0, a->si20); + tcg_gen_concat_tl_i64(t1, cpu_gpr[a->rd], t0); + gen_store_gpr(t1, a->rd); + + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_pcaddi(DisasContext *ctx, arg_pcaddi *a) +{ + target_ulong pc = ctx->base.pc_next; + target_ulong addr = pc + (a->si20 << 2); + tcg_gen_movi_tl(cpu_gpr[a->rd], addr); + return true; +} + +static bool trans_pcalau12i(DisasContext *ctx, arg_pcalau12i *a) +{ + target_ulong pc = ctx->base.pc_next; + target_ulong addr = (pc + (a->si20 << 12)) & ~0xfff; + tcg_gen_movi_tl(cpu_gpr[a->rd], addr); + return true; +} + +static bool trans_pcaddu12i(DisasContext *ctx, arg_pcaddu12i *a) +{ + target_ulong pc = ctx->base.pc_next; + target_ulong addr = pc + (a->si20 << 12); + tcg_gen_movi_tl(cpu_gpr[a->rd], addr); + return true; +} + +static bool trans_pcaddu18i(DisasContext *ctx, arg_pcaddu18i *a) +{ + target_ulong pc = ctx->base.pc_next; + target_ulong addr = pc + ((target_ulong)(a->si20) << 18); + tcg_gen_movi_tl(cpu_gpr[a->rd], addr); + return true; +} + +static bool trans_slti(DisasContext *ctx, arg_slti *a) +{ + gen_slt_imm(ctx, OPC_LARCH_SLTI, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_sltui(DisasContext *ctx, arg_sltui *a) +{ + gen_slt_imm(ctx, OPC_LARCH_SLTIU, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_lu52i_d(DisasContext *ctx, arg_lu52i_d *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + gen_load_gpr(t1, a->rj); + + tcg_gen_movi_tl(t0, a->si12); + tcg_gen_shli_tl(t0, t0, 52); + tcg_gen_andi_tl(t1, t1, 0xfffffffffffffU); + tcg_gen_or_tl(cpu_gpr[a->rd], t0, t1); + + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_ori(DisasContext *ctx, arg_ori *a) +{ + gen_logic_imm(ctx, OPC_LARCH_ORI, a->rd, a->rj, a->ui12); + return true; +} + +static bool trans_xori(DisasContext *ctx, arg_xori *a) +{ + gen_logic_imm(ctx, OPC_LARCH_XORI, a->rd, a->rj, a->ui12); + return true; +} + +static bool trans_bstrins_d(DisasContext *ctx, arg_bstrins_d *a) +{ + int lsb = a->lsbd; + int msb = a->msbd; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + if (lsb > msb) { + return false; + } + + gen_load_gpr(t1, a->rj); + gen_load_gpr(t0, a->rd); + tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1); + gen_store_gpr(t0, a->rd); + + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_bstrpick_d(DisasContext *ctx, arg_bstrpick_d *a) +{ + int lsb = a->lsbd; + int msb = a->msbd; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + if (lsb > msb) { + return false; + } + + gen_load_gpr(t1, a->rj); + gen_load_gpr(t0, a->rd); + tcg_gen_extract_tl(t0, t1, lsb, msb - lsb + 1); + gen_store_gpr(t0, a->rd); + + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_bstrins_w(DisasContext *ctx, arg_bstrins_w *a) +{ + gen_bitops(ctx, OPC_LARCH_TRINS_W, a->rd, a->rj, a->lsbw, a->msbw); + return true; +} + +static bool trans_bstrpick_w(DisasContext *ctx, arg_bstrpick_w *a) +{ + if (a->lsbw > a->msbw) { + return false; + } + gen_bitops(ctx, OPC_LARCH_TRPICK_W, + a->rd, a->rj, a->lsbw, a->msbw - a->lsbw); + return true; +} + +static bool trans_ldptr_w(DisasContext *ctx, arg_ldptr_w *a) +{ + gen_ld(ctx, OPC_LARCH_LDPTR_W, a->rd, a->rj, a->si14 << 2); + return true; +} + +static bool trans_stptr_w(DisasContext *ctx, arg_stptr_w *a) +{ + gen_st(ctx, OPC_LARCH_STPTR_W, a->rd, a->rj, a->si14 << 2); + return true; +} + +static bool trans_ldptr_d(DisasContext *ctx, arg_ldptr_d *a) +{ + gen_ld(ctx, OPC_LARCH_LDPTR_D, a->rd, a->rj, a->si14 << 2); + return true; +} + +static bool trans_stptr_d(DisasContext *ctx, arg_stptr_d *a) +{ + gen_st(ctx, OPC_LARCH_STPTR_D, a->rd, a->rj, a->si14 << 2); + return true; +} + +static bool trans_ld_b(DisasContext *ctx, arg_ld_b *a) +{ + gen_ld(ctx, OPC_LARCH_LD_B, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_ld_h(DisasContext *ctx, arg_ld_h *a) +{ + gen_ld(ctx, OPC_LARCH_LD_H, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_ld_w(DisasContext *ctx, arg_ld_w *a) +{ + gen_ld(ctx, OPC_LARCH_LD_W, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_ld_d(DisasContext *ctx, arg_ld_d *a) +{ + gen_ld(ctx, OPC_LARCH_LD_D, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_st_b(DisasContext *ctx, arg_st_b *a) +{ + gen_st(ctx, OPC_LARCH_ST_B, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_st_h(DisasContext *ctx, arg_st_h *a) +{ + gen_st(ctx, OPC_LARCH_ST_H, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_st_w(DisasContext *ctx, arg_st_w *a) +{ + gen_st(ctx, OPC_LARCH_ST_W, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_st_d(DisasContext *ctx, arg_st_d *a) +{ + gen_st(ctx, OPC_LARCH_ST_D, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_ld_bu(DisasContext *ctx, arg_ld_bu *a) +{ + gen_ld(ctx, OPC_LARCH_LD_BU, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_ld_hu(DisasContext *ctx, arg_ld_hu *a) +{ + gen_ld(ctx, OPC_LARCH_LD_HU, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_ld_wu(DisasContext *ctx, arg_ld_wu *a) +{ + gen_ld(ctx, OPC_LARCH_LD_WU, a->rd, a->rj, a->si12); + return true; +} + +static bool trans_preld(DisasContext *ctx, arg_preld *a) +{ + /* Treat as NOP. */ + return true; +} + +static bool trans_ll_w(DisasContext *ctx, arg_ll_w *a) +{ + gen_ld(ctx, OPC_LARCH_LL_W, a->rd, a->rj, a->si14 << 2); + return true; +} + +static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a) +{ + gen_st_cond(ctx, a->rd, a->rj, a->si14 << 2, MO_TESL, false); + return true; +} + +static bool trans_ll_d(DisasContext *ctx, arg_ll_d *a) +{ + gen_ld(ctx, OPC_LARCH_LL_D, a->rd, a->rj, a->si14 << 2); + return true; +} + +static bool trans_sc_d(DisasContext *ctx, arg_sc_d *a) +{ + gen_st_cond(ctx, a->rd, a->rj, a->si14 << 2, MO_TEQ, false); + return true; +} + +static bool trans_fld_s(DisasContext *ctx, arg_fld_s *a) +{ + gen_fp_ldst(ctx, OPC_LARCH_FLD_S, a->fd, a->rj, a->si12); + return true; +} + +static bool trans_fst_s(DisasContext *ctx, arg_fst_s *a) +{ + gen_fp_ldst(ctx, OPC_LARCH_FST_S, a->fd, a->rj, a->si12); + return true; +} + +static bool trans_fld_d(DisasContext *ctx, arg_fld_d *a) +{ + gen_fp_ldst(ctx, OPC_LARCH_FLD_D, a->fd, a->rj, a->si12); + return true; +} + +static bool trans_fst_d(DisasContext *ctx, arg_fst_d *a) +{ + gen_fp_ldst(ctx, OPC_LARCH_FST_D, a->fd, a->rj, a->si12); + return true; +} + +static bool trans_ldx_b(DisasContext *ctx, arg_ldx_b *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); + tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_SB); + gen_store_gpr(t1, a->rd); + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_ldx_h(DisasContext *ctx, arg_ldx_h *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); + tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TESW | ctx->default_tcg_memop_mask); + gen_store_gpr(t1, a->rd); + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_ldx_w(DisasContext *ctx, arg_ldx_w *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); + tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TESL | ctx->default_tcg_memop_mask); + gen_store_gpr(t1, a->rd); + tcg_temp_free(t0); + return true; +} + +static bool trans_ldx_d(DisasContext *ctx, arg_ldx_d *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); + tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TEQ | ctx->default_tcg_memop_mask); + gen_store_gpr(t1, a->rd); + tcg_temp_free(t1); + return true; +} + +static bool trans_stx_b(DisasContext *ctx, arg_stx_b *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); + gen_load_gpr(t1, a->rd); + tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8); + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_stx_h(DisasContext *ctx, arg_stx_h *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); + gen_load_gpr(t1, a->rd); + tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW | + ctx->default_tcg_memop_mask); + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_stx_w(DisasContext *ctx, arg_stx_w *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); + gen_load_gpr(t1, a->rd); + tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL | + ctx->default_tcg_memop_mask); + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_stx_d(DisasContext *ctx, arg_stx_d *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); + gen_load_gpr(t1, a->rd); + tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_ldx_bu(DisasContext *ctx, arg_ldx_bu *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); + tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB); + gen_store_gpr(t1, a->rd); + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_ldx_hu(DisasContext *ctx, arg_ldx_hu *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); + tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TEUW | + ctx->default_tcg_memop_mask); + gen_store_gpr(t1, a->rd); + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_ldx_wu(DisasContext *ctx, arg_ldx_wu *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_op_addr_add(ctx, t0, cpu_gpr[a->rj], cpu_gpr[a->rk]); + tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_TEUL | + ctx->default_tcg_memop_mask); + gen_store_gpr(t1, a->rd); + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_fldx_s(DisasContext *ctx, arg_fldx_s *a) +{ + gen_flt3_ldst(ctx, OPC_LARCH_FLDX_S, a->fd, 0, a->rj, a->rk); + return true; +} + +static bool trans_fldx_d(DisasContext *ctx, arg_fldx_d *a) +{ + gen_flt3_ldst(ctx, OPC_LARCH_FLDX_D, a->fd, 0, a->rj, a->rk); + return true; +} + +static bool trans_fstx_s(DisasContext *ctx, arg_fstx_s *a) +{ + gen_flt3_ldst(ctx, OPC_LARCH_FSTX_S, 0, a->fd, a->rj, a->rk); + return true; +} + +static bool trans_fstx_d(DisasContext *ctx, arg_fstx_d *a) +{ + gen_flt3_ldst(ctx, OPC_LARCH_FSTX_D, 0, a->fd, a->rj, a->rk); + return true; +} + +#define TRANS_AM_W(name, op) \ +static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ +{ \ + if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ + printf("%s: warning, register equal\n", __func__); \ + return false; \ + } \ + int mem_idx = ctx->mem_idx; \ + TCGv addr = tcg_temp_new(); \ + TCGv val = tcg_temp_new(); \ + TCGv ret = tcg_temp_new(); \ +\ + gen_load_gpr(addr, a->rj); \ + gen_load_gpr(val, a->rk); \ + tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TESL | \ + ctx->default_tcg_memop_mask); \ + gen_store_gpr(ret, a->rd); \ +\ + tcg_temp_free(addr); \ + tcg_temp_free(val); \ + tcg_temp_free(ret); \ + return true; \ +} +#define TRANS_AM_D(name, op) \ +static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ +{ \ + if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ + printf("%s: warning, register equal\n", __func__); \ + return false; \ + } \ + int mem_idx = ctx->mem_idx; \ + TCGv addr = tcg_temp_new(); \ + TCGv val = tcg_temp_new(); \ + TCGv ret = tcg_temp_new(); \ +\ + gen_load_gpr(addr, a->rj); \ + gen_load_gpr(val, a->rk); \ + tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TEQ | \ + ctx->default_tcg_memop_mask); \ + gen_store_gpr(ret, a->rd); \ +\ + tcg_temp_free(addr); \ + tcg_temp_free(val); \ + tcg_temp_free(ret); \ + return true; \ +} +#define TRANS_AM(name, op) \ + TRANS_AM_W(name##_w, op) \ + TRANS_AM_D(name##_d, op) +TRANS_AM(amswap, xchg) /* trans_amswap_w, trans_amswap_d */ +TRANS_AM(amadd, fetch_add) /* trans_amadd_w, trans_amadd_d */ +TRANS_AM(amand, fetch_and) /* trans_amand_w, trans_amand_d */ +TRANS_AM(amor, fetch_or) /* trans_amor_w, trans_amor_d */ +TRANS_AM(amxor, fetch_xor) /* trans_amxor_w, trans_amxor_d */ +TRANS_AM(ammax, fetch_smax) /* trans_ammax_w, trans_ammax_d */ +TRANS_AM(ammin, fetch_smin) /* trans_ammin_w, trans_ammin_d */ +TRANS_AM_W(ammax_wu, fetch_umax) /* trans_ammax_wu */ +TRANS_AM_D(ammax_du, fetch_umax) /* trans_ammax_du */ +TRANS_AM_W(ammin_wu, fetch_umin) /* trans_ammin_wu */ +TRANS_AM_D(ammin_du, fetch_umin) /* trans_ammin_du */ +#undef TRANS_AM +#undef TRANS_AM_W +#undef TRANS_AM_D + +#define TRANS_AM_DB_W(name, op) \ +static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ +{ \ + if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ + printf("%s: warning, register equal\n", __func__); \ + return false; \ + } \ + int mem_idx = ctx->mem_idx; \ + TCGv addr = tcg_temp_new(); \ + TCGv val = tcg_temp_new(); \ + TCGv ret = tcg_temp_new(); \ +\ + gen_sync(0x10); /* TCG_MO_ALL */ \ + gen_load_gpr(addr, a->rj); \ + gen_load_gpr(val, a->rk); \ + tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TESL | \ + ctx->default_tcg_memop_mask); \ + gen_store_gpr(ret, a->rd); \ +\ + tcg_temp_free(addr); \ + tcg_temp_free(val); \ + tcg_temp_free(ret); \ + return true; \ +} +#define TRANS_AM_DB_D(name, op) \ +static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \ +{ \ + if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \ + printf("%s: warning, register equal\n", __func__); \ + return false; \ + } \ + int mem_idx = ctx->mem_idx; \ + TCGv addr = tcg_temp_new(); \ + TCGv val = tcg_temp_new(); \ + TCGv ret = tcg_temp_new(); \ +\ + gen_sync(0x10); /* TCG_MO_ALL */ \ + gen_load_gpr(addr, a->rj); \ + gen_load_gpr(val, a->rk); \ + tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TEQ | \ + ctx->default_tcg_memop_mask); \ + gen_store_gpr(ret, a->rd); \ +\ + tcg_temp_free(addr); \ + tcg_temp_free(val); \ + tcg_temp_free(ret); \ + return true; \ +} +#define TRANS_AM_DB(name, op) \ + TRANS_AM_DB_W(name##_db_w, op) \ + TRANS_AM_DB_D(name##_db_d, op) +TRANS_AM_DB(amswap, xchg) /* trans_amswap_db_w, trans_amswap_db_d */ +TRANS_AM_DB(amadd, fetch_add) /* trans_amadd_db_w, trans_amadd_db_d */ +TRANS_AM_DB(amand, fetch_and) /* trans_amand_db_w, trans_amand_db_d */ +TRANS_AM_DB(amor, fetch_or) /* trans_amor_db_w, trans_amor_db_d */ +TRANS_AM_DB(amxor, fetch_xor) /* trans_amxor_db_w, trans_amxor_db_d */ +TRANS_AM_DB(ammax, fetch_smax) /* trans_ammax_db_w, trans_ammax_db_d */ +TRANS_AM_DB(ammin, fetch_smin) /* trans_ammin_db_w, trans_ammin_db_d */ +TRANS_AM_DB_W(ammax_db_wu, fetch_umax) /* trans_ammax_db_wu */ +TRANS_AM_DB_D(ammax_db_du, fetch_umax) /* trans_ammax_db_du */ +TRANS_AM_DB_W(ammin_db_wu, fetch_umin) /* trans_ammin_db_wu */ +TRANS_AM_DB_D(ammin_db_du, fetch_umin) /* trans_ammin_db_du */ +#undef TRANS_AM_DB +#undef TRANS_AM_DB_W +#undef TRANS_AM_DB_D + +static bool trans_dbar(DisasContext *ctx, arg_dbar * a) +{ + gen_sync(a->whint); + return true; +} + +static bool trans_ibar(DisasContext *ctx, arg_ibar *a) +{ + /* + * FENCE_I is a no-op in QEMU, + * however we need to end the translation block + */ + ctx->base.is_jmp = DISAS_STOP; + return true; +} + +#define ASRTGT \ +do { \ + TCGv t1 = tcg_temp_new(); \ + TCGv t2 = tcg_temp_new(); \ + gen_load_gpr(t1, a->rj); \ + gen_load_gpr(t2, a->rk); \ + gen_helper_asrtgt_d(cpu_env, t1, t2); \ + tcg_temp_free(t1); \ + tcg_temp_free(t2); \ +} while (0) + +#define ASRTLE \ +do {\ + TCGv t1 = tcg_temp_new(); \ + TCGv t2 = tcg_temp_new(); \ + gen_load_gpr(t1, a->rj); \ + gen_load_gpr(t2, a->rk); \ + gen_helper_asrtle_d(cpu_env, t1, t2); \ + tcg_temp_free(t1); \ + tcg_temp_free(t2); \ +} while (0) + +static bool trans_fldgt_s(DisasContext *ctx, arg_fldgt_s *a) +{ + ASRTGT; + gen_flt3_ldst(ctx, OPC_LARCH_FLDGT_S, a->fd, 0, a->rj, a->rk); + return true; +} + +static bool trans_fldgt_d(DisasContext *ctx, arg_fldgt_d *a) +{ + ASRTGT; + gen_flt3_ldst(ctx, OPC_LARCH_FLDGT_D, a->fd, 0, a->rj, a->rk); + return true; +} + +static bool trans_fldle_s(DisasContext *ctx, arg_fldle_s *a) +{ + ASRTLE; + gen_flt3_ldst(ctx, OPC_LARCH_FLDLE_S, a->fd, 0, a->rj, a->rk); + return true; +} + +static bool trans_fldle_d(DisasContext *ctx, arg_fldle_d *a) +{ + ASRTLE; + gen_flt3_ldst(ctx, OPC_LARCH_FLDLE_D, a->fd, 0, a->rj, a->rk); + return true; +} + +static bool trans_fstgt_s(DisasContext *ctx, arg_fstgt_s *a) +{ + ASRTGT; + gen_flt3_ldst(ctx, OPC_LARCH_FSTGT_S, 0, a->fd, a->rj, a->rk); + return true; +} + +static bool trans_fstgt_d(DisasContext *ctx, arg_fstgt_d *a) +{ + ASRTGT; + gen_flt3_ldst(ctx, OPC_LARCH_FSTGT_D, 0, a->fd, a->rj, a->rk); + return true; +} + +static bool trans_fstle_s(DisasContext *ctx, arg_fstle_s *a) +{ + ASRTLE; + gen_flt3_ldst(ctx, OPC_LARCH_FSTLE_S, 0, a->fd, a->rj, a->rk); + return true; +} + +static bool trans_fstle_d(DisasContext *ctx, arg_fstle_d *a) +{ + ASRTLE; + gen_flt3_ldst(ctx, OPC_LARCH_FSTLE_D, 0, a->fd, a->rj, a->rk); + return true; +} + +#define DECL_ARG(name) \ + arg_ ## name arg = { \ + .rd = a->rd, \ + .rj = a->rj, \ + .rk = a->rk, \ + }; + +static bool trans_ldgt_b(DisasContext *ctx, arg_ldgt_b *a) +{ + ASRTGT; + DECL_ARG(ldx_b) + trans_ldx_b(ctx, &arg); + return true; +} + +static bool trans_ldgt_h(DisasContext *ctx, arg_ldgt_h *a) +{ + ASRTGT; + DECL_ARG(ldx_h) + trans_ldx_h(ctx, &arg); + return true; +} + +static bool trans_ldgt_w(DisasContext *ctx, arg_ldgt_w *a) +{ + ASRTGT; + DECL_ARG(ldx_w) + trans_ldx_w(ctx, &arg); + return true; +} + +static bool trans_ldgt_d(DisasContext *ctx, arg_ldgt_d *a) +{ + ASRTGT; + DECL_ARG(ldx_d) + trans_ldx_d(ctx, &arg); + return true; +} + +static bool trans_ldle_b(DisasContext *ctx, arg_ldle_b *a) +{ + ASRTLE; + DECL_ARG(ldx_b) + trans_ldx_b(ctx, &arg); + return true; +} + +static bool trans_ldle_h(DisasContext *ctx, arg_ldle_h *a) +{ + ASRTLE; + DECL_ARG(ldx_h) + trans_ldx_h(ctx, &arg); + return true; +} + +static bool trans_ldle_w(DisasContext *ctx, arg_ldle_w *a) +{ + ASRTLE; + DECL_ARG(ldx_w) + trans_ldx_w(ctx, &arg); + return true; +} + +static bool trans_ldle_d(DisasContext *ctx, arg_ldle_d *a) +{ + ASRTLE; + DECL_ARG(ldx_d) + trans_ldx_d(ctx, &arg); + return true; +} + +static bool trans_stgt_b(DisasContext *ctx, arg_stgt_b *a) +{ + ASRTGT; + DECL_ARG(stx_b) + trans_stx_b(ctx, &arg); + return true; +} + +static bool trans_stgt_h(DisasContext *ctx, arg_stgt_h *a) +{ + ASRTGT; + DECL_ARG(stx_h) + trans_stx_h(ctx, &arg); + return true; +} + +static bool trans_stgt_w(DisasContext *ctx, arg_stgt_w *a) +{ + ASRTGT; + DECL_ARG(stx_w) + trans_stx_w(ctx, &arg); + return true; +} + +static bool trans_stgt_d(DisasContext *ctx, arg_stgt_d *a) +{ + ASRTGT; + DECL_ARG(stx_d) + trans_stx_d(ctx, &arg); + return true; +} + +static bool trans_stle_b(DisasContext *ctx, arg_stle_b *a) +{ + ASRTLE; + DECL_ARG(stx_b) + trans_stx_b(ctx, &arg); + return true; +} + +static bool trans_stle_h(DisasContext *ctx, arg_stle_h *a) +{ + ASRTLE; + DECL_ARG(stx_h) + trans_stx_h(ctx, &arg); + return true; +} + +static bool trans_stle_w(DisasContext *ctx, arg_stle_w *a) +{ + ASRTLE; + DECL_ARG(stx_w) + trans_stx_w(ctx, &arg); + return true; +} + +static bool trans_stle_d(DisasContext *ctx, arg_stle_d *a) +{ + ASRTLE; + DECL_ARG(stx_d) + trans_stx_d(ctx, &arg); + return true; +} + +#undef ASRTGT +#undef ASRTLE +#undef DECL_ARG + +static bool trans_beqz(DisasContext *ctx, arg_beqz *a) +{ + gen_compute_branch(ctx, OPC_LARCH_BEQZ, 4, a->rj, 0, a->offs21 << 2); + return true; +} + +static bool trans_bnez(DisasContext *ctx, arg_bnez *a) +{ + gen_compute_branch(ctx, OPC_LARCH_BNEZ, 4, a->rj, 0, a->offs21 << 2); + return true; +} + +static bool trans_bceqz(DisasContext *ctx, arg_bceqz *a) +{ + TCGv_i32 cj = tcg_const_i32(a->cj); + TCGv v0 = tcg_temp_new(); + TCGv v1 = tcg_const_i64(0); + + gen_helper_movcf2reg(v0, cpu_env, cj); + tcg_gen_setcond_tl(TCG_COND_EQ, bcond, v0, v1); + ctx->hflags |= LARCH_HFLAG_BC; + ctx->btarget = ctx->base.pc_next + (a->offs21 << 2); + + tcg_temp_free_i32(cj); + tcg_temp_free(v0); + tcg_temp_free(v1); + return true; +} + +static bool trans_bcnez(DisasContext *ctx, arg_bcnez *a) +{ + TCGv_i32 cj = tcg_const_i32(a->cj); + TCGv v0 = tcg_temp_new(); + TCGv v1 = tcg_const_i64(0); + + gen_helper_movcf2reg(v0, cpu_env, cj); + tcg_gen_setcond_tl(TCG_COND_NE, bcond, v0, v1); + ctx->hflags |= LARCH_HFLAG_BC; + ctx->btarget = ctx->base.pc_next + (a->offs21 << 2); + + tcg_temp_free_i32(cj); + tcg_temp_free(v0); + tcg_temp_free(v1); + return true; +} + +static bool trans_b(DisasContext *ctx, arg_b *a) +{ + gen_compute_branch(ctx, OPC_LARCH_B, 4, 0, 0, a->offs << 2); + return true; +} + +static bool trans_bl(DisasContext *ctx, arg_bl *a) +{ + ctx->btarget = ctx->base.pc_next + (a->offs << 2); + tcg_gen_movi_tl(cpu_gpr[1], ctx->base.pc_next + 4); + ctx->hflags |= LARCH_HFLAG_B; + gen_branch(ctx, 4); + return true; +} + +static bool trans_blt(DisasContext *ctx, arg_blt *a) +{ + gen_compute_branch(ctx, OPC_LARCH_BLT, 4, a->rj, a->rd, a->offs16 << 2); + return true; +} + +static bool trans_bge(DisasContext *ctx, arg_bge *a) +{ + gen_compute_branch(ctx, OPC_LARCH_BGE, 4, a->rj, a->rd, a->offs16 << 2); + return true; +} + +static bool trans_bltu(DisasContext *ctx, arg_bltu *a) +{ + gen_compute_branch(ctx, OPC_LARCH_BLTU, 4, a->rj, a->rd, a->offs16 << 2); + return true; +} + +static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a) +{ + gen_compute_branch(ctx, OPC_LARCH_BGEU, 4, a->rj, a->rd, a->offs16 << 2); + return true; +} + +static bool trans_beq(DisasContext *ctx, arg_beq *a) +{ + gen_compute_branch(ctx, OPC_LARCH_BEQ, 4, a->rj, a->rd, a->offs16 << 2); + return true; +} + +static bool trans_bne(DisasContext *ctx, arg_bne *a) +{ + gen_compute_branch(ctx, OPC_LARCH_BNE, 4, a->rj, a->rd, a->offs16 << 2); + return true; +} + +static bool trans_jirl(DisasContext *ctx, arg_jirl *a) +{ + gen_base_offset_addr(ctx, btarget, a->rj, a->offs16 << 2); + if (a->rd != 0) { + tcg_gen_movi_tl(cpu_gpr[a->rd], ctx->base.pc_next + 4); + } + ctx->hflags |= LARCH_HFLAG_BR; + gen_branch(ctx, 4); + + return true; +} + +#define TRANS_F4FR(name, fmt, op, bits) \ +static bool trans_ ## name ## _ ## fmt(DisasContext *ctx, \ + arg_##name##_##fmt * a) \ +{ \ + check_cp1_enabled(ctx); \ + TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \ + TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \ + TCGv_i ## bits fp2 = tcg_temp_new_i ## bits(); \ + TCGv_i ## bits fp3 = tcg_temp_new_i ## bits(); \ + check_cp1_enabled(ctx); \ + gen_load_fpr ## bits(ctx, fp0, a->fj); \ + gen_load_fpr ## bits(ctx, fp1, a->fk); \ + gen_load_fpr ## bits(ctx, fp2, a->fa); \ + gen_helper_float_ ## op ## _ ## fmt(fp3, \ + cpu_env, fp0, fp1, fp2); \ + gen_store_fpr ## bits(ctx, fp3, a->fd); \ + tcg_temp_free_i ## bits(fp3); \ + tcg_temp_free_i ## bits(fp2); \ + tcg_temp_free_i ## bits(fp1); \ + tcg_temp_free_i ## bits(fp0); \ + return true; \ +} + +TRANS_F4FR(fmadd , s, maddf , 32) /* trans_fmadd_s */ +TRANS_F4FR(fmadd , d, maddf , 64) /* trans_fmadd_d */ +TRANS_F4FR(fmsub , s, msubf , 32) /* trans_fmsub_s */ +TRANS_F4FR(fmsub , d, msubf , 64) /* trans_fmsub_d */ +TRANS_F4FR(fnmadd, s, nmaddf, 32) /* trans_fnmadd_s */ +TRANS_F4FR(fnmadd, d, nmaddf, 64) /* trans_fnmadd_d */ +TRANS_F4FR(fnmsub, s, nmsubf, 32) /* trans_fnmsub_s */ +TRANS_F4FR(fnmsub, d, nmsubf, 64) /* trans_fnmsub_d */ +#undef TRANS_F4FR + +static bool trans_fadd_s(DisasContext *ctx, arg_fadd_s * a) +{ + gen_farith(ctx, OPC_LARCH_FADD_S, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fadd_d(DisasContext *ctx, arg_fadd_d *a) +{ + gen_farith(ctx, OPC_LARCH_FADD_D, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fsub_s(DisasContext *ctx, arg_fsub_s *a) +{ + gen_farith(ctx, OPC_LARCH_FSUB_S, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fsub_d(DisasContext *ctx, arg_fsub_d *a) +{ + gen_farith(ctx, OPC_LARCH_FSUB_D, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmul_s(DisasContext *ctx, arg_fmul_s *a) +{ + gen_farith(ctx, OPC_LARCH_FMUL_S, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmul_d(DisasContext *ctx, arg_fmul_d *a) +{ + gen_farith(ctx, OPC_LARCH_FMUL_D, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fdiv_s(DisasContext *ctx, arg_fdiv_s *a) +{ + gen_farith(ctx, OPC_LARCH_FDIV_S, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fdiv_d(DisasContext *ctx, arg_fdiv_d *a) +{ + gen_farith(ctx, OPC_LARCH_FDIV_D, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmax_s(DisasContext *ctx, arg_fmax_s *a) +{ + gen_farith(ctx, OPC_LARCH_FMAX_S, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmax_d(DisasContext *ctx, arg_fmax_d *a) +{ + gen_farith(ctx, OPC_LARCH_FMAX_D, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmin_s(DisasContext *ctx, arg_fmin_s *a) +{ + gen_farith(ctx, OPC_LARCH_FMIN_S, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmin_d(DisasContext *ctx, arg_fmin_d *a) +{ + gen_farith(ctx, OPC_LARCH_FMIN_D, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmaxa_s(DisasContext *ctx, arg_fmaxa_s *a) +{ + gen_farith(ctx, OPC_LARCH_FMAXA_S, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmaxa_d(DisasContext *ctx, arg_fmaxa_d *a) +{ + gen_farith(ctx, OPC_LARCH_FMAXA_D, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmina_s(DisasContext *ctx, arg_fmina_s *a) +{ + gen_farith(ctx, OPC_LARCH_FMINA_S, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmina_d(DisasContext *ctx, arg_fmina_d *a) +{ + gen_farith(ctx, OPC_LARCH_FMINA_D, a->fk, a->fj, a->fd, 0); + return true; +} + +static bool trans_fscaleb_s(DisasContext *ctx, arg_fscaleb_s *a) +{ + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + + check_cp1_enabled(ctx); + gen_load_fpr32(ctx, fp0, a->fj); + gen_load_fpr32(ctx, fp1, a->fk); + gen_helper_float_exp2_s(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i32(fp1); + gen_store_fpr32(ctx, fp0, a->fd); + tcg_temp_free_i32(fp0); + return true; +} + +static bool trans_fscaleb_d(DisasContext *ctx, arg_fscaleb_d *a) +{ + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + + check_cp1_enabled(ctx); + gen_load_fpr64(ctx, fp0, a->fj); + gen_load_fpr64(ctx, fp1, a->fk); + gen_helper_float_exp2_d(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i64(fp1); + gen_store_fpr64(ctx, fp0, a->fd); + tcg_temp_free_i64(fp0); + return true; +} + +static bool trans_fcopysign_s(DisasContext *ctx, arg_fcopysign_s *a) +{ + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + TCGv_i32 fp2 = tcg_temp_new_i32(); + + check_cp1_enabled(ctx); + gen_load_fpr32(ctx, fp0, a->fj); + gen_load_fpr32(ctx, fp1, a->fk); + tcg_gen_deposit_i32(fp2, fp1, fp0, 0, 31); + gen_store_fpr32(ctx, fp2, a->fd); + + tcg_temp_free_i32(fp2); + tcg_temp_free_i32(fp1); + tcg_temp_free_i32(fp0); + return true; +} + +static bool trans_fcopysign_d(DisasContext *ctx, arg_fcopysign_d *a) +{ + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + TCGv_i64 fp2 = tcg_temp_new_i64(); + + check_cp1_enabled(ctx); + gen_load_fpr64(ctx, fp0, a->fj); + gen_load_fpr64(ctx, fp1, a->fk); + tcg_gen_deposit_i64(fp2, fp1, fp0, 0, 63); + gen_store_fpr64(ctx, fp2, a->fd); + + tcg_temp_free_i64(fp2); + tcg_temp_free_i64(fp1); + tcg_temp_free_i64(fp0); + return true; +} + +static bool trans_fabs_s(DisasContext *ctx, arg_fabs_s *a) +{ + gen_farith(ctx, OPC_LARCH_FABS_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_fabs_d(DisasContext *ctx, arg_fabs_d *a) +{ + gen_farith(ctx, OPC_LARCH_FABS_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_fneg_s(DisasContext *ctx, arg_fneg_s *a) +{ + gen_farith(ctx, OPC_LARCH_FNEG_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_fneg_d(DisasContext *ctx, arg_fneg_d *a) +{ + gen_farith(ctx, OPC_LARCH_FNEG_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_flogb_s(DisasContext *ctx, arg_flogb_s *a) +{ + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + + check_cp1_enabled(ctx); + gen_load_fpr32(ctx, fp0, a->fj); + gen_helper_float_logb_s(fp1, cpu_env, fp0); + gen_store_fpr32(ctx, fp1, a->fd); + + tcg_temp_free_i32(fp0); + tcg_temp_free_i32(fp1); + return true; +} + +static bool trans_flogb_d(DisasContext *ctx, arg_flogb_d *a) +{ + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + + check_cp1_enabled(ctx); + gen_load_fpr64(ctx, fp0, a->fj); + gen_helper_float_logb_d(fp1, cpu_env, fp0); + gen_store_fpr64(ctx, fp1, a->fd); + + tcg_temp_free_i64(fp0); + tcg_temp_free_i64(fp1); + return true; +} + +static bool trans_fclass_s(DisasContext *ctx, arg_fclass_s *a) +{ + gen_farith(ctx, OPC_LARCH_FCLASS_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_fclass_d(DisasContext *ctx, arg_fclass_d *a) +{ + gen_farith(ctx, OPC_LARCH_FCLASS_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_fsqrt_s(DisasContext *ctx, arg_fsqrt_s *a) +{ + gen_farith(ctx, OPC_LARCH_FSQRT_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_fsqrt_d(DisasContext *ctx, arg_fsqrt_d *a) +{ + gen_farith(ctx, OPC_LARCH_FSQRT_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_frecip_s(DisasContext *ctx, arg_frecip_s *a) +{ + gen_farith(ctx, OPC_LARCH_FRECIP_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_frecip_d(DisasContext *ctx, arg_frecip_d *a) +{ + gen_farith(ctx, OPC_LARCH_FRECIP_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_frsqrt_s(DisasContext *ctx, arg_frsqrt_s *a) +{ + gen_farith(ctx, OPC_LARCH_FRSQRT_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_frsqrt_d(DisasContext *ctx, arg_frsqrt_d *a) +{ + gen_farith(ctx, OPC_LARCH_FRSQRT_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmov_s(DisasContext *ctx, arg_fmov_s *a) +{ + gen_farith(ctx, OPC_LARCH_FMOV_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_fmov_d(DisasContext *ctx, arg_fmov_d *a) +{ + gen_farith(ctx, OPC_LARCH_FMOV_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_movgr2fr_w(DisasContext *ctx, arg_movgr2fr_w *a) +{ + gen_cp1(ctx, OPC_LARCH_GR2FR_W, a->rj, a->fd); + return true; +} + +static bool trans_movgr2fr_d(DisasContext *ctx, arg_movgr2fr_d *a) +{ + gen_cp1(ctx, OPC_LARCH_GR2FR_D, a->rj, a->fd); + return true; +} + +static bool trans_movgr2frh_w(DisasContext *ctx, arg_movgr2frh_w *a) +{ + gen_cp1(ctx, OPC_LARCH_GR2FRH_W, a->rj, a->fd); + return true; +} + +static bool trans_movfr2gr_s(DisasContext *ctx, arg_movfr2gr_s *a) +{ + gen_cp1(ctx, OPC_LARCH_FR2GR_S, a->rd, a->fj); + return true; +} + +static bool trans_movfr2gr_d(DisasContext *ctx, arg_movfr2gr_d *a) +{ + gen_cp1(ctx, OPC_LARCH_FR2GR_D, a->rd, a->fj); + return true; +} + +static bool trans_movfrh2gr_s(DisasContext *ctx, arg_movfrh2gr_s *a) +{ + gen_cp1(ctx, OPC_LARCH_FRH2GR_S, a->rd, a->fj); + return true; +} + +static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a) +{ + TCGv t0 = tcg_temp_new(); + + check_cp1_enabled(ctx); + gen_load_gpr(t0, a->rj); + save_cpu_state(ctx, 0); + { + TCGv_i32 fs_tmp = tcg_const_i32(a->fcsrd); + gen_helper_0e2i(movgr2fcsr, t0, fs_tmp, a->rj); + tcg_temp_free_i32(fs_tmp); + } + /* Stop translation as we may have changed hflags */ + ctx->base.is_jmp = DISAS_STOP; + + tcg_temp_free(t0); + return true; +} + +static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a) +{ + TCGv t0 = tcg_temp_new(); + gen_helper_1e0i(movfcsr2gr, t0, a->fcsrs); + gen_store_gpr(t0, a->rd); + tcg_temp_free(t0); + return true; +} + +static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a) +{ + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i32 cd = tcg_const_i32(a->cd); + + check_cp1_enabled(ctx); + gen_load_fpr64(ctx, fp0, a->fj); + gen_helper_movreg2cf(cpu_env, cd, fp0); + + tcg_temp_free_i64(fp0); + tcg_temp_free_i32(cd); + return true; +} + +static bool trans_movcf2fr(DisasContext *ctx, arg_movcf2fr *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv_i32 cj = tcg_const_i32(a->cj); + + check_cp1_enabled(ctx); + gen_helper_movcf2reg(t0, cpu_env, cj); + gen_store_fpr64(ctx, t0, a->fd); + + tcg_temp_free(t0); + return true; +} + +static bool trans_movgr2cf(DisasContext *ctx, arg_movgr2cf *a) +{ + TCGv t0 = tcg_temp_new(); + TCGv_i32 cd = tcg_const_i32(a->cd); + + check_cp1_enabled(ctx); + gen_load_gpr(t0, a->rj); + gen_helper_movreg2cf(cpu_env, cd, t0); + + tcg_temp_free(t0); + tcg_temp_free_i32(cd); + return true; +} + +static bool trans_movcf2gr(DisasContext *ctx, arg_movcf2gr *a) +{ + TCGv_i32 cj = tcg_const_i32(a->cj); + + check_cp1_enabled(ctx); + gen_helper_movcf2reg(cpu_gpr[a->rd], cpu_env, cj); + + tcg_temp_free_i32(cj); + return true; +} + +static bool trans_fcvt_s_d(DisasContext *ctx, arg_fcvt_s_d *a) +{ + gen_farith(ctx, OPC_LARCH_FCVT_S_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_fcvt_d_s(DisasContext *ctx, arg_fcvt_d_s *a) +{ + gen_farith(ctx, OPC_LARCH_FCVT_D_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrm_w_s(DisasContext *ctx, arg_ftintrm_l_s *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRM_W_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrm_w_d(DisasContext *ctx, arg_ftintrm_l_d *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRM_W_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrm_l_s(DisasContext *ctx, arg_ftintrm_l_s *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRM_L_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrm_l_d(DisasContext *ctx, arg_ftintrm_l_d *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRM_L_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrp_w_s(DisasContext *ctx, arg_ftintrp_w_s *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRP_W_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrp_w_d(DisasContext *ctx, arg_ftintrp_w_d *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRP_W_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrp_l_s(DisasContext *ctx, arg_ftintrp_l_s *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRP_L_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrp_l_d(DisasContext *ctx, arg_ftintrp_l_d *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRP_L_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrz_w_s(DisasContext *ctx, arg_ftintrz_w_s *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRZ_W_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrz_w_d(DisasContext *ctx, arg_ftintrz_w_d *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRZ_W_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrz_l_s(DisasContext *ctx, arg_ftintrz_l_s *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRZ_L_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrz_l_d(DisasContext *ctx, arg_ftintrz_l_d *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRZ_L_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrne_w_s(DisasContext *ctx, arg_ftintrne_w_s *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRNE_W_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrne_w_d(DisasContext *ctx, arg_ftintrne_w_d *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRNE_W_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrne_l_s(DisasContext *ctx, arg_ftintrne_l_s *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRNE_L_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftintrne_l_d(DisasContext *ctx, arg_ftintrne_l_d *a) +{ + gen_farith(ctx, OPC_LARCH_FTINTRNE_L_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftint_w_s(DisasContext *ctx, arg_ftint_w_s *a) +{ + gen_farith(ctx, OPC_LARCH_FTINT_W_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftint_w_d(DisasContext *ctx, arg_ftint_w_d *a) +{ + gen_farith(ctx, OPC_LARCH_FTINT_W_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftint_l_s(DisasContext *ctx, arg_ftint_l_s *a) +{ + gen_farith(ctx, OPC_LARCH_FTINT_L_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ftint_l_d(DisasContext *ctx, arg_ftint_l_d *a) +{ + gen_farith(ctx, OPC_LARCH_FTINT_L_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ffint_s_w(DisasContext *ctx, arg_ffint_s_w *a) +{ + gen_farith(ctx, OPC_LARCH_FFINT_S_W, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ffint_s_l(DisasContext *ctx, arg_ffint_s_l *a) +{ + gen_farith(ctx, OPC_LARCH_FFINT_S_L, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ffint_d_w(DisasContext *ctx, arg_ffint_d_w *a) +{ + gen_farith(ctx, OPC_LARCH_FFINT_D_W, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_ffint_d_l(DisasContext *ctx, arg_ffint_d_l *a) +{ + gen_farith(ctx, OPC_LARCH_FFINT_D_L, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_frint_s(DisasContext *ctx, arg_frint_s *a) +{ + gen_farith(ctx, OPC_LARCH_FRINT_S, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_frint_d(DisasContext *ctx, arg_frint_d *a) +{ + gen_farith(ctx, OPC_LARCH_FRINT_D, 0, a->fj, a->fd, 0); + return true; +} + +static bool trans_alsl_w(DisasContext *ctx, arg_alsl_w *a) +{ + gen_lsa(ctx, OPC_LARCH_ALSL_W, a->rd, a->rj, a->rk, a->sa2); + return true; +} + +static bool trans_alsl_wu(DisasContext *ctx, arg_alsl_wu *a) +{ + TCGv t0, t1; + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + gen_load_gpr(t0, a->rj); + gen_load_gpr(t1, a->rk); + tcg_gen_shli_tl(t0, t0, a->sa2 + 1); + tcg_gen_add_tl(t0, t0, t1); + tcg_gen_ext32u_tl(cpu_gpr[a->rd], t0); + tcg_temp_free(t0); + tcg_temp_free(t1); + + return true; +} + +static bool trans_alsl_d(DisasContext *ctx, arg_alsl_d *a) +{ + check_larch_64(ctx); + gen_lsa(ctx, OPC_LARCH_ALSL_D, a->rd, a->rj, a->rk, a->sa2); + return true; +} + +static bool trans_bytepick_w(DisasContext *ctx, arg_bytepick_w *a) +{ + gen_align(ctx, 32, a->rd, a->rj, a->rk, a->sa2); + return true; +} + +static bool trans_bytepick_d(DisasContext *ctx, arg_bytepick_d *a) +{ + check_larch_64(ctx); + gen_align(ctx, 64, a->rd, a->rj, a->rk, a->sa3); + return true; +} + +static bool trans_add_w(DisasContext *ctx, arg_add_w *a) +{ + gen_arith(ctx, OPC_LARCH_ADD_W, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_sub_w(DisasContext *ctx, arg_sub_w *a) +{ + gen_arith(ctx, OPC_LARCH_SUB_W, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_add_d(DisasContext *ctx, arg_add_d *a) +{ + gen_arith(ctx, OPC_LARCH_ADD_D, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_sub_d(DisasContext *ctx, arg_sub_d *a) +{ + check_larch_64(ctx); + gen_arith(ctx, OPC_LARCH_SUB_D, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_slt(DisasContext *ctx, arg_slt *a) +{ + gen_slt(ctx, OPC_LARCH_SLT, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_sltu(DisasContext *ctx, arg_sltu *a) +{ + gen_slt(ctx, OPC_LARCH_SLTU, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_maskeqz(DisasContext *ctx, arg_maskeqz *a) +{ + gen_cond_move(ctx, OPC_LARCH_MASKEQZ, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_masknez(DisasContext *ctx, arg_masknez *a) +{ + gen_cond_move(ctx, OPC_LARCH_MASKNEZ, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_nor(DisasContext *ctx, arg_nor *a) +{ + gen_logic(ctx, OPC_LARCH_NOR, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_and(DisasContext *ctx, arg_and *a) +{ + gen_logic(ctx, OPC_LARCH_AND, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_or(DisasContext *ctx, arg_or *a) +{ + gen_logic(ctx, OPC_LARCH_OR, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_xor(DisasContext *ctx, arg_xor *a) +{ + gen_logic(ctx, OPC_LARCH_XOR, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_orn(DisasContext *ctx, arg_orn *a) +{ + TCGv t0 = tcg_temp_new(); + gen_load_gpr(t0, a->rk); + tcg_gen_not_tl(t0, t0); + tcg_gen_or_tl(cpu_gpr[a->rd], cpu_gpr[a->rj], t0); + tcg_temp_free(t0); + return true; +} + +static bool trans_andn(DisasContext *ctx, arg_andn *a) +{ + TCGv t0, t1; + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + gen_load_gpr(t0, a->rk); + gen_load_gpr(t1, a->rj); + tcg_gen_not_tl(t0, t0); + tcg_gen_and_tl(cpu_gpr[a->rd], t1, t0); + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +static bool trans_sll_w(DisasContext *ctx, arg_sll_w *a) +{ + gen_shift(ctx, OPC_LARCH_SLL_W, a->rd, a->rk, a->rj); + return true; +} + +static bool trans_srl_w(DisasContext *ctx, arg_srl_w *a) +{ + gen_shift(ctx, OPC_LARCH_SRL_W, a->rd, a->rk, a->rj); + return true; +} + +static bool trans_sra_w(DisasContext *ctx, arg_sra_w *a) +{ + gen_shift(ctx, OPC_LARCH_SRA_W, a->rd, a->rk, a->rj); + return true; +} + +static bool trans_sll_d(DisasContext *ctx, arg_sll_d *a) +{ + check_larch_64(ctx); + gen_shift(ctx, OPC_LARCH_SLL_D, a->rd, a->rk, a->rj); + return true; +} + +static bool trans_srl_d(DisasContext *ctx, arg_srl_d *a) +{ + check_larch_64(ctx); + gen_shift(ctx, OPC_LARCH_SRL_D, a->rd, a->rk, a->rj); + return true; +} + +static bool trans_sra_d(DisasContext *ctx, arg_sra_d *a) +{ + check_larch_64(ctx); + gen_shift(ctx, OPC_LARCH_SRA_D, a->rd, a->rk, a->rj); + return true; +} + +static bool trans_rotr_w(DisasContext *ctx, arg_rotr_w *a) +{ + gen_shift(ctx, OPC_LARCH_ROTR_W, a->rd, a->rk, a->rj); + return true; +} + +static bool trans_rotr_d(DisasContext *ctx, arg_rotr_d *a) +{ + check_larch_64(ctx); + gen_shift(ctx, OPC_LARCH_ROTR_D, a->rd, a->rk, a->rj); + return true; +} + +static bool trans_crc_w_b_w(DisasContext *ctx, arg_crc_w_b_w *a) +{ + gen_crc32(ctx, a->rd, a->rj, a->rk, 1, 0); + return true; +} + +static bool trans_crc_w_h_w(DisasContext *ctx, arg_crc_w_h_w *a) +{ + gen_crc32(ctx, a->rd, a->rj, a->rk, 2, 0); + return true; +} + +static bool trans_crc_w_w_w(DisasContext *ctx, arg_crc_w_w_w *a) +{ + gen_crc32(ctx, a->rd, a->rj, a->rk, 4, 0); + return true; +} + +static bool trans_crc_w_d_w(DisasContext *ctx, arg_crc_w_d_w *a) +{ + gen_crc32(ctx, a->rd, a->rj, a->rk, 8, 0); + return true; +} + +static bool trans_crcc_w_b_w(DisasContext *ctx, arg_crcc_w_b_w *a) +{ + gen_crc32(ctx, a->rd, a->rj, a->rk, 1, 1); + return true; +} + +static bool trans_crcc_w_h_w(DisasContext *ctx, arg_crcc_w_h_w *a) +{ + gen_crc32(ctx, a->rd, a->rj, a->rk, 2, 1); + return true; +} + +static bool trans_crcc_w_w_w(DisasContext *ctx, arg_crcc_w_w_w *a) +{ + gen_crc32(ctx, a->rd, a->rj, a->rk, 4, 1); + return true; +} + +static bool trans_crcc_w_d_w(DisasContext *ctx, arg_crcc_w_d_w *a) +{ + gen_crc32(ctx, a->rd, a->rj, a->rk, 8, 1); + return true; +} + +static bool trans_mul_w(DisasContext *ctx, arg_mul_w *a) +{ + gen_r6_muldiv(ctx, OPC_LARCH_MUL_W, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_mulh_w(DisasContext *ctx, arg_mulh_w *a) +{ + gen_r6_muldiv(ctx, OPC_LARCH_MULH_W, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_mulh_wu(DisasContext *ctx, arg_mulh_wu *a) +{ + gen_r6_muldiv(ctx, OPC_LARCH_MULH_WU, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_mul_d(DisasContext *ctx, arg_mul_d *a) +{ + check_larch_64(ctx); + gen_r6_muldiv(ctx, OPC_LARCH_MUL_D, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_mulh_d(DisasContext *ctx, arg_mulh_d *a) +{ + check_larch_64(ctx); + gen_r6_muldiv(ctx, OPC_LARCH_MULH_D, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_mulh_du(DisasContext *ctx, arg_mulh_du *a) +{ + check_larch_64(ctx); + gen_r6_muldiv(ctx, OPC_LARCH_MULH_DU, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_mulw_d_w(DisasContext *ctx, arg_mulw_d_w *a) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + gen_load_gpr(t0, a->rj); + gen_load_gpr(t1, a->rk); + tcg_gen_ext32s_i64(t0, t0); + tcg_gen_ext32s_i64(t1, t1); + tcg_gen_mul_i64(t2, t0, t1); + gen_store_gpr(t2, a->rd); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + return true; +} + +static bool trans_mulw_d_wu(DisasContext *ctx, arg_mulw_d_wu *a) +{ + TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 t2 = tcg_temp_new_i64(); + gen_load_gpr(t0, a->rj); + gen_load_gpr(t1, a->rk); + tcg_gen_ext32u_i64(t0, t0); + tcg_gen_ext32u_i64(t1, t1); + tcg_gen_mul_i64(t2, t0, t1); + gen_store_gpr(t2, a->rd); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + return true; +} + +static bool trans_div_w(DisasContext *ctx, arg_div_w *a) +{ + gen_r6_muldiv(ctx, OPC_LARCH_DIV_W, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_mod_w(DisasContext *ctx, arg_mod_w *a) +{ + gen_r6_muldiv(ctx, OPC_LARCH_MOD_W, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_div_wu(DisasContext *ctx, arg_div_wu *a) +{ + gen_r6_muldiv(ctx, OPC_LARCH_DIV_WU, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_mod_wu(DisasContext *ctx, arg_mod_wu *a) +{ + gen_r6_muldiv(ctx, OPC_LARCH_MOD_WU, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_div_d(DisasContext *ctx, arg_div_d *a) +{ + check_larch_64(ctx); + gen_r6_muldiv(ctx, OPC_LARCH_DIV_D, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_mod_d(DisasContext *ctx, arg_mod_d *a) +{ + check_larch_64(ctx); + gen_r6_muldiv(ctx, OPC_LARCH_MOD_D, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_div_du(DisasContext *ctx, arg_div_du *a) +{ + check_larch_64(ctx); + gen_r6_muldiv(ctx, OPC_LARCH_DIV_DU, a->rd, a->rj, a->rk); + return true; +} + +static bool trans_mod_du(DisasContext *ctx, arg_mod_du *a) +{ + check_larch_64(ctx); + gen_r6_muldiv(ctx, OPC_LARCH_MOD_DU, a->rd, a->rj, a->rk); + return true; +} + +/* do not update CP0.BadVaddr */ +static bool trans_asrtle_d(DisasContext *ctx, arg_asrtle_d * a) +{ + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + gen_load_gpr(t1, a->rj); + gen_load_gpr(t2, a->rk); + gen_helper_asrtle_d(cpu_env, t1, t2); + tcg_temp_free(t1); + tcg_temp_free(t2); + return true; +} + +/* do not update CP0.BadVaddr */ +static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a) +{ + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + gen_load_gpr(t1, a->rj); + gen_load_gpr(t2, a->rk); + gen_helper_asrtgt_d(cpu_env, t1, t2); + tcg_temp_free(t1); + tcg_temp_free(t2); + return true; +} + +#ifdef CONFIG_USER_ONLY +static bool trans_gr2scr(DisasContext *ctx, arg_gr2scr *a) +{ + return false; +} + +static bool trans_scr2gr(DisasContext *ctx, arg_scr2gr *a) +{ + return false; +} +#else +static bool trans_gr2scr(DisasContext *ctx, arg_gr2scr *a) +{ + TCGv_i32 sd = tcg_const_i32(a->sd); + TCGv val = tcg_temp_new(); + check_lbt_enabled(ctx); + gen_load_gpr(val, a->rj); + gen_helper_store_scr(cpu_env, sd, val); + tcg_temp_free_i32(sd); + tcg_temp_free(val); + return true; +} + +static bool trans_scr2gr(DisasContext *ctx, arg_scr2gr *a) +{ + if (a->rd == 0) { + /* Nop */ + return true; + } + + TCGv_i32 tsj = tcg_const_i32(a->sj); + check_lbt_enabled(ctx); + gen_helper_load_scr(cpu_gpr[a->rd], cpu_env, tsj); + tcg_temp_free_i32(tsj); + return true; +} +#endif + +static bool trans_clo_w(DisasContext *ctx, arg_clo_w *a) +{ + gen_cl(ctx, OPC_LARCH_CLO_W, a->rd, a->rj); + return true; +} + +static bool trans_clz_w(DisasContext *ctx, arg_clz_w *a) +{ + gen_cl(ctx, OPC_LARCH_CLZ_W, a->rd, a->rj); + return true; +} + +static bool trans_cto_w(DisasContext *ctx, arg_cto_w *a) +{ + TCGv t0 = tcg_temp_new(); + + gen_load_gpr(t0, a->rj); + gen_helper_cto_w(cpu_gpr[a->rd], cpu_env, t0); + + tcg_temp_free(t0); + return true; +} + +static bool trans_ctz_w(DisasContext *ctx, arg_ctz_w *a) +{ + TCGv t0 = tcg_temp_new(); + + gen_load_gpr(t0, a->rj); + gen_helper_ctz_w(cpu_gpr[a->rd], cpu_env, t0); + + tcg_temp_free(t0); + return true; +} + +static bool trans_clo_d(DisasContext *ctx, arg_clo_d *a) +{ + check_larch_64(ctx); + gen_cl(ctx, OPC_LARCH_CLO_D, a->rd, a->rj); + return true; +} + +static bool trans_clz_d(DisasContext *ctx, arg_clz_d *a) +{ + check_larch_64(ctx); + gen_cl(ctx, OPC_LARCH_CLZ_D, a->rd, a->rj); + return true; +} + +static bool trans_cto_d(DisasContext *ctx, arg_cto_d *a) +{ + TCGv t0 = tcg_temp_new(); + + gen_load_gpr(t0, a->rj); + gen_helper_cto_d(cpu_gpr[a->rd], cpu_env, t0); + + tcg_temp_free(t0); + return true; +} + +static bool trans_ctz_d(DisasContext *ctx, arg_ctz_d *a) +{ + TCGv t0 = tcg_temp_new(); + + gen_load_gpr(t0, a->rj); + gen_helper_ctz_d(cpu_gpr[a->rd], cpu_env, t0); + + tcg_temp_free(t0); + return true; +} + +static bool trans_revb_2h(DisasContext *ctx, arg_revb_2h *a) +{ + gen_bshfl(ctx, OPC_LARCH_REVB_2H, a->rj, a->rd); + return true; +} + +static bool trans_revb_4h(DisasContext *ctx, arg_revb_4h *a) +{ + check_larch_64(ctx); + gen_bshfl(ctx, OPC_LARCH_REVB_4H, a->rj, a->rd); + return true; +} + +static bool trans_revb_2w(DisasContext *ctx, arg_revb_2w *a) +{ + handle_rev32(ctx, a->rj, a->rd); + return true; +} + +static bool trans_revb_d(DisasContext *ctx, arg_revb_d *a) +{ + handle_rev64(ctx, a->rj, a->rd); + return true; +} + +static bool trans_revh_2w(DisasContext *ctx, arg_revh_2w *a) +{ + handle_rev16(ctx, a->rj, a->rd); + return true; +} + +static bool trans_revh_d(DisasContext *ctx, arg_revh_d *a) +{ + check_larch_64(ctx); + gen_bshfl(ctx, OPC_LARCH_REVH_D, a->rj, a->rd); + return true; +} + +static bool trans_bitrev_4b(DisasContext *ctx, arg_bitrev_4b *a) +{ + gen_bitswap(ctx, OPC_LARCH_BREV_4B, a->rd, a->rj); + return true; +} + +static bool trans_bitrev_8b(DisasContext *ctx, arg_bitrev_8b *a) +{ + check_larch_64(ctx); + gen_bitswap(ctx, OPC_LARCH_BREV_8B, a->rd, a->rj); + return true; +} + +static bool trans_bitrev_w(DisasContext *ctx, arg_bitrev_w *a) +{ + TCGv t0 = tcg_temp_new(); + gen_load_gpr(t0, a->rj); + gen_helper_bitrev_w(cpu_gpr[a->rd], cpu_env, t0); + tcg_temp_free(t0); + return true; +} + +static bool trans_bitrev_d(DisasContext *ctx, arg_bitrev_d *a) +{ + TCGv t0 = tcg_temp_new(); + gen_load_gpr(t0, a->rj); + gen_helper_bitrev_d(cpu_gpr[a->rd], cpu_env, t0); + tcg_temp_free(t0); + return true; +} + +static bool trans_ext_w_h(DisasContext *ctx, arg_ext_w_h *a) +{ + gen_bshfl(ctx, OPC_LARCH_EXT_WH, a->rj, a->rd); + return true; +} + +static bool trans_ext_w_b(DisasContext *ctx, arg_ext_w_b *a) +{ + gen_bshfl(ctx, OPC_LARCH_EXT_WB, a->rj, a->rd); + return true; +} + +static bool trans_srli_w(DisasContext *ctx, arg_srli_w *a) +{ + gen_shift_imm(ctx, OPC_LARCH_SRLI_W, a->rd, a->rj, a->ui5); + return true; +} + +static bool trans_srai_w(DisasContext *ctx, arg_srai_w *a) +{ + gen_shift_imm(ctx, OPC_LARCH_SRAI_W, a->rd, a->rj, a->ui5); + return true; +} + +static bool trans_srai_d(DisasContext *ctx, arg_srai_d *a) +{ + TCGv t0; + check_larch_64(ctx); + t0 = tcg_temp_new(); + gen_load_gpr(t0, a->rj); + tcg_gen_sari_tl(cpu_gpr[a->rd], t0, a->ui6); + tcg_temp_free(t0); + return true; +} + +static bool trans_rotri_w(DisasContext *ctx, arg_rotri_w *a) +{ + gen_shift_imm(ctx, OPC_LARCH_ROTRI_W, a->rd, a->rj, a->ui5); + return true; +} + +static bool trans_rotri_d(DisasContext *ctx, arg_rotri_d *a) +{ + TCGv t0; + check_larch_64(ctx); + t0 = tcg_temp_new(); + gen_load_gpr(t0, a->rj); + tcg_gen_rotri_tl(cpu_gpr[a->rd], t0, a->ui6); + tcg_temp_free(t0); + return true; +} + +static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a) +{ + check_cp1_enabled(ctx); + gen_fcmp_s(ctx, a->fcond, a->fk, a->fj, a->cd); + return true; +} + +static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a) +{ + check_cp1_enabled(ctx); + gen_fcmp_d(ctx, a->fcond, a->fk, a->fj, a->cd); + return true; +} + +static bool trans_fsel(DisasContext *ctx, arg_fsel *a) +{ + TCGv_i64 fj = tcg_temp_new_i64(); + TCGv_i64 fk = tcg_temp_new_i64(); + TCGv_i64 fd = tcg_temp_new_i64(); + TCGv_i32 ca = tcg_const_i32(a->ca); + check_cp1_enabled(ctx); + gen_load_fpr64(ctx, fj, a->fj); + gen_load_fpr64(ctx, fk, a->fk); + gen_helper_fsel(fd, cpu_env, fj, fk, ca); + gen_store_fpr64(ctx, fd, a->fd); + tcg_temp_free_i64(fj); + tcg_temp_free_i64(fk); + tcg_temp_free_i64(fd); + tcg_temp_free_i32(ca); + return true; +} + +#include "cpu-csr.h" + +#ifdef CONFIG_USER_ONLY + +static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) +{ + return false; +} + +#else + + +#define GEN_CSRRQ_CASE(name) \ + do { \ + case LOONGARCH_CSR_ ## name: \ + gen_csr_rdq(ctx, cpu_gpr[rd], LOONGARCH_CSR_ ## name);\ + } while (0) + +static bool trans_csrrd(DisasContext *ctx, unsigned rd, unsigned csr) +{ + switch (csr) { + GEN_CSRRQ_CASE(CRMD); + break; + GEN_CSRRQ_CASE(PRMD); + break; + GEN_CSRRQ_CASE(EUEN); + break; + GEN_CSRRQ_CASE(MISC); + break; + GEN_CSRRQ_CASE(ECFG); + break; + GEN_CSRRQ_CASE(ESTAT); + break; + GEN_CSRRQ_CASE(ERA); + break; + GEN_CSRRQ_CASE(BADV); + break; + GEN_CSRRQ_CASE(BADI); + break; + GEN_CSRRQ_CASE(EEPN); + break; + GEN_CSRRQ_CASE(TLBIDX); + break; + GEN_CSRRQ_CASE(TLBEHI); + break; + GEN_CSRRQ_CASE(TLBELO0); + break; + GEN_CSRRQ_CASE(TLBELO1); + break; + GEN_CSRRQ_CASE(TLBWIRED); + break; + GEN_CSRRQ_CASE(GTLBC); + break; + GEN_CSRRQ_CASE(TRGP); + break; + GEN_CSRRQ_CASE(ASID); + break; + GEN_CSRRQ_CASE(PGDL); + break; + GEN_CSRRQ_CASE(PGDH); + break; + case LOONGARCH_CSR_PGD: + gen_helper_read_pgd(cpu_gpr[rd], cpu_env); + break; + GEN_CSRRQ_CASE(PWCTL0); + break; + GEN_CSRRQ_CASE(PWCTL1); + break; + GEN_CSRRQ_CASE(STLBPGSIZE); + break; + GEN_CSRRQ_CASE(RVACFG); + break; + GEN_CSRRQ_CASE(CPUID); + break; + GEN_CSRRQ_CASE(PRCFG1); + break; + GEN_CSRRQ_CASE(PRCFG2); + break; + GEN_CSRRQ_CASE(PRCFG3); + break; + GEN_CSRRQ_CASE(KS0); + break; + GEN_CSRRQ_CASE(KS1); + break; + GEN_CSRRQ_CASE(KS2); + break; + GEN_CSRRQ_CASE(KS3); + break; + GEN_CSRRQ_CASE(KS4); + break; + GEN_CSRRQ_CASE(KS5); + break; + GEN_CSRRQ_CASE(KS6); + break; + GEN_CSRRQ_CASE(KS7); + break; + GEN_CSRRQ_CASE(KS8); + break; + GEN_CSRRQ_CASE(TMID); + break; + GEN_CSRRQ_CASE(TCFG); + break; + GEN_CSRRQ_CASE(TVAL); + break; + GEN_CSRRQ_CASE(CNTC); + break; + GEN_CSRRQ_CASE(TINTCLR); + break; + GEN_CSRRQ_CASE(GSTAT); + break; + GEN_CSRRQ_CASE(GCFG); + break; + GEN_CSRRQ_CASE(GINTC); + break; + GEN_CSRRQ_CASE(GCNTC); + break; + GEN_CSRRQ_CASE(LLBCTL); + break; + GEN_CSRRQ_CASE(IMPCTL1); + break; + GEN_CSRRQ_CASE(IMPCTL2); + break; + GEN_CSRRQ_CASE(GNMI); + break; + GEN_CSRRQ_CASE(TLBRENT); + break; + GEN_CSRRQ_CASE(TLBRBADV); + break; + GEN_CSRRQ_CASE(TLBRERA); + break; + GEN_CSRRQ_CASE(TLBRSAVE); + break; + GEN_CSRRQ_CASE(TLBRELO0); + break; + GEN_CSRRQ_CASE(TLBRELO1); + break; + GEN_CSRRQ_CASE(TLBREHI); + break; + GEN_CSRRQ_CASE(TLBRPRMD); + break; + GEN_CSRRQ_CASE(ERRCTL); + break; + GEN_CSRRQ_CASE(ERRINFO); + break; + GEN_CSRRQ_CASE(ERRINFO1); + break; + GEN_CSRRQ_CASE(ERRENT); + break; + GEN_CSRRQ_CASE(ERRERA); + break; + GEN_CSRRQ_CASE(ERRSAVE); + break; + GEN_CSRRQ_CASE(CTAG); + break; + GEN_CSRRQ_CASE(DMWIN0); + break; + GEN_CSRRQ_CASE(DMWIN1); + break; + GEN_CSRRQ_CASE(DMWIN2); + break; + GEN_CSRRQ_CASE(DMWIN3); + break; + GEN_CSRRQ_CASE(PERFCTRL0); + break; + GEN_CSRRQ_CASE(PERFCNTR0); + break; + GEN_CSRRQ_CASE(PERFCTRL1); + break; + GEN_CSRRQ_CASE(PERFCNTR1); + break; + GEN_CSRRQ_CASE(PERFCTRL2); + break; + GEN_CSRRQ_CASE(PERFCNTR2); + break; + GEN_CSRRQ_CASE(PERFCTRL3); + break; + GEN_CSRRQ_CASE(PERFCNTR3); + break; + /* debug */ + GEN_CSRRQ_CASE(MWPC); + break; + GEN_CSRRQ_CASE(MWPS); + break; + GEN_CSRRQ_CASE(DB0ADDR); + break; + GEN_CSRRQ_CASE(DB0MASK); + break; + GEN_CSRRQ_CASE(DB0CTL); + break; + GEN_CSRRQ_CASE(DB0ASID); + break; + GEN_CSRRQ_CASE(DB1ADDR); + break; + GEN_CSRRQ_CASE(DB1MASK); + break; + GEN_CSRRQ_CASE(DB1CTL); + break; + GEN_CSRRQ_CASE(DB1ASID); + break; + GEN_CSRRQ_CASE(DB2ADDR); + break; + GEN_CSRRQ_CASE(DB2MASK); + break; + GEN_CSRRQ_CASE(DB2CTL); + break; + GEN_CSRRQ_CASE(DB2ASID); + break; + GEN_CSRRQ_CASE(DB3ADDR); + break; + GEN_CSRRQ_CASE(DB3MASK); + break; + GEN_CSRRQ_CASE(DB3CTL); + break; + GEN_CSRRQ_CASE(DB3ASID); + break; + GEN_CSRRQ_CASE(FWPC); + break; + GEN_CSRRQ_CASE(FWPS); + break; + GEN_CSRRQ_CASE(IB0ADDR); + break; + GEN_CSRRQ_CASE(IB0MASK); + break; + GEN_CSRRQ_CASE(IB0CTL); + break; + GEN_CSRRQ_CASE(IB0ASID); + break; + GEN_CSRRQ_CASE(IB1ADDR); + break; + GEN_CSRRQ_CASE(IB1MASK); + break; + GEN_CSRRQ_CASE(IB1CTL); + break; + GEN_CSRRQ_CASE(IB1ASID); + break; + GEN_CSRRQ_CASE(IB2ADDR); + break; + GEN_CSRRQ_CASE(IB2MASK); + break; + GEN_CSRRQ_CASE(IB2CTL); + break; + GEN_CSRRQ_CASE(IB2ASID); + break; + GEN_CSRRQ_CASE(IB3ADDR); + break; + GEN_CSRRQ_CASE(IB3MASK); + break; + GEN_CSRRQ_CASE(IB3CTL); + break; + GEN_CSRRQ_CASE(IB3ASID); + break; + GEN_CSRRQ_CASE(IB4ADDR); + break; + GEN_CSRRQ_CASE(IB4MASK); + break; + GEN_CSRRQ_CASE(IB4CTL); + break; + GEN_CSRRQ_CASE(IB4ASID); + break; + GEN_CSRRQ_CASE(IB5ADDR); + break; + GEN_CSRRQ_CASE(IB5MASK); + break; + GEN_CSRRQ_CASE(IB5CTL); + break; + GEN_CSRRQ_CASE(IB5ASID); + break; + GEN_CSRRQ_CASE(IB6ADDR); + break; + GEN_CSRRQ_CASE(IB6MASK); + break; + GEN_CSRRQ_CASE(IB6CTL); + break; + GEN_CSRRQ_CASE(IB6ASID); + break; + GEN_CSRRQ_CASE(IB7ADDR); + break; + GEN_CSRRQ_CASE(IB7MASK); + break; + GEN_CSRRQ_CASE(IB7CTL); + break; + GEN_CSRRQ_CASE(IB7ASID); + break; + GEN_CSRRQ_CASE(DEBUG); + break; + GEN_CSRRQ_CASE(DERA); + break; + GEN_CSRRQ_CASE(DESAVE); + break; + default: + return false; + } + + #undef GEN_CSRRQ_CASE + + return true; +} + +#define GEN_CSRWQ_CASE(name) \ +do { \ + case LOONGARCH_CSR_ ## name: \ + gen_csr_wrq(ctx, cpu_gpr[rd], LOONGARCH_CSR_ ## name); \ +} while (0) + +static bool trans_csrwr(DisasContext *ctx, unsigned rd, unsigned csr) +{ + + switch (csr) { + case LOONGARCH_CSR_CRMD: + save_cpu_state(ctx, 1); + gen_csr_wrq(ctx, cpu_gpr[rd], LOONGARCH_CSR_CRMD); + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; + break; + GEN_CSRWQ_CASE(PRMD); + break; + case LOONGARCH_CSR_EUEN: + gen_csr_wrq(ctx, cpu_gpr[rd], LOONGARCH_CSR_EUEN); + /* Stop translation */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; + break; + GEN_CSRWQ_CASE(MISC); + break; + GEN_CSRWQ_CASE(ECFG); + break; + GEN_CSRWQ_CASE(ESTAT); + break; + GEN_CSRWQ_CASE(ERA); + break; + GEN_CSRWQ_CASE(BADV); + break; + GEN_CSRWQ_CASE(BADI); + break; + GEN_CSRWQ_CASE(EEPN); + break; + GEN_CSRWQ_CASE(TLBIDX); + break; + GEN_CSRWQ_CASE(TLBEHI); + break; + GEN_CSRWQ_CASE(TLBELO0); + break; + GEN_CSRWQ_CASE(TLBELO1); + break; + GEN_CSRWQ_CASE(TLBWIRED); + break; + GEN_CSRWQ_CASE(GTLBC); + break; + GEN_CSRWQ_CASE(TRGP); + break; + GEN_CSRWQ_CASE(ASID); + break; + GEN_CSRWQ_CASE(PGDL); + break; + GEN_CSRWQ_CASE(PGDH); + break; + GEN_CSRWQ_CASE(PGD); + break; + GEN_CSRWQ_CASE(PWCTL0); + break; + GEN_CSRWQ_CASE(PWCTL1); + break; + GEN_CSRWQ_CASE(STLBPGSIZE); + break; + GEN_CSRWQ_CASE(RVACFG); + break; + GEN_CSRWQ_CASE(CPUID); + break; + GEN_CSRWQ_CASE(PRCFG1); + break; + GEN_CSRWQ_CASE(PRCFG2); + break; + GEN_CSRWQ_CASE(PRCFG3); + break; + GEN_CSRWQ_CASE(KS0); + break; + GEN_CSRWQ_CASE(KS1); + break; + GEN_CSRWQ_CASE(KS2); + break; + GEN_CSRWQ_CASE(KS3); + break; + GEN_CSRWQ_CASE(KS4); + break; + GEN_CSRWQ_CASE(KS5); + break; + GEN_CSRWQ_CASE(KS6); + break; + GEN_CSRWQ_CASE(KS7); + break; + GEN_CSRWQ_CASE(KS8); + break; + GEN_CSRWQ_CASE(TMID); + break; + GEN_CSRWQ_CASE(TCFG); + break; + GEN_CSRWQ_CASE(TVAL); + break; + GEN_CSRWQ_CASE(CNTC); + break; + GEN_CSRWQ_CASE(TINTCLR); + break; + GEN_CSRWQ_CASE(GSTAT); + break; + GEN_CSRWQ_CASE(GCFG); + break; + GEN_CSRWQ_CASE(GINTC); + break; + GEN_CSRWQ_CASE(GCNTC); + break; + GEN_CSRWQ_CASE(LLBCTL); + break; + GEN_CSRWQ_CASE(IMPCTL1); + break; + GEN_CSRWQ_CASE(IMPCTL2); + break; + GEN_CSRWQ_CASE(GNMI); + break; + GEN_CSRWQ_CASE(TLBRENT); + break; + GEN_CSRWQ_CASE(TLBRBADV); + break; + GEN_CSRWQ_CASE(TLBRERA); + break; + GEN_CSRWQ_CASE(TLBRSAVE); + break; + GEN_CSRWQ_CASE(TLBRELO0); + break; + GEN_CSRWQ_CASE(TLBRELO1); + break; + GEN_CSRWQ_CASE(TLBREHI); + break; + GEN_CSRWQ_CASE(TLBRPRMD); + break; + GEN_CSRWQ_CASE(ERRCTL); + break; + GEN_CSRWQ_CASE(ERRINFO); + break; + GEN_CSRWQ_CASE(ERRINFO1); + break; + GEN_CSRWQ_CASE(ERRENT); + break; + GEN_CSRWQ_CASE(ERRERA); + break; + GEN_CSRWQ_CASE(ERRSAVE); + break; + GEN_CSRWQ_CASE(CTAG); + break; + GEN_CSRWQ_CASE(DMWIN0); + break; + GEN_CSRWQ_CASE(DMWIN1); + break; + GEN_CSRWQ_CASE(DMWIN2); + break; + GEN_CSRWQ_CASE(DMWIN3); + break; + GEN_CSRWQ_CASE(PERFCTRL0); + break; + GEN_CSRWQ_CASE(PERFCNTR0); + break; + GEN_CSRWQ_CASE(PERFCTRL1); + break; + GEN_CSRWQ_CASE(PERFCNTR1); + break; + GEN_CSRWQ_CASE(PERFCTRL2); + break; + GEN_CSRWQ_CASE(PERFCNTR2); + break; + GEN_CSRWQ_CASE(PERFCTRL3); + break; + GEN_CSRWQ_CASE(PERFCNTR3); + break; + /* debug */ + GEN_CSRWQ_CASE(MWPC); + break; + GEN_CSRWQ_CASE(MWPS); + break; + GEN_CSRWQ_CASE(DB0ADDR); + break; + GEN_CSRWQ_CASE(DB0MASK); + break; + GEN_CSRWQ_CASE(DB0CTL); + break; + GEN_CSRWQ_CASE(DB0ASID); + break; + GEN_CSRWQ_CASE(DB1ADDR); + break; + GEN_CSRWQ_CASE(DB1MASK); + break; + GEN_CSRWQ_CASE(DB1CTL); + break; + GEN_CSRWQ_CASE(DB1ASID); + break; + GEN_CSRWQ_CASE(DB2ADDR); + break; + GEN_CSRWQ_CASE(DB2MASK); + break; + GEN_CSRWQ_CASE(DB2CTL); + break; + GEN_CSRWQ_CASE(DB2ASID); + break; + GEN_CSRWQ_CASE(DB3ADDR); + break; + GEN_CSRWQ_CASE(DB3MASK); + break; + GEN_CSRWQ_CASE(DB3CTL); + break; + GEN_CSRWQ_CASE(DB3ASID); + break; + GEN_CSRWQ_CASE(FWPC); + break; + GEN_CSRWQ_CASE(FWPS); + break; + GEN_CSRWQ_CASE(IB0ADDR); + break; + GEN_CSRWQ_CASE(IB0MASK); + break; + GEN_CSRWQ_CASE(IB0CTL); + break; + GEN_CSRWQ_CASE(IB0ASID); + break; + GEN_CSRWQ_CASE(IB1ADDR); + break; + GEN_CSRWQ_CASE(IB1MASK); + break; + GEN_CSRWQ_CASE(IB1CTL); + break; + GEN_CSRWQ_CASE(IB1ASID); + break; + GEN_CSRWQ_CASE(IB2ADDR); + break; + GEN_CSRWQ_CASE(IB2MASK); + break; + GEN_CSRWQ_CASE(IB2CTL); + break; + GEN_CSRWQ_CASE(IB2ASID); + break; + GEN_CSRWQ_CASE(IB3ADDR); + break; + GEN_CSRWQ_CASE(IB3MASK); + break; + GEN_CSRWQ_CASE(IB3CTL); + break; + GEN_CSRWQ_CASE(IB3ASID); + break; + GEN_CSRWQ_CASE(IB4ADDR); + break; + GEN_CSRWQ_CASE(IB4MASK); + break; + GEN_CSRWQ_CASE(IB4CTL); + break; + GEN_CSRWQ_CASE(IB4ASID); + break; + GEN_CSRWQ_CASE(IB5ADDR); + break; + GEN_CSRWQ_CASE(IB5MASK); + break; + GEN_CSRWQ_CASE(IB5CTL); + break; + GEN_CSRWQ_CASE(IB5ASID); + break; + GEN_CSRWQ_CASE(IB6ADDR); + break; + GEN_CSRWQ_CASE(IB6MASK); + break; + GEN_CSRWQ_CASE(IB6CTL); + break; + GEN_CSRWQ_CASE(IB6ASID); + break; + GEN_CSRWQ_CASE(IB7ADDR); + break; + GEN_CSRWQ_CASE(IB7MASK); + break; + GEN_CSRWQ_CASE(IB7CTL); + break; + GEN_CSRWQ_CASE(IB7ASID); + break; + GEN_CSRWQ_CASE(DEBUG); + break; + GEN_CSRWQ_CASE(DERA); + break; + GEN_CSRWQ_CASE(DESAVE); + break; + default: + return false; + } + + #undef GEN_CSRWQ_CASE + + return true; +} + +#define GEN_CSRXQ_CASE(name) \ +do { \ + case LOONGARCH_CSR_ ## name: \ + if (rd == 0) { \ + gen_csr_xchgq(ctx, zero, cpu_gpr[rj], \ + LOONGARCH_CSR_ ## name); \ + } else { \ + gen_csr_xchgq(ctx, cpu_gpr[rd], cpu_gpr[rj], \ + LOONGARCH_CSR_ ## name); \ + } \ +} while (0) + +static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) +{ + unsigned rd, rj, csr; + TCGv zero = tcg_const_tl(0); + rd = a->rd; + rj = a->rj; + csr = a->csr; + + if (rj == 0) { + return trans_csrrd(ctx, rd, csr); + } else if (rj == 1) { + return trans_csrwr(ctx, rd, csr); + } + + switch (csr) { + case LOONGARCH_CSR_CRMD: + save_cpu_state(ctx, 1); + if (rd == 0) { + gen_csr_xchgq(ctx, zero, cpu_gpr[rj], LOONGARCH_CSR_CRMD); + } else { + gen_csr_xchgq(ctx, cpu_gpr[rd], cpu_gpr[rj], LOONGARCH_CSR_CRMD); + } + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; + break; + + GEN_CSRXQ_CASE(PRMD); + break; + case LOONGARCH_CSR_EUEN: + if (rd == 0) { + gen_csr_xchgq(ctx, zero, cpu_gpr[rj], LOONGARCH_CSR_EUEN); + } else { + gen_csr_xchgq(ctx, cpu_gpr[rd], cpu_gpr[rj], LOONGARCH_CSR_EUEN); + } + /* Stop translation */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; + break; + GEN_CSRXQ_CASE(MISC); + break; + GEN_CSRXQ_CASE(ECFG); + break; + GEN_CSRXQ_CASE(ESTAT); + break; + GEN_CSRXQ_CASE(ERA); + break; + GEN_CSRXQ_CASE(BADV); + break; + GEN_CSRXQ_CASE(BADI); + break; + GEN_CSRXQ_CASE(EEPN); + break; + GEN_CSRXQ_CASE(TLBIDX); + break; + GEN_CSRXQ_CASE(TLBEHI); + break; + GEN_CSRXQ_CASE(TLBELO0); + break; + GEN_CSRXQ_CASE(TLBELO1); + break; + GEN_CSRXQ_CASE(TLBWIRED); + break; + GEN_CSRXQ_CASE(GTLBC); + break; + GEN_CSRXQ_CASE(TRGP); + break; + GEN_CSRXQ_CASE(ASID); + break; + GEN_CSRXQ_CASE(PGDL); + break; + GEN_CSRXQ_CASE(PGDH); + break; + GEN_CSRXQ_CASE(PGD); + break; + GEN_CSRXQ_CASE(PWCTL0); + break; + GEN_CSRXQ_CASE(PWCTL1); + break; + GEN_CSRXQ_CASE(STLBPGSIZE); + break; + GEN_CSRXQ_CASE(RVACFG); + break; + GEN_CSRXQ_CASE(CPUID); + break; + GEN_CSRXQ_CASE(PRCFG1); + break; + GEN_CSRXQ_CASE(PRCFG2); + break; + GEN_CSRXQ_CASE(PRCFG3); + break; + GEN_CSRXQ_CASE(KS0); + break; + GEN_CSRXQ_CASE(KS1); + break; + GEN_CSRXQ_CASE(KS2); + break; + GEN_CSRXQ_CASE(KS3); + break; + GEN_CSRXQ_CASE(KS4); + break; + GEN_CSRXQ_CASE(KS5); + break; + GEN_CSRXQ_CASE(KS6); + break; + GEN_CSRXQ_CASE(KS7); + break; + GEN_CSRXQ_CASE(KS8); + break; + GEN_CSRXQ_CASE(TMID); + break; + GEN_CSRXQ_CASE(TCFG); + break; + GEN_CSRXQ_CASE(TVAL); + break; + GEN_CSRXQ_CASE(CNTC); + break; + GEN_CSRXQ_CASE(TINTCLR); + break; + GEN_CSRXQ_CASE(GSTAT); + break; + GEN_CSRXQ_CASE(GCFG); + break; + GEN_CSRXQ_CASE(GINTC); + break; + GEN_CSRXQ_CASE(GCNTC); + break; + GEN_CSRXQ_CASE(LLBCTL); + break; + GEN_CSRXQ_CASE(IMPCTL1); + break; + GEN_CSRXQ_CASE(IMPCTL2); + break; + GEN_CSRXQ_CASE(GNMI); + break; + GEN_CSRXQ_CASE(TLBRENT); + break; + GEN_CSRXQ_CASE(TLBRBADV); + break; + GEN_CSRXQ_CASE(TLBRERA); + break; + GEN_CSRXQ_CASE(TLBRSAVE); + break; + GEN_CSRXQ_CASE(TLBRELO0); + break; + GEN_CSRXQ_CASE(TLBRELO1); + break; + GEN_CSRXQ_CASE(TLBREHI); + break; + GEN_CSRXQ_CASE(TLBRPRMD); + break; + GEN_CSRXQ_CASE(ERRCTL); + break; + GEN_CSRXQ_CASE(ERRINFO); + break; + GEN_CSRXQ_CASE(ERRINFO1); + break; + GEN_CSRXQ_CASE(ERRENT); + break; + GEN_CSRXQ_CASE(ERRERA); + break; + GEN_CSRXQ_CASE(ERRSAVE); + break; + GEN_CSRXQ_CASE(CTAG); + break; + GEN_CSRXQ_CASE(DMWIN0); + break; + GEN_CSRXQ_CASE(DMWIN1); + break; + GEN_CSRXQ_CASE(DMWIN2); + break; + GEN_CSRXQ_CASE(DMWIN3); + break; + GEN_CSRXQ_CASE(PERFCTRL0); + break; + GEN_CSRXQ_CASE(PERFCNTR0); + break; + GEN_CSRXQ_CASE(PERFCTRL1); + break; + GEN_CSRXQ_CASE(PERFCNTR1); + break; + GEN_CSRXQ_CASE(PERFCTRL2); + break; + GEN_CSRXQ_CASE(PERFCNTR2); + break; + GEN_CSRXQ_CASE(PERFCTRL3); + break; + GEN_CSRXQ_CASE(PERFCNTR3); + break; + /* debug */ + GEN_CSRXQ_CASE(MWPC); + break; + GEN_CSRXQ_CASE(MWPS); + break; + GEN_CSRXQ_CASE(DB0ADDR); + break; + GEN_CSRXQ_CASE(DB0MASK); + break; + GEN_CSRXQ_CASE(DB0CTL); + break; + GEN_CSRXQ_CASE(DB0ASID); + break; + GEN_CSRXQ_CASE(DB1ADDR); + break; + GEN_CSRXQ_CASE(DB1MASK); + break; + GEN_CSRXQ_CASE(DB1CTL); + break; + GEN_CSRXQ_CASE(DB1ASID); + break; + GEN_CSRXQ_CASE(DB2ADDR); + break; + GEN_CSRXQ_CASE(DB2MASK); + break; + GEN_CSRXQ_CASE(DB2CTL); + break; + GEN_CSRXQ_CASE(DB2ASID); + break; + GEN_CSRXQ_CASE(DB3ADDR); + break; + GEN_CSRXQ_CASE(DB3MASK); + break; + GEN_CSRXQ_CASE(DB3CTL); + break; + GEN_CSRXQ_CASE(DB3ASID); + break; + GEN_CSRXQ_CASE(FWPC); + break; + GEN_CSRXQ_CASE(FWPS); + break; + GEN_CSRXQ_CASE(IB0ADDR); + break; + GEN_CSRXQ_CASE(IB0MASK); + break; + GEN_CSRXQ_CASE(IB0CTL); + break; + GEN_CSRXQ_CASE(IB0ASID); + break; + GEN_CSRXQ_CASE(IB1ADDR); + break; + GEN_CSRXQ_CASE(IB1MASK); + break; + GEN_CSRXQ_CASE(IB1CTL); + break; + GEN_CSRXQ_CASE(IB1ASID); + break; + GEN_CSRXQ_CASE(IB2ADDR); + break; + GEN_CSRXQ_CASE(IB2MASK); + break; + GEN_CSRXQ_CASE(IB2CTL); + break; + GEN_CSRXQ_CASE(IB2ASID); + break; + GEN_CSRXQ_CASE(IB3ADDR); + break; + GEN_CSRXQ_CASE(IB3MASK); + break; + GEN_CSRXQ_CASE(IB3CTL); + break; + GEN_CSRXQ_CASE(IB3ASID); + break; + GEN_CSRXQ_CASE(IB4ADDR); + break; + GEN_CSRXQ_CASE(IB4MASK); + break; + GEN_CSRXQ_CASE(IB4CTL); + break; + GEN_CSRXQ_CASE(IB4ASID); + break; + GEN_CSRXQ_CASE(IB5ADDR); + break; + GEN_CSRXQ_CASE(IB5MASK); + break; + GEN_CSRXQ_CASE(IB5CTL); + break; + GEN_CSRXQ_CASE(IB5ASID); + break; + GEN_CSRXQ_CASE(IB6ADDR); + break; + GEN_CSRXQ_CASE(IB6MASK); + break; + GEN_CSRXQ_CASE(IB6CTL); + break; + GEN_CSRXQ_CASE(IB6ASID); + break; + GEN_CSRXQ_CASE(IB7ADDR); + break; + GEN_CSRXQ_CASE(IB7MASK); + break; + GEN_CSRXQ_CASE(IB7CTL); + break; + GEN_CSRXQ_CASE(IB7ASID); + break; + GEN_CSRXQ_CASE(DEBUG); + break; + GEN_CSRXQ_CASE(DERA); + break; + GEN_CSRXQ_CASE(DESAVE); + break; + default: + return false; + } + + #undef GEN_CSRXQ_CASE + tcg_temp_free(zero); + return true; +} + +#endif + +static bool trans_cacop(DisasContext *ctx, arg_cacop *a) +{ + /* Treat as NOP. */ + return true; +} + +#ifdef CONFIG_USER_ONLY + +static bool trans_ldpte(DisasContext *ctx, arg_ldpte *a) +{ + return false; +} + +static bool trans_lddir(DisasContext *ctx, arg_lddir *a) +{ + return false; +} + +static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a) +{ + return false; +} + +static bool trans_iocsrrd_h(DisasContext *ctx, arg_iocsrrd_h *a) +{ + return false; +} + +static bool trans_iocsrrd_w(DisasContext *ctx, arg_iocsrrd_w *a) +{ + return false; +} + +static bool trans_iocsrrd_d(DisasContext *ctx, arg_iocsrrd_d *a) +{ + return false; +} + +static bool trans_iocsrwr_b(DisasContext *ctx, arg_iocsrwr_b *a) +{ + return false; +} + +static bool trans_iocsrwr_h(DisasContext *ctx, arg_iocsrwr_h *a) +{ + return false; +} + +static bool trans_iocsrwr_w(DisasContext *ctx, arg_iocsrwr_w *a) +{ + return false; +} + +static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a) +{ + return false; +} +#else + +static bool trans_ldpte(DisasContext *ctx, arg_ldpte *a) +{ + TCGv t0, t1; + TCGv_i32 t2; + t0 = tcg_const_tl(a->rj); + t1 = tcg_const_tl(a->seq); + t2 = tcg_const_i32(ctx->mem_idx); + gen_helper_ldpte(cpu_env, t0, t1, t2); + + return true; +} + +static bool trans_lddir(DisasContext *ctx, arg_lddir *a) +{ + TCGv t0, t1, t2; + TCGv_i32 t3; + t0 = tcg_const_tl(a->rj); + t1 = tcg_const_tl(a->rd); + t2 = tcg_const_tl(a->level); + t3 = tcg_const_i32(ctx->mem_idx); + gen_helper_lddir(cpu_env, t0, t1, t2, t3); + + return true; +} + +static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a) +{ + return false; +} + +static bool trans_iocsrrd_h(DisasContext *ctx, arg_iocsrrd_h *a) +{ + return false; +} + +static bool trans_iocsrrd_w(DisasContext *ctx, arg_iocsrrd_w *a) +{ + TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_LD_W); + TCGv t0, t1; + t0 = tcg_const_tl(a->rj); + t1 = tcg_const_tl(a->rd); + gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); + return true; +} + +static bool trans_iocsrrd_d(DisasContext *ctx, arg_iocsrrd_d *a) +{ + TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_LD_D); + TCGv t0, t1; + t0 = tcg_const_tl(a->rj); + t1 = tcg_const_tl(a->rd); + gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); + return true; +} + +static bool trans_iocsrwr_b(DisasContext *ctx, arg_iocsrwr_b *a) +{ + TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_ST_B); + TCGv t0, t1; + t0 = tcg_const_tl(a->rj); + t1 = tcg_const_tl(a->rd); + gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); + return true; +} + +static bool trans_iocsrwr_h(DisasContext *ctx, arg_iocsrwr_h *a) +{ + return false; +} + +static bool trans_iocsrwr_w(DisasContext *ctx, arg_iocsrwr_w *a) +{ + TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_ST_W); + TCGv t0, t1; + t0 = tcg_const_tl(a->rj); + t1 = tcg_const_tl(a->rd); + gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); + return true; +} + +static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a) +{ + TCGv_i32 iocsr_op = tcg_const_i32(OPC_LARCH_ST_D); + TCGv t0, t1; + t0 = tcg_const_tl(a->rj); + t1 = tcg_const_tl(a->rd); + gen_helper_iocsr(cpu_env, t0, t1, iocsr_op); + return true; +} +#endif /* !CONFIG_USER_ONLY */ + + +#ifdef CONFIG_USER_ONLY + +#define GEN_FALSE_TRANS(name) \ +static bool trans_##name(DisasContext *ctx, arg_##name * a) \ +{ \ + return false; \ +} + +GEN_FALSE_TRANS(tlbclr) +GEN_FALSE_TRANS(invtlb) +GEN_FALSE_TRANS(tlbflush) +GEN_FALSE_TRANS(tlbsrch) +GEN_FALSE_TRANS(tlbrd) +GEN_FALSE_TRANS(tlbwr) +GEN_FALSE_TRANS(tlbfill) +GEN_FALSE_TRANS(ertn) + +#else + +static bool trans_tlbclr(DisasContext *ctx, arg_tlbclr *a) +{ + gen_helper_tlbclr(cpu_env); + return true; +} + +static bool trans_tlbflush(DisasContext *ctx, arg_tlbflush *a) +{ + gen_helper_tlbflush(cpu_env); + return true; +} + +static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a) +{ + TCGv addr = tcg_temp_new(); + TCGv info = tcg_temp_new(); + TCGv op = tcg_const_tl(a->invop); + + gen_load_gpr(addr, a->addr); + gen_load_gpr(info, a->info); + gen_helper_invtlb(cpu_env, addr, info, op); + + tcg_temp_free(addr); + tcg_temp_free(info); + tcg_temp_free(op); + return true; +} + +static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a) +{ + gen_helper_tlbsrch(cpu_env); + return true; +} + +static bool trans_tlbrd(DisasContext *ctx, arg_tlbrd *a) +{ + gen_helper_tlbrd(cpu_env); + return true; +} + +static bool trans_tlbwr(DisasContext *ctx, arg_tlbwr *a) +{ + gen_helper_tlbwr(cpu_env); + return true; +} + +static bool trans_tlbfill(DisasContext *ctx, arg_tlbfill *a) +{ + gen_helper_tlbfill(cpu_env); + return true; +} + +static bool trans_ertn(DisasContext *ctx, arg_ertn *a) +{ + gen_helper_ertn(cpu_env); + ctx->base.is_jmp = DISAS_EXIT; + return true; +} + +#endif /* CONFIG_USER_ONLY */ + +static bool trans_idle(DisasContext *ctx, arg_idle *a) +{ + ctx->base.pc_next += 4; + save_cpu_state(ctx, 1); + ctx->base.pc_next -= 4; + gen_helper_idle(cpu_env); + ctx->base.is_jmp = DISAS_NORETURN; + return true; +} + +#ifdef CONFIG_USER_ONLY + +static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) +{ + /* Nop */ + return true; +} + +#else + +static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) +{ + TCGv t0, t1; + t0 = tcg_const_tl(a->rd); + t1 = tcg_const_tl(a->rj); + gen_helper_drdtime(cpu_env, t0, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); + return true; +} + +#endif + +static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a) +{ + TCGv t0 = tcg_temp_new(); + gen_load_gpr(t0, a->rj); + gen_helper_cpucfg(cpu_gpr[a->rd], cpu_env, t0); + tcg_temp_free(t0); + return true; +} diff --git a/target/loongarch64/translate.c b/target/loongarch64/translate.c new file mode 100644 index 0000000000..fe122e4c31 --- /dev/null +++ b/target/loongarch64/translate.c @@ -0,0 +1,2892 @@ +/* + * LOONGARCH emulation for QEMU - main translation routines + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "internal.h" +#include "disas/disas.h" +#include "exec/exec-all.h" +#include "tcg/tcg-op.h" +#include "exec/cpu_ldst.h" +#include "hw/loongarch/cpudevs.h" + +#include "exec/helper-proto.h" +#include "exec/helper-gen.h" +#include "semihosting/semihost.h" + +#include "trace-tcg.h" +#include "exec/translator.h" +#include "exec/log.h" + +#include "instmap.h" + +#define LARCH_DEBUG_DISAS 0 + +/* Values for the fmt field in FP instructions */ +enum { + /* 0 - 15 are reserved */ + FMT_S = 16, /* single fp */ + FMT_D = 17, /* double fp */ +}; + +/* global register indices */ +static TCGv cpu_gpr[32], cpu_PC; +static TCGv btarget, bcond; +static TCGv cpu_lladdr, cpu_llval; +static TCGv_i32 hflags; +static TCGv_i32 fpu_fcsr0; +static TCGv_i64 fpu_f64[32]; + +#include "exec/gen-icount.h" + +#define gen_helper_0e0i(name, arg) do { \ + TCGv_i32 helper_tmp = tcg_const_i32(arg); \ + gen_helper_##name(cpu_env, helper_tmp); \ + tcg_temp_free_i32(helper_tmp); \ + } while (0) + +#define gen_helper_0e1i(name, arg1, arg2) do { \ + TCGv_i32 helper_tmp = tcg_const_i32(arg2); \ + gen_helper_##name(cpu_env, arg1, helper_tmp); \ + tcg_temp_free_i32(helper_tmp); \ + } while (0) + +#define gen_helper_1e0i(name, ret, arg1) do { \ + TCGv_i32 helper_tmp = tcg_const_i32(arg1); \ + gen_helper_##name(ret, cpu_env, helper_tmp); \ + tcg_temp_free_i32(helper_tmp); \ + } while (0) + +#define gen_helper_1e1i(name, ret, arg1, arg2) do { \ + TCGv_i32 helper_tmp = tcg_const_i32(arg2); \ + gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \ + tcg_temp_free_i32(helper_tmp); \ + } while (0) + +#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \ + TCGv_i32 helper_tmp = tcg_const_i32(arg3); \ + gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \ + tcg_temp_free_i32(helper_tmp); \ + } while (0) + +#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \ + TCGv_i32 helper_tmp = tcg_const_i32(arg3); \ + gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \ + tcg_temp_free_i32(helper_tmp); \ + } while (0) + +#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \ + TCGv_i32 helper_tmp = tcg_const_i32(arg4); \ + gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \ + tcg_temp_free_i32(helper_tmp); \ + } while (0) + +typedef struct DisasContext { + DisasContextBase base; + target_ulong saved_pc; + target_ulong page_start; + uint32_t opcode; + uint64_t insn_flags; + /* Routine used to access memory */ + int mem_idx; + MemOp default_tcg_memop_mask; + uint32_t hflags, saved_hflags; + target_ulong btarget; +} DisasContext; + +#define DISAS_STOP DISAS_TARGET_0 +#define DISAS_EXIT DISAS_TARGET_1 + +#define LOG_DISAS(...) \ + do { \ + if (LARCH_DEBUG_DISAS) { \ + qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \ + } \ + } while (0) + +#define LARCH_INVAL(op) \ + do { \ + if (LARCH_DEBUG_DISAS) { \ + qemu_log_mask(CPU_LOG_TB_IN_ASM, \ + TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \ + ctx->base.pc_next, ctx->opcode, op, \ + ctx->opcode >> 26, ctx->opcode & 0x3F, \ + ((ctx->opcode >> 16) & 0x1F)); \ + } \ + } while (0) + +/* General purpose registers moves. */ +static inline void gen_load_gpr(TCGv t, int reg) +{ + if (reg == 0) { + tcg_gen_movi_tl(t, 0); + } else { + tcg_gen_mov_tl(t, cpu_gpr[reg]); + } +} + +static inline void gen_store_gpr(TCGv t, int reg) +{ + if (reg != 0) { + tcg_gen_mov_tl(cpu_gpr[reg], t); + } +} + +/* Moves to/from shadow registers. */ +/* Tests */ +static inline void gen_save_pc(target_ulong pc) +{ + tcg_gen_movi_tl(cpu_PC, pc); +} + +static inline void save_cpu_state(DisasContext *ctx, int do_save_pc) +{ + LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags); + if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) { + gen_save_pc(ctx->base.pc_next); + ctx->saved_pc = ctx->base.pc_next; + } + if (ctx->hflags != ctx->saved_hflags) { + tcg_gen_movi_i32(hflags, ctx->hflags); + ctx->saved_hflags = ctx->hflags; + switch (ctx->hflags & LARCH_HFLAG_BMASK) { + case LARCH_HFLAG_BR: + break; + case LARCH_HFLAG_BC: + case LARCH_HFLAG_B: + tcg_gen_movi_tl(btarget, ctx->btarget); + break; + } + } +} + +static inline void restore_cpu_state(CPULOONGARCHState *env, DisasContext *ctx) +{ + ctx->saved_hflags = ctx->hflags; + switch (ctx->hflags & LARCH_HFLAG_BMASK) { + case LARCH_HFLAG_BR: + break; + case LARCH_HFLAG_BC: + case LARCH_HFLAG_B: + ctx->btarget = env->btarget; + break; + } +} + +static inline void generate_exception_err(DisasContext *ctx, int excp, int err) +{ + TCGv_i32 texcp = tcg_const_i32(excp); + TCGv_i32 terr = tcg_const_i32(err); + save_cpu_state(ctx, 1); + gen_helper_raise_exception_err(cpu_env, texcp, terr); + tcg_temp_free_i32(terr); + tcg_temp_free_i32(texcp); + ctx->base.is_jmp = DISAS_NORETURN; +} + +static inline void generate_exception_end(DisasContext *ctx, int excp) +{ + generate_exception_err(ctx, excp, 0); +} + +/* Floating point register moves. */ +static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg) +{ + tcg_gen_extrl_i64_i32(t, fpu_f64[reg]); +} + +static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg) +{ + TCGv_i64 t64; + t64 = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(t64, t); + tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32); + tcg_temp_free_i64(t64); +} + +static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg) +{ + tcg_gen_extrh_i64_i32(t, fpu_f64[reg]); +} + +static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg) +{ + TCGv_i64 t64 = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(t64, t); + tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32); + tcg_temp_free_i64(t64); +} + +static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg) +{ + tcg_gen_mov_i64(t, fpu_f64[reg]); +} + +static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg) +{ + tcg_gen_mov_i64(fpu_f64[reg], t); +} + +static inline int get_fp_bit(int cc) +{ + if (cc) { + return 24 + cc; + } else { + return 23; + } +} + +/* Addresses computation */ +static inline void gen_op_addr_add(DisasContext *ctx, + TCGv ret, TCGv arg0, TCGv arg1) +{ + tcg_gen_add_tl(ret, arg0, arg1); + + if (ctx->hflags & LARCH_HFLAG_AWRAP) { + tcg_gen_ext32s_i64(ret, ret); + } +} + +static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base, + target_long ofs) +{ + tcg_gen_addi_tl(ret, base, ofs); + + if (ctx->hflags & LARCH_HFLAG_AWRAP) { + tcg_gen_ext32s_i64(ret, ret); + } +} + +/* Sign-extract the low 32-bits to a target_long. */ +static inline void gen_move_low32(TCGv ret, TCGv_i64 arg) +{ + tcg_gen_ext32s_i64(ret, arg); +} + +/* Sign-extract the high 32-bits to a target_long. */ +static inline void gen_move_high32(TCGv ret, TCGv_i64 arg) +{ + tcg_gen_sari_i64(ret, arg, 32); +} + +static inline void check_cp1_enabled(DisasContext *ctx) +{ +#ifndef CONFIG_USER_ONLY + if (unlikely(!(ctx->hflags & LARCH_HFLAG_FPU))) { + generate_exception_err(ctx, EXCP_FPDIS, 1); + } +#endif +} + +static inline void check_lsx_enabled(DisasContext *ctx) +{ +#ifndef CONFIG_USER_ONLY + if (unlikely(!(ctx->hflags & LARCH_HFLAG_LSX))) { + generate_exception_err(ctx, EXCP_LSXDIS, 1); + } +#endif +} + +static inline void check_lasx_enabled(DisasContext *ctx) +{ +#ifndef CONFIG_USER_ONLY + if (unlikely(!(ctx->hflags & LARCH_HFLAG_LASX))) { + generate_exception_err(ctx, EXCP_LASXDIS, 1); + } +#endif +} + +static inline void check_lbt_enabled(DisasContext *ctx) +{ +#ifndef CONFIG_USER_ONLY + if (unlikely(!(ctx->hflags & LARCH_HFLAG_LBT))) { + generate_exception_err(ctx, EXCP_BTDIS, 1); + } +#endif +} + +/* This code generates a "reserved instruction" exception if the + CPU does not support the instruction set corresponding to flags. */ +static inline void check_insn(DisasContext *ctx, uint64_t flags) +{ + if (unlikely(!(ctx->insn_flags & flags))) { + generate_exception_end(ctx, EXCP_RI); + } +} + +/* This code generates a "reserved instruction" exception if the + CPU has corresponding flag set which indicates that the instruction + has been removed. */ +static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags) +{ + if (unlikely(ctx->insn_flags & flags)) { + generate_exception_end(ctx, EXCP_RI); + } +} + +/* + * The Linux kernel traps certain reserved instruction exceptions to + * emulate the corresponding instructions. QEMU is the kernel in user + * mode, so those traps are emulated by accepting the instructions. + * + * A reserved instruction exception is generated for flagged CPUs if + * QEMU runs in system mode. + */ +static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags) +{ +#ifndef CONFIG_USER_ONLY + check_insn_opc_removed(ctx, flags); +#endif +} + +/* This code generates a "reserved instruction" exception if 64-bit + instructions are not enabled. */ +static inline void check_larch_64(DisasContext *ctx) +{ + if (unlikely(!(ctx->hflags & LARCH_HFLAG_64))) { + generate_exception_end(ctx, EXCP_RI); + } +} + +/* Define small wrappers for gen_load_fpr* so that we have a uniform + calling interface for 32 and 64-bit FPRs. No sense in changing + all callers for gen_load_fpr32 when we need the CTX parameter for + this one use. */ +#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y) +#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y) +#define FCOP_CONDNS(fmt, ifmt, bits, STORE) \ +static inline void gen_fcmp_ ## fmt(DisasContext *ctx, int n, \ + int ft, int fs, int cd) \ +{ \ + TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \ + TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \ + TCGv_i32 fcc = tcg_const_i32(cd); \ + check_cp1_enabled(ctx); \ + gen_ldcmp_fpr ## bits(ctx, fp0, fs); \ + gen_ldcmp_fpr ## bits(ctx, fp1, ft); \ + switch (n) { \ + case 0: \ + gen_helper_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \ + break; \ + case 1: \ + gen_helper_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \ + break; \ + case 2: \ + gen_helper_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \ + break; \ + case 3: \ + gen_helper_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \ + break; \ + case 4: \ + gen_helper_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \ + break; \ + case 5: \ + gen_helper_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \ + break; \ + case 6: \ + gen_helper_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \ + break; \ + case 7: \ + gen_helper_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \ + break; \ + case 8: \ + gen_helper_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \ + break; \ + case 9: \ + gen_helper_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \ + break; \ + case 10: \ + gen_helper_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \ + break; \ + case 11: \ + gen_helper_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \ + break; \ + case 12: \ + gen_helper_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \ + break; \ + case 13: \ + gen_helper_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \ + break; \ + case 14: \ + gen_helper_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \ + break; \ + case 15: \ + gen_helper_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \ + break; \ + case 16: \ + gen_helper_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \ + break; \ + case 17: \ + gen_helper_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \ + break; \ + case 20: \ + gen_helper_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \ + break; \ + case 21: \ + gen_helper_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \ + break; \ + case 24: \ + gen_helper_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \ + break; \ + case 25: \ + gen_helper_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \ + break; \ + default: \ + abort(); \ + } \ + STORE; \ + tcg_temp_free_i ## bits(fp0); \ + tcg_temp_free_i ## bits(fp1); \ + tcg_temp_free_i32(fcc); \ +} + +FCOP_CONDNS(d, FMT_D, 64, gen_helper_movreg2cf_i64(cpu_env, fcc, fp0)) +FCOP_CONDNS(s, FMT_S, 32, gen_helper_movreg2cf_i32(cpu_env, fcc, fp0)) +#undef FCOP_CONDNS +#undef gen_ldcmp_fpr32 +#undef gen_ldcmp_fpr64 + +/* load/store instructions. */ +#ifdef CONFIG_USER_ONLY +#define OP_LD_ATOMIC(insn, fname) \ +static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \ + DisasContext *ctx) \ +{ \ + TCGv t0 = tcg_temp_new(); \ + tcg_gen_mov_tl(t0, arg1); \ + tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \ + tcg_gen_st_tl(t0, cpu_env, \ + offsetof(CPULOONGARCHState, lladdr)); \ + tcg_gen_st_tl(ret, cpu_env, \ + offsetof(CPULOONGARCHState, llval)); \ + tcg_temp_free(t0); \ +} +#else +#define OP_LD_ATOMIC(insn, fname) \ +static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \ + DisasContext *ctx) \ +{ \ + gen_helper_1e1i(insn, ret, arg1, mem_idx); \ +} +#endif +#if 0 +OP_LD_ATOMIC(ll, ld32s); +OP_LD_ATOMIC(lld, ld64); +#endif +#undef OP_LD_ATOMIC + +static void gen_base_offset_addr(DisasContext *ctx, TCGv addr, + int base, int offset) +{ + if (base == 0) { + tcg_gen_movi_tl(addr, offset); + } else if (offset == 0) { + gen_load_gpr(addr, base); + } else { + tcg_gen_movi_tl(addr, offset); + gen_op_addr_add(ctx, addr, cpu_gpr[base], addr); + } +} + +/* Load */ +static void gen_ld(DisasContext *ctx, uint32_t opc, + int rt, int base, int offset) +{ + TCGv t0; + int mem_idx = ctx->mem_idx; + + t0 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, base, offset); + + switch (opc) { + case OPC_LARCH_LD_WU: + tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; + case OPC_LARCH_LDPTR_D: + case OPC_LARCH_LD_D: + tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; + case OPC_LARCH_LL_D: +#if 0 + op_ld_lld(t0, t0, mem_idx, ctx); +#endif + gen_store_gpr(t0, rt); + break; + case OPC_LARCH_LDPTR_W: + case OPC_LARCH_LD_W: + tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; + case OPC_LARCH_LD_H: + tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; + case OPC_LARCH_LD_HU: + tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; + case OPC_LARCH_LD_B: + tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB); + gen_store_gpr(t0, rt); + break; + case OPC_LARCH_LD_BU: + tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB); + gen_store_gpr(t0, rt); + break; + case OPC_LARCH_LL_W: +#if 0 + op_ld_ll(t0, t0, mem_idx, ctx); +#endif + gen_store_gpr(t0, rt); + break; + } + + tcg_temp_free(t0); +} + +/* Store */ +static void gen_st(DisasContext *ctx, uint32_t opc, int rt, + int base, int offset) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + int mem_idx = ctx->mem_idx; + + gen_base_offset_addr(ctx, t0, base, offset); + gen_load_gpr(t1, rt); + + switch (opc) { + case OPC_LARCH_STPTR_D: + case OPC_LARCH_ST_D: + tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + break; + case OPC_LARCH_STPTR_W: + case OPC_LARCH_ST_W: + tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL | + ctx->default_tcg_memop_mask); + break; + case OPC_LARCH_ST_H: + tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW | + ctx->default_tcg_memop_mask); + break; + case OPC_LARCH_ST_B: + tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8); + break; + } + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +/* Store conditional */ +static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset, + MemOp tcg_mo, bool eva) +{ + TCGv addr, t0, val; + TCGLabel *l1 = gen_new_label(); + TCGLabel *done = gen_new_label(); + + t0 = tcg_temp_new(); + addr = tcg_temp_new(); + /* compare the address against that of the preceeding LL */ + gen_base_offset_addr(ctx, addr, base, offset); + tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1); + tcg_temp_free(addr); + tcg_gen_movi_tl(t0, 0); + gen_store_gpr(t0, rt); + tcg_gen_br(done); + + gen_set_label(l1); + /* generate cmpxchg */ + val = tcg_temp_new(); + gen_load_gpr(val, rt); + tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val, + eva ? LARCH_HFLAG_UM : ctx->mem_idx, tcg_mo); + tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval); + gen_store_gpr(t0, rt); + tcg_temp_free(val); + + gen_set_label(done); + tcg_temp_free(t0); +} + +/* Load and store */ +static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft, + TCGv t0) +{ + /* Don't do NOP if destination is zero: we must perform the actual + memory access. */ + switch (opc) { + case OPC_LARCH_FLD_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL | + ctx->default_tcg_memop_mask); + gen_store_fpr32(ctx, fp0, ft); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FST_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, ft); + tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL | + ctx->default_tcg_memop_mask); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FLD_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_fpr64(ctx, fp0, ft); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FST_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, ft); + tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free_i64(fp0); + } + break; + default: + LARCH_INVAL("flt_ldst"); + generate_exception_end(ctx, EXCP_RI); + break; + } +} + +static void gen_fp_ldst(DisasContext *ctx, uint32_t op, int rt, + int rs, int16_t imm) +{ + TCGv t0 = tcg_temp_new(); + + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, imm); + gen_flt_ldst(ctx, op, rt, t0); + tcg_temp_free(t0); +} + +/* Arithmetic with immediate operand */ +static void gen_arith_imm(DisasContext *ctx, uint32_t opc, + int rt, int rs, int imm) +{ + target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */ + + if (rt == 0) { + /* If no destination, treat it as a NOP. + For addi, we must generate the overflow exception when needed. */ + return; + } + switch (opc) { + case OPC_LARCH_ADDI_W: + if (rs != 0) { + tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); + } else { + tcg_gen_movi_tl(cpu_gpr[rt], uimm); + } + break; + case OPC_LARCH_ADDI_D: + if (rs != 0) { + tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); + } else { + tcg_gen_movi_tl(cpu_gpr[rt], uimm); + } + break; + } +} + +/* Logic with immediate operand */ +static void gen_logic_imm(DisasContext *ctx, uint32_t opc, + int rt, int rs, int16_t imm) +{ + target_ulong uimm; + + if (rt == 0) { + /* If no destination, treat it as a NOP. */ + return; + } + uimm = (uint16_t)imm; + switch (opc) { + case OPC_LARCH_ANDI: + if (likely(rs != 0)) { + tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); + } else { + tcg_gen_movi_tl(cpu_gpr[rt], 0); + } + break; + case OPC_LARCH_ORI: + if (rs != 0) { + tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); + } else { + tcg_gen_movi_tl(cpu_gpr[rt], uimm); + } + break; + case OPC_LARCH_XORI: + if (likely(rs != 0)) { + tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm); + } else { + tcg_gen_movi_tl(cpu_gpr[rt], uimm); + } + break; + default: + break; + } +} + +/* Set on less than with immediate operand */ +static void gen_slt_imm(DisasContext *ctx, uint32_t opc, + int rt, int rs, int16_t imm) +{ + target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */ + TCGv t0; + + if (rt == 0) { + /* If no destination, treat it as a NOP. */ + return; + } + t0 = tcg_temp_new(); + gen_load_gpr(t0, rs); + switch (opc) { + case OPC_LARCH_SLTI: + tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm); + break; + case OPC_LARCH_SLTIU: + tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm); + break; + } + tcg_temp_free(t0); +} + +/* Shifts with immediate operand */ +static void gen_shift_imm(DisasContext *ctx, uint32_t opc, + int rt, int rs, int16_t imm) +{ + target_ulong uimm = ((uint16_t)imm) & 0x1f; + TCGv t0; + + if (rt == 0) { + /* If no destination, treat it as a NOP. */ + return; + } + + t0 = tcg_temp_new(); + gen_load_gpr(t0, rs); + switch (opc) { + case OPC_LARCH_SRAI_W: + tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm); + break; + case OPC_LARCH_SRLI_W: + if (uimm != 0) { + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm); + } else { + tcg_gen_ext32s_tl(cpu_gpr[rt], t0); + } + break; + case OPC_LARCH_ROTRI_W: + if (uimm != 0) { + TCGv_i32 t1 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t1, t0); + tcg_gen_rotri_i32(t1, t1, uimm); + tcg_gen_ext_i32_tl(cpu_gpr[rt], t1); + tcg_temp_free_i32(t1); + } else { + tcg_gen_ext32s_tl(cpu_gpr[rt], t0); + } + break; + } + tcg_temp_free(t0); +} + +/* Arithmetic */ +static void gen_arith(DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) +{ + if (rd == 0) { + /* If no destination, treat it as a NOP. + For add & sub, we must generate the + overflow exception when needed. */ + return; + } + + switch (opc) { + case OPC_LARCH_ADD_W: + if (rs != 0 && rt != 0) { + tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + } else if (rs == 0 && rt != 0) { + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); + } else if (rs != 0 && rt == 0) { + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); + } else { + tcg_gen_movi_tl(cpu_gpr[rd], 0); + } + break; + case OPC_LARCH_SUB_W: + if (rs != 0 && rt != 0) { + tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + } else if (rs == 0 && rt != 0) { + tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + } else if (rs != 0 && rt == 0) { + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); + } else { + tcg_gen_movi_tl(cpu_gpr[rd], 0); + } + break; + case OPC_LARCH_ADD_D: + if (rs != 0 && rt != 0) { + tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); + } else if (rs == 0 && rt != 0) { + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); + } else if (rs != 0 && rt == 0) { + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); + } else { + tcg_gen_movi_tl(cpu_gpr[rd], 0); + } + break; + case OPC_LARCH_SUB_D: + if (rs != 0 && rt != 0) { + tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); + } else if (rs == 0 && rt != 0) { + tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]); + } else if (rs != 0 && rt == 0) { + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); + } else { + tcg_gen_movi_tl(cpu_gpr[rd], 0); + } + break; + } +} + +/* Conditional move */ +static void gen_cond_move(DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) +{ + TCGv t0, t1, t2; + + if (rd == 0) { + /* If no destination, treat it as a NOP. */ + return; + } + + t0 = tcg_temp_new(); + gen_load_gpr(t0, rt); + t1 = tcg_const_tl(0); + t2 = tcg_temp_new(); + gen_load_gpr(t2, rs); + switch (opc) { + case OPC_LARCH_MASKEQZ: + tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1); + break; + case OPC_LARCH_MASKNEZ: + tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1); + break; + } + tcg_temp_free(t2); + tcg_temp_free(t1); + tcg_temp_free(t0); +} + +/* Logic */ +static void gen_logic(DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) +{ + if (rd == 0) { + /* If no destination, treat it as a NOP. */ + return; + } + + switch (opc) { + case OPC_LARCH_AND: + if (likely(rs != 0 && rt != 0)) { + tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); + } else { + tcg_gen_movi_tl(cpu_gpr[rd], 0); + } + break; + case OPC_LARCH_NOR: + if (rs != 0 && rt != 0) { + tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); + } else if (rs == 0 && rt != 0) { + tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]); + } else if (rs != 0 && rt == 0) { + tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]); + } else { + tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0)); + } + break; + case OPC_LARCH_OR: + if (likely(rs != 0 && rt != 0)) { + tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); + } else if (rs == 0 && rt != 0) { + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); + } else if (rs != 0 && rt == 0) { + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); + } else { + tcg_gen_movi_tl(cpu_gpr[rd], 0); + } + break; + case OPC_LARCH_XOR: + if (likely(rs != 0 && rt != 0)) { + tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]); + } else if (rs == 0 && rt != 0) { + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]); + } else if (rs != 0 && rt == 0) { + tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]); + } else { + tcg_gen_movi_tl(cpu_gpr[rd], 0); + } + break; + } +} + +/* Set on lower than */ +static void gen_slt(DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) +{ + TCGv t0, t1; + + if (rd == 0) { + /* If no destination, treat it as a NOP. */ + return; + } + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + switch (opc) { + case OPC_LARCH_SLT: + tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1); + break; + case OPC_LARCH_SLTU: + tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1); + break; + } + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +/* Shifts */ +static void gen_shift(DisasContext *ctx, uint32_t opc, + int rd, int rs, int rt) +{ + TCGv t0, t1; + + if (rd == 0) { + /* If no destination, treat it as a NOP. + For add & sub, we must generate the + overflow exception when needed. */ + return; + } + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + switch (opc) { + case OPC_LARCH_SLL_W: + tcg_gen_andi_tl(t0, t0, 0x1f); + tcg_gen_shl_tl(t0, t1, t0); + tcg_gen_ext32s_tl(cpu_gpr[rd], t0); + break; + case OPC_LARCH_SRA_W: + tcg_gen_andi_tl(t0, t0, 0x1f); + tcg_gen_sar_tl(cpu_gpr[rd], t1, t0); + break; + case OPC_LARCH_SRL_W: + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_andi_tl(t0, t0, 0x1f); + tcg_gen_shr_tl(t0, t1, t0); + tcg_gen_ext32s_tl(cpu_gpr[rd], t0); + break; + case OPC_LARCH_ROTR_W: + { + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_andi_i32(t2, t2, 0x1f); + tcg_gen_rotr_i32(t2, t3, t2); + tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + break; + case OPC_LARCH_SLL_D: + tcg_gen_andi_tl(t0, t0, 0x3f); + tcg_gen_shl_tl(cpu_gpr[rd], t1, t0); + break; + case OPC_LARCH_SRA_D: + tcg_gen_andi_tl(t0, t0, 0x3f); + tcg_gen_sar_tl(cpu_gpr[rd], t1, t0); + break; + case OPC_LARCH_SRL_D: + tcg_gen_andi_tl(t0, t0, 0x3f); + tcg_gen_shr_tl(cpu_gpr[rd], t1, t0); + break; + case OPC_LARCH_ROTR_D: + tcg_gen_andi_tl(t0, t0, 0x3f); + tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0); + break; + } + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static inline void gen_r6_ld(target_long addr, int reg, int memidx, + MemOp memop) +{ + TCGv t0 = tcg_const_tl(addr); + tcg_gen_qemu_ld_tl(t0, t0, memidx, memop); + gen_store_gpr(t0, reg); + tcg_temp_free(t0); +} + +static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) +{ + TCGv t0, t1; + + if (rd == 0) { + /* Treat as NOP. */ + return; + } + + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + + switch (opc) { + case OPC_LARCH_DIV_W: + { + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + tcg_gen_ext32s_tl(t0, t0); + tcg_gen_ext32s_tl(t1, t1); + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); + tcg_gen_div_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + break; + case OPC_LARCH_MOD_W: + { + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + tcg_gen_ext32s_tl(t0, t0); + tcg_gen_ext32s_tl(t1, t1); + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); + tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + break; + case OPC_LARCH_DIV_WU: + { + TCGv t2 = tcg_const_tl(0); + TCGv t3 = tcg_const_tl(1); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); + tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + break; + case OPC_LARCH_MOD_WU: + { + TCGv t2 = tcg_const_tl(0); + TCGv t3 = tcg_const_tl(1); + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_ext32u_tl(t1, t1); + tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); + tcg_gen_remu_tl(cpu_gpr[rd], t0, t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + break; + case OPC_LARCH_MUL_W: + { + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_mul_i32(t2, t2, t3); + tcg_gen_ext_i32_tl(cpu_gpr[rd], t2); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + break; + case OPC_LARCH_MULH_W: + { + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_muls2_i32(t2, t3, t2, t3); + tcg_gen_ext_i32_tl(cpu_gpr[rd], t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + break; + case OPC_LARCH_MULH_WU: + { + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(t2, t0); + tcg_gen_trunc_tl_i32(t3, t1); + tcg_gen_mulu2_i32(t2, t3, t2, t3); + tcg_gen_ext_i32_tl(cpu_gpr[rd], t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); + } + break; + case OPC_LARCH_DIV_D: + { + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); + tcg_gen_div_tl(cpu_gpr[rd], t0, t1); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + break; + case OPC_LARCH_MOD_D: + { + TCGv t2 = tcg_temp_new(); + TCGv t3 = tcg_temp_new(); + tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL); + tcg_gen_and_tl(t2, t2, t3); + tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); + tcg_gen_or_tl(t2, t2, t3); + tcg_gen_movi_tl(t3, 0); + tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); + tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + break; + case OPC_LARCH_DIV_DU: + { + TCGv t2 = tcg_const_tl(0); + TCGv t3 = tcg_const_tl(1); + tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); + tcg_gen_divu_i64(cpu_gpr[rd], t0, t1); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + break; + case OPC_LARCH_MOD_DU: + { + TCGv t2 = tcg_const_tl(0); + TCGv t3 = tcg_const_tl(1); + tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); + tcg_gen_remu_i64(cpu_gpr[rd], t0, t1); + tcg_temp_free(t3); + tcg_temp_free(t2); + } + break; + case OPC_LARCH_MUL_D: + tcg_gen_mul_i64(cpu_gpr[rd], t0, t1); + break; + case OPC_LARCH_MULH_D: + { + TCGv t2 = tcg_temp_new(); + tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1); + tcg_temp_free(t2); + } + break; + case OPC_LARCH_MULH_DU: + { + TCGv t2 = tcg_temp_new(); + tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1); + tcg_temp_free(t2); + } + break; + default: + LARCH_INVAL("r6 mul/div"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_cl(DisasContext *ctx, uint32_t opc, + int rd, int rs) +{ + TCGv t0; + + if (rd == 0) { + /* Treat as NOP. */ + return; + } + t0 = cpu_gpr[rd]; + gen_load_gpr(t0, rs); + + switch (opc) { + case OPC_LARCH_CLO_W: + case OPC_LARCH_CLO_D: + tcg_gen_not_tl(t0, t0); + break; + } + + switch (opc) { + case OPC_LARCH_CLO_W: + case OPC_LARCH_CLZ_W: + tcg_gen_ext32u_tl(t0, t0); + tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS); + tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32); + break; + case OPC_LARCH_CLO_D: + case OPC_LARCH_CLZ_D: + tcg_gen_clzi_i64(t0, t0, 64); + break; + } +} + +static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) +{ + if (unlikely(ctx->base.singlestep_enabled)) { + return false; + } + +#ifndef CONFIG_USER_ONLY + return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); +#else + return true; +#endif +} + +static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) +{ + if (use_goto_tb(ctx, dest)) { + tcg_gen_goto_tb(n); + gen_save_pc(dest); + tcg_gen_exit_tb(ctx->base.tb, n); + } else { + gen_save_pc(dest); + if (ctx->base.singlestep_enabled) { + save_cpu_state(ctx, 0); + gen_helper_raise_exception_debug(cpu_env); + } + tcg_gen_lookup_and_goto_ptr(); + } +} + +/* Branches */ +static void gen_compute_branch(DisasContext *ctx, uint32_t opc, + int insn_bytes, + int rs, int rt, int32_t offset) +{ + target_ulong btgt = -1; + int bcond_compute = 0; + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + if (ctx->hflags & LARCH_HFLAG_BMASK) { +#ifdef LARCH_DEBUG_DISAS + LOG_DISAS("Branch at PC 0x" + TARGET_FMT_lx "\n", ctx->base.pc_next); +#endif + generate_exception_end(ctx, EXCP_RI); + goto out; + } + + /* Load needed operands */ + switch (opc) { + case OPC_LARCH_BLT: + case OPC_LARCH_BGE: + case OPC_LARCH_BLTU: + case OPC_LARCH_BGEU: + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + bcond_compute = 1; + btgt = ctx->base.pc_next + offset; + break; + case OPC_LARCH_BEQZ: + case OPC_LARCH_B: + case OPC_LARCH_BEQ: + case OPC_LARCH_BNEZ: + case OPC_LARCH_BNE: + /* Compare two registers */ + if (rs != rt) { + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + bcond_compute = 1; + } + btgt = ctx->base.pc_next + offset; + break; + default: + LARCH_INVAL("branch/jump"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + if (bcond_compute == 0) { + /* No condition to be computed */ + switch (opc) { + case OPC_LARCH_BEQZ: /* rx == rx */ + case OPC_LARCH_B: + case OPC_LARCH_BEQ: + /* Always take */ + ctx->hflags |= LARCH_HFLAG_B; + break; + case OPC_LARCH_BNEZ: + case OPC_LARCH_BNE: + /* Treat as NOP. */ + goto out; + default: + LARCH_INVAL("branch/jump"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + } else { + switch (opc) { + case OPC_LARCH_BLT: + tcg_gen_setcond_tl(TCG_COND_LT, bcond, t0, t1); + goto not_likely; + case OPC_LARCH_BGE: + tcg_gen_setcond_tl(TCG_COND_GE, bcond, t0, t1); + goto not_likely; + case OPC_LARCH_BLTU: + tcg_gen_setcond_tl(TCG_COND_LTU, bcond, t0, t1); + goto not_likely; + case OPC_LARCH_BGEU: + tcg_gen_setcond_tl(TCG_COND_GEU, bcond, t0, t1); + goto not_likely; + case OPC_LARCH_BEQZ: + case OPC_LARCH_B: + case OPC_LARCH_BEQ: + tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); + goto not_likely; + case OPC_LARCH_BNEZ: + case OPC_LARCH_BNE: + tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); + goto not_likely; + not_likely: + ctx->hflags |= LARCH_HFLAG_BC; + break; + default: + LARCH_INVAL("conditional branch/jump"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + } + + ctx->btarget = btgt; + + out: + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +/* special3 bitfield operations */ +static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt, + int rs, int lsb, int msb) +{ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + gen_load_gpr(t1, rs); + switch (opc) { + case OPC_LARCH_TRPICK_W: + if (lsb + msb > 31) { + goto fail; + } + if (msb != 31) { + tcg_gen_extract_tl(t0, t1, lsb, msb + 1); + } else { + /* + * The two checks together imply that lsb == 0, + * so this is a simple sign-extension. + */ + tcg_gen_ext32s_tl(t0, t1); + } + break; + case OPC_LARCH_TRINS_W: + if (lsb > msb) { + goto fail; + } + gen_load_gpr(t0, rt); + tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1); + tcg_gen_ext32s_tl(t0, t0); + break; + default: +fail: + LARCH_INVAL("bitops"); + generate_exception_end(ctx, EXCP_RI); + tcg_temp_free(t0); + tcg_temp_free(t1); + return; + } + gen_store_gpr(t0, rt); + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd) +{ + TCGv t0; + + if (rd == 0) { + /* If no destination, treat it as a NOP. */ + return; + } + + t0 = tcg_temp_new(); + gen_load_gpr(t0, rt); + switch (op2) { + case OPC_LARCH_REVB_2H: + { + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_const_tl(0x00FF00FF); + + tcg_gen_shri_tl(t1, t0, 8); + tcg_gen_and_tl(t1, t1, t2); + tcg_gen_and_tl(t0, t0, t2); + tcg_gen_shli_tl(t0, t0, 8); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t2); + tcg_temp_free(t1); + tcg_gen_ext32s_tl(cpu_gpr[rd], t0); + } + break; + case OPC_LARCH_EXT_WB: + tcg_gen_ext8s_tl(cpu_gpr[rd], t0); + break; + case OPC_LARCH_EXT_WH: + tcg_gen_ext16s_tl(cpu_gpr[rd], t0); + break; + case OPC_LARCH_REVB_4H: + { + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL); + + tcg_gen_shri_tl(t1, t0, 8); + tcg_gen_and_tl(t1, t1, t2); + tcg_gen_and_tl(t0, t0, t2); + tcg_gen_shli_tl(t0, t0, 8); + tcg_gen_or_tl(cpu_gpr[rd], t0, t1); + tcg_temp_free(t2); + tcg_temp_free(t1); + } + break; + case OPC_LARCH_REVH_D: + { + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL); + + tcg_gen_shri_tl(t1, t0, 16); + tcg_gen_and_tl(t1, t1, t2); + tcg_gen_and_tl(t0, t0, t2); + tcg_gen_shli_tl(t0, t0, 16); + tcg_gen_or_tl(t0, t0, t1); + tcg_gen_shri_tl(t1, t0, 32); + tcg_gen_shli_tl(t0, t0, 32); + tcg_gen_or_tl(cpu_gpr[rd], t0, t1); + tcg_temp_free(t2); + tcg_temp_free(t1); + } + break; + default: + LARCH_INVAL("bsfhl"); + generate_exception_end(ctx, EXCP_RI); + tcg_temp_free(t0); + return; + } + tcg_temp_free(t0); +} + +/* REV with sf==1, opcode==3 ("REV64") */ +static void handle_rev64(DisasContext *ctx, + unsigned int rn, unsigned int rd) +{ + tcg_gen_bswap64_i64(cpu_gpr[rd], cpu_gpr[rn]); +} + +/* REV with sf==0, opcode==2 + * REV32 (sf==1, opcode==2) + */ +static void handle_rev32(DisasContext *ctx, + unsigned int rn, unsigned int rd) +{ + TCGv_i64 tcg_rd = tcg_temp_new_i64(); + gen_load_gpr(tcg_rd, rd); + + TCGv_i64 tcg_tmp = tcg_temp_new_i64(); + TCGv_i64 tcg_rn = tcg_temp_new_i64(); + gen_load_gpr(tcg_rn, rn); + + /* bswap32_i64 requires zero high word */ + tcg_gen_ext32u_i64(tcg_tmp, tcg_rn); + tcg_gen_bswap32_i64(tcg_rd, tcg_tmp, TCG_BSWAP_OZ); + tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32); + tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp, TCG_BSWAP_OZ); + tcg_gen_concat32_i64(cpu_gpr[rd], tcg_rd, tcg_tmp); + + tcg_temp_free_i64(tcg_tmp); + tcg_temp_free_i64(tcg_rd); + tcg_temp_free_i64(tcg_rn); +} + +/* REV16 */ +static void handle_rev16(DisasContext *ctx, unsigned int rn, unsigned int rd) +{ + TCGv_i64 tcg_rd = tcg_temp_new_i64(); + TCGv_i64 tcg_rn = tcg_temp_new_i64(); + gen_load_gpr(tcg_rd, rd); + gen_load_gpr(tcg_rn, rn); + TCGv_i64 tcg_tmp = tcg_temp_new_i64(); + TCGv_i64 mask = tcg_const_i64(0x0000ffff0000ffffull); + + tcg_gen_shri_i64(tcg_tmp, tcg_rn, 16); + tcg_gen_and_i64(tcg_rd, tcg_rn, mask); + tcg_gen_and_i64(tcg_tmp, tcg_tmp, mask); + tcg_gen_shli_i64(tcg_rd, tcg_rd, 16); + tcg_gen_or_i64(cpu_gpr[rd], tcg_rd, tcg_tmp); + + tcg_temp_free_i64(mask); + tcg_temp_free_i64(tcg_tmp); + tcg_temp_free_i64(tcg_rd); + tcg_temp_free_i64(tcg_rn); +} + +static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt, + int imm2) +{ + TCGv t0; + TCGv t1; + if (rd == 0) { + /* Treat as NOP. */ + return; + } + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + gen_load_gpr(t0, rs); + gen_load_gpr(t1, rt); + tcg_gen_shli_tl(t0, t0, imm2 + 1); + tcg_gen_add_tl(cpu_gpr[rd], t0, t1); + if (opc == OPC_LARCH_ALSL_W) { + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); + } + + tcg_temp_free(t1); + tcg_temp_free(t0); + + return; +} + +static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs, + int rt, int bits) +{ + TCGv t0; + if (rd == 0) { + /* Treat as NOP. */ + return; + } + t0 = tcg_temp_new(); + if (bits == 0 || bits == wordsz) { + if (bits == 0) { + gen_load_gpr(t0, rt); + } else { + gen_load_gpr(t0, rs); + } + switch (wordsz) { + case 32: + tcg_gen_ext32s_tl(cpu_gpr[rd], t0); + break; + case 64: + tcg_gen_mov_tl(cpu_gpr[rd], t0); + break; + } + } else { + TCGv t1 = tcg_temp_new(); + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); + switch (wordsz) { + case 32: + { + TCGv_i64 t2 = tcg_temp_new_i64(); + tcg_gen_concat_tl_i64(t2, t1, t0); + tcg_gen_shri_i64(t2, t2, 32 - bits); + gen_move_low32(cpu_gpr[rd], t2); + tcg_temp_free_i64(t2); + } + break; + case 64: + tcg_gen_shli_tl(t0, t0, bits); + tcg_gen_shri_tl(t1, t1, 64 - bits); + tcg_gen_or_tl(cpu_gpr[rd], t1, t0); + break; + } + tcg_temp_free(t1); + } + + tcg_temp_free(t0); +} + +static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, + int bp) +{ + gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8); +} + +static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt) +{ + TCGv t0; + if (rd == 0) { + /* Treat as NOP. */ + return; + } + t0 = tcg_temp_new(); + gen_load_gpr(t0, rt); + switch (opc) { + case OPC_LARCH_BREV_4B: + gen_helper_bitswap(cpu_gpr[rd], t0); + break; + case OPC_LARCH_BREV_8B: + gen_helper_dbitswap(cpu_gpr[rd], t0); + break; + } + tcg_temp_free(t0); +} + +static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs) +{ + TCGv t0 = tcg_temp_new(); + check_cp1_enabled(ctx); + + switch (opc) { + case OPC_LARCH_FR2GR_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + tcg_gen_ext_i32_tl(t0, fp0); + tcg_temp_free_i32(fp0); + } + gen_store_gpr(t0, rt); + break; + case OPC_LARCH_GR2FR_W: + gen_load_gpr(t0, rt); + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(fp0, t0); + gen_store_fpr32(ctx, fp0, fs); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FR2GR_D: + gen_load_fpr64(ctx, t0, fs); + gen_store_gpr(t0, rt); + break; + case OPC_LARCH_GR2FR_D: + gen_load_gpr(t0, rt); + gen_store_fpr64(ctx, t0, fs); + break; + case OPC_LARCH_FRH2GR_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32h(ctx, fp0, fs); + tcg_gen_ext_i32_tl(t0, fp0); + tcg_temp_free_i32(fp0); + } + gen_store_gpr(t0, rt); + break; + case OPC_LARCH_GR2FRH_W: + gen_load_gpr(t0, rt); + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(fp0, t0); + gen_store_fpr32h(ctx, fp0, fs); + tcg_temp_free_i32(fp0); + } + break; + default: + LARCH_INVAL("cp1 move"); + generate_exception_end(ctx, EXCP_RI); + goto out; + } + + out: + tcg_temp_free(t0); +} + +static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd, + int cc, int tf) +{ + int cond; + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGLabel *l1 = gen_new_label(); + TCGLabel *l2 = gen_new_label(); + + if (tf) { + cond = TCG_COND_EQ; + } else { + cond = TCG_COND_NE; + } + + tcg_gen_andi_i32(t0, fpu_fcsr0, 1 << get_fp_bit(cc)); + tcg_gen_brcondi_i32(cond, t0, 0, l1); + gen_load_fpr32(ctx, t0, fs); + gen_store_fpr32(ctx, t0, fd); + gen_set_label(l1); + + tcg_gen_andi_i32(t0, fpu_fcsr0, 1 << get_fp_bit(cc + 1)); + tcg_gen_brcondi_i32(cond, t0, 0, l2); + gen_load_fpr32h(ctx, t0, fs); + gen_store_fpr32h(ctx, t0, fd); + tcg_temp_free_i32(t0); + gen_set_label(l2); +} + +static void gen_farith(DisasContext *ctx, uint32_t opc, + int ft, int fs, int fd, int cc) +{ + check_cp1_enabled(ctx); + switch (opc) { + case OPC_LARCH_FADD_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_load_fpr32(ctx, fp1, ft); + gen_helper_float_add_s(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i32(fp1); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FSUB_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_load_fpr32(ctx, fp1, ft); + gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i32(fp1); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FMUL_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_load_fpr32(ctx, fp1, ft); + gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i32(fp1); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FDIV_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_load_fpr32(ctx, fp1, ft); + gen_helper_float_div_s(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i32(fp1); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FSQRT_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_sqrt_s(fp0, cpu_env, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FABS_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_abs_s(fp0, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FMOV_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FNEG_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_chs_s(fp0, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FTINTRNE_L_S: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr32(ctx, fp32, fs); + gen_helper_float_round_l_s(fp64, cpu_env, fp32); + tcg_temp_free_i32(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free_i64(fp64); + } + break; + case OPC_LARCH_FTINTRZ_L_S: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr32(ctx, fp32, fs); + gen_helper_float_trunc_l_s(fp64, cpu_env, fp32); + tcg_temp_free_i32(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free_i64(fp64); + } + break; + case OPC_LARCH_FTINTRP_L_S: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr32(ctx, fp32, fs); + gen_helper_float_ceil_l_s(fp64, cpu_env, fp32); + tcg_temp_free_i32(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free_i64(fp64); + } + break; + case OPC_LARCH_FTINTRM_L_S: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr32(ctx, fp32, fs); + gen_helper_float_floor_l_s(fp64, cpu_env, fp32); + tcg_temp_free_i32(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free_i64(fp64); + } + break; + case OPC_LARCH_FTINTRNE_W_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_round_w_s(fp0, cpu_env, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FTINTRZ_W_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_trunc_w_s(fp0, cpu_env, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FTINTRP_W_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_ceil_w_s(fp0, cpu_env, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FTINTRM_W_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_floor_w_s(fp0, cpu_env, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FRECIP_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_recip_s(fp0, cpu_env, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FRSQRT_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_rsqrt_s(fp0, cpu_env, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FRINT_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_rint_s(fp0, cpu_env, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FCLASS_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_class_s(fp0, cpu_env, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FMIN_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + TCGv_i32 fp2 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, fs); + gen_load_fpr32(ctx, fp1, ft); + gen_helper_float_min_s(fp2, cpu_env, fp0, fp1); + gen_store_fpr32(ctx, fp2, fd); + tcg_temp_free_i32(fp2); + tcg_temp_free_i32(fp1); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FMINA_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + TCGv_i32 fp2 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, fs); + gen_load_fpr32(ctx, fp1, ft); + gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1); + gen_store_fpr32(ctx, fp2, fd); + tcg_temp_free_i32(fp2); + tcg_temp_free_i32(fp1); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FMAX_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, fs); + gen_load_fpr32(ctx, fp1, ft); + gen_helper_float_max_s(fp1, cpu_env, fp0, fp1); + gen_store_fpr32(ctx, fp1, fd); + tcg_temp_free_i32(fp1); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FMAXA_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + TCGv_i32 fp1 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, fs); + gen_load_fpr32(ctx, fp1, ft); + gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1); + gen_store_fpr32(ctx, fp1, fd); + tcg_temp_free_i32(fp1); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FCVT_D_S: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr32(ctx, fp32, fs); + gen_helper_float_cvtd_s(fp64, cpu_env, fp32); + tcg_temp_free_i32(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free_i64(fp64); + } + break; + case OPC_LARCH_FTINT_W_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_cvt_w_s(fp0, cpu_env, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FTINT_L_S: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr32(ctx, fp32, fs); + gen_helper_float_cvt_l_s(fp64, cpu_env, fp32); + tcg_temp_free_i32(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free_i64(fp64); + } + break; + case OPC_LARCH_FADD_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_add_d(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i64(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FSUB_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i64(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FMUL_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i64(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FDIV_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_div_d(fp0, cpu_env, fp0, fp1); + tcg_temp_free_i64(fp1); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FSQRT_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_sqrt_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FABS_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_abs_d(fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FMOV_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FNEG_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_chs_d(fp0, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FTINTRNE_L_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_round_l_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FTINTRZ_L_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_trunc_l_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FTINTRP_L_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_ceil_l_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FTINTRM_L_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_floor_l_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FTINTRNE_W_D: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp64, fs); + gen_helper_float_round_w_d(fp32, cpu_env, fp64); + tcg_temp_free_i64(fp64); + gen_store_fpr32(ctx, fp32, fd); + tcg_temp_free_i32(fp32); + } + break; + case OPC_LARCH_FTINTRZ_W_D: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp64, fs); + gen_helper_float_trunc_w_d(fp32, cpu_env, fp64); + tcg_temp_free_i64(fp64); + gen_store_fpr32(ctx, fp32, fd); + tcg_temp_free_i32(fp32); + } + break; + case OPC_LARCH_FTINTRP_W_D: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp64, fs); + gen_helper_float_ceil_w_d(fp32, cpu_env, fp64); + tcg_temp_free_i64(fp64); + gen_store_fpr32(ctx, fp32, fd); + tcg_temp_free_i32(fp32); + } + break; + case OPC_LARCH_FTINTRM_W_D: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp64, fs); + gen_helper_float_floor_w_d(fp32, cpu_env, fp64); + tcg_temp_free_i64(fp64); + gen_store_fpr32(ctx, fp32, fd); + tcg_temp_free_i32(fp32); + } + break; + case OPC_LARCH_FRECIP_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_recip_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FRSQRT_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_rsqrt_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FRINT_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_rint_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FCLASS_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_class_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FMIN_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_min_d(fp1, cpu_env, fp0, fp1); + gen_store_fpr64(ctx, fp1, fd); + tcg_temp_free_i64(fp1); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FMINA_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1); + gen_store_fpr64(ctx, fp1, fd); + tcg_temp_free_i64(fp1); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FMAX_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_max_d(fp1, cpu_env, fp0, fp1); + gen_store_fpr64(ctx, fp1, fd); + tcg_temp_free_i64(fp1); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FMAXA_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + TCGv_i64 fp1 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + gen_load_fpr64(ctx, fp1, ft); + gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1); + gen_store_fpr64(ctx, fp1, fd); + tcg_temp_free_i64(fp1); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FCVT_S_D: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp64, fs); + gen_helper_float_cvts_d(fp32, cpu_env, fp64); + tcg_temp_free_i64(fp64); + gen_store_fpr32(ctx, fp32, fd); + tcg_temp_free_i32(fp32); + } + break; + case OPC_LARCH_FTINT_W_D: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp64, fs); + gen_helper_float_cvt_w_d(fp32, cpu_env, fp64); + tcg_temp_free_i64(fp64); + gen_store_fpr32(ctx, fp32, fd); + tcg_temp_free_i32(fp32); + } + break; + case OPC_LARCH_FTINT_L_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_cvt_l_d(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FFINT_S_W: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + gen_load_fpr32(ctx, fp0, fs); + gen_helper_float_cvts_w(fp0, cpu_env, fp0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FFINT_D_W: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr32(ctx, fp32, fs); + gen_helper_float_cvtd_w(fp64, cpu_env, fp32); + tcg_temp_free_i32(fp32); + gen_store_fpr64(ctx, fp64, fd); + tcg_temp_free_i64(fp64); + } + break; + case OPC_LARCH_FFINT_S_L: + { + TCGv_i32 fp32 = tcg_temp_new_i32(); + TCGv_i64 fp64 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp64, fs); + gen_helper_float_cvts_l(fp32, cpu_env, fp64); + tcg_temp_free_i64(fp64); + gen_store_fpr32(ctx, fp32, fd); + tcg_temp_free_i32(fp32); + } + break; + case OPC_LARCH_FFINT_D_L: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + + gen_load_fpr64(ctx, fp0, fs); + gen_helper_float_cvtd_l(fp0, cpu_env, fp0); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + default: + LARCH_INVAL("farith"); + generate_exception_end(ctx, EXCP_RI); + return; + } +} + +/* Coprocessor 3 (FPU) */ +static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc, + int fd, int fs, int base, int index) +{ + TCGv t0 = tcg_temp_new(); + + check_cp1_enabled(ctx); + if (base == 0) { + gen_load_gpr(t0, index); + } else if (index == 0) { + gen_load_gpr(t0, base); + } else { + gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]); + } + + /* + * Don't do NOP if destination is zero: we must perform the actual + * memory access. + */ + switch (opc) { + case OPC_LARCH_FLDX_S: + case OPC_LARCH_FLDGT_S: + case OPC_LARCH_FLDLE_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL); + tcg_gen_trunc_tl_i32(fp0, t0); + gen_store_fpr32(ctx, fp0, fd); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FLDX_D: + case OPC_LARCH_FLDGT_D: + case OPC_LARCH_FLDLE_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ); + gen_store_fpr64(ctx, fp0, fd); + tcg_temp_free_i64(fp0); + } + break; + case OPC_LARCH_FSTX_S: + case OPC_LARCH_FSTGT_S: + case OPC_LARCH_FSTLE_S: + { + TCGv_i32 fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, fs); + tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL); + tcg_temp_free_i32(fp0); + } + break; + case OPC_LARCH_FSTX_D: + case OPC_LARCH_FSTGT_D: + case OPC_LARCH_FSTLE_D: + { + TCGv_i64 fp0 = tcg_temp_new_i64(); + gen_load_fpr64(ctx, fp0, fs); + tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ); + tcg_temp_free_i64(fp0); + } + break; + } + tcg_temp_free(t0); +} + +static inline void clear_branch_hflags(DisasContext *ctx) +{ + ctx->hflags &= ~LARCH_HFLAG_BMASK; + if (ctx->base.is_jmp == DISAS_NEXT) { + save_cpu_state(ctx, 0); + } else { + /* + * It is not safe to save ctx->hflags as hflags may be changed + * in execution time. + */ + tcg_gen_andi_i32(hflags, hflags, ~LARCH_HFLAG_BMASK); + } +} + +static void gen_branch(DisasContext *ctx, int insn_bytes) +{ + if (ctx->hflags & LARCH_HFLAG_BMASK) { + int proc_hflags = ctx->hflags & LARCH_HFLAG_BMASK; + /* Branches completion */ + clear_branch_hflags(ctx); + ctx->base.is_jmp = DISAS_NORETURN; + /* FIXME: Need to clear can_do_io. */ + switch (proc_hflags & LARCH_HFLAG_BMASK) { + case LARCH_HFLAG_B: + /* unconditional branch */ + gen_goto_tb(ctx, 0, ctx->btarget); + break; + case LARCH_HFLAG_BC: + /* Conditional branch */ + { + TCGLabel *l1 = gen_new_label(); + + tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1); + gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes); + gen_set_label(l1); + gen_goto_tb(ctx, 0, ctx->btarget); + } + break; + case LARCH_HFLAG_BR: + /* unconditional branch to register */ + tcg_gen_mov_tl(cpu_PC, btarget); + if (ctx->base.singlestep_enabled) { + save_cpu_state(ctx, 0); + gen_helper_raise_exception_debug(cpu_env); + } + tcg_gen_lookup_and_goto_ptr(); + break; + default: + fprintf(stderr, "unknown branch 0x%x\n", proc_hflags); + abort(); + } + } +} + +/* Signed immediate */ +#define SIMM(op, start, width) \ + ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \ + << (32 - width)) \ + >> (32 - width)) +/* Zero-extended immediate */ +#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width))) + +static void gen_sync(int stype) +{ + TCGBar tcg_mo = TCG_BAR_SC; + + switch (stype) { + case 0x4: /* SYNC_WMB */ + tcg_mo |= TCG_MO_ST_ST; + break; + case 0x10: /* SYNC_MB */ + tcg_mo |= TCG_MO_ALL; + break; + case 0x11: /* SYNC_ACQUIRE */ + tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST; + break; + case 0x12: /* SYNC_RELEASE */ + tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST; + break; + case 0x13: /* SYNC_RMB */ + tcg_mo |= TCG_MO_LD_LD; + break; + default: + tcg_mo |= TCG_MO_ALL; + break; + } + + tcg_gen_mb(tcg_mo); +} + +static void gen_crc32(DisasContext *ctx, int rd, int rs, int rt, int sz, + int crc32c) +{ + TCGv t0; + TCGv t1; + TCGv_i32 tsz = tcg_const_i32(1 << sz); + if (rd == 0) { + /* Treat as NOP. */ + return; + } + t0 = tcg_temp_new(); + t1 = tcg_temp_new(); + + gen_load_gpr(t0, rt); + gen_load_gpr(t1, rs); + + if (crc32c) { + gen_helper_crc32c(cpu_gpr[rd], t0, t1, tsz); + } else { + gen_helper_crc32(cpu_gpr[rd], t0, t1, tsz); + } + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free_i32(tsz); +} + +#include "cpu-csr.h" + +#ifndef CONFIG_USER_ONLY + +/* + * 64-bit CSR read + * + * @arg : GPR to store the value of CSR register + * @csr : CSR register number + */ +static void gen_csr_rdq(DisasContext *ctx, TCGv rd, int64_t a1) +{ + TCGv_i64 csr = tcg_const_i64(a1); + gen_helper_csr_rdq(rd, cpu_env, csr); +} + +/* + * 64-bit CSR write + * + * @arg : GPR that stores the new value of CSR register + * @csr : CSR register number + */ +static void gen_csr_wrq(DisasContext *ctx, TCGv val, int64_t a1) +{ + TCGv_i64 csr = tcg_const_i64(a1); + gen_helper_csr_wrq(val, cpu_env, val, csr); +} + +/* + * 64-bit CSR exchange + * + * @arg : GPR that stores the new value of CSR register + * @csr : CSR register number + */ +static void gen_csr_xchgq(DisasContext *ctx, TCGv val, TCGv mask, int64_t a1) +{ + TCGv_i64 csr = tcg_const_i64(a1); + gen_helper_csr_xchgq(val, cpu_env, val, mask, csr); +} +#endif /* !CONFIG_USER_ONLY */ + +static void loongarch_tr_init_disas_context(DisasContextBase *dcbase, + CPUState *cs) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + CPULOONGARCHState *env = cs->env_ptr; + + ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK; + ctx->saved_pc = -1; + ctx->insn_flags = env->insn_flags; + ctx->btarget = 0; + /* Restore state from the tb context. */ + ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */ + restore_cpu_state(env, ctx); +#ifdef CONFIG_USER_ONLY + ctx->mem_idx = LARCH_HFLAG_UM; +#else + ctx->mem_idx = hflags_mmu_index(ctx->hflags); +#endif + ctx->default_tcg_memop_mask = MO_ALIGN; + + LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx, + ctx->hflags); +} + +static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) +{ +} + +static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + + tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & LARCH_HFLAG_BMASK, + ctx->btarget); +} +#if 0 +static bool loongarch_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, + const CPUBreakpoint *bp) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + + save_cpu_state(ctx, 1); + ctx->base.is_jmp = DISAS_NORETURN; + gen_helper_raise_exception_debug(cpu_env); + /* The address covered by the breakpoint must be included in + [tb->pc, tb->pc + tb->size) in order to for it to be + properly cleared -- thus we increment the PC here so that + the logic setting tb->size below does the right thing. */ + ctx->base.pc_next += 4; + return true; +} +#endif +/* 128 and 256 lsx vector instructions are not supported yet */ +static bool decode_vector_lsx(uint32_t opcode) +{ + uint32_t value = (opcode & 0xff000000); + + if ((opcode & 0xf0000000) == 0x70000000) { + return true; + } else if ((opcode & 0xfff00000) == 0x38400000) { + return true; + } else { + switch (value) { + case 0x09000000: + case 0x0a000000: + case 0x0e000000: + case 0x0f000000: + case 0x2c000000: + case 0x30000000: + case 0x31000000: + case 0x32000000: + case 0x33000000: + return true; + } + } + return false; +} + +static bool decode_insn(DisasContext *ctx, uint32_t insn); +#include "decode-insn.c.inc" +#include "trans.inc.c" + +static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) +{ + CPULOONGARCHState *env = cs->env_ptr; + DisasContext *ctx = container_of(dcbase, DisasContext, base); + int insn_bytes = 4; + + ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next); + + if (!decode_insn(ctx, ctx->opcode)) { + if (decode_vector_lsx(ctx->opcode)) { + generate_exception_end(ctx, EXCP_RI); + } else { + fprintf(stderr, "Error: unkown opcode. 0x%lx: 0x%x\n", + ctx->base.pc_next, ctx->opcode); + generate_exception_end(ctx, EXCP_RI); + } + } + + if (ctx->hflags & LARCH_HFLAG_BMASK) { + gen_branch(ctx, insn_bytes); + } + ctx->base.pc_next += insn_bytes; +} + +static void loongarch_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + + if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) { + save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT); + gen_helper_raise_exception_debug(cpu_env); + } else { + switch (ctx->base.is_jmp) { + case DISAS_STOP: + gen_save_pc(ctx->base.pc_next); + tcg_gen_lookup_and_goto_ptr(); + break; + case DISAS_NEXT: + case DISAS_TOO_MANY: + save_cpu_state(ctx, 0); + gen_goto_tb(ctx, 0, ctx->base.pc_next); + break; + case DISAS_EXIT: + tcg_gen_exit_tb(NULL, 0); + break; + case DISAS_NORETURN: + break; + default: + g_assert_not_reached(); + } + } +} + +static void loongarch_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) +{ + qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first)); + log_target_disas(cs, dcbase->pc_first, dcbase->tb->size); +} + +static const TranslatorOps loongarch_tr_ops = { + .init_disas_context = loongarch_tr_init_disas_context, + .tb_start = loongarch_tr_tb_start, + .insn_start = loongarch_tr_insn_start, +#if 0 + .breakpoint_check = loongarch_tr_breakpoint_check, +#endif + .translate_insn = loongarch_tr_translate_insn, + .tb_stop = loongarch_tr_tb_stop, + .disas_log = loongarch_tr_disas_log, +}; + +void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb, int max_insns) +{ + DisasContext ctx; + + translator_loop(&loongarch_tr_ops, &ctx.base, cs, tb, max_insns); +} + +void loongarch_tcg_init(void) +{ + int i; + + for (i = 0; i < 32; i++) + cpu_gpr[i] = tcg_global_mem_new(cpu_env, + offsetof(CPULOONGARCHState, + active_tc.gpr[i]), + regnames[i]); + + for (i = 0; i < 32; i++) { + int off = offsetof(CPULOONGARCHState, active_fpu.fpr[i].d); + fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]); + } + + cpu_PC = tcg_global_mem_new(cpu_env, + offsetof(CPULOONGARCHState, active_tc.PC), "PC"); + bcond = tcg_global_mem_new(cpu_env, + offsetof(CPULOONGARCHState, bcond), "bcond"); + btarget = tcg_global_mem_new(cpu_env, + offsetof(CPULOONGARCHState, btarget), "btarget"); + hflags = tcg_global_mem_new_i32(cpu_env, + offsetof(CPULOONGARCHState, hflags), "hflags"); + fpu_fcsr0 = tcg_global_mem_new_i32(cpu_env, + offsetof(CPULOONGARCHState, active_fpu.fcsr0), + "fcsr0"); + cpu_lladdr = tcg_global_mem_new(cpu_env, + offsetof(CPULOONGARCHState, lladdr), + "lladdr"); + cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPULOONGARCHState, llval), + "llval"); +} + +void restore_state_to_opc(CPULOONGARCHState *env, TranslationBlock *tb, + target_ulong *data) +{ + env->active_tc.PC = data[0]; + env->hflags &= ~LARCH_HFLAG_BMASK; + env->hflags |= data[1]; + switch (env->hflags & LARCH_HFLAG_BMASK) { + case LARCH_HFLAG_BR: + break; + case LARCH_HFLAG_BC: + case LARCH_HFLAG_B: + env->btarget = data[2]; + break; + } +} diff --git a/target/meson.build b/target/meson.build index 2f6940255e..ac0ce618b7 100644 --- a/target/meson.build +++ b/target/meson.build @@ -5,6 +5,7 @@ subdir('cris') subdir('hexagon') subdir('hppa') subdir('i386') +subdir('loongarch64') subdir('m68k') subdir('microblaze') subdir('mips') -- Gitee From f52dc9cff70751a4cc6afc838521f5bb90b7bbf6 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Fri, 19 Aug 2022 23:47:06 -0400 Subject: [PATCH 05/29] Add linux-headers and linux-user. Change-Id: If052442a981fed87c03ca431c010629dc8e872ca Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- linux-headers/asm-loongarch64/bitsperlong.h | 9 + linux-headers/asm-loongarch64/kvm.h | 346 ++++++++++++++++++++ linux-headers/asm-loongarch64/sgidefs.h | 20 ++ linux-headers/asm-loongarch64/unistd.h | 23 ++ linux-user/loongarch64/cpu_loop.c | 193 +++++++++++ linux-user/loongarch64/meson.build | 6 + linux-user/loongarch64/signal.c | 212 ++++++++++++ linux-user/loongarch64/sockbits.h | 1 + linux-user/loongarch64/syscall_nr.h | 287 ++++++++++++++++ linux-user/loongarch64/target_cpu.h | 45 +++ linux-user/loongarch64/target_elf.h | 14 + linux-user/loongarch64/target_fcntl.h | 13 + linux-user/loongarch64/target_signal.h | 23 ++ linux-user/loongarch64/target_structs.h | 62 ++++ linux-user/loongarch64/target_syscall.h | 44 +++ linux-user/loongarch64/termbits.h | 224 +++++++++++++ 16 files changed, 1522 insertions(+) create mode 100644 linux-headers/asm-loongarch64/bitsperlong.h create mode 100644 linux-headers/asm-loongarch64/kvm.h create mode 100644 linux-headers/asm-loongarch64/sgidefs.h create mode 100644 linux-headers/asm-loongarch64/unistd.h create mode 100644 linux-user/loongarch64/cpu_loop.c create mode 100644 linux-user/loongarch64/meson.build create mode 100644 linux-user/loongarch64/signal.c create mode 100644 linux-user/loongarch64/sockbits.h create mode 100644 linux-user/loongarch64/syscall_nr.h create mode 100644 linux-user/loongarch64/target_cpu.h create mode 100644 linux-user/loongarch64/target_elf.h create mode 100644 linux-user/loongarch64/target_fcntl.h create mode 100644 linux-user/loongarch64/target_signal.h create mode 100644 linux-user/loongarch64/target_structs.h create mode 100644 linux-user/loongarch64/target_syscall.h create mode 100644 linux-user/loongarch64/termbits.h diff --git a/linux-headers/asm-loongarch64/bitsperlong.h b/linux-headers/asm-loongarch64/bitsperlong.h new file mode 100644 index 0000000000..5c2c8779a6 --- /dev/null +++ b/linux-headers/asm-loongarch64/bitsperlong.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __ASM_LOONGARCH_BITSPERLONG_H +#define __ASM_LOONGARCH_BITSPERLONG_H + +#define __BITS_PER_LONG _LOONGARCH_SZLONG + +#include + +#endif /* __ASM_LOONGARCH_BITSPERLONG_H */ diff --git a/linux-headers/asm-loongarch64/kvm.h b/linux-headers/asm-loongarch64/kvm.h new file mode 100644 index 0000000000..a24375ee59 --- /dev/null +++ b/linux-headers/asm-loongarch64/kvm.h @@ -0,0 +1,346 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2020 Loongson Technologies, Inc. All rights reserved. + * Authors: Sanjay Lal + * Authors: Xing Li + */ + +#ifndef __LINUX_KVM_LOONGARCH_H +#define __LINUX_KVM_LOONGARCH_H + +#include + +#define __KVM_HAVE_GUEST_DEBUG +#define KVM_GUESTDBG_USE_SW_BP 0x00010000 +#define KVM_GUESTDBG_USE_HW_BP 0x00020000 +#define KVM_DATA_HW_BREAKPOINT_NUM 8 +#define KVM_INST_HW_BREAKPOINT_NUM 8 + +/* + * KVM Loongarch specific structures and definitions. + * + * Some parts derived from the x86 version of this file. + */ + +#define __KVM_HAVE_READONLY_MEM + +#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 + +#define KVM_LARCH_VCPU_PVTIME_CTRL 2 +#define KVM_LARCH_VCPU_PVTIME_IPA 0 + +/* + * for KVM_GET_REGS and KVM_SET_REGS + */ +struct kvm_regs { + /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */ + __u64 gpr[32]; + __u64 pc; +}; + +/* + * for KVM_GET_CPUCFG + */ +struct kvm_cpucfg { + /* out (KVM_GET_CPUCFG) */ + __u32 cpucfg[64]; +}; + +/* + * for KVM_GET_FPU and KVM_SET_FPU + */ +struct kvm_fpu { + __u32 fcsr; + __u32 vcsr; + __u64 fcc; /* 8x8 */ + struct kvm_fpureg { + __u64 val64[4]; //support max 256 bits + }fpr[32]; +}; + +/* + * For LOONGARCH, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various + * registers. The id field is broken down as follows: + * + * bits[63..52] - As per linux/kvm.h + * bits[51..32] - Must be zero. + * bits[31..16] - Register set. + * + * Register set = 0: GP registers from kvm_regs (see definitions below). + * + * Register set = 1: CP0 registers. + * bits[15..8] - COP0 register set. + * + * COP0 register set = 0: Main CP0 registers. + * bits[7..3] - Register 'rd' index. + * bits[2..0] - Register 'sel' index. + * + * COP0 register set = 1: MAARs. + * bits[7..0] - MAAR index. + * + * Register set = 2: KVM specific registers (see definitions below). + * + * Register set = 3: FPU / MSA registers (see definitions below). + * + * Other sets registers may be added in the future. Each set would + * have its own identifier in bits[31..16]. + */ + +#define KVM_REG_LOONGARCH_GP (KVM_REG_LOONGARCH | 0x0000000000000000ULL) +#define KVM_REG_LOONGARCH_CSR (KVM_REG_LOONGARCH | 0x0000000000010000ULL) +#define KVM_REG_LOONGARCH_KVM (KVM_REG_LOONGARCH | 0x0000000000020000ULL) +#define KVM_REG_LOONGARCH_FPU (KVM_REG_LOONGARCH | 0x0000000000030000ULL) + + +/* + * KVM_REG_LOONGARCH_GP - General purpose registers from kvm_regs. + */ + +#define KVM_REG_LOONGARCH_R0 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 0) +#define KVM_REG_LOONGARCH_R1 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 1) +#define KVM_REG_LOONGARCH_R2 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 2) +#define KVM_REG_LOONGARCH_R3 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 3) +#define KVM_REG_LOONGARCH_R4 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 4) +#define KVM_REG_LOONGARCH_R5 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 5) +#define KVM_REG_LOONGARCH_R6 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 6) +#define KVM_REG_LOONGARCH_R7 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 7) +#define KVM_REG_LOONGARCH_R8 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 8) +#define KVM_REG_LOONGARCH_R9 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 9) +#define KVM_REG_LOONGARCH_R10 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 10) +#define KVM_REG_LOONGARCH_R11 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 11) +#define KVM_REG_LOONGARCH_R12 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 12) +#define KVM_REG_LOONGARCH_R13 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 13) +#define KVM_REG_LOONGARCH_R14 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 14) +#define KVM_REG_LOONGARCH_R15 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 15) +#define KVM_REG_LOONGARCH_R16 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 16) +#define KVM_REG_LOONGARCH_R17 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 17) +#define KVM_REG_LOONGARCH_R18 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 18) +#define KVM_REG_LOONGARCH_R19 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 19) +#define KVM_REG_LOONGARCH_R20 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 20) +#define KVM_REG_LOONGARCH_R21 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 21) +#define KVM_REG_LOONGARCH_R22 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 22) +#define KVM_REG_LOONGARCH_R23 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 23) +#define KVM_REG_LOONGARCH_R24 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 24) +#define KVM_REG_LOONGARCH_R25 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 25) +#define KVM_REG_LOONGARCH_R26 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 26) +#define KVM_REG_LOONGARCH_R27 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 27) +#define KVM_REG_LOONGARCH_R28 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 28) +#define KVM_REG_LOONGARCH_R29 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 29) +#define KVM_REG_LOONGARCH_R30 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 30) +#define KVM_REG_LOONGARCH_R31 (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 31) + +#define KVM_REG_LOONGARCH_HI (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 32) +#define KVM_REG_LOONGARCH_LO (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 33) +#define KVM_REG_LOONGARCH_PC (KVM_REG_LOONGARCH_GP | KVM_REG_SIZE_U64 | 34) + + +/* + * KVM_REG_LOONGARCH_KVM - KVM specific control registers. + */ + +/* + * CP0_Count control + * DC: Set 0: Master disable CP0_Count and set COUNT_RESUME to now + * Set 1: Master re-enable CP0_Count with unchanged bias, handling timer + * interrupts since COUNT_RESUME + * This can be used to freeze the timer to get a consistent snapshot of + * the CP0_Count and timer interrupt pending state, while also resuming + * safely without losing time or guest timer interrupts. + * Other: Reserved, do not change. + */ +#define KVM_REG_LOONGARCH_COUNT_CTL (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 0) +#define KVM_REG_LOONGARCH_COUNT_CTL_DC 0x00000001 + +/* + * CP0_Count resume monotonic nanoseconds + * The monotonic nanosecond time of the last set of COUNT_CTL.DC (master + * disable). Any reads and writes of Count related registers while + * COUNT_CTL.DC=1 will appear to occur at this time. When COUNT_CTL.DC is + * cleared again (master enable) any timer interrupts since this time will be + * emulated. + * Modifications to times in the future are rejected. + */ +#define KVM_REG_LOONGARCH_COUNT_RESUME (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 1) +/* + * CP0_Count rate in Hz + * Specifies the rate of the CP0_Count timer in Hz. Modifications occur without + * discontinuities in CP0_Count. + */ +#define KVM_REG_LOONGARCH_COUNT_HZ (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 2) + +#define KVM_REG_LOONGARCH_COUNTER (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 3) + +#define KVM_REG_LOONGARCH_VCPU_RESET (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 4) + +struct kvm_iocsr_entry { + __u32 addr; + __u32 pad; + __u64 data; +}; + +struct kvm_csr_entry { + __u32 index; + __u32 reserved; + __u64 data; +}; + +/* for KVM_GET_MSRS and KVM_SET_MSRS */ +struct kvm_msrs { + __u32 ncsrs; /* number of msrs in entries */ + __u32 pad; + struct kvm_csr_entry entries[0]; +}; + +#define __KVM_HAVE_IRQ_LINE + +struct kvm_debug_exit_arch { + __u64 epc; + __u32 fwps; + __u32 mwps; + __u32 exception; +}; + +/* for KVM_SET_GUEST_DEBUG */ +struct hw_breakpoint { + __u64 addr; + __u64 mask; + __u32 asid; + __u32 ctrl; +}; + +struct kvm_guest_debug_arch { + struct hw_breakpoint data_breakpoint[KVM_DATA_HW_BREAKPOINT_NUM]; + struct hw_breakpoint inst_breakpoint[KVM_INST_HW_BREAKPOINT_NUM]; + int inst_bp_nums, data_bp_nums; +}; + +/* definition of registers in kvm_run */ +struct kvm_sync_regs { +}; + +/* dummy definition */ +struct kvm_sregs { +}; + +struct kvm_loongarch_interrupt { + /* in */ + __u32 cpu; + __u32 irq; +}; + +#define KVM_IRQCHIP_LS7A_IOAPIC 0x0 +#define KVM_IRQCHIP_LS3A_GIPI 0x1 +#define KVM_IRQCHIP_LS3A_HT_IRQ 0x2 +#define KVM_IRQCHIP_LS3A_ROUTE 0x3 +#define KVM_IRQCHIP_LS3A_EXTIRQ 0x4 +#define KVM_IRQCHIP_LS3A_IPMASK 0x5 +#define KVM_NR_IRQCHIPS 1 +#define KVM_IRQCHIP_NUM_PINS 64 + +#define KVM_MAX_CORES 256 +#define KVM_EXTIOI_IRQS (256) +#define KVM_EXTIOI_IRQS_BITMAP_SIZE (KVM_EXTIOI_IRQS / 8) +/* map to ipnum per 32 irqs */ +#define KVM_EXTIOI_IRQS_IPMAP_SIZE (KVM_EXTIOI_IRQS / 32) +#define KVM_EXTIOI_IRQS_PER_GROUP 32 +#define KVM_EXTIOI_IRQS_COREMAP_SIZE (KVM_EXTIOI_IRQS) +#define KVM_EXTIOI_IRQS_NODETYPE_SIZE 16 + +struct ls7a_ioapic_state { + __u64 int_id; + /* 0x020 interrupt mask register */ + __u64 int_mask; + /* 0x040 1=msi */ + __u64 htmsi_en; + /* 0x060 edge=1 level =0 */ + __u64 intedge; + /* 0x080 for clean edge int,set 1 clean,set 0 is noused */ + __u64 intclr; + /* 0x0c0 */ + __u64 auto_crtl0; + /* 0x0e0 */ + __u64 auto_crtl1; + /* 0x100 - 0x140 */ + __u8 route_entry[64]; + /* 0x200 - 0x240 */ + __u8 htmsi_vector[64]; + /* 0x300 */ + __u64 intisr_chip0; + /* 0x320 */ + __u64 intisr_chip1; + /* edge detection */ + __u64 last_intirr; + /* 0x380 interrupt request register */ + __u64 intirr; + /* 0x3a0 interrupt service register */ + __u64 intisr; + /* 0x3e0 interrupt level polarity selection register, + * 0 for high level tirgger + */ + __u64 int_polarity; +}; + +struct loongarch_gipi_single { + __u32 status; + __u32 en; + __u32 set; + __u32 clear; + __u64 buf[4]; +}; + +struct loongarch_gipiState { + struct loongarch_gipi_single core[KVM_MAX_CORES]; +}; + +struct kvm_loongarch_ls3a_extirq_state { + union ext_en_r { + uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; + uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; + uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE]; + } ext_en_r; + union bounce_r { + uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; + uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; + uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE]; + } bounce_r; + union ext_isr_r { + uint64_t reg_u64[KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; + uint32_t reg_u32[KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; + uint8_t reg_u8[KVM_EXTIOI_IRQS_BITMAP_SIZE]; + } ext_isr_r; + union ext_core_isr_r { + uint64_t reg_u64[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE / 8]; + uint32_t reg_u32[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE / 4]; + uint8_t reg_u8[KVM_MAX_CORES][KVM_EXTIOI_IRQS_BITMAP_SIZE]; + } ext_core_isr_r; + union ip_map_r { + uint64_t reg_u64; + uint32_t reg_u32[KVM_EXTIOI_IRQS_IPMAP_SIZE / 4]; + uint8_t reg_u8[KVM_EXTIOI_IRQS_IPMAP_SIZE]; + } ip_map_r; + union core_map_r { + uint64_t reg_u64[KVM_EXTIOI_IRQS_COREMAP_SIZE / 8]; + uint32_t reg_u32[KVM_EXTIOI_IRQS_COREMAP_SIZE / 4]; + uint8_t reg_u8[KVM_EXTIOI_IRQS_COREMAP_SIZE]; + } core_map_r; + union node_type_r { + uint64_t reg_u64[KVM_EXTIOI_IRQS_NODETYPE_SIZE / 4]; + uint32_t reg_u32[KVM_EXTIOI_IRQS_NODETYPE_SIZE / 2]; + uint16_t reg_u16[KVM_EXTIOI_IRQS_NODETYPE_SIZE]; + uint8_t reg_u8[KVM_EXTIOI_IRQS_NODETYPE_SIZE * 2]; + } node_type_r; +}; + +struct loongarch_kvm_irqchip { + __u16 chip_id; + __u16 len; + __u16 vcpu_id; + __u16 reserved; + char data[0]; +}; + +#endif /* __LINUX_KVM_LOONGARCH_H */ diff --git a/linux-headers/asm-loongarch64/sgidefs.h b/linux-headers/asm-loongarch64/sgidefs.h new file mode 100644 index 0000000000..b809608349 --- /dev/null +++ b/linux-headers/asm-loongarch64/sgidefs.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* +* Copyright (C) 2020 Loongson Technology Corporation Limited +* +* Author: Hanlu Li +*/ +#ifndef __ASM_SGIDEFS_H +#define __ASM_SGIDEFS_H + +#define _LOONGARCH_ISA_LOONGARCH32 6 +#define _LOONGARCH_ISA_LOONGARCH64 7 + +/* + * Subprogram calling convention + */ +#define _LOONGARCH_SIM_ABILP32 1 +#define _LOONGARCH_SIM_ABILPX32 2 +#define _LOONGARCH_SIM_ABILP64 3 + +#endif /* __ASM_SGIDEFS_H */ diff --git a/linux-headers/asm-loongarch64/unistd.h b/linux-headers/asm-loongarch64/unistd.h new file mode 100644 index 0000000000..2a6014562a --- /dev/null +++ b/linux-headers/asm-loongarch64/unistd.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Copyright (C) 2020 Loongson Technologies, Inc. + * Authors: Jun Yi + */ + +#ifdef __LP64__ +#define __ARCH_WANT_NEW_STAT +#endif /* __LP64__ */ + +#include diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c new file mode 100644 index 0000000000..6d4093e1d7 --- /dev/null +++ b/linux-user/loongarch64/cpu_loop.c @@ -0,0 +1,193 @@ +/* + * qemu user cpu loop + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "qemu.h" +#include "cpu_loop-common.h" +#include "elf.h" + +/* Break codes */ +enum { + BRK_OVERFLOW = 6, + BRK_DIVZERO = 7 +}; + +static int do_break(CPULOONGARCHState *env, target_siginfo_t *info, + unsigned int code) +{ + int ret = -1; + + switch (code) { + case BRK_OVERFLOW: + case BRK_DIVZERO: + info->si_signo = TARGET_SIGFPE; + info->si_errno = 0; + info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; + queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); + ret = 0; + break; + default: + info->si_signo = TARGET_SIGTRAP; + info->si_errno = 0; + queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); + ret = 0; + break; + } + + return ret; +} + +void cpu_loop(CPULOONGARCHState *env) +{ + CPUState *cs = CPU(loongarch_env_get_cpu(env)); + target_siginfo_t info; + int trapnr; + abi_long ret; + + for (;;) { + cpu_exec_start(cs); + trapnr = cpu_exec(cs); + cpu_exec_end(cs); + process_queued_cpu_work(cs); + + switch (trapnr) { + case EXCP_SYSCALL: + env->active_tc.PC += 4; + ret = do_syscall(env, env->active_tc.gpr[11], + env->active_tc.gpr[4], env->active_tc.gpr[5], + env->active_tc.gpr[6], env->active_tc.gpr[7], + env->active_tc.gpr[8], env->active_tc.gpr[9], + -1, -1); + if (ret == -TARGET_ERESTARTSYS) { + env->active_tc.PC -= 4; + break; + } + if (ret == -TARGET_QEMU_ESIGRETURN) { + /* Returning from a successful sigreturn syscall. + Avoid clobbering register state. */ + break; + } + env->active_tc.gpr[4] = ret; + break; + case EXCP_TLBL: + case EXCP_TLBS: + case EXCP_AdEL: + case EXCP_AdES: + info.si_signo = TARGET_SIGSEGV; + info.si_errno = 0; + /* XXX: check env->error_code */ + info.si_code = TARGET_SEGV_MAPERR; + info._sifields._sigfault._addr = env->CSR_BADV; + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + break; + case EXCP_FPDIS: + case EXCP_LSXDIS: + case EXCP_LASXDIS: + case EXCP_RI: + info.si_signo = TARGET_SIGILL; + info.si_errno = 0; + info.si_code = 0; + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + break; + case EXCP_INTERRUPT: + /* just indicate that signals should be handled asap */ + break; + case EXCP_DEBUG: + info.si_signo = TARGET_SIGTRAP; + info.si_errno = 0; + info.si_code = TARGET_TRAP_BRKPT; + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + break; + case EXCP_FPE: + info.si_signo = TARGET_SIGFPE; + info.si_errno = 0; + info.si_code = TARGET_FPE_FLTUNK; + if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_INVALID) { + info.si_code = TARGET_FPE_FLTINV; + } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_DIV0) { + info.si_code = TARGET_FPE_FLTDIV; + } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_OVERFLOW) { + info.si_code = TARGET_FPE_FLTOVF; + } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_UNDERFLOW) { + info.si_code = TARGET_FPE_FLTUND; + } else if (GET_FP_CAUSE(env->active_fpu.fcsr0) & FP_INEXACT) { + info.si_code = TARGET_FPE_FLTRES; + } + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + break; + case EXCP_BREAK: + { + abi_ulong trap_instr; + unsigned int code; + + ret = get_user_u32(trap_instr, env->active_tc.PC); + if (ret != 0) { + goto error; + } + + code = trap_instr & 0x7fff; + + if (do_break(env, &info, code) != 0) { + goto error; + } + } + break; + case EXCP_TRAP: + { + abi_ulong trap_instr; + unsigned int code = 0; + + ret = get_user_u32(trap_instr, env->active_tc.PC); + + if (ret != 0) { + goto error; + } + + /* The immediate versions don't provide a code. */ + if (!(trap_instr & 0xFC000000)) { + code = ((trap_instr >> 6) & ((1 << 10) - 1)); + } + + if (do_break(env, &info, code) != 0) { + goto error; + } + } + break; + case EXCP_ATOMIC: + cpu_exec_step_atomic(cs); + break; + default: +error: + printf("111111\n"); + EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); + abort(); + } + process_pending_signals(env); + } +} + +void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) +{ + int i; + + for (i = 0; i < 32; i++) { + env->active_tc.gpr[i] = regs->regs[i]; + } + env->active_tc.PC = regs->csr_era & ~(target_ulong)1; +} diff --git a/linux-user/loongarch64/meson.build b/linux-user/loongarch64/meson.build new file mode 100644 index 0000000000..c4c0b4d701 --- /dev/null +++ b/linux-user/loongarch64/meson.build @@ -0,0 +1,6 @@ +syscall_nr_generators += { + 'loongarch64': generator(sh, + arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@', + '', 'TARGET_SYSCALL_OFFSET' ], + output: '@BASENAME@_nr.h') +} diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c new file mode 100644 index 0000000000..6fe6852758 --- /dev/null +++ b/linux-user/loongarch64/signal.c @@ -0,0 +1,212 @@ +/* + * Emulation of Linux signals + * + * Copyright (c) 2003 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#include "qemu/osdep.h" +#include "qemu.h" +#include "signal-common.h" +#include "linux-user/trace.h" + +#define FPU_REG_WIDTH 256 +union fpureg { + uint32_t val32[FPU_REG_WIDTH / 32]; + uint64_t val64[FPU_REG_WIDTH / 64]; +}; + +struct target_sigcontext { + uint64_t sc_pc; + uint64_t sc_regs[32]; + uint32_t sc_flags; + + uint32_t sc_fcsr; + uint32_t sc_vcsr; + uint64_t sc_fcc; + union fpureg sc_fpregs[32] __attribute__((aligned(32))); + + uint32_t sc_reserved; + +}; + +struct sigframe { + uint32_t sf_ass[4]; /* argument save space for o32 */ + uint32_t sf_code[2]; /* signal trampoline */ + struct target_sigcontext sf_sc; + target_sigset_t sf_mask; +}; + +struct target_ucontext { + target_ulong tuc_flags; + target_ulong tuc_link; + target_stack_t tuc_stack; + target_ulong pad0; + struct target_sigcontext tuc_mcontext; + target_sigset_t tuc_sigmask; +}; + +struct target_rt_sigframe { + uint32_t rs_ass[4]; /* argument save space for o32 */ + uint32_t rs_code[2]; /* signal trampoline */ + struct target_siginfo rs_info; + struct target_ucontext rs_uc; +}; + +static inline void setup_sigcontext(CPULOONGARCHState *regs, + struct target_sigcontext *sc) +{ + int i; + + __put_user(exception_resume_pc(regs), &sc->sc_pc); + regs->hflags &= ~LARCH_HFLAG_BMASK; + + __put_user(0, &sc->sc_regs[0]); + for (i = 1; i < 32; ++i) { + __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); + } + + for (i = 0; i < 32; ++i) { + __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i].val64[0]); + } +} + +static inline void +restore_sigcontext(CPULOONGARCHState *regs, struct target_sigcontext *sc) +{ + int i; + + __get_user(regs->CSR_ERA, &sc->sc_pc); + + for (i = 1; i < 32; ++i) { + __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); + } + + for (i = 0; i < 32; ++i) { + __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i].val64[0]); + } +} + +/* + * Determine which stack to use.. + */ +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPULOONGARCHState *regs, + size_t frame_size) +{ + unsigned long sp; + + /* + * FPU emulator may have its own trampoline active just + * above the user stack, 16-bytes before the next lowest + * 16 byte boundary. Try to avoid trashing it. + */ + sp = target_sigsp(get_sp_from_cpustate(regs) - 32, ka); + + return (sp - frame_size) & ~7; +} + +void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPULOONGARCHState *env) +{ + struct target_rt_sigframe *frame; + abi_ulong frame_addr; + int i; + + frame_addr = get_sigframe(ka, env, sizeof(*frame)); + trace_user_setup_rt_frame(env, frame_addr); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { + goto give_sigsegv; + } + + /* ori a7, $r0, TARGET_NR_rt_sigreturn */ + /* syscall 0 */ + __put_user(0x0380000b + (TARGET_NR_rt_sigreturn << 10), &frame->rs_code[0]); + __put_user(0x002b0000, &frame->rs_code[1]); + + tswap_siginfo(&frame->rs_info, info); + + __put_user(0, &frame->rs_uc.tuc_flags); + __put_user(0, &frame->rs_uc.tuc_link); + target_save_altstack(&frame->rs_uc.tuc_stack, env); + + setup_sigcontext(env, &frame->rs_uc.tuc_mcontext); + + for (i = 0; i < TARGET_NSIG_WORDS; i++) { + __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]); + } + + /* + * Arguments to signal handler: + * + * a0 = signal number + * a1 = pointer to siginfo_t + * a2 = pointer to ucontext_t + * + * $25 and PC point to the signal handler, $29 points to the + * struct sigframe. + */ + env->active_tc.gpr[4] = sig; + env->active_tc.gpr[5] = frame_addr + + offsetof(struct target_rt_sigframe, rs_info); + env->active_tc.gpr[6] = frame_addr + + offsetof(struct target_rt_sigframe, rs_uc); + env->active_tc.gpr[3] = frame_addr; + env->active_tc.gpr[1] = frame_addr + + offsetof(struct target_rt_sigframe, rs_code); + /* The original kernel code sets CP0_ERA to the handler + * since it returns to userland using ertn + * we cannot do this here, and we must set PC directly */ + env->active_tc.PC = env->active_tc.gpr[20] = ka->_sa_handler; + unlock_user_struct(frame, frame_addr, 1); + return; + +give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); + force_sigsegv(sig); +} + +long do_rt_sigreturn(CPULOONGARCHState *env) +{ + struct target_rt_sigframe *frame; + abi_ulong frame_addr; + sigset_t blocked; + + frame_addr = env->active_tc.gpr[3]; + trace_user_do_rt_sigreturn(env, frame_addr); + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { + goto badframe; + } + + target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); + set_sigmask(&blocked); + + restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); + + if (do_sigaltstack(frame_addr + + offsetof(struct target_rt_sigframe, rs_uc.tuc_stack), + 0, get_sp_from_cpustate(env)) == -EFAULT) + goto badframe; + + env->active_tc.PC = env->CSR_ERA; + /* I am not sure this is right, but it seems to work + * maybe a problem with nested signals ? */ + env->CSR_ERA = 0; + return -TARGET_QEMU_ESIGRETURN; + +badframe: + force_sig(TARGET_SIGSEGV); + return -TARGET_QEMU_ESIGRETURN; +} diff --git a/linux-user/loongarch64/sockbits.h b/linux-user/loongarch64/sockbits.h new file mode 100644 index 0000000000..0e4c8f012d --- /dev/null +++ b/linux-user/loongarch64/sockbits.h @@ -0,0 +1 @@ +#include "../generic/sockbits.h" diff --git a/linux-user/loongarch64/syscall_nr.h b/linux-user/loongarch64/syscall_nr.h new file mode 100644 index 0000000000..a30aca8d8e --- /dev/null +++ b/linux-user/loongarch64/syscall_nr.h @@ -0,0 +1,287 @@ +#ifndef LINUX_USER_LOONGARCH_SYSCALL_NR_H +#define LINUX_USER_LOONGARCH_SYSCALL_NR_H + +#define TARGET_NR_io_setup 0 +#define TARGET_NR_io_destroy 1 +#define TARGET_NR_io_submit 2 +#define TARGET_NR_io_cancel 3 +#define TARGET_NR_io_getevents 4 +#define TARGET_NR_setxattr 5 +#define TARGET_NR_lsetxattr 6 +#define TARGET_NR_fsetxattr 7 +#define TARGET_NR_getxattr 8 +#define TARGET_NR_lgetxattr 9 +#define TARGET_NR_fgetxattr 10 +#define TARGET_NR_listxattr 11 +#define TARGET_NR_llistxattr 12 +#define TARGET_NR_flistxattr 13 +#define TARGET_NR_removexattr 14 +#define TARGET_NR_lremovexattr 15 +#define TARGET_NR_fremovexattr 16 +#define TARGET_NR_getcwd 17 +#define TARGET_NR_lookup_dcookie 18 +#define TARGET_NR_eventfd2 19 +#define TARGET_NR_epoll_create1 20 +#define TARGET_NR_epoll_ctl 21 +#define TARGET_NR_epoll_pwait 22 +#define TARGET_NR_dup 23 +#define TARGET_NR_dup3 24 +#define TARGET_NR_fcntl 25 +#define TARGET_NR_inotify_init1 26 +#define TARGET_NR_inotify_add_watch 27 +#define TARGET_NR_inotify_rm_watch 28 +#define TARGET_NR_ioctl 29 +#define TARGET_NR_ioprio_set 30 +#define TARGET_NR_ioprio_get 31 +#define TARGET_NR_flock 32 +#define TARGET_NR_mknodat 33 +#define TARGET_NR_mkdirat 34 +#define TARGET_NR_unlinkat 35 +#define TARGET_NR_symlinkat 36 +#define TARGET_NR_linkat 37 +#define TARGET_NR_renameat 38 +#define TARGET_NR_umount2 39 +#define TARGET_NR_mount 40 +#define TARGET_NR_pivot_root 41 +#define TARGET_NR_nfsservctl 42 +#define TARGET_NR_statfs 43 +#define TARGET_NR_fstatfs 44 +#define TARGET_NR_truncate 45 +#define TARGET_NR_ftruncate 46 +#define TARGET_NR_fallocate 47 +#define TARGET_NR_faccessat 48 +#define TARGET_NR_chdir 49 +#define TARGET_NR_fchdir 50 +#define TARGET_NR_chroot 51 +#define TARGET_NR_fchmod 52 +#define TARGET_NR_fchmodat 53 +#define TARGET_NR_fchownat 54 +#define TARGET_NR_fchown 55 +#define TARGET_NR_openat 56 +#define TARGET_NR_close 57 +#define TARGET_NR_vhangup 58 +#define TARGET_NR_pipe2 59 +#define TARGET_NR_quotactl 60 +#define TARGET_NR_getdents64 61 +#define TARGET_NR_lseek 62 +#define TARGET_NR_read 63 +#define TARGET_NR_write 64 +#define TARGET_NR_readv 65 +#define TARGET_NR_writev 66 +#define TARGET_NR_pread64 67 +#define TARGET_NR_pwrite64 68 +#define TARGET_NR_preadv 69 +#define TARGET_NR_pwritev 70 +#define TARGET_NR_sendfile 71 +#define TARGET_NR_pselect6 72 +#define TARGET_NR_ppoll 73 +#define TARGET_NR_signalfd4 74 +#define TARGET_NR_vmsplice 75 +#define TARGET_NR_splice 76 +#define TARGET_NR_tee 77 +#define TARGET_NR_readlinkat 78 +#define TARGET_NR_newfstatat 79 +#define TARGET_NR_fstat 80 +#define TARGET_NR_sync 81 +#define TARGET_NR_fsync 82 +#define TARGET_NR_fdatasync 83 +#define TARGET_NR_sync_file_range 84 +#define TARGET_NR_timerfd_create 85 +#define TARGET_NR_timerfd_settime 86 +#define TARGET_NR_timerfd_gettime 87 +#define TARGET_NR_utimensat 88 +#define TARGET_NR_acct 89 +#define TARGET_NR_capget 90 +#define TARGET_NR_capset 91 +#define TARGET_NR_personality 92 +#define TARGET_NR_exit 93 +#define TARGET_NR_exit_group 94 +#define TARGET_NR_waitid 95 +#define TARGET_NR_set_tid_address 96 +#define TARGET_NR_unshare 97 +#define TARGET_NR_futex 98 +#define TARGET_NR_set_robust_list 99 +#define TARGET_NR_get_robust_list 100 +#define TARGET_NR_nanosleep 101 +#define TARGET_NR_getitimer 102 +#define TARGET_NR_setitimer 103 +#define TARGET_NR_kexec_load 104 +#define TARGET_NR_init_module 105 +#define TARGET_NR_delete_module 106 +#define TARGET_NR_timer_create 107 +#define TARGET_NR_timer_gettime 108 +#define TARGET_NR_timer_getoverrun 109 +#define TARGET_NR_timer_settime 110 +#define TARGET_NR_timer_delete 111 +#define TARGET_NR_clock_settime 112 +#define TARGET_NR_clock_gettime 113 +#define TARGET_NR_clock_getres 114 +#define TARGET_NR_clock_nanosleep 115 +#define TARGET_NR_syslog 116 +#define TARGET_NR_ptrace 117 +#define TARGET_NR_sched_setparam 118 +#define TARGET_NR_sched_setscheduler 119 +#define TARGET_NR_sched_getscheduler 120 +#define TARGET_NR_sched_getparam 121 +#define TARGET_NR_sched_setaffinity 122 +#define TARGET_NR_sched_getaffinity 123 +#define TARGET_NR_sched_yield 124 +#define TARGET_NR_sched_get_priority_max 125 +#define TARGET_NR_sched_get_priority_min 126 +#define TARGET_NR_sched_rr_get_interval 127 +#define TARGET_NR_restart_syscall 128 +#define TARGET_NR_kill 129 +#define TARGET_NR_tkill 130 +#define TARGET_NR_tgkill 131 +#define TARGET_NR_sigaltstack 132 +#define TARGET_NR_rt_sigsuspend 133 +#define TARGET_NR_rt_sigaction 134 +#define TARGET_NR_rt_sigprocmask 135 +#define TARGET_NR_rt_sigpending 136 +#define TARGET_NR_rt_sigtimedwait 137 +#define TARGET_NR_rt_sigqueueinfo 138 +#define TARGET_NR_rt_sigreturn 139 +#define TARGET_NR_setpriority 140 +#define TARGET_NR_getpriority 141 +#define TARGET_NR_reboot 142 +#define TARGET_NR_setregid 143 +#define TARGET_NR_setgid 144 +#define TARGET_NR_setreuid 145 +#define TARGET_NR_setuid 146 +#define TARGET_NR_setresuid 147 +#define TARGET_NR_getresuid 148 +#define TARGET_NR_setresgid 149 +#define TARGET_NR_getresgid 150 +#define TARGET_NR_setfsuid 151 +#define TARGET_NR_setfsgid 152 +#define TARGET_NR_times 153 +#define TARGET_NR_setpgid 154 +#define TARGET_NR_getpgid 155 +#define TARGET_NR_getsid 156 +#define TARGET_NR_setsid 157 +#define TARGET_NR_getgroups 158 +#define TARGET_NR_setgroups 159 +#define TARGET_NR_uname 160 +#define TARGET_NR_sethostname 161 +#define TARGET_NR_setdomainname 162 +#define TARGET_NR_getrlimit 163 +#define TARGET_NR_setrlimit 164 +#define TARGET_NR_getrusage 165 +#define TARGET_NR_umask 166 +#define TARGET_NR_prctl 167 +#define TARGET_NR_getcpu 168 +#define TARGET_NR_gettimeofday 169 +#define TARGET_NR_settimeofday 170 +#define TARGET_NR_adjtimex 171 +#define TARGET_NR_getpid 172 +#define TARGET_NR_getppid 173 +#define TARGET_NR_getuid 174 +#define TARGET_NR_geteuid 175 +#define TARGET_NR_getgid 176 +#define TARGET_NR_getegid 177 +#define TARGET_NR_gettid 178 +#define TARGET_NR_sysinfo 179 +#define TARGET_NR_mq_open 180 +#define TARGET_NR_mq_unlink 181 +#define TARGET_NR_mq_timedsend 182 +#define TARGET_NR_mq_timedreceive 183 +#define TARGET_NR_mq_notify 184 +#define TARGET_NR_mq_getsetattr 185 +#define TARGET_NR_msgget 186 +#define TARGET_NR_msgctl 187 +#define TARGET_NR_msgrcv 188 +#define TARGET_NR_msgsnd 189 +#define TARGET_NR_semget 190 +#define TARGET_NR_semctl 191 +#define TARGET_NR_semtimedop 192 +#define TARGET_NR_semop 193 +#define TARGET_NR_shmget 194 +#define TARGET_NR_shmctl 195 +#define TARGET_NR_shmat 196 +#define TARGET_NR_shmdt 197 +#define TARGET_NR_socket 198 +#define TARGET_NR_socketpair 199 +#define TARGET_NR_bind 200 +#define TARGET_NR_listen 201 +#define TARGET_NR_accept 202 +#define TARGET_NR_connect 203 +#define TARGET_NR_getsockname 204 +#define TARGET_NR_getpeername 205 +#define TARGET_NR_sendto 206 +#define TARGET_NR_recvfrom 207 +#define TARGET_NR_setsockopt 208 +#define TARGET_NR_getsockopt 209 +#define TARGET_NR_shutdown 210 +#define TARGET_NR_sendmsg 211 +#define TARGET_NR_recvmsg 212 +#define TARGET_NR_readahead 213 +#define TARGET_NR_brk 214 +#define TARGET_NR_munmap 215 +#define TARGET_NR_mremap 216 +#define TARGET_NR_add_key 217 +#define TARGET_NR_request_key 218 +#define TARGET_NR_keyctl 219 +#define TARGET_NR_clone 220 +#define TARGET_NR_execve 221 +#define TARGET_NR_mmap 222 +#define TARGET_NR_fadvise64 223 +#define TARGET_NR_swapon 224 +#define TARGET_NR_swapoff 225 +#define TARGET_NR_mprotect 226 +#define TARGET_NR_msync 227 +#define TARGET_NR_mlock 228 +#define TARGET_NR_munlock 229 +#define TARGET_NR_mlockall 230 +#define TARGET_NR_munlockall 231 +#define TARGET_NR_mincore 232 +#define TARGET_NR_madvise 233 +#define TARGET_NR_remap_file_pages 234 +#define TARGET_NR_mbind 235 +#define TARGET_NR_get_mempolicy 236 +#define TARGET_NR_set_mempolicy 237 +#define TARGET_NR_migrate_pages 238 +#define TARGET_NR_move_pages 239 +#define TARGET_NR_rt_tgsigqueueinfo 240 +#define TARGET_NR_perf_event_open 241 +#define TARGET_NR_accept4 242 +#define TARGET_NR_recvmmsg 243 +#define TARGET_NR_arch_specific_syscall 244 +#define TARGET_NR_wait4 260 +#define TARGET_NR_prlimit64 261 +#define TARGET_NR_fanotify_init 262 +#define TARGET_NR_fanotify_mark 263 +#define TARGET_NR_name_to_handle_at 264 +#define TARGET_NR_open_by_handle_at 265 +#define TARGET_NR_clock_adjtime 266 +#define TARGET_NR_syncfs 267 +#define TARGET_NR_setns 268 +#define TARGET_NR_sendmmsg 269 +#define TARGET_NR_process_vm_readv 270 +#define TARGET_NR_process_vm_writev 271 +#define TARGET_NR_kcmp 272 +#define TARGET_NR_finit_module 273 +#define TARGET_NR_sched_setattr 274 +#define TARGET_NR_sched_getattr 275 +#define TARGET_NR_renameat2 276 +#define TARGET_NR_seccomp 277 +#define TARGET_NR_getrandom 278 +#define TARGET_NR_memfd_create 279 +#define TARGET_NR_bpf 280 +#define TARGET_NR_execveat 281 +#define TARGET_NR_userfaultfd 282 +#define TARGET_NR_membarrier 283 +#define TARGET_NR_mlock2 284 +#define TARGET_NR_copy_file_range 285 +#define TARGET_NR_preadv2 286 +#define TARGET_NR_pwritev2 287 +#define TARGET_NR_pkey_mprotect 288 +#define TARGET_NR_pkey_alloc 289 +#define TARGET_NR_pkey_free 290 +#define TARGET_NR_statx 291 +#define TARGET_NR_io_pgetevents 292 +#define TARGET_NR_rseq 293 +#define TARGET_NR_kexec_file_load 294 + +#define TARGET_NR_syscalls (TARGET_NR_kexec_file_load + 1) + +#endif diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h new file mode 100644 index 0000000000..0f6845737f --- /dev/null +++ b/linux-user/loongarch64/target_cpu.h @@ -0,0 +1,45 @@ +/* + * MIPS specific CPU ABI and functions for linux-user + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef LOONGARCH_TARGET_CPU_H +#define LOONGARCH_TARGET_CPU_H + +static inline void cpu_clone_regs_child(CPULOONGARCHState *env, target_ulong newsp, + unsigned flags) +{ + if (newsp) { + env->active_tc.gpr[3] = newsp; + } + env->active_tc.gpr[7] = 0; + env->active_tc.gpr[4] = 0; +} + +static inline void cpu_clone_regs_parent(CPULOONGARCHState *env, unsigned flags) +{ +} + +static inline void cpu_set_tls(CPULOONGARCHState *env, target_ulong newtls) +{ + env->active_tc.gpr[2] = newtls; +} + +static inline abi_ulong get_sp_from_cpustate(CPULOONGARCHState *state) +{ + return state->active_tc.gpr[3]; +} +#endif diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h new file mode 100644 index 0000000000..6c153d12c4 --- /dev/null +++ b/linux-user/loongarch64/target_elf.h @@ -0,0 +1,14 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation, or (at your option) any + * later version. See the COPYING file in the top-level directory. + */ + +#ifndef LOONGARCH_TARGET_ELF_H +#define LOONGARCH_TARGET_ELF_H +static inline const char *cpu_get_model(uint32_t eflags) +{ + return "Loongson-3A5000"; +} +#endif diff --git a/linux-user/loongarch64/target_fcntl.h b/linux-user/loongarch64/target_fcntl.h new file mode 100644 index 0000000000..a3d7b46062 --- /dev/null +++ b/linux-user/loongarch64/target_fcntl.h @@ -0,0 +1,13 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation, or (at your option) any + * later version. See the COPYING file in the top-level directory. + */ + +#ifndef LOONGARCH_TARGET_FCNTL_H +#define LOONGARCH_TARGET_FCNTL_H + +#include "../generic/fcntl.h" + +#endif /* LOONGARCH_TARGET_FCNTL_H */ diff --git a/linux-user/loongarch64/target_signal.h b/linux-user/loongarch64/target_signal.h new file mode 100644 index 0000000000..e418c8e8f5 --- /dev/null +++ b/linux-user/loongarch64/target_signal.h @@ -0,0 +1,23 @@ +#ifndef LOONGARCH_TARGET_SIGNAL_H +#define LOONGARCH_TARGET_SIGNAL_H + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { + abi_long ss_sp; + abi_int ss_flags; + abi_ulong ss_size; +} target_stack_t; + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK 1 +#define TARGET_SS_DISABLE 2 + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_SIGSTKSZ 8192 + +#include "../generic/signal.h" + +#endif /* LOONGARCH_TARGET_SIGNAL_H */ diff --git a/linux-user/loongarch64/target_structs.h b/linux-user/loongarch64/target_structs.h new file mode 100644 index 0000000000..280acd0971 --- /dev/null +++ b/linux-user/loongarch64/target_structs.h @@ -0,0 +1,62 @@ +/* + * LOONGARCH specific structures for linux-user + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef LOONGARCH_TARGET_STRUCTS_H +#define LOONGARCH_TARGET_STRUCTS_H + +struct target_ipc_perm { + abi_int __key; /* Key. */ + abi_uint uid; /* Owner's user ID. */ + abi_uint gid; /* Owner's group ID. */ + abi_uint cuid; /* Creator's user ID. */ + abi_uint cgid; /* Creator's group ID. */ + abi_uint mode; /* Read/write permission. */ + abi_ushort __seq; /* Sequence number. */ + abi_ushort __pad1; + abi_ulong __unused1; + abi_ulong __unused2; +}; + +struct target_shmid_ds { + struct target_ipc_perm shm_perm; /* operation permission struct */ + abi_long shm_segsz; /* size of segment in bytes */ + abi_ulong shm_atime; /* time of last shmat() */ + abi_ulong shm_dtime; /* time of last shmdt() */ + abi_ulong shm_ctime; /* time of last change by shmctl() */ + abi_int shm_cpid; /* pid of creator */ + abi_int shm_lpid; /* pid of last shmop */ + abi_ulong shm_nattch; /* number of current attaches */ + abi_ulong __unused1; + abi_ulong __unused2; +}; + +#define TARGET_SEMID64_DS + +/* + * The semid64_ds structure for the MIPS architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + */ +struct target_semid64_ds { + struct target_ipc_perm sem_perm; + abi_ulong sem_otime; + abi_ulong sem_ctime; + abi_ulong sem_nsems; + abi_ulong __unused1; + abi_ulong __unused2; +}; + +#endif diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h new file mode 100644 index 0000000000..cb77f07080 --- /dev/null +++ b/linux-user/loongarch64/target_syscall.h @@ -0,0 +1,44 @@ +#ifndef LOONGARCH_TARGET_SYSCALL_H +#define LOONGARCH_TARGET_SYSCALL_H + +/* this struct defines the way the registers are stored on the + stack during a system call. */ + +struct target_pt_regs { + /* Saved main processor registers. */ + target_ulong regs[32]; + + /* Saved special registers. */ + /* Saved special registers. */ + target_ulong csr_crmd; + target_ulong csr_prmd; + target_ulong csr_euen; + target_ulong csr_ecfg; + target_ulong csr_estat; + target_ulong csr_era; + target_ulong csr_badvaddr; + target_ulong orig_a0; + target_ulong __last[0]; +}; + +#define UNAME_MACHINE "loongarch" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_CLONE_BACKWARDS +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE 2 + +#define TARGET_FORCE_SHMLBA + +static inline abi_ulong target_shmlba(CPULOONGARCHState *env) +{ + return 0x40000; +} + +#define TARGET_PR_SET_FP_MODE 45 +#define TARGET_PR_GET_FP_MODE 46 +#define TARGET_PR_FP_MODE_FR (1 << 0) +#define TARGET_PR_FP_MODE_FRE (1 << 1) + +#endif /* LOONGARCH_TARGET_SYSCALL_H */ diff --git a/linux-user/loongarch64/termbits.h b/linux-user/loongarch64/termbits.h new file mode 100644 index 0000000000..6c613a1973 --- /dev/null +++ b/linux-user/loongarch64/termbits.h @@ -0,0 +1,224 @@ +#ifndef LINUX_USER_LOONGARCH_TERMBITS_H +#define LINUX_USER_LOONGARCH_TERMBITS_H + +#define TARGET_NCCS 19 + +struct target_termios { + unsigned int c_iflag; /* input mode flags */ + unsigned int c_oflag; /* output mode flags */ + unsigned int c_cflag; /* control mode flags */ + unsigned int c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[TARGET_NCCS]; /* control characters */ +}; + +/* c_iflag bits */ +#define TARGET_IGNBRK 0000001 +#define TARGET_BRKINT 0000002 +#define TARGET_IGNPAR 0000004 +#define TARGET_PARMRK 0000010 +#define TARGET_INPCK 0000020 +#define TARGET_ISTRIP 0000040 +#define TARGET_INLCR 0000100 +#define TARGET_IGNCR 0000200 +#define TARGET_ICRNL 0000400 +#define TARGET_IUCLC 0001000 +#define TARGET_IXON 0002000 +#define TARGET_IXANY 0004000 +#define TARGET_IXOFF 0010000 +#define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8 0040000 + +/* c_oflag bits */ +#define TARGET_OPOST 0000001 +#define TARGET_OLCUC 0000002 +#define TARGET_ONLCR 0000004 +#define TARGET_OCRNL 0000010 +#define TARGET_ONOCR 0000020 +#define TARGET_ONLRET 0000040 +#define TARGET_OFILL 0000100 +#define TARGET_OFDEL 0000200 +#define TARGET_NLDLY 0000400 +#define TARGET_NL0 0000000 +#define TARGET_NL1 0000400 +#define TARGET_CRDLY 0003000 +#define TARGET_CR0 0000000 +#define TARGET_CR1 0001000 +#define TARGET_CR2 0002000 +#define TARGET_CR3 0003000 +#define TARGET_TABDLY 0014000 +#define TARGET_TAB0 0000000 +#define TARGET_TAB1 0004000 +#define TARGET_TAB2 0010000 +#define TARGET_TAB3 0014000 +#define TARGET_XTABS 0014000 +#define TARGET_BSDLY 0020000 +#define TARGET_BS0 0000000 +#define TARGET_BS1 0020000 +#define TARGET_VTDLY 0040000 +#define TARGET_VT0 0000000 +#define TARGET_VT1 0040000 +#define TARGET_FFDLY 0100000 +#define TARGET_FF0 0000000 +#define TARGET_FF1 0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD 0010017 +#define TARGET_B0 0000000 /* hang up */ +#define TARGET_B50 0000001 +#define TARGET_B75 0000002 +#define TARGET_B110 0000003 +#define TARGET_B134 0000004 +#define TARGET_B150 0000005 +#define TARGET_B200 0000006 +#define TARGET_B300 0000007 +#define TARGET_B600 0000010 +#define TARGET_B1200 0000011 +#define TARGET_B1800 0000012 +#define TARGET_B2400 0000013 +#define TARGET_B4800 0000014 +#define TARGET_B9600 0000015 +#define TARGET_B19200 0000016 +#define TARGET_B38400 0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE 0000060 +#define TARGET_CS5 0000000 +#define TARGET_CS6 0000020 +#define TARGET_CS7 0000040 +#define TARGET_CS8 0000060 +#define TARGET_CSTOPB 0000100 +#define TARGET_CREAD 0000200 +#define TARGET_PARENB 0000400 +#define TARGET_PARODD 0001000 +#define TARGET_HUPCL 0002000 +#define TARGET_CLOCAL 0004000 +#define TARGET_CBAUDEX 0010000 +#define TARGET_B57600 0010001 +#define TARGET_B115200 0010002 +#define TARGET_B230400 0010003 +#define TARGET_B460800 0010004 +#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ +#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ +#define TARGET_CRTSCTS 020000000000 /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG 0000001 +#define TARGET_ICANON 0000002 +#define TARGET_XCASE 0000004 +#define TARGET_ECHO 0000010 +#define TARGET_ECHOE 0000020 +#define TARGET_ECHOK 0000040 +#define TARGET_ECHONL 0000100 +#define TARGET_NOFLSH 0000200 +#define TARGET_TOSTOP 0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE 0004000 +#define TARGET_FLUSHO 0010000 +#define TARGET_PENDIN 0040000 +#define TARGET_IEXTEN 0100000 + +/* c_cc character offsets */ +#define TARGET_VINTR 0 +#define TARGET_VQUIT 1 +#define TARGET_VERASE 2 +#define TARGET_VKILL 3 +#define TARGET_VEOF 4 +#define TARGET_VTIME 5 +#define TARGET_VMIN 6 +#define TARGET_VSWTC 7 +#define TARGET_VSTART 8 +#define TARGET_VSTOP 9 +#define TARGET_VSUSP 10 +#define TARGET_VEOL 11 +#define TARGET_VREPRINT 12 +#define TARGET_VDISCARD 13 +#define TARGET_VWERASE 14 +#define TARGET_VLNEXT 15 +#define TARGET_VEOL2 16 + +/* ioctls */ + +#define TARGET_TCGETS 0x5401 +#define TARGET_TCSETS 0x5402 +#define TARGET_TCSETSW 0x5403 +#define TARGET_TCSETSF 0x5404 +#define TARGET_TCGETA 0x5405 +#define TARGET_TCSETA 0x5406 +#define TARGET_TCSETAW 0x5407 +#define TARGET_TCSETAF 0x5408 +#define TARGET_TCSBRK 0x5409 +#define TARGET_TCXONC 0x540A +#define TARGET_TCFLSH 0x540B + +#define TARGET_TIOCEXCL 0x540C +#define TARGET_TIOCNXCL 0x540D +#define TARGET_TIOCSCTTY 0x540E +#define TARGET_TIOCGPGRP 0x540F +#define TARGET_TIOCSPGRP 0x5410 +#define TARGET_TIOCOUTQ 0x5411 +#define TARGET_TIOCSTI 0x5412 +#define TARGET_TIOCGWINSZ 0x5413 +#define TARGET_TIOCSWINSZ 0x5414 +#define TARGET_TIOCMGET 0x5415 +#define TARGET_TIOCMBIS 0x5416 +#define TARGET_TIOCMBIC 0x5417 +#define TARGET_TIOCMSET 0x5418 +#define TARGET_TIOCGSOFTCAR 0x5419 +#define TARGET_TIOCSSOFTCAR 0x541A +#define TARGET_FIONREAD 0x541B +#define TARGET_TIOCINQ TARGET_FIONREAD +#define TARGET_TIOCLINUX 0x541C +#define TARGET_TIOCCONS 0x541D +#define TARGET_TIOCGSERIAL 0x541E +#define TARGET_TIOCSSERIAL 0x541F +#define TARGET_TIOCPKT 0x5420 +#define TARGET_FIONBIO 0x5421 +#define TARGET_TIOCNOTTY 0x5422 +#define TARGET_TIOCSETD 0x5423 +#define TARGET_TIOCGETD 0x5424 +#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ +#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ +#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int) + /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int) + /* Lock/unlock Pty */ +#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) + /* Safely open the slave */ + +#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */ +#define TARGET_FIOCLEX 0x5451 +#define TARGET_FIOASYNC 0x5452 +#define TARGET_TIOCSERCONFIG 0x5453 +#define TARGET_TIOCSERGWILD 0x5454 +#define TARGET_TIOCSERSWILD 0x5455 +#define TARGET_TIOCGLCKTRMIOS 0x5456 +#define TARGET_TIOCSLCKTRMIOS 0x5457 +#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT 0x545C + /* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT 0x545D + /* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA 0 +#define TARGET_TIOCPKT_FLUSHREAD 1 +#define TARGET_TIOCPKT_FLUSHWRITE 2 +#define TARGET_TIOCPKT_STOP 4 +#define TARGET_TIOCPKT_START 8 +#define TARGET_TIOCPKT_NOSTOP 16 +#define TARGET_TIOCPKT_DOSTOP 32 + +#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +#endif -- Gitee From f85581b4a0bb26c25f405dc8c8891e23a5c75e5f Mon Sep 17 00:00:00 2001 From: lixianglai Date: Fri, 19 Aug 2022 23:51:12 -0400 Subject: [PATCH 06/29] Add disas gdb. Change-Id: If41c0fc8aa128796e342319c7673fab3ccbf3913 Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- .../devices/loongarch64-softmmu/default.mak | 154 + configs/targets/loongarch64-softmmu.mak | 4 + disas/loongarch.c | 2748 +++++++++++++++++ disas/meson.build | 1 + gdb-xml/loongarch-base32.xml | 43 + gdb-xml/loongarch-base64.xml | 43 + gdb-xml/loongarch-fpu32.xml | 52 + gdb-xml/loongarch-fpu64.xml | 57 + 8 files changed, 3102 insertions(+) create mode 100644 configs/devices/loongarch64-softmmu/default.mak create mode 100644 configs/targets/loongarch64-softmmu.mak create mode 100644 disas/loongarch.c create mode 100644 gdb-xml/loongarch-base32.xml create mode 100644 gdb-xml/loongarch-base64.xml create mode 100644 gdb-xml/loongarch-fpu32.xml create mode 100644 gdb-xml/loongarch-fpu64.xml diff --git a/configs/devices/loongarch64-softmmu/default.mak b/configs/devices/loongarch64-softmmu/default.mak new file mode 100644 index 0000000000..fcb7e45dd2 --- /dev/null +++ b/configs/devices/loongarch64-softmmu/default.mak @@ -0,0 +1,154 @@ +# Default configuration for loongarch-softmmu + +CONFIG_PCI=y +CONFIG_ACPI_PCI=y +# For now, CONFIG_IDE_CORE requires ISA, so we enable it here +CONFIG_ISA_BUS=y +CONFIG_VIRTIO_PCI=y + +CONFIG_VGA_PCI=y +CONFIG_ACPI_SMBUS=y +#CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) +CONFIG_VHOST_USER_SCSI=y +#CONFIG_VHOST_USER_BLK=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) +CONFIG_VHOST_USER_BLK=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_CRYPTO=y +CONFIG_VIRTIO_GPU=y +CONFIG_VIRTIO_INPUT=y +CONFIG_VIRTIO_NET=y +CONFIG_VIRTIO_RNG=y +CONFIG_SCSI=y +CONFIG_VIRTIO_SCSI=y +CONFIG_VIRTIO_SERIAL=y + +CONFIG_USB_UHCI=y +CONFIG_USB_OHCI=y +CONFIG_USB_OHCI_PCI=y +CONFIG_USB_XHCI=y +CONFIG_USB_XHCI_NEC=y +CONFIG_NE2000_PCI=y +CONFIG_EEPRO100_PCI=y +CONFIG_PCNET_PCI=y +CONFIG_PCNET_COMMON=y +CONFIG_AC97=y +CONFIG_HDA=y +CONFIG_ES1370=y +CONFIG_SCSI=y +CONFIG_LSI_SCSI_PCI=y +CONFIG_VMW_PVSCSI_SCSI_PCI=y +CONFIG_MEGASAS_SCSI_PCI=y +CONFIG_MPTSAS_SCSI_PCI=y +CONFIG_RTL8139_PCI=y +CONFIG_E1000_PCI=y +CONFIG_IDE_CORE=y +CONFIG_IDE_QDEV=y +CONFIG_IDE_PCI=y +CONFIG_AHCI=y +CONFIG_AHCI_ICH9=y +CONFIG_ESP=y +CONFIG_ESP_PCI=y +CONFIG_SERIAL=y +CONFIG_SERIAL_ISA=y +CONFIG_SERIAL_PCI=y +CONFIG_CAN_BUS=y +CONFIG_CAN_SJA1000=y +CONFIG_CAN_PCI=y +CONFIG_USB_UHCI=y +CONFIG_USB_OHCI=y +CONFIG_USB_XHCI=y +CONFIG_USB_XHCI_NEC=y +CONFIG_NE2000_PCI=y +CONFIG_EEPRO100_PCI=y +CONFIG_PCNET_PCI=y +CONFIG_PCNET_COMMON=y +CONFIG_AC97=y +CONFIG_HDA=y +CONFIG_ES1370=y +CONFIG_SCSI=y +CONFIG_LSI_SCSI_PCI=y +CONFIG_VMW_PVSCSI_SCSI_PCI=y +CONFIG_MEGASAS_SCSI_PCI=y +CONFIG_MPTSAS_SCSI_PCI=y +CONFIG_RTL8139_PCI=y +CONFIG_E1000_PCI=y +CONFIG_IDE_CORE=y +CONFIG_IDE_QDEV=y +CONFIG_IDE_PCI=y +CONFIG_AHCI=y +CONFIG_ESP=y +CONFIG_ESP_PCI=y +CONFIG_SERIAL=y +CONFIG_SERIAL_ISA=y +CONFIG_SERIAL_PCI=y +CONFIG_CAN_BUS=y +CONFIG_CAN_SJA1000=y +CONFIG_CAN_PCI=y + +CONFIG_SPICE=y +CONFIG_QXL=y +CONFIG_ESP=y +CONFIG_SCSI=y +CONFIG_VGA_ISA=y +CONFIG_VGA_ISA_MM=y +CONFIG_VGA_CIRRUS=y +CONFIG_VMWARE_VGA=y +CONFIG_VIRTIO_VGA=y +CONFIG_SERIAL=y +CONFIG_SERIAL_ISA=y +CONFIG_PARALLEL=y +CONFIG_I8254=y +CONFIG_PCSPK=y +CONFIG_PCKBD=y +CONFIG_FDC=y +CONFIG_ACPI=y +CONFIG_ACPI_MEMORY_HOTPLUG=y +CONFIG_ACPI_NVDIMM=y +CONFIG_ACPI_CPU_HOTPLUG=y +CONFIG_APM=y +CONFIG_I8257=y +CONFIG_PIIX4=y +CONFIG_IDE_ISA=y +CONFIG_IDE_PIIX=y +#CONFIG_NE2000_ISA=y +CONFIG_MIPSNET=y +CONFIG_PFLASH_CFI01=y +CONFIG_I8259=y +CONFIG_MC146818RTC=y +CONFIG_ISA_TESTDEV=y +CONFIG_EMPTY_SLOT=y +CONFIG_I2C=y +CONFIG_DIMM=y +CONFIG_MEM_DEVICE=y + +# Arch Specified CONFIG defines +CONFIG_IDE_VIA=y +CONFIG_VT82C686=y +CONFIG_RC4030=y +CONFIG_DP8393X=y +CONFIG_DS1225Y=y +CONFIG_FITLOADER=y +CONFIG_SMBIOS=y + +CONFIG_PCIE_PORT=y +CONFIG_I82801B11=y +CONFIG_XIO3130=y +CONFIG_PCI_EXPRESS=y +CONFIG_MSI_NONBROKEN=y +CONFIG_IOH3420=y +CONFIG_SD=y +CONFIG_SDHCI=y +CONFIG_VIRTFS=y +CONFIG_VIRTIO_9P=y +CONFIG_USB_EHCI=y +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_EHCI_SYSBUS=y +CONFIG_USB_STORAGE_BOT=y +CONFIG_TPM_EMULATOR=y +CONFIG_TPM_TIS=y +CONFIG_PLATFORM_BUS=y +CONFIG_TPM_TIS_SYSBUS=y +CONFIG_ACPI_LOONGARCH=y +CONFIG_LS7A_RTC=y diff --git a/configs/targets/loongarch64-softmmu.mak b/configs/targets/loongarch64-softmmu.mak new file mode 100644 index 0000000000..dc5ab39661 --- /dev/null +++ b/configs/targets/loongarch64-softmmu.mak @@ -0,0 +1,4 @@ +TARGET_ARCH=loongarch64 +TARGET_SUPPORTS_MTTCG=y +TARGET_XML_FILES= gdb-xml/loongarch-base64.xml gdb-xml/loongarch-fpu64.xml + diff --git a/disas/loongarch.c b/disas/loongarch.c new file mode 100644 index 0000000000..14dd131e2e --- /dev/null +++ b/disas/loongarch.c @@ -0,0 +1,2748 @@ +/* + * QEMU Loongarch Disassembler + * + * Copyright (c) 2020-2021. + * Author: Song Gao, gaosong@loongson.cn + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "disas/dis-asm.h" + +#define INSNLEN 4 + +/* types */ + +typedef uint16_t la_opcode; + +/* enums */ + +typedef enum { + la_op_illegal = 0, + la_op_gr2scr = 1, + la_op_scr2gr = 2, + la_op_clo_w = 3, + la_op_clz_w = 4, + la_op_cto_w = 5, + la_op_ctz_w = 6, + la_op_clo_d = 7, + la_op_clz_d = 8, + la_op_cto_d = 9, + la_op_ctz_d = 10, + la_op_revb_2h = 11, + la_op_revb_4h = 12, + la_op_revb_2w = 13, + la_op_revb_d = 14, + la_op_revh_2w = 15, + la_op_revh_d = 16, + la_op_bitrev_4b = 17, + la_op_bitrev_8b = 18, + la_op_bitrev_w = 19, + la_op_bitrev_d = 20, + la_op_ext_w_h = 21, + la_op_ext_w_b = 22, + la_op_rdtime_d = 23, + la_op_cpucfg = 24, + la_op_asrtle_d = 25, + la_op_asrtgt_d = 26, + la_op_alsl_w = 27, + la_op_alsl_wu = 28, + la_op_bytepick_w = 29, + la_op_bytepick_d = 30, + la_op_add_w = 31, + la_op_add_d = 32, + la_op_sub_w = 33, + la_op_sub_d = 34, + la_op_slt = 35, + la_op_sltu = 36, + la_op_maskeqz = 37, + la_op_masknez = 38, + la_op_nor = 39, + la_op_and = 40, + la_op_or = 41, + la_op_xor = 42, + la_op_orn = 43, + la_op_andn = 44, + la_op_sll_w = 45, + la_op_srl_w = 46, + la_op_sra_w = 47, + la_op_sll_d = 48, + la_op_srl_d = 49, + la_op_sra_d = 50, + la_op_rotr_w = 51, + la_op_rotr_d = 52, + la_op_mul_w = 53, + la_op_mulh_w = 54, + la_op_mulh_wu = 55, + la_op_mul_d = 56, + la_op_mulh_d = 57, + la_op_mulh_du = 58, + la_op_mulw_d_w = 59, + la_op_mulw_d_wu = 60, + la_op_div_w = 61, + la_op_mod_w = 62, + la_op_div_wu = 63, + la_op_mod_wu = 64, + la_op_div_d = 65, + la_op_mod_d = 66, + la_op_div_du = 67, + la_op_mod_du = 68, + la_op_crc_w_b_w = 69, + la_op_crc_w_h_w = 70, + la_op_crc_w_w_w = 71, + la_op_crc_w_d_w = 72, + la_op_crcc_w_b_w = 73, + la_op_crcc_w_h_w = 74, + la_op_crcc_w_w_w = 75, + la_op_crcc_w_d_w = 76, + la_op_break = 77, + la_op_dbcl = 78, + la_op_syscall = 79, + la_op_alsl_d = 80, + la_op_slli_w = 81, + la_op_slli_d = 82, + la_op_srli_w = 83, + la_op_srli_d = 84, + la_op_srai_w = 85, + la_op_srai_d = 86, + la_op_rotri_w = 87, + la_op_rotri_d = 88, + la_op_bstrins_w = 89, + la_op_bstrpick_w = 90, + la_op_bstrins_d = 91, + la_op_bstrpick_d = 92, + la_op_fadd_s = 93, + la_op_fadd_d = 94, + la_op_fsub_s = 95, + la_op_fsub_d = 96, + la_op_fmul_s = 97, + la_op_fmul_d = 98, + la_op_fdiv_s = 99, + la_op_fdiv_d = 100, + la_op_fmax_s = 101, + la_op_fmax_d = 102, + la_op_fmin_s = 103, + la_op_fmin_d = 104, + la_op_fmaxa_s = 105, + la_op_fmaxa_d = 106, + la_op_fmina_s = 107, + la_op_fmina_d = 108, + la_op_fscaleb_s = 109, + la_op_fscaleb_d = 110, + la_op_fcopysign_s = 111, + la_op_fcopysign_d = 112, + la_op_fabs_s = 113, + la_op_fabs_d = 114, + la_op_fneg_s = 115, + la_op_fneg_d = 116, + la_op_flogb_s = 117, + la_op_flogb_d = 118, + la_op_fclass_s = 119, + la_op_fclass_d = 120, + la_op_fsqrt_s = 121, + la_op_fsqrt_d = 122, + la_op_frecip_s = 123, + la_op_frecip_d = 124, + la_op_frsqrt_s = 125, + la_op_frsqrt_d = 126, + la_op_fmov_s = 127, + la_op_fmov_d = 128, + la_op_movgr2fr_w = 129, + la_op_movgr2fr_d = 130, + la_op_movgr2frh_w = 131, + la_op_movfr2gr_s = 132, + la_op_movfr2gr_d = 133, + la_op_movfrh2gr_s = 134, + la_op_movgr2fcsr = 135, + la_op_movfcsr2gr = 136, + la_op_movfr2cf = 137, + la_op_movcf2fr = 138, + la_op_movgr2cf = 139, + la_op_movcf2gr = 140, + la_op_fcvt_s_d = 141, + la_op_fcvt_d_s = 142, + + la_op_ftintrm_w_s = 143, + la_op_ftintrm_w_d = 144, + la_op_ftintrm_l_s = 145, + la_op_ftintrm_l_d = 146, + la_op_ftintrp_w_s = 147, + la_op_ftintrp_w_d = 148, + la_op_ftintrp_l_s = 149, + la_op_ftintrp_l_d = 150, + la_op_ftintrz_w_s = 151, + la_op_ftintrz_w_d = 152, + la_op_ftintrz_l_s = 153, + la_op_ftintrz_l_d = 154, + la_op_ftintrne_w_s = 155, + la_op_ftintrne_w_d = 156, + la_op_ftintrne_l_s = 157, + la_op_ftintrne_l_d = 158, + la_op_ftint_w_s = 159, + la_op_ftint_w_d = 160, + la_op_ftint_l_s = 161, + la_op_ftint_l_d = 162, + la_op_ffint_s_w = 163, + la_op_ffint_s_l = 164, + la_op_ffint_d_w = 165, + la_op_ffint_d_l = 166, + la_op_frint_s = 167, + la_op_frint_d = 168, + + la_op_slti = 169, + la_op_sltui = 170, + la_op_addi_w = 171, + la_op_addi_d = 172, + la_op_lu52i_d = 173, + la_op_addi = 174, + la_op_ori = 175, + la_op_xori = 176, + + la_op_csrxchg = 177, + la_op_cacop = 178, + la_op_lddir = 179, + la_op_ldpte = 180, + la_op_iocsrrd_b = 181, + la_op_iocsrrd_h = 182, + la_op_iocsrrd_w = 183, + la_op_iocsrrd_d = 184, + la_op_iocsrwr_b = 185, + la_op_iocsrwr_h = 186, + la_op_iocsrwr_w = 187, + la_op_iocsrwr_d = 188, + la_op_tlbclr = 189, + la_op_tlbflush = 190, + la_op_tlbsrch = 191, + la_op_tlbrd = 192, + la_op_tlbwr = 193, + la_op_tlbfill = 194, + la_op_ertn = 195, + la_op_idle = 196, + la_op_invtlb = 197, + + la_op_fmadd_s = 198, + la_op_fmadd_d = 199, + la_op_fmsub_s = 200, + la_op_fmsub_d = 201, + la_op_fnmadd_s = 202, + la_op_fnmadd_d = 203, + la_op_fnmsub_s = 204, + la_op_fnmsub_d = 205, + la_op_fcmp_cond_s = 206, + la_op_fcmp_cond_d = 207, + la_op_fsel = 208, + la_op_addu16i_d = 209, + la_op_lu12i_w = 210, + la_op_lu32i_d = 211, + la_op_pcaddi = 212, + la_op_pcalau12i = 213, + la_op_pcaddu12i = 214, + la_op_pcaddu18i = 215, + + la_op_ll_w = 216, + la_op_sc_w = 217, + la_op_ll_d = 218, + la_op_sc_d = 219, + la_op_ldptr_w = 220, + la_op_stptr_w = 221, + la_op_ldptr_d = 222, + la_op_stptr_d = 223, + la_op_ld_b = 224, + la_op_ld_h = 225, + la_op_ld_w = 226, + la_op_ld_d = 227, + la_op_st_b = 228, + la_op_st_h = 229, + la_op_st_w = 230, + la_op_st_d = 231, + la_op_ld_bu = 232, + la_op_ld_hu = 233, + la_op_ld_wu = 234, + la_op_preld = 235, + la_op_fld_s = 236, + la_op_fst_s = 237, + la_op_fld_d = 238, + la_op_fst_d = 239, + la_op_ldl_w = 240, + la_op_ldr_w = 241, + la_op_ldl_d = 242, + la_op_ldr_d = 243, + la_op_stl_d = 244, + la_op_str_d = 245, + la_op_ldx_b = 246, + la_op_ldx_h = 247, + la_op_ldx_w = 248, + la_op_ldx_d = 249, + la_op_stx_b = 250, + la_op_stx_h = 251, + la_op_stx_w = 252, + la_op_stx_d = 253, + la_op_ldx_bu = 254, + la_op_ldx_hu = 255, + la_op_ldx_wu = 256, + la_op_fldx_s = 257, + la_op_fldx_d = 258, + la_op_fstx_s = 259, + la_op_fstx_d = 260, + + la_op_amswap_w = 261, + la_op_amswap_d = 262, + la_op_amadd_w = 263, + la_op_amadd_d = 264, + la_op_amand_w = 265, + la_op_amand_d = 266, + la_op_amor_w = 267, + la_op_amor_d = 268, + la_op_amxor_w = 269, + la_op_amxor_d = 270, + la_op_ammax_w = 271, + la_op_ammax_d = 272, + la_op_ammin_w = 273, + la_op_ammin_d = 274, + la_op_ammax_wu = 275, + la_op_ammax_du = 276, + la_op_ammin_wu = 277, + la_op_ammin_du = 278, + la_op_amswap_db_w = 279, + la_op_amswap_db_d = 280, + la_op_amadd_db_w = 281, + la_op_amadd_db_d = 282, + la_op_amand_db_w = 283, + la_op_amand_db_d = 284, + la_op_amor_db_w = 285, + la_op_amor_db_d = 286, + la_op_amxor_db_w = 287, + la_op_amxor_db_d = 288, + la_op_ammax_db_w = 289, + la_op_ammax_db_d = 290, + la_op_ammin_db_w = 291, + la_op_ammin_db_d = 292, + la_op_ammax_db_wu = 293, + la_op_ammax_db_du = 294, + la_op_ammin_db_wu = 295, + la_op_ammin_db_du = 296, + la_op_dbar = 297, + la_op_ibar = 298, + la_op_fldgt_s = 299, + la_op_fldgt_d = 300, + la_op_fldle_s = 301, + la_op_fldle_d = 302, + la_op_fstgt_s = 303, + la_op_fstgt_d = 304, + ls_op_fstle_s = 305, + la_op_fstle_d = 306, + la_op_ldgt_b = 307, + la_op_ldgt_h = 308, + la_op_ldgt_w = 309, + la_op_ldgt_d = 310, + la_op_ldle_b = 311, + la_op_ldle_h = 312, + la_op_ldle_w = 313, + la_op_ldle_d = 314, + la_op_stgt_b = 315, + la_op_stgt_h = 316, + la_op_stgt_w = 317, + la_op_stgt_d = 318, + la_op_stle_b = 319, + la_op_stle_h = 320, + la_op_stle_w = 321, + la_op_stle_d = 322, + la_op_beqz = 323, + la_op_bnez = 324, + la_op_bceqz = 325, + la_op_bcnez = 326, + la_op_jirl = 327, + la_op_b = 328, + la_op_bl = 329, + la_op_beq = 330, + la_op_bne = 331, + la_op_blt = 332, + la_op_bge = 333, + la_op_bltu = 334, + la_op_bgeu = 335, + + /* vz insn */ + la_op_hvcl = 336, + +} la_op; + +typedef enum { + la_codec_illegal, + la_codec_empty, + la_codec_2r, + la_codec_2r_u5, + la_codec_2r_u6, + la_codec_2r_2bw, + la_codec_2r_2bd, + la_codec_3r, + la_codec_3r_rd0, + la_codec_3r_sa2, + la_codec_3r_sa3, + la_codec_4r, + la_codec_r_im20, + la_codec_2r_im16, + la_codec_2r_im14, + la_codec_2r_im12, + la_codec_im5_r_im12, + la_codec_2r_im8, + la_codec_r_sd, + la_codec_r_sj, + la_codec_r_cd, + la_codec_r_cj, + la_codec_r_seq, + la_codec_code, + la_codec_whint, + la_codec_invtlb, + la_codec_r_ofs21, + la_codec_cj_ofs21, + la_codec_ofs26, + la_codec_cond, + la_codec_sel, + +} la_codec; + +#define la_fmt_illegal "nte" +#define la_fmt_empty "nt" +#define la_fmt_sd_rj "ntA,1" +#define la_fmt_rd_sj "nt0,B" +#define la_fmt_rd_rj "nt0,1" +#define la_fmt_rj_rk "nt1,2" +#define la_fmt_rj_seq "nt1,x" +#define la_fmt_rd_si20 "nt0,i(x)" +#define la_fmt_rd_rj_ui5 "nt0,1,C" +#define la_fmt_rd_rj_ui6 "nt0,1.C" +#define la_fmt_rd_rj_level "nt0,1,x" +#define la_fmt_rd_rj_msbw_lsbw "nt0,1,C,D" +#define la_fmt_rd_rj_msbd_lsbd "nt0,1,C,D" +#define la_fmt_rd_rj_si12 "nt0,1,i(x)" +#define la_fmt_hint_rj_si12 "ntE,1,i(x)" +#define la_fmt_rd_rj_csr "nt0,1,x" +#define la_fmt_rd_rj_si14 "nt0,1,i(x)" +#define la_fmt_rd_rj_si16 "nt0,1,i(x)" +#define la_fmt_rd_rj_rk "nt0,1,2" +#define la_fmt_fd_rj_rk "nt3,1,2" +#define la_fmt_rd_rj_rk_sa2 "nt0,1,2,D" +#define la_fmt_rd_rj_rk_sa3 "nt0,1,2,D" +#define la_fmt_fd_rj "nt3,1" +#define la_fmt_rd_fj "nt0,4" +#define la_fmt_fd_fj "nt3,4" +#define la_fmt_fd_fj_si12 "nt3,4,i(x)" +#define la_fmt_fcsrd_rj "ntF,1" +#define la_fmt_rd_fcsrs "nt0,G" +#define la_fmt_cd_fj "ntH,4" +#define la_fmt_fd_cj "nt3,I" +#define la_fmt_fd_fj_fk "nt3,4,5" +#define la_fmt_code "ntJ" +#define la_fmt_whint "ntx" +#define la_fmt_invtlb "ntx,1,2" /* op,rj,rk */ +#define la_fmt_offs26 "nto(X)p" +#define la_fmt_rj_offs21 "nt1,o(X)p" +#define la_fmt_cj_offs21 "ntQ,o(X)p" +#define la_fmt_rd_rj_offs16 "nt0,1,o(X)" +#define la_fmt_rj_rd_offs16 "nt1,0,o(X)p" +#define la_fmt_s_cd_fj_fk "K.stH,4,5" +#define la_fmt_d_cd_fj_fk "K.dtH,4,5" +#define la_fmt_fd_fj_fk_fa "nt3,4,5,6" +#define la_fmt_fd_fj_fk_ca "nt3,4,5,L" +#define la_fmt_cop_rj_si12 "ntM,1,i(x)" + +/* structures */ + +typedef struct { + uint32_t pc; + uint32_t insn; + int32_t imm; + int32_t imm2; + uint16_t op; + uint16_t code; + uint8_t codec; + uint8_t r1; + uint8_t r2; + uint8_t r3; + uint8_t r4; + uint8_t bit; +} la_decode; + +typedef struct { + const char * const name; + const la_codec codec; + const char * const format; +} la_opcode_data; + +/* reg names */ + +const char * const loongarch_r_normal_name[32] = { + "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", + "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", + "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23", + "$r24", "$r25", "$r26", "$r27", "$r28", "$r29", "$r30", "$r31", +}; + +const char * const loongarch_f_normal_name[32] = { + "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", + "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", + "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", + "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", +}; + +const char * const loongarch_cr_normal_name[4] = { + "$scr0", "$scr1", "$scr2", "$scr3", +}; + +const char * const loongarch_c_normal_name[8] = { + "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7", +}; + +/* instruction data */ + +const la_opcode_data opcode_data[] = { + { "illegal", la_codec_illegal, la_fmt_illegal }, + { "gr2scr", la_codec_r_sd, la_fmt_sd_rj }, + { "scr2gr", la_codec_r_sj, la_fmt_rd_sj }, + { "clo.w", la_codec_2r, la_fmt_rd_rj }, + { "clz.w", la_codec_2r, la_fmt_rd_rj }, + { "cto.w", la_codec_2r, la_fmt_rd_rj }, + { "ctz.w", la_codec_2r, la_fmt_rd_rj }, + { "clo.d", la_codec_2r, la_fmt_rd_rj }, + { "clz.d", la_codec_2r, la_fmt_rd_rj }, + { "cto.d", la_codec_2r, la_fmt_rd_rj }, + { "ctz_d", la_codec_2r, la_fmt_rd_rj }, + { "revb.2h", la_codec_2r, la_fmt_rd_rj }, + { "revb.4h", la_codec_2r, la_fmt_rd_rj }, + { "revb.2w", la_codec_2r, la_fmt_rd_rj }, + { "revb.d", la_codec_2r, la_fmt_rd_rj }, + { "revh.2w", la_codec_2r, la_fmt_rd_rj }, + { "revh.d", la_codec_2r, la_fmt_rd_rj }, + { "bitrev.4b", la_codec_2r, la_fmt_rd_rj }, + { "bitrev.8b", la_codec_2r, la_fmt_rd_rj }, + { "bitrev.w", la_codec_2r, la_fmt_rd_rj }, + { "bitrev.d", la_codec_2r, la_fmt_rd_rj }, + { "ext.w.h", la_codec_2r, la_fmt_rd_rj }, + { "ext.w.b", la_codec_2r, la_fmt_rd_rj }, + { "rdtime.d", la_codec_2r, la_fmt_rd_rj }, + { "cpucfg", la_codec_2r, la_fmt_rd_rj }, + { "asrtle.d", la_codec_3r_rd0, la_fmt_rj_rk }, + { "asrtgt.d", la_codec_3r_rd0, la_fmt_rj_rk }, + { "alsl.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, + { "alsl.wu", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, + { "bytepick.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, + { "bytepick.d", la_codec_3r_sa3, la_fmt_rd_rj_rk_sa3 }, + { "add.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "add.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "sub.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "sub.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "slt", la_codec_3r, la_fmt_rd_rj_rk }, + { "sltu", la_codec_3r, la_fmt_rd_rj_rk }, + { "maskeqz", la_codec_3r, la_fmt_rd_rj_rk }, + { "masknez", la_codec_3r, la_fmt_rd_rj_rk }, + { "nor", la_codec_3r, la_fmt_rd_rj_rk }, + { "and", la_codec_3r, la_fmt_rd_rj_rk }, + { "or", la_codec_3r, la_fmt_rd_rj_rk }, + { "xor", la_codec_3r, la_fmt_rd_rj_rk }, + { "orn", la_codec_3r, la_fmt_rd_rj_rk }, + { "andn", la_codec_3r, la_fmt_rd_rj_rk }, + { "sll.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "srl.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "sra.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "sll.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "srl.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "sra.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "rotr.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "rotr.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "mul.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulh.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulh.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "mul.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulh.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulh.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulw.d.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "mulw.d.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "div.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "mod.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "div.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "mod.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "div.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "mod.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "div.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "mod.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "crc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crcc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crcc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crcc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "crcc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "break", la_codec_code, la_fmt_code }, + { "dbcl", la_codec_code, la_fmt_code }, + { "syscall", la_codec_code, la_fmt_code }, + { "alsl.d", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 }, + { "slli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, + { "slli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, + { "srli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, + { "srli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, + { "srai.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, + { "srai.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, + { "rotri.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 }, + { "rotri.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 }, + { "bstrins.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw }, + { "bstrpick.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw }, + { "bstrins.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd }, + { "bstrpick.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd }, + { "fadd.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fadd.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fsub.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fsub.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmul.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmul.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fdiv.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fdiv.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmax.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmax.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmin.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmin.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmaxa.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmaxa.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmina.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fmina.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fscaleb.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fscaleb.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fcopysign.s", la_codec_3r, la_fmt_fd_fj_fk }, + { "fcopysign.d", la_codec_3r, la_fmt_fd_fj_fk }, + { "fabs.s", la_codec_2r, la_fmt_fd_fj }, + { "fabs.d", la_codec_2r, la_fmt_fd_fj }, + { "fneg.s", la_codec_2r, la_fmt_fd_fj }, + { "fneg.d", la_codec_2r, la_fmt_fd_fj }, + { "flogb.s", la_codec_2r, la_fmt_fd_fj }, + { "flogb.d", la_codec_2r, la_fmt_fd_fj }, + { "fclass.s", la_codec_2r, la_fmt_fd_fj }, + { "fclass.d", la_codec_2r, la_fmt_fd_fj }, + { "fsqrt.s", la_codec_2r, la_fmt_fd_fj }, + { "fsqrt.d", la_codec_2r, la_fmt_fd_fj }, + { "frecip.s", la_codec_2r, la_fmt_fd_fj }, + { "frecip.d", la_codec_2r, la_fmt_fd_fj }, + { "frsqrt.s", la_codec_2r, la_fmt_fd_fj }, + { "frsqrt.d", la_codec_2r, la_fmt_fd_fj }, + { "fmov.s", la_codec_2r, la_fmt_fd_fj }, + { "fmov.d", la_codec_2r, la_fmt_fd_fj }, + { "movgr2fr.w", la_codec_2r, la_fmt_fd_rj }, + { "movgr2fr.d", la_codec_2r, la_fmt_fd_rj }, + { "movgr2frh.w", la_codec_2r, la_fmt_fd_rj }, + { "movfr2gr.s", la_codec_2r, la_fmt_rd_fj }, + { "movfr2gr.d", la_codec_2r, la_fmt_rd_fj }, + { "movfrh2gr.s", la_codec_2r, la_fmt_rd_fj }, + { "movgr2fcsr", la_codec_2r, la_fmt_fcsrd_rj }, + { "movfcsr2gr", la_codec_2r, la_fmt_rd_fcsrs }, + { "movfr2cf", la_codec_r_cd, la_fmt_cd_fj }, + { "movcf2fr", la_codec_r_cj, la_fmt_fd_cj }, + { "movgr2cf", la_codec_r_cd, la_fmt_cd_fj }, + { "movcf2gr", la_codec_r_cj, la_fmt_fd_cj }, + { "fcvt.s.d", la_codec_2r, la_fmt_fd_fj }, + { "fcvt.d.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrm.w.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrm.w.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrm.l.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrm.l.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrp.w.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrp.w.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrp.l.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrp.l.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrz.w.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrz.w.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrz.l.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrz.l.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrne.w.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrne.w.d", la_codec_2r, la_fmt_fd_fj }, + { "ftintrne.l.s", la_codec_2r, la_fmt_fd_fj }, + { "ftintrne.l.d", la_codec_2r, la_fmt_fd_fj }, + { "ftint.w.s", la_codec_2r, la_fmt_fd_fj }, + { "ftint.w.d", la_codec_2r, la_fmt_fd_fj }, + { "ftint.l.s", la_codec_2r, la_fmt_fd_fj }, + { "ftint.l.d", la_codec_2r, la_fmt_fd_fj }, + { "ffint.s.w", la_codec_2r, la_fmt_fd_fj }, + { "ffint.s.l", la_codec_2r, la_fmt_fd_fj }, + { "ffint.d.w", la_codec_2r, la_fmt_fd_fj }, + { "ffint.d.l", la_codec_2r, la_fmt_fd_fj }, + { "frint.s", la_codec_2r, la_fmt_fd_fj }, + { "frint.d", la_codec_2r, la_fmt_fd_fj }, + { "slti", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "sltui", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "addi.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "addi.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "lu52i.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "addi", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ori", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "xori", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "csrxchg", la_codec_2r_im14, la_fmt_rd_rj_csr }, + { "cacop", la_codec_im5_r_im12, la_fmt_cop_rj_si12 }, + { "lddir", la_codec_2r_im8, la_fmt_rd_rj_level }, + { "ldpte", la_codec_r_seq, la_fmt_rj_seq }, + { "iocsrrd.b", la_codec_2r, la_fmt_rd_rj }, + { "iocsrrd.h", la_codec_2r, la_fmt_rd_rj }, + { "iocsrrd.w", la_codec_2r, la_fmt_rd_rj }, + { "iocsrrd.d", la_codec_2r, la_fmt_rd_rj }, + { "iocsrwr.b", la_codec_2r, la_fmt_rd_rj }, + { "iocsrwr.h", la_codec_2r, la_fmt_rd_rj }, + { "iocsrwr.w", la_codec_2r, la_fmt_rd_rj }, + { "iocsrwr.d", la_codec_2r, la_fmt_rd_rj }, + { "tlbclr", la_codec_empty, la_fmt_empty }, + { "tlbflush", la_codec_empty, la_fmt_empty }, + { "tlbsrch", la_codec_empty, la_fmt_empty }, + { "tlbrd", la_codec_empty, la_fmt_empty }, + { "tlbwr", la_codec_empty, la_fmt_empty }, + { "tlbfill", la_codec_empty, la_fmt_empty }, + { "ertn", la_codec_empty, la_fmt_empty }, + { "idle", la_codec_whint, la_fmt_whint }, + { "invtlb", la_codec_invtlb, la_fmt_invtlb }, + { "fmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fnmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fnmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fnmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fnmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa }, + { "fcmp.cond.s", la_codec_cond, la_fmt_s_cd_fj_fk }, + { "fcmp.cond.d", la_codec_cond, la_fmt_d_cd_fj_fk }, + { "fsel", la_codec_sel, la_fmt_fd_fj_fk_ca }, + { "addu16i.d", la_codec_2r_im16, la_fmt_rd_rj_si16 }, + { "lu12i.w", la_codec_r_im20, la_fmt_rd_si20 }, + { "lu32i.d", la_codec_r_im20, la_fmt_rd_si20 }, + { "pcaddi", la_codec_r_im20, la_fmt_rd_si20 }, + { "pcalau12i", la_codec_r_im20, la_fmt_rd_si20 }, + { "pcaddu12i", la_codec_r_im20, la_fmt_rd_si20 }, + { "pcaddu18i", la_codec_r_im20, la_fmt_rd_si20 }, + { "ll.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "sc.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "ll.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "sc.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "ldptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "stptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "ldptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "stptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 }, + { "ld.b", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.h", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "st.b", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "st.h", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "st.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "st.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.bu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.hu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ld.wu", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "preld", la_codec_2r_im12, la_fmt_hint_rj_si12 }, + { "fld.s", la_codec_2r_im12, la_fmt_fd_fj_si12 }, + { "fst.s", la_codec_2r_im12, la_fmt_fd_fj_si12 }, + { "fld.d", la_codec_2r_im12, la_fmt_fd_fj_si12 }, + { "fst.d", la_codec_2r_im12, la_fmt_fd_fj_si12 }, + { "ldl.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ldr.w", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ldl.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ldr.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "stl.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "str.d", la_codec_2r_im12, la_fmt_rd_rj_si12 }, + { "ldx.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "stx.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "stx.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "stx.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "stx.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.bu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.hu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldx.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "fldx.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fldx.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstx.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstx.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "amswap.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amswap.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amadd.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amadd.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amand.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amand.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amor.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amor.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amxor.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amxor.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "amswap.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amswap.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amadd.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amadd.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amand.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amand.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amor.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amor.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "amxor.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "amxor.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.db.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.db.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.db.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammax.db.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.db.wu", la_codec_3r, la_fmt_rd_rj_rk }, + { "ammin.db.du", la_codec_3r, la_fmt_rd_rj_rk }, + { "dbar", la_codec_whint, la_fmt_whint }, + { "ibar", la_codec_whint, la_fmt_whint }, + { "fldgt.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fldgt.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "fldle.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fldle.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstgt.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstgt.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstle.s", la_codec_3r, la_fmt_fd_rj_rk }, + { "fstle.d", la_codec_3r, la_fmt_fd_rj_rk }, + { "ldgt.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldgt.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldgt.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldgt.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldle.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldle.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldle.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "ldle.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "stgt.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "stgt.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "stgt.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "stgt.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "stle.b", la_codec_3r, la_fmt_rd_rj_rk }, + { "stle.h", la_codec_3r, la_fmt_rd_rj_rk }, + { "stle.w", la_codec_3r, la_fmt_rd_rj_rk }, + { "stle.d", la_codec_3r, la_fmt_rd_rj_rk }, + { "beqz", la_codec_r_ofs21, la_fmt_rj_offs21 }, + { "bnez", la_codec_r_ofs21, la_fmt_rj_offs21 }, + { "bceqz", la_codec_cj_ofs21, la_fmt_cj_offs21 }, + { "bcnez", la_codec_cj_ofs21, la_fmt_cj_offs21 }, + { "jirl", la_codec_2r_im16, la_fmt_rd_rj_offs16 }, + { "b", la_codec_ofs26, la_fmt_offs26 }, + { "bl", la_codec_ofs26, la_fmt_offs26 }, + { "beq", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + { "bne", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + { "blt", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + { "bge", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + { "bltu", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + { "bgeu", la_codec_2r_im16, la_fmt_rj_rd_offs16 }, + + /* vz insn */ + { "hvcl", la_codec_code, la_fmt_code }, + +}; + + +/* decode opcode */ + +static void decode_insn_opcode(la_decode *dec) +{ + uint32_t insn = dec->insn; + uint16_t op = la_op_illegal; + switch ((insn >> 26) & 0x3f) { + case 0x0: + switch ((insn >> 22) & 0xf) { + case 0x0: + switch ((insn >> 18) & 0xf) { + case 0x0: + switch ((insn >> 15) & 0x7) { + case 0x0: + switch ((insn >> 10) & 0x1f) { + case 0x2: + switch ((insn >> 2) & 0x7) { + case 0x0: + op = la_op_gr2scr; + break; + } + break; + case 0x3: + switch ((insn >> 7) & 0x7) { + case 0x0: + op = la_op_scr2gr; + break; + } + break; + case 0x4: + op = la_op_clo_w; + break; + case 0x5: + op = la_op_clz_w; + break; + case 0x6: + op = la_op_cto_w; + break; + case 0x7: + op = la_op_ctz_w; + break; + case 0x8: + op = la_op_clo_d; + break; + case 0x9: + op = la_op_clz_d; + break; + case 0xa: + op = la_op_cto_d; + break; + case 0xb: + op = la_op_ctz_d; + break; + case 0xc: + op = la_op_revb_2h; + break; + case 0xd: + op = la_op_revb_4h; + break; + case 0xe: + op = la_op_revb_2w; + break; + case 0xf: + op = la_op_revb_d; + break; + case 0x10: + op = la_op_revh_2w; + break; + case 0x11: + op = la_op_revh_d; + break; + case 0x12: + op = la_op_bitrev_4b; + break; + case 0x13: + op = la_op_bitrev_8b; + break; + case 0x14: + op = la_op_bitrev_w; + break; + case 0x15: + op = la_op_bitrev_d; + break; + case 0x16: + op = la_op_ext_w_h; + break; + case 0x17: + op = la_op_ext_w_b; + break; + case 0x1a: + op = la_op_rdtime_d; + break; + case 0x1b: + op = la_op_cpucfg; + break; + } + break; + case 0x2: + switch (insn & 0x0000001f) { + case 0x00000000: + op = la_op_asrtle_d; + break; + } + break; + case 0x3: + switch (insn & 0x0000001f) { + case 0x00000000: + op = la_op_asrtgt_d; + break; + } + break; + } + break; + case 0x1: + switch ((insn >> 17) & 0x1) { + case 0x0: + op = la_op_alsl_w; + break; + case 0x1: + op = la_op_alsl_wu; + break; + } + break; + case 0x2: + switch ((insn >> 17) & 0x1) { + case 0x0: + op = la_op_bytepick_w; + break; + } + break; + case 0x3: + op = la_op_bytepick_d; + break; + case 0x4: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_add_w; + break; + case 0x1: + op = la_op_add_d; + break; + case 0x2: + op = la_op_sub_w; + break; + case 0x3: + op = la_op_sub_d; + break; + case 0x4: + op = la_op_slt; + break; + case 0x5: + op = la_op_sltu; + break; + case 0x6: + op = la_op_maskeqz; + break; + case 0x7: + op = la_op_masknez; + break; + } + break; + case 0x5: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_nor; + break; + case 0x1: + op = la_op_and; + break; + case 0x2: + op = la_op_or; + break; + case 0x3: + op = la_op_xor; + break; + case 0x4: + op = la_op_orn; + break; + case 0x5: + op = la_op_andn; + break; + case 0x6: + op = la_op_sll_w; + break; + case 0x7: + op = la_op_srl_w; + break; + } + break; + case 0x6: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_sra_w; + break; + case 0x1: + op = la_op_sll_d; + break; + case 0x2: + op = la_op_srl_d; + break; + case 0x3: + op = la_op_sra_d; + break; + case 0x6: + op = la_op_rotr_w; + break; + case 0x7: + op = la_op_rotr_d; + break; + } + break; + case 0x7: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_mul_w; + break; + case 0x1: + op = la_op_mulh_w; + break; + case 0x2: + op = la_op_mulh_wu; + break; + case 0x3: + op = la_op_mul_d; + break; + case 0x4: + op = la_op_mulh_d; + break; + case 0x5: + op = la_op_mulh_du; + break; + case 0x6: + op = la_op_mulw_d_w; + break; + case 0x7: + op = la_op_mulw_d_wu; + break; + } + break; + case 0x8: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_div_w; + break; + case 0x1: + op = la_op_mod_w; + break; + case 0x2: + op = la_op_div_wu; + break; + case 0x3: + op = la_op_mod_wu; + break; + case 0x4: + op = la_op_div_d; + break; + case 0x5: + op = la_op_mod_d; + break; + case 0x6: + op = la_op_div_du; + break; + case 0x7: + op = la_op_mod_du; + break; + } + break; + case 0x9: + switch ((insn >> 15) & 0x7) { + case 0x0: + op = la_op_crc_w_b_w; + break; + case 0x1: + op = la_op_crc_w_h_w; + break; + case 0x2: + op = la_op_crc_w_w_w; + break; + case 0x3: + op = la_op_crc_w_d_w; + break; + case 0x4: + op = la_op_crcc_w_b_w; + break; + case 0x5: + op = la_op_crcc_w_h_w; + break; + case 0x6: + op = la_op_crcc_w_w_w; + break; + case 0x7: + op = la_op_crcc_w_d_w; + break; + } + break; + case 0xa: + switch ((insn >> 15) & 0x7) { + case 0x4: + op = la_op_break; + break; + case 0x5: + op = la_op_dbcl; + break; + case 0x6: + op = la_op_syscall; + break; + case 0x7: + op = la_op_hvcl; + break; + } + break; + case 0xb: + switch ((insn >> 17) & 0x1) { + case 0x0: + op = la_op_alsl_d; + break; + } + break; + } + break; + case 0x1: + switch ((insn >> 21) & 0x1) { + case 0x0: + switch ((insn >> 16) & 0x1f) { + case 0x0: + switch ((insn >> 15) & 0x1) { + case 0x1: + op = la_op_slli_w; + break; + } + break; + case 0x1: + op = la_op_slli_d; + break; + case 0x4: + switch ((insn >> 15) & 0x1) { + case 0x1: + op = la_op_srli_w; + break; + } + break; + case 0x5: + op = la_op_srli_d; + break; + case 0x8: + switch ((insn >> 15) & 0x1) { + case 0x1: + op = la_op_srai_w; + break; + } + break; + case 0x9: + op = la_op_srai_d; + break; + case 0xc: + switch ((insn >> 15) & 0x1) { + case 0x1: + op = la_op_rotri_w; + break; + } + break; + case 0xd: + op = la_op_rotri_d; + break; + } + break; + case 0x1: + switch ((insn >> 15) & 0x1) { + case 0x0: + op = la_op_bstrins_w; + break; + case 0x1: + op = la_op_bstrpick_w; + break; + } + break; + } + break; + case 0x2: + op = la_op_bstrins_d; + break; + case 0x3: + op = la_op_bstrpick_d; + break; + case 0x4: + switch ((insn >> 15) & 0x7f) { + case 0x1: + op = la_op_fadd_s; + break; + case 0x2: + op = la_op_fadd_d; + break; + case 0x5: + op = la_op_fsub_s; + break; + case 0x6: + op = la_op_fsub_d; + break; + case 0x9: + op = la_op_fmul_s; + break; + case 0xa: + op = la_op_fmul_d; + break; + case 0xd: + op = la_op_fdiv_s; + break; + case 0xe: + op = la_op_fdiv_d; + break; + case 0x11: + op = la_op_fmax_s; + break; + case 0x12: + op = la_op_fmax_d; + break; + case 0x15: + op = la_op_fmin_s; + break; + case 0x16: + op = la_op_fmin_d; + break; + case 0x19: + op = la_op_fmaxa_s; + break; + case 0x1a: + op = la_op_fmaxa_d; + break; + case 0x1d: + op = la_op_fmina_s; + break; + case 0x1e: + op = la_op_fmina_d; + break; + case 0x21: + op = la_op_fscaleb_s; + break; + case 0x22: + op = la_op_fscaleb_d; + break; + case 0x25: + op = la_op_fcopysign_s; + break; + case 0x26: + op = la_op_fcopysign_d; + break; + case 0x28: + switch ((insn >> 10) & 0x1f) { + case 0x1: + op = la_op_fabs_s; + break; + case 0x2: + op = la_op_fabs_d; + break; + case 0x5: + op = la_op_fneg_s; + break; + case 0x6: + op = la_op_fneg_d; + break; + case 0x9: + op = la_op_flogb_s; + break; + case 0xa: + op = la_op_flogb_d; + break; + case 0xd: + op = la_op_fclass_s; + break; + case 0xe: + op = la_op_fclass_d; + break; + case 0x11: + op = la_op_fsqrt_s; + break; + case 0x12: + op = la_op_fsqrt_d; + break; + case 0x15: + op = la_op_frecip_s; + break; + case 0x16: + op = la_op_frecip_d; + break; + case 0x19: + op = la_op_frsqrt_s; + break; + case 0x1a: + op = la_op_frsqrt_d; + break; + } + break; + case 0x29: + switch ((insn >> 10) & 0x1f) { + case 0x5: + op = la_op_fmov_s; + break; + case 0x6: + op = la_op_fmov_d; + break; + case 0x9: + op = la_op_movgr2fr_w; + break; + case 0xa: + op = la_op_movgr2fr_d; + break; + case 0xb: + op = la_op_movgr2frh_w; + break; + case 0xd: + op = la_op_movfr2gr_s; + break; + case 0xe: + op = la_op_movfr2gr_d; + break; + case 0xf: + op = la_op_movfrh2gr_s; + break; + case 0x10: + op = la_op_movgr2fcsr; + break; + case 0x12: + op = la_op_movfcsr2gr; + break; + case 0x14: + switch ((insn >> 3) & 0x3) { + case 0x0: + op = la_op_movfr2cf; + break; + } + break; + case 0x15: + switch ((insn >> 8) & 0x3) { + case 0x0: + op = la_op_movcf2fr; + break; + } + break; + case 0x16: + switch ((insn >> 3) & 0x3) { + case 0x0: + op = la_op_movgr2cf; + break; + } + break; + case 0x17: + switch ((insn >> 8) & 0x3) { + case 0x0: + op = la_op_movcf2gr; + break; + } + break; + } + break; + case 0x32: + switch ((insn >> 10) & 0x1f) { + case 0x6: + op = la_op_fcvt_s_d; + break; + case 0x9: + op = la_op_fcvt_d_s; + break; + } + break; + case 0x34: + switch ((insn >> 10) & 0x1f) { + case 0x1: + op = la_op_ftintrm_w_s; + break; + case 0x2: + op = la_op_ftintrm_w_d; + break; + case 0x9: + op = la_op_ftintrm_l_s; + break; + case 0xa: + op = la_op_ftintrm_l_d; + break; + case 0x11: + op = la_op_ftintrp_w_s; + break; + case 0x12: + op = la_op_ftintrp_w_d; + break; + case 0x19: + op = la_op_ftintrp_l_s; + break; + case 0x1a: + op = la_op_ftintrp_l_d; + break; + } + break; + case 0x35: + switch ((insn >> 10) & 0x1f) { + case 0x1: + op = la_op_ftintrz_w_s; + break; + case 0x2: + op = la_op_ftintrz_w_d; + break; + case 0x9: + op = la_op_ftintrz_l_s; + break; + case 0xa: + op = la_op_ftintrz_l_d; + break; + case 0x11: + op = la_op_ftintrne_w_s; + break; + case 0x12: + op = la_op_ftintrne_w_d; + break; + case 0x19: + op = la_op_ftintrne_l_s; + break; + case 0x1a: + op = la_op_ftintrne_l_d; + break; + } + break; + case 0x36: + switch ((insn >> 10) & 0x1f) { + case 0x1: + op = la_op_ftint_w_s; + break; + case 0x2: + op = la_op_ftint_w_d; + break; + case 0x9: + op = la_op_ftint_l_s; + break; + case 0xa: + op = la_op_ftint_l_d; + break; + } + break; + case 0x3a: + switch ((insn >> 10) & 0x1f) { + case 0x4: + op = la_op_ffint_s_w; + break; + case 0x6: + op = la_op_ffint_s_l; + break; + case 0x8: + op = la_op_ffint_d_w; + break; + case 0xa: + op = la_op_ffint_d_l; + break; + } + break; + case 0x3c: + switch ((insn >> 10) & 0x1f) { + case 0x11: + op = la_op_frint_s; + break; + case 0x12: + op = la_op_frint_d; + break; + } + break; + } + break; + case 0x8: + op = la_op_slti; + break; + case 0x9: + op = la_op_sltui; + break; + case 0xa: + op = la_op_addi_w; + break; + case 0xb: + op = la_op_addi_d; + break; + case 0xc: + op = la_op_lu52i_d; + break; + case 0xd: + op = la_op_addi; + break; + case 0xe: + op = la_op_ori; + break; + case 0xf: + op = la_op_xori; + break; + } + break; + case 0x1: + switch ((insn >> 24) & 0x3) { + case 0x0: + op = la_op_csrxchg; + break; + case 0x2: + switch ((insn >> 22) & 0x3) { + case 0x0: + op = la_op_cacop; + break; + case 0x1: + switch ((insn >> 18) & 0xf) { + case 0x0: + op = la_op_lddir; + break; + case 0x1: + switch (insn & 0x0000001f) { + case 0x00000000: + op = la_op_ldpte; + break; + } + break; + case 0x2: + switch ((insn >> 15) & 0x7) { + case 0x0: + switch ((insn >> 10) & 0x1f) { + case 0x0: + op = la_op_iocsrrd_b; + break; + case 0x1: + op = la_op_iocsrrd_h; + break; + case 0x2: + op = la_op_iocsrrd_w; + break; + case 0x3: + op = la_op_iocsrrd_d; + break; + case 0x4: + op = la_op_iocsrwr_b; + break; + case 0x5: + op = la_op_iocsrwr_h; + break; + case 0x6: + op = la_op_iocsrwr_w; + break; + case 0x7: + op = la_op_iocsrwr_d; + break; + case 0x8: + switch (insn & 0x000003ff) { + case 0x00000000: + op = la_op_tlbclr; + break; + } + break; + case 0x9: + switch (insn & 0x000003ff) { + case 0x00000000: + op = la_op_tlbflush; + break; + } + break; + case 0xa: + switch (insn & 0x000003ff) { + case 0x00000000: + op = la_op_tlbsrch; + break; + } + break; + case 0xb: + switch (insn & 0x000003ff) { + case 0x00000000: + op = la_op_tlbrd; + break; + } + break; + case 0xc: + switch (insn & 0x000003ff) { + case 0x00000000: + op = la_op_tlbwr; + break; + } + break; + case 0xd: + switch (insn & 0x000003ff) { + case 0x00000000: + op = la_op_tlbfill; + break; + } + break; + case 0xe: + switch (insn & 0x000003ff) { + case 0x00000000: + op = la_op_ertn; + break; + } + break; + } + break; + case 0x1: + op = la_op_idle; + break; + case 0x3: + op = la_op_invtlb; + break; + } + break; + } + break; + } + break; + } + break; + case 0x2: + switch ((insn >> 20) & 0x3f) { + case 0x1: + op = la_op_fmadd_s; + break; + case 0x2: + op = la_op_fmadd_d; + break; + case 0x5: + op = la_op_fmsub_s; + break; + case 0x6: + op = la_op_fmsub_d; + break; + case 0x9: + op = la_op_fnmadd_s; + break; + case 0xa: + op = la_op_fnmadd_d; + break; + case 0xd: + op = la_op_fnmsub_s; + break; + case 0xe: + op = la_op_fnmsub_d; + break; + } + break; + case 0x3: + switch ((insn >> 20) & 0x3f) { + case 0x1: + switch ((insn >> 3) & 0x3) { + case 0x0: + op = la_op_fcmp_cond_s; + break; + } + break; + case 0x2: + switch ((insn >> 3) & 0x3) { + case 0x0: + op = la_op_fcmp_cond_d; + break; + } + break; + case 0x10: + switch ((insn >> 18) & 0x3) { + case 0x0: + op = la_op_fsel; + break; + } + break; + } + break; + case 0x4: + op = la_op_addu16i_d; + break; + case 0x5: + switch ((insn >> 25) & 0x1) { + case 0x0: + op = la_op_lu12i_w; + break; + case 0x1: + op = la_op_lu32i_d; + break; + } + break; + case 0x6: + switch ((insn >> 25) & 0x1) { + case 0x0: + op = la_op_pcaddi; + break; + case 0x1: + op = la_op_pcalau12i; + break; + } + break; + case 0x7: + switch ((insn >> 25) & 0x1) { + case 0x0: + op = la_op_pcaddu12i; + break; + case 0x1: + op = la_op_pcaddu18i; + break; + } + break; + case 0x8: + switch ((insn >> 24) & 0x3) { + case 0x0: + op = la_op_ll_w; + break; + case 0x1: + op = la_op_sc_w; + break; + case 0x2: + op = la_op_ll_d; + break; + case 0x3: + op = la_op_sc_d; + break; + } + break; + case 0x9: + switch ((insn >> 24) & 0x3) { + case 0x0: + op = la_op_ldptr_w; + break; + case 0x1: + op = la_op_stptr_w; + break; + case 0x2: + op = la_op_ldptr_d; + break; + case 0x3: + op = la_op_stptr_d; + break; + } + break; + case 0xa: + switch ((insn >> 22) & 0xf) { + case 0x0: + op = la_op_ld_b; + break; + case 0x1: + op = la_op_ld_h; + break; + case 0x2: + op = la_op_ld_w; + break; + case 0x3: + op = la_op_ld_d; + break; + case 0x4: + op = la_op_st_b; + break; + case 0x5: + op = la_op_st_h; + break; + case 0x6: + op = la_op_st_w; + break; + case 0x7: + op = la_op_st_d; + break; + case 0x8: + op = la_op_ld_bu; + break; + case 0x9: + op = la_op_ld_hu; + break; + case 0xa: + op = la_op_ld_wu; + break; + case 0xb: + op = la_op_preld; + break; + case 0xc: + op = la_op_fld_s; + break; + case 0xd: + op = la_op_fst_s; + break; + case 0xe: + op = la_op_fld_d; + break; + case 0xf: + op = la_op_fst_d; + break; + } + break; + case 0xb: + switch ((insn >> 22) & 0xf) { + case 0x8: + op = la_op_ldl_w; + break; + case 0x9: + op = la_op_ldr_w; + break; + case 0xa: + op = la_op_ldl_d; + break; + case 0xb: + op = la_op_ldr_d; + break; + case 0xe: + op = la_op_stl_d; + break; + case 0xf: + op = la_op_str_d; + break; + } + break; + case 0xe: + switch ((insn >> 15) & 0x7ff) { + case 0x0: + op = la_op_ldx_b; + break; + case 0x8: + op = la_op_ldx_h; + break; + case 0x10: + op = la_op_ldx_w; + break; + case 0x18: + op = la_op_ldx_d; + break; + case 0x20: + op = la_op_stx_b; + break; + case 0x28: + op = la_op_stx_h; + break; + case 0x30: + op = la_op_stx_w; + break; + case 0x38: + op = la_op_stx_d; + break; + case 0x40: + op = la_op_ldx_bu; + break; + case 0x48: + op = la_op_ldx_hu; + break; + case 0x50: + op = la_op_ldx_wu; + break; + case 0x60: + op = la_op_fldx_s; + break; + case 0x68: + op = la_op_fldx_d; + break; + case 0x70: + op = la_op_fstx_s; + break; + case 0x78: + op = la_op_fstx_d; + break; + case 0xc0: + op = la_op_amswap_w; + break; + case 0xc1: + op = la_op_amswap_d; + break; + case 0xc2: + op = la_op_amadd_w; + break; + case 0xc3: + op = la_op_amadd_d; + break; + case 0xc4: + op = la_op_amand_w; + break; + case 0xc5: + op = la_op_amand_d; + break; + case 0xc6: + op = la_op_amor_w; + break; + case 0xc7: + op = la_op_amor_d; + break; + case 0xc8: + op = la_op_amxor_w; + break; + case 0xc9: + op = la_op_amxor_d; + break; + case 0xca: + op = la_op_ammax_w; + break; + case 0xcb: + op = la_op_ammax_d; + break; + case 0xcc: + op = la_op_ammin_w; + break; + case 0xcd: + op = la_op_ammin_d; + break; + case 0xce: + op = la_op_ammax_wu; + break; + case 0xcf: + op = la_op_ammax_du; + break; + case 0xd0: + op = la_op_ammin_wu; + break; + case 0xd1: + op = la_op_ammin_du; + break; + case 0xd2: + op = la_op_amswap_db_w; + break; + case 0xd3: + op = la_op_amswap_db_d; + break; + case 0xd4: + op = la_op_amadd_db_w; + break; + case 0xd5: + op = la_op_amadd_db_d; + break; + case 0xd6: + op = la_op_amand_db_w; + break; + case 0xd7: + op = la_op_amand_db_d; + break; + case 0xd8: + op = la_op_amor_db_w; + break; + case 0xd9: + op = la_op_amor_db_d; + break; + case 0xda: + op = la_op_amxor_db_w; + break; + case 0xdb: + op = la_op_amxor_db_d; + break; + case 0xdc: + op = la_op_ammax_db_w; + break; + case 0xdd: + op = la_op_ammax_db_d; + break; + case 0xde: + op = la_op_ammin_db_w; + break; + case 0xdf: + op = la_op_ammin_db_d; + break; + case 0xe0: + op = la_op_ammax_db_wu; + break; + case 0xe1: + op = la_op_ammax_db_du; + break; + case 0xe2: + op = la_op_ammin_db_wu; + break; + case 0xe3: + op = la_op_ammin_db_du; + break; + case 0xe4: + op = la_op_dbar; + break; + case 0xe5: + op = la_op_ibar; + break; + case 0xe8: + op = la_op_fldgt_s; + break; + case 0xe9: + op = la_op_fldgt_d; + break; + case 0xea: + op = la_op_fldle_s; + break; + case 0xeb: + op = la_op_fldle_d; + break; + case 0xec: + op = la_op_fstgt_s; + break; + case 0xed: + op = la_op_fstgt_d; + break; + case 0xee: + op = ls_op_fstle_s; + break; + case 0xef: + op = la_op_fstle_d; + break; + case 0xf0: + op = la_op_ldgt_b; + break; + case 0xf1: + op = la_op_ldgt_h; + break; + case 0xf2: + op = la_op_ldgt_w; + break; + case 0xf3: + op = la_op_ldgt_d; + break; + case 0xf4: + op = la_op_ldle_b; + break; + case 0xf5: + op = la_op_ldle_h; + break; + case 0xf6: + op = la_op_ldle_w; + break; + case 0xf7: + op = la_op_ldle_d; + break; + case 0xf8: + op = la_op_stgt_b; + break; + case 0xf9: + op = la_op_stgt_h; + break; + case 0xfa: + op = la_op_stgt_w; + break; + case 0xfb: + op = la_op_stgt_d; + break; + case 0xfc: + op = la_op_stle_b; + break; + case 0xfd: + op = la_op_stle_h; + break; + case 0xfe: + op = la_op_stle_w; + break; + case 0xff: + op = la_op_stle_d; + break; + } + break; + case 0x10: + op = la_op_beqz; + break; + case 0x11: + op = la_op_bnez; + break; + case 0x12: + switch ((insn >> 8) & 0x3) { + case 0x0: + op = la_op_bceqz; + break; + case 0x1: + op = la_op_bcnez; + break; + } + break; + case 0x13: + op = la_op_jirl; + break; + case 0x14: + op = la_op_b; + break; + case 0x15: + op = la_op_bl; + break; + case 0x16: + op = la_op_beq; + break; + case 0x17: + op = la_op_bne; + break; + case 0x18: + op = la_op_blt; + break; + case 0x19: + op = la_op_bge; + break; + case 0x1a: + op = la_op_bltu; + break; + case 0x1b: + op = la_op_bgeu; + break; + default: + op = la_op_illegal; + break; + } + dec->op = op; +} + +/* operand extractors */ + +#define IM_5 5 +#define IM_8 8 +#define IM_12 12 +#define IM_14 14 +#define IM_15 15 +#define IM_16 16 +#define IM_20 20 +#define IM_21 21 +#define IM_26 26 + +static uint32_t operand_r1(uint32_t insn) +{ + return insn & 0x1f; +} + +static uint32_t operand_r2(uint32_t insn) +{ + return (insn >> 5) & 0x1f; +} + +static uint32_t operand_r3(uint32_t insn) +{ + return (insn >> 10) & 0x1f; +} + +static uint32_t operand_r4(uint32_t insn) +{ + return (insn >> 15) & 0x1f; +} + +static uint32_t operand_u6(uint32_t insn) +{ + return (insn >> 10) & 0x3f; +} + +static uint32_t operand_bw1(uint32_t insn) +{ + return (insn >> 10) & 0x1f; +} + +static uint32_t operand_bw2(uint32_t insn) +{ + return (insn >> 16) & 0x1f; +} + +static uint32_t operand_bd1(uint32_t insn) +{ + return (insn >> 10) & 0x3f; +} + +static uint32_t operand_bd2(uint32_t insn) +{ + return (insn >> 16) & 0x3f; +} + +static uint32_t operand_sa2(uint32_t insn) +{ + return (insn >> 15) & 0x3; +} + +static uint32_t operand_sa3(uint32_t insn) +{ + return (insn >> 15) & 0x3; +} + +static int32_t operand_im20(uint32_t insn) +{ + int32_t imm = (int32_t)((insn >> 5) & 0xfffff); + return imm > (1 << 19) ? imm - (1 << 20) : imm; +} + +static int32_t operand_im16(uint32_t insn) +{ + int32_t imm = (int32_t)((insn >> 10) & 0xffff); + return imm > (1 << 15) ? imm - (1 << 16) : imm; +} + +static int32_t operand_im14(uint32_t insn) +{ + int32_t imm = (int32_t)((insn >> 10) & 0x3fff); + return imm > (1 << 13) ? imm - (1 << 14) : imm; +} + +static int32_t operand_im12(uint32_t insn) +{ + int32_t imm = (int32_t)((insn >> 10) & 0xfff); + return imm > (1 << 11) ? imm - (1 << 12) : imm; +} + +static int32_t operand_im8(uint32_t insn) +{ + int32_t imm = (int32_t)((insn >> 10) & 0xff); + return imm > (1 << 7) ? imm - (1 << 8) : imm; +} + +static uint32_t operand_sd(uint32_t insn) +{ + return insn & 0x3; +} + +static uint32_t operand_sj(uint32_t insn) +{ + return (insn >> 5) & 0x3; +} + +static uint32_t operand_cd(uint32_t insn) +{ + return insn & 0x7; +} + +static uint32_t operand_cj(uint32_t insn) +{ + return (insn >> 5) & 0x7; +} + +static uint32_t operand_code(uint32_t insn) +{ + return insn & 0x7fff; +} + +static int32_t operand_whint(uint32_t insn) +{ + int32_t imm = (int32_t)(insn & 0x7fff); + return imm > (1 << 14) ? imm - (1 << 15) : imm; +} + +static int32_t operand_invop(uint32_t insn) +{ + int32_t imm = (int32_t)(insn & 0x1f); + return imm > (1 << 4) ? imm - (1 << 5) : imm; +} + +static int32_t operand_ofs21(uint32_t insn) +{ + int32_t imm = (((int32_t)insn & 0x1f) << 16) | + ((insn >> 10) & 0xffff); + return imm > (1 << 20) ? imm - (1 << 21) : imm; +} + +static int32_t operand_ofs26(uint32_t insn) +{ + int32_t imm = (((int32_t)insn & 0x3ff) << 16) | + ((insn >> 10) & 0xffff); + return imm > (1 << 25) ? imm - (1 << 26) : imm; +} + +static uint32_t operand_fcond(uint32_t insn) +{ + return (insn >> 15) & 0x1f; +} + +static uint32_t operand_sel(uint32_t insn) +{ + return (insn >> 15) & 0x7; +} + +/* decode operands */ + +static void decode_insn_operands(la_decode *dec) +{ + uint32_t insn = dec->insn; + dec->codec = opcode_data[dec->op].codec; + switch (dec->codec) { + case la_codec_illegal: + case la_codec_empty: + break; + case la_codec_2r: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + break; + case la_codec_2r_u5: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + break; + case la_codec_2r_u6: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_u6(insn); + break; + case la_codec_2r_2bw: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_bw1(insn); + dec->r4 = operand_bw2(insn); + break; + case la_codec_2r_2bd: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_bd1(insn); + dec->r4 = operand_bd2(insn); + break; + case la_codec_3r: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + break; + case la_codec_3r_rd0: + dec->r1 = 0; + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + break; + case la_codec_3r_sa2: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + dec->r4 = operand_sa2(insn); + break; + case la_codec_3r_sa3: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + dec->r4 = operand_sa3(insn); + break; + case la_codec_4r: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + dec->r4 = operand_r4(insn); + break; + case la_codec_r_im20: + dec->r1 = operand_r1(insn); + dec->imm = operand_im20(insn); + dec->bit = IM_20; + break; + case la_codec_2r_im16: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->imm = operand_im16(insn); + dec->bit = IM_16; + break; + case la_codec_2r_im14: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->imm = operand_im14(insn); + dec->bit = IM_14; + break; + case la_codec_im5_r_im12: + dec->imm2 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->imm = operand_im12(insn); + dec->bit = IM_12; + break; + case la_codec_2r_im12: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->imm = operand_im12(insn); + dec->bit = IM_12; + break; + case la_codec_2r_im8: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->imm = operand_im8(insn); + dec->bit = IM_8; + break; + case la_codec_r_sd: + dec->r1 = operand_sd(insn); + dec->r2 = operand_r2(insn); + break; + case la_codec_r_sj: + dec->r1 = operand_r1(insn); + dec->r2 = operand_sj(insn); + break; + case la_codec_r_cd: + dec->r1 = operand_cd(insn); + dec->r2 = operand_r2(insn); + break; + case la_codec_r_cj: + dec->r1 = operand_r1(insn); + dec->r2 = operand_cj(insn); + break; + case la_codec_r_seq: + dec->r1 = 0; + dec->r2 = operand_r1(insn); + dec->imm = operand_im8(insn); + dec->bit = IM_8; + break; + case la_codec_code: + dec->code = operand_code(insn); + break; + case la_codec_whint: + dec->imm = operand_whint(insn); + dec->bit = IM_15; + break; + case la_codec_invtlb: + dec->imm = operand_invop(insn); + dec->bit = IM_5; + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + break; + case la_codec_r_ofs21: + dec->imm = operand_ofs21(insn); + dec->bit = IM_21; + dec->r2 = operand_r2(insn); + break; + case la_codec_cj_ofs21: + dec->imm = operand_ofs21(insn); + dec->bit = IM_21; + dec->r2 = operand_cj(insn); + break; + case la_codec_ofs26: + dec->imm = operand_ofs26(insn); + dec->bit = IM_26; + break; + case la_codec_cond: + dec->r1 = operand_cd(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + dec->r4 = operand_fcond(insn); + break; + case la_codec_sel: + dec->r1 = operand_r1(insn); + dec->r2 = operand_r2(insn); + dec->r3 = operand_r3(insn); + dec->r4 = operand_sel(insn); + break; + } +} + +/* format instruction */ + +static void append(char *s1, const char *s2, size_t n) +{ + size_t l1 = strlen(s1); + if (n - l1 - 1 > 0) { + strncat(s1, s2, n - l1); + } +} + +static void format_insn(char *buf, size_t buflen, size_t tab, la_decode *dec) +{ + char tmp[16]; + const char *fmt; + + fmt = opcode_data[dec->op].format; + while (*fmt) { + switch (*fmt) { + case 'n': /* name */ + append(buf, opcode_data[dec->op].name, buflen); + break; + case 's': + append(buf, "s", buflen); + break; + case 'd': + append(buf, "d", buflen); + break; + case 'e': /* illegal */ + snprintf(tmp, sizeof(tmp), "%x", dec->insn); + append(buf, tmp, buflen); + break; + case 't': + while (strlen(buf) < tab) { + append(buf, " ", buflen); + } + break; + case '(': + append(buf, "(", buflen); + break; + case ',': + append(buf, ",", buflen); + break; + case '.': + append(buf, ".", buflen); + break; + case ')': + append(buf, ")", buflen); + break; + case '0': /* rd */ + append(buf, loongarch_r_normal_name[dec->r1], buflen); + break; + case '1': /* rj */ + append(buf, loongarch_r_normal_name[dec->r2], buflen); + break; + case '2': /* rk */ + append(buf, loongarch_r_normal_name[dec->r3], buflen); + break; + case '3': /* fd */ + append(buf, loongarch_f_normal_name[dec->r1], buflen); + break; + case '4': /* fj */ + append(buf, loongarch_f_normal_name[dec->r2], buflen); + break; + case '5': /* fk */ + append(buf, loongarch_f_normal_name[dec->r3], buflen); + break; + case '6': /* fa */ + append(buf, loongarch_f_normal_name[dec->r4], buflen); + break; + case 'A': /* sd */ + append(buf, loongarch_cr_normal_name[dec->r1], buflen); + break; + case 'B': /* sj */ + append(buf, loongarch_cr_normal_name[dec->r2], buflen); + break; + case 'C': /* r3 */ + snprintf(tmp, sizeof(tmp), "%x", dec->r3); + append(buf, tmp, buflen); + break; + case 'D': /* r4 */ + snprintf(tmp, sizeof(tmp), "%x", dec->r4); + append(buf, tmp, buflen); + break; + case 'E': /* r1 */ + snprintf(tmp, sizeof(tmp), "%x", dec->r1); + append(buf, tmp, buflen); + break; + case 'F': /* fcsrd */ + append(buf, loongarch_r_normal_name[dec->r1], buflen); + break; + case 'G': /* fcsrs */ + append(buf, loongarch_r_normal_name[dec->r2], buflen); + break; + case 'H': /* cd */ + append(buf, loongarch_c_normal_name[dec->r1], buflen); + break; + case 'I': /* cj */ + append(buf, loongarch_c_normal_name[dec->r2], buflen); + break; + case 'J': /* code */ + snprintf(tmp, sizeof(tmp), "0x%x", dec->code); + append(buf, tmp, buflen); + break; + case 'K': /* cond */ + switch (dec->r4) { + case 0x0: + append(buf, "caf", buflen); + break; + case 0x1: + append(buf, "saf", buflen); + break; + case 0x2: + append(buf, "clt", buflen); + break; + case 0x3: + append(buf, "slt", buflen); + break; + case 0x4: + append(buf, "ceq", buflen); + break; + case 0x5: + append(buf, "seq", buflen); + break; + case 0x6: + append(buf, "cle", buflen); + break; + case 0x7: + append(buf, "sle", buflen); + break; + case 0x8: + append(buf, "cun", buflen); + break; + case 0x9: + append(buf, "sun", buflen); + break; + case 0xA: + append(buf, "cult", buflen); + break; + case 0xB: + append(buf, "sult", buflen); + break; + case 0xC: + append(buf, "cueq", buflen); + break; + case 0xD: + append(buf, "sueq", buflen); + break; + case 0xE: + append(buf, "cule", buflen); + break; + case 0xF: + append(buf, "sule", buflen); + break; + case 0x10: + append(buf, "cne", buflen); + break; + case 0x11: + append(buf, "sne", buflen); + break; + case 0x14: + append(buf, "cor", buflen); + break; + case 0x15: + append(buf, "sor", buflen); + break; + case 0x18: + append(buf, "cune", buflen); + break; + case 0x19: + append(buf, "sune", buflen); + break; + } + break; + case 'L': /* ca */ + append(buf, loongarch_c_normal_name[dec->r4], buflen); + break; + case 'M': /* cop */ + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm2) & 0x1f); + append(buf, tmp, buflen); + break; + case 'i': /* sixx d */ + snprintf(tmp, sizeof(tmp), "%d", dec->imm); + append(buf, tmp, buflen); + break; + case 'o': /* offset */ + snprintf(tmp, sizeof(tmp), "%d", (dec->imm) << 2); + append(buf, tmp, buflen); + break; + case 'x': /* sixx x */ + switch (dec->bit) { + case IM_5: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x1f); + append(buf, tmp, buflen); + break; + case IM_8: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xff); + append(buf, tmp, buflen); + break; + case IM_12: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfff); + append(buf, tmp, buflen); + break; + case IM_14: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x3fff); + append(buf, tmp, buflen); + break; + case IM_15: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x7fff); + append(buf, tmp, buflen); + break; + case IM_16: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xffff); + append(buf, tmp, buflen); + break; + case IM_20: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfffff); + append(buf, tmp, buflen); + break; + default: + snprintf(tmp, sizeof(tmp), "0x%x", dec->imm); + append(buf, tmp, buflen); + break; + } + break; + case 'X': /* offset x*/ + switch (dec->bit) { + case IM_16: + snprintf(tmp, sizeof(tmp), "0x%x", + ((dec->imm) << 2) & 0xffff); + append(buf, tmp, buflen); + break; + case IM_21: + snprintf(tmp, sizeof(tmp), "0x%x", + ((dec->imm) << 2) & 0x1fffff); + append(buf, tmp, buflen); + break; + case IM_26: + snprintf(tmp, sizeof(tmp), "0x%x", + ((dec->imm) << 2) & 0x3ffffff); + append(buf, tmp, buflen); + break; + default: + snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) << 2); + append(buf, tmp, buflen); + break; + } + break; + case 'p': /* pc */ + snprintf(tmp, sizeof(tmp), " # 0x%"PRIx32"", + dec->pc + ((dec->imm) << 2)); + append(buf, tmp, buflen); + break; + default: + break; + } + fmt++; + } +} + + +/* disassemble instruction */ + +static void +disasm_insn(char *buf, size_t buflen, bfd_vma pc, unsigned long int insn) +{ + la_decode dec = { 0 }; + dec.pc = pc; + dec.insn = insn; + decode_insn_opcode(&dec); + decode_insn_operands(&dec); + format_insn(buf, buflen, 16, &dec); +} + +int +print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info) +{ + char buf[128] = { 0 }; + bfd_byte buffer[INSNLEN]; + unsigned long insn; + int status; + + status = (*info->read_memory_func)(memaddr, buffer, INSNLEN, info); + if (status == 0) { + insn = (uint32_t) bfd_getl32(buffer); + (*info->fprintf_func)(info->stream, "%08" PRIx64 " ", insn); + } else { + (*info->memory_error_func)(status, memaddr, info); + return -1; + } + disasm_insn(buf, sizeof(buf), memaddr, insn); + (*info->fprintf_func)(info->stream, "\t%s", buf); + return INSNLEN; +} diff --git a/disas/meson.build b/disas/meson.build index 449f99e1de..06a69d9d72 100644 --- a/disas/meson.build +++ b/disas/meson.build @@ -12,6 +12,7 @@ common_ss.add(when: 'CONFIG_I386_DIS', if_true: files('i386.c')) common_ss.add(when: 'CONFIG_M68K_DIS', if_true: files('m68k.c')) common_ss.add(when: 'CONFIG_MICROBLAZE_DIS', if_true: files('microblaze.c')) common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c')) +common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: files('loongarch.c')) common_ss.add(when: 'CONFIG_NANOMIPS_DIS', if_true: files('nanomips.cpp')) common_ss.add(when: 'CONFIG_NIOS2_DIS', if_true: files('nios2.c')) common_ss.add(when: 'CONFIG_PPC_DIS', if_true: files('ppc.c')) diff --git a/gdb-xml/loongarch-base32.xml b/gdb-xml/loongarch-base32.xml new file mode 100644 index 0000000000..04891e023f --- /dev/null +++ b/gdb-xml/loongarch-base32.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb-xml/loongarch-base64.xml b/gdb-xml/loongarch-base64.xml new file mode 100644 index 0000000000..6308fb6ecb --- /dev/null +++ b/gdb-xml/loongarch-base64.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb-xml/loongarch-fpu32.xml b/gdb-xml/loongarch-fpu32.xml new file mode 100644 index 0000000000..a5b4d80e6c --- /dev/null +++ b/gdb-xml/loongarch-fpu32.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb-xml/loongarch-fpu64.xml b/gdb-xml/loongarch-fpu64.xml new file mode 100644 index 0000000000..74ab55a015 --- /dev/null +++ b/gdb-xml/loongarch-fpu64.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- Gitee From 0dd8d0c8194085424c89d6fa5e7b40983b325f51 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Sat, 20 Aug 2022 02:18:41 -0400 Subject: [PATCH 07/29] Modify kvm cpu vga qapi. Change-Id: I7923af804bdbe6d44d3f521df1859aa081afceba Signed-off-by: lixianglai Signed-off-by: Mao Bibo Signed-off-by: Xianglai Li --- hw/acpi/cpu.c | 11 ++++++ hw/loongarch/iocsr.c | 2 ++ hw/loongarch/larch_3a.c | 18 +++++----- hw/meson.build | 1 + include/disas/dis-asm.h | 1 + include/elf.h | 2 ++ include/hw/loongarch/larch.h | 1 - include/qemu/osdep.h | 3 ++ include/sysemu/arch_init.h | 1 + linux-headers/linux/kvm.h | 23 +++++++++++++ linux-user/elfload.c | 67 ++++++++++++++++++++++++++++++++++++ linux-user/meson.build | 1 + linux-user/qemu.h | 2 +- linux-user/syscall.c | 3 ++ linux-user/syscall_defs.h | 9 ++--- meson.build | 1 + pc-bios/meson.build | 1 + qapi/machine-target.json | 6 ++-- qapi/machine.json | 2 +- qapi/misc-target.json | 1 + 20 files changed, 138 insertions(+), 18 deletions(-) diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c index b20903ea30..cd73fab65b 100644 --- a/hw/acpi/cpu.c +++ b/hw/acpi/cpu.c @@ -371,14 +371,25 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0)); crs = aml_resource_template(); +#ifdef __loongarch__ + aml_append(crs, aml_memory32_fixed(io_base, + ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE)); +#else aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1, ACPI_CPU_HOTPLUG_REG_LEN)); +#endif aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs)); /* declare CPU hotplug MMIO region with related access fields */ +#ifdef __loongarch__ + aml_append(cpu_ctrl_dev, + aml_operation_region("PRST", AML_SYSTEM_MEMORY, aml_int(io_base), + ACPI_CPU_HOTPLUG_REG_LEN)); +#else aml_append(cpu_ctrl_dev, aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base), ACPI_CPU_HOTPLUG_REG_LEN)); +#endif field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS); diff --git a/hw/loongarch/iocsr.c b/hw/loongarch/iocsr.c index 14521c2d5c..60daafd6e1 100644 --- a/hw/loongarch/iocsr.c +++ b/hw/loongarch/iocsr.c @@ -59,6 +59,7 @@ enum { IOCSR_MAX }; +#ifdef CONFIG_KVM static uint32_t iocsr_array[IOCSR_MAX] = { [IOCSR_FEATURES] = LOONGARCH_IOCSR_FEATURES, [IOCSR_VENDOR] = LOONGARCH_IOCSR_VENDOR, @@ -66,6 +67,7 @@ static uint32_t iocsr_array[IOCSR_MAX] = { [IOCSR_NODECNT] = LOONGARCH_IOCSR_NODECNT, [IOCSR_MISC_FUNC] = LOONGARCH_IOCSR_MISC_FUNC, }; +#endif #define TYPE_IOCSR "iocsr" diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c index 3db269274f..3194a822cc 100644 --- a/hw/loongarch/larch_3a.c +++ b/hw/loongarch/larch_3a.c @@ -846,7 +846,7 @@ static void fw_cfg_add_kernel_info(FWCfgState *fw_cfg, if (0 < initrd_size) { if (initrd_size > highram_size) { error_report("initrd size is too big, should below %ld MB", - highram_size / S_1MiB); + highram_size / MiB); /*prevent write io memory address space*/ exit(1); } @@ -1033,7 +1033,9 @@ static void *ls3a_intctl_init(MachineState *machine, CPULOONGARCHState *env[]) SysBusDevice *busdev; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *iomem = NULL; +#ifdef CONFIG_KVM int i; +#endif s = g_malloc0(sizeof(ls3a_intctlstate)); @@ -1214,8 +1216,6 @@ static void loongarch_build_smbios(LoongarchMachineState *lsms) product = "Loongarch-3A5K-7A1000-TCG"; } - host_cpufreq = get_host_cpu_freq(); - smbios_set_defaults("Loongson", product, lsmc->cpu_name, false, true, NULL, NULL, SMBIOS_ENTRY_POINT_30); @@ -1672,15 +1672,15 @@ static void ls3a5k_init(MachineState *args) offset += lowram_size; if (nb_numa_nodes > 0) { - highram_size = numa_info[0].node_mem - S_256MiB; - if (numa_info[0].node_mem > S_1GiB) { - memmap_size = numa_info[0].node_mem - S_1GiB; + highram_size = numa_info[0].node_mem - 256 * MiB; + if (numa_info[0].node_mem > GiB) { + memmap_size = numa_info[0].node_mem - GiB; la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); } } else { - highram_size = ram_size - S_256MiB; - if (ram_size > S_1GiB) { - memmap_size = ram_size - S_1GiB; + highram_size = ram_size - 256 * MiB; + if (ram_size > GiB) { + memmap_size = ram_size - GiB; la_memmap_add_entry(0xc0000000ULL, memmap_size, SYSTEM_RAM); } } diff --git a/hw/meson.build b/hw/meson.build index b3366c888e..f224f8ad28 100644 --- a/hw/meson.build +++ b/hw/meson.build @@ -17,6 +17,7 @@ subdir('intc') subdir('ipack') subdir('ipmi') subdir('isa') +subdir('loongarch') subdir('mem') subdir('misc') subdir('net') diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h index 08e1beec85..95b93f1002 100644 --- a/include/disas/dis-asm.h +++ b/include/disas/dis-asm.h @@ -461,6 +461,7 @@ int print_insn_riscv32 (bfd_vma, disassemble_info*); int print_insn_riscv64 (bfd_vma, disassemble_info*); int print_insn_rx(bfd_vma, disassemble_info *); int print_insn_hexagon(bfd_vma, disassemble_info *); +int print_insn_loongarch (bfd_vma, disassemble_info*); #ifdef CONFIG_CAPSTONE bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size); diff --git a/include/elf.h b/include/elf.h index 4edab8e5a2..c614bfb124 100644 --- a/include/elf.h +++ b/include/elf.h @@ -182,6 +182,8 @@ typedef struct mips_elf_abiflags_v0 { #define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */ +#define EM_LOONGARCH 258 /* Loongarch */ + /* * This is an interim value that we will use until the committee comes * up with a final number. diff --git a/include/hw/loongarch/larch.h b/include/hw/loongarch/larch.h index 0886ed52af..62e2830e27 100644 --- a/include/hw/loongarch/larch.h +++ b/include/hw/loongarch/larch.h @@ -159,5 +159,4 @@ bool loongarch_is_acpi_enabled(LoongarchMachineState *vms); void ls7a_madt_cpu_entry(AcpiDeviceIf *adev, int uid, const CPUArchIdList *apic_ids, GArray *entry, bool force_enabled); void slave_cpu_reset(void *opaque); -extern uint64_t host_cpufreq; #endif diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 60718fc342..903475bb21 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -533,6 +533,9 @@ static inline void qemu_cleanup_generic_vfree(void *p) Valgrind does not support alignments larger than 1 MiB, therefore we need special code which handles running on Valgrind. */ # define QEMU_VMALLOC_ALIGN (512 * 4096) +#elif defined(__linux__) && defined(__loongarch__) + /* Use 32 MiB alignment so transparent hugepages can be used by KVM. */ +# define QEMU_VMALLOC_ALIGN (qemu_real_host_page_size * qemu_real_host_page_size / 8) #elif defined(__linux__) && defined(__s390x__) /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */ # define QEMU_VMALLOC_ALIGN (256 * 4096) diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h index 70c579560a..62d1a4b92d 100644 --- a/include/sysemu/arch_init.h +++ b/include/sysemu/arch_init.h @@ -24,6 +24,7 @@ enum { QEMU_ARCH_RX = (1 << 20), QEMU_ARCH_AVR = (1 << 21), QEMU_ARCH_HEXAGON = (1 << 22), + QEMU_ARCH_LOONGARCH64 = (1 << 23), }; extern const uint32_t arch_type; diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index f06bc701ee..3875127a37 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -2215,6 +2215,29 @@ struct kvm_stats_desc { char name[]; }; +#ifdef __loongarch__ +struct kvm_loongarch_vcpu_state { + __u8 online_vcpus; + __u8 is_migrate; + __u32 cpu_freq; + __u32 count_ctl; + __u64 pending_exceptions; + __u64 pending_exceptions_clr; + __u64 core_ext_ioisr[4]; +}; + +#define KVM_CAP_LOONGARCH_FPU 165 +#define KVM_CAP_LOONGARCH_LSX 166 +#define KVM_CAP_LOONGARCH_VZ 167 +#define KVM_REG_LOONGARCH 0x8000000000000000ULL +#define KVM_LARCH_GET_VCPU_STATE _IOR(KVMIO, 0xc0, struct kvm_loongarch_vcpu_state) +#define KVM_LARCH_SET_VCPU_STATE _IOW(KVMIO, 0xc1, struct kvm_loongarch_vcpu_state) +#define KVM_LARCH_GET_CPUCFG _IOR(KVMIO, 0xc2, struct kvm_cpucfg) +#define KVM_LOONGARCH_GET_IOCSR _IOR(KVMIO, 0xc3, struct kvm_iocsr_entry) +#define KVM_LOONGARCH_SET_IOCSR _IOW(KVMIO, 0xc4, struct kvm_iocsr_entry) +#define KVM_LARCH_SET_CPUCFG _IOR(KVMIO, 0xc5, struct kvm_cpucfg) +#endif + #define KVM_GET_STATS_FD _IO(KVMIO, 0xce) /* Available with KVM_CAP_XSAVE2 */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 767f54c76d..9fb632780a 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1041,6 +1041,73 @@ static uint32_t get_elf_hwcap(void) #endif /* TARGET_MIPS */ +#ifdef TARGET_LOONGARCH64 + +#define ELF_START_MMAP 0x80000000 + +#define ELF_CLASS ELFCLASS64 +#define ELF_ARCH EM_LOONGARCH + +#define elf_check_arch(x) ((x) == EM_LOONGARCH) + +static inline void init_thread(struct target_pt_regs *regs, + struct image_info *infop) +{ + regs->csr_crmd = 2 << 3; + regs->csr_era = infop->entry; + regs->regs[3] = infop->start_stack; +} + +/* See linux kernel: arch/mips/include/asm/elf.h. */ +#define ELF_NREG 45 +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +/* See linux kernel: arch/loongarch/include/uapi/asm/reg.h */ +enum { + TARGET_EF_R0 = 0, + TARGET_EF_R26 = TARGET_EF_R0 + 26, + TARGET_EF_R27 = TARGET_EF_R0 + 27, + TARGET_EF_CSR_ERA = TARGET_EF_R0 + 32, + TARGET_EF_CSR_BADV = TARGET_EF_R0 + 33, + TARGET_EF_CSR_CRMD = TARGET_EF_R0 + 34, + TARGET_EF_CSR_ESTAT = TARGET_EF_R0 + 38 +}; + +/* See linux kernel: arch/loongarch/kernel/process.c:elf_dump_regs. */ +static void elf_core_copy_regs(target_elf_gregset_t *regs, + const CPULOONGARCHState *env) +{ + int i; + + for (i = 0; i < TARGET_EF_R0; i++) { + (*regs)[i] = 0; + } + (*regs)[TARGET_EF_R0] = 0; + + for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) { + (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]); + } + + (*regs)[TARGET_EF_R26] = 0; + (*regs)[TARGET_EF_R27] = 0; + (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->active_tc.PC); + (*regs)[TARGET_EF_CSR_BADV] = tswapreg(env->CSR_BADV); + (*regs)[TARGET_EF_CSR_CRMD] = tswapreg(env->CSR_CRMD); + (*regs)[TARGET_EF_CSR_ESTAT] = tswapreg(env->CSR_ESTAT); +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + +#define ELF_HWCAP get_elf_hwcap() + +static uint32_t get_elf_hwcap(void) +{ + return 0; +} + +#endif /* TARGET_LOONGARCH64 */ + #ifdef TARGET_MICROBLAZE #define ELF_START_MMAP 0x80000000 diff --git a/linux-user/meson.build b/linux-user/meson.build index bf62c13e37..195f9e83ac 100644 --- a/linux-user/meson.build +++ b/linux-user/meson.build @@ -39,3 +39,4 @@ subdir('sh4') subdir('sparc') subdir('x86_64') subdir('xtensa') +subdir('loongarch64') diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 5c713fa8ab..66ddb25d1c 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -61,7 +61,7 @@ struct image_info { /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */ uint32_t note_flags; -#ifdef TARGET_MIPS +#if defined(TARGET_MIPS) || defined(TARGET_LOONGARCH64) int fp_abi; int interp_fp_abi; #endif diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f1cfcc8104..729131ecd0 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1614,6 +1614,9 @@ static abi_long do_pipe(void *cpu_env, abi_ulong pipedes, #elif defined(TARGET_MIPS) ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1]; return host_pipe[0]; +#elif defined(TARGET_LOONGARCH64) + ((CPULOONGARCHState *)cpu_env)->active_tc.gpr[5] = host_pipe[1]; + return host_pipe[0]; #elif defined(TARGET_SH4) ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; return host_pipe[0]; diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 0b13975937..7e2915d53e 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -74,7 +74,7 @@ || defined(TARGET_M68K) || defined(TARGET_CRIS) \ || defined(TARGET_S390X) || defined(TARGET_OPENRISC) \ || defined(TARGET_NIOS2) || defined(TARGET_RISCV) \ - || defined(TARGET_XTENSA) + || defined(TARGET_XTENSA) || defined(TARGET_LOONGARCH64) #define TARGET_IOC_SIZEBITS 14 #define TARGET_IOC_DIRBITS 2 @@ -450,7 +450,7 @@ struct target_dirent64 { #define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */ #define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */ -#ifdef TARGET_MIPS +#if defined(TARGET_MIPS) || defined(TARGET_LOONGARCH64) #define TARGET_NSIG 128 #else #define TARGET_NSIG 64 @@ -2133,7 +2133,7 @@ struct target_stat64 { abi_ulong __unused5; }; -#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV) +#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV) || defined(TARGET_LOONGARCH64) /* These are the asm-generic versions of the stat and stat64 structures */ @@ -2161,7 +2161,7 @@ struct target_stat { unsigned int __unused5; }; -#if !defined(TARGET_RISCV64) +#if !(defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)) #define TARGET_HAS_STRUCT_STAT64 struct target_stat64 { uint64_t st_dev; @@ -2331,6 +2331,7 @@ struct target_statfs64 { }; #elif (defined(TARGET_PPC64) || defined(TARGET_X86_64) || \ defined(TARGET_SPARC64) || defined(TARGET_AARCH64) || \ + defined(TARGET_LOONGARCH64) || \ defined(TARGET_RISCV)) && !defined(TARGET_ABI32) struct target_statfs { abi_long f_type; diff --git a/meson.build b/meson.build index 5f6ba86dbb..fc2dc58f33 100644 --- a/meson.build +++ b/meson.build @@ -1814,6 +1814,7 @@ disassemblers = { 'sh4' : ['CONFIG_SH4_DIS'], 'sparc' : ['CONFIG_SPARC_DIS'], 'xtensa' : ['CONFIG_XTENSA_DIS'], + 'loongarch64' : ['CONFIG_LOONGARCH_DIS'], } if link_language == 'cpp' disassemblers += { diff --git a/pc-bios/meson.build b/pc-bios/meson.build index b40ff3f2bd..a09ca4d03c 100644 --- a/pc-bios/meson.build +++ b/pc-bios/meson.build @@ -83,6 +83,7 @@ blobs = files( 'opensbi-riscv32-generic-fw_dynamic.elf', 'opensbi-riscv64-generic-fw_dynamic.elf', 'npcm7xx_bootrom.bin', + 'loongarch_bios.bin', ) if get_option('install_blobs') diff --git a/qapi/machine-target.json b/qapi/machine-target.json index f5ec4bc172..682dc86b42 100644 --- a/qapi/machine-target.json +++ b/qapi/machine-target.json @@ -324,7 +324,8 @@ 'TARGET_ARM', 'TARGET_I386', 'TARGET_S390X', - 'TARGET_MIPS' ] } } + 'TARGET_MIPS', + 'TARGET_LOONGARCH64' ] } } ## # @query-cpu-definitions: @@ -340,4 +341,5 @@ 'TARGET_ARM', 'TARGET_I386', 'TARGET_S390X', - 'TARGET_MIPS' ] } } + 'TARGET_MIPS', + 'TARGET_LOONGARCH64' ] } } diff --git a/qapi/machine.json b/qapi/machine.json index a9f33d0f27..cd47b8d6bc 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -34,7 +34,7 @@ 'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc', 'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4', 'sh4eb', 'sparc', 'sparc64', 'tricore', - 'x86_64', 'xtensa', 'xtensaeb' ] } + 'x86_64', 'xtensa', 'xtensaeb', 'loongarch64' ] } ## # @CpuS390State: diff --git a/qapi/misc-target.json b/qapi/misc-target.json index ede9052440..2cf4fa418d 100644 --- a/qapi/misc-target.json +++ b/qapi/misc-target.json @@ -33,6 +33,7 @@ 'TARGET_PPC64', 'TARGET_S390X', 'TARGET_SH4', + 'TARGET_LOONGARCH64', 'TARGET_SPARC' ] } } ## -- Gitee From 00a6f164ae17562cd0121320a6fadeb112cc14c5 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 22 Aug 2022 08:22:03 -0400 Subject: [PATCH 08/29] Modify compile script. Change-Id: I8573477d64f5974092001869d7aa9bb093f347e8 Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- meson.build | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index fc2dc58f33..c0fb5788f7 100644 --- a/meson.build +++ b/meson.build @@ -56,7 +56,7 @@ python = import('python').find_installation() supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux'] supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv', 'x86', 'x86_64', - 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64'] + 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64', 'loongarch64'] cpu = host_machine.cpu_family() @@ -77,6 +77,8 @@ elif cpu in ['ppc', 'ppc64'] kvm_targets = ['ppc-softmmu', 'ppc64-softmmu'] elif cpu in ['mips', 'mips64'] kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu'] +elif cpu == 'loongarch64' + kvm_targets = ['loongarch64-softmmu'] else kvm_targets = [] endif -- Gitee From bbcd317f9573e88995b84b39c1fda0e6a7c9da05 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Wed, 24 Aug 2022 22:56:29 -0400 Subject: [PATCH 09/29] Add loongarch64-rh-devices.mak. Change-Id: I375face82c0aa68c053254b879267830d6981756 Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- .../loongarch64-rh-devices.mak | 155 ++ configure | 5 + meson.build | 2 + pc-bios/meson.build | 1 + tcg/loongarch64/tcg-insn-defs.c.inc | 979 +++++++++ tcg/loongarch64/tcg-target-con-set.h | 31 + tcg/loongarch64/tcg-target-con-str.h | 28 + tcg/loongarch64/tcg-target.c.inc | 1744 +++++++++++++++++ tcg/loongarch64/tcg-target.h | 178 ++ 9 files changed, 3123 insertions(+) create mode 100644 configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak create mode 100644 tcg/loongarch64/tcg-insn-defs.c.inc create mode 100644 tcg/loongarch64/tcg-target-con-set.h create mode 100644 tcg/loongarch64/tcg-target-con-str.h create mode 100644 tcg/loongarch64/tcg-target.c.inc create mode 100644 tcg/loongarch64/tcg-target.h diff --git a/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak b/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak new file mode 100644 index 0000000000..e7b5bdc8e9 --- /dev/null +++ b/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak @@ -0,0 +1,155 @@ + +include ../rh-virtio.mak +# Default configuration for loongarch-softmmu + +CONFIG_PCI=y +CONFIG_ACPI_PCI=y +# For now, CONFIG_IDE_CORE requires ISA, so we enable it here +CONFIG_ISA_BUS=y +CONFIG_VIRTIO_PCI=y + +CONFIG_VGA_PCI=y +CONFIG_ACPI_SMBUS=y +#CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) +CONFIG_VHOST_USER_SCSI=y +#CONFIG_VHOST_USER_BLK=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) +CONFIG_VHOST_USER_BLK=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_CRYPTO=y +CONFIG_VIRTIO_GPU=y +CONFIG_VIRTIO_INPUT=y +CONFIG_VIRTIO_NET=y +CONFIG_VIRTIO_RNG=y +CONFIG_SCSI=y +CONFIG_VIRTIO_SCSI=y +CONFIG_VIRTIO_SERIAL=y + +CONFIG_USB_UHCI=y +CONFIG_USB_OHCI=y +CONFIG_USB_OHCI_PCI=y +CONFIG_USB_XHCI=y +CONFIG_USB_XHCI_NEC=y +CONFIG_NE2000_PCI=y +CONFIG_EEPRO100_PCI=y +CONFIG_PCNET_PCI=y +CONFIG_PCNET_COMMON=y +CONFIG_AC97=y +CONFIG_HDA=y +CONFIG_ES1370=y +CONFIG_SCSI=y +CONFIG_LSI_SCSI_PCI=y +CONFIG_VMW_PVSCSI_SCSI_PCI=y +CONFIG_MEGASAS_SCSI_PCI=y +CONFIG_MPTSAS_SCSI_PCI=y +CONFIG_RTL8139_PCI=y +CONFIG_E1000_PCI=y +CONFIG_IDE_CORE=y +CONFIG_IDE_QDEV=y +CONFIG_IDE_PCI=y +CONFIG_AHCI=y +CONFIG_AHCI_ICH9=y +CONFIG_ESP=y +CONFIG_ESP_PCI=y +CONFIG_SERIAL=y +CONFIG_SERIAL_ISA=y +CONFIG_SERIAL_PCI=y +CONFIG_CAN_BUS=y +CONFIG_CAN_SJA1000=y +CONFIG_CAN_PCI=y +CONFIG_USB_UHCI=y +CONFIG_USB_OHCI=y +CONFIG_USB_XHCI=y +CONFIG_USB_XHCI_NEC=y +CONFIG_NE2000_PCI=y +CONFIG_EEPRO100_PCI=y +CONFIG_PCNET_PCI=y +CONFIG_PCNET_COMMON=y +CONFIG_AC97=y +CONFIG_HDA=y +CONFIG_ES1370=y +CONFIG_SCSI=y +CONFIG_LSI_SCSI_PCI=y +CONFIG_VMW_PVSCSI_SCSI_PCI=y +CONFIG_MEGASAS_SCSI_PCI=y +CONFIG_MPTSAS_SCSI_PCI=y +CONFIG_RTL8139_PCI=y +CONFIG_E1000_PCI=y +CONFIG_IDE_CORE=y +CONFIG_IDE_QDEV=y +CONFIG_IDE_PCI=y +CONFIG_AHCI=y +CONFIG_ESP=y +CONFIG_ESP_PCI=y +CONFIG_SERIAL=y +CONFIG_SERIAL_ISA=y +CONFIG_SERIAL_PCI=y +CONFIG_CAN_BUS=y +CONFIG_CAN_SJA1000=y +CONFIG_CAN_PCI=y + +CONFIG_SPICE=y +CONFIG_QXL=y +CONFIG_ESP=y +CONFIG_SCSI=y +CONFIG_VGA_ISA=y +CONFIG_VGA_ISA_MM=y +CONFIG_VGA_CIRRUS=y +CONFIG_VMWARE_VGA=y +CONFIG_VIRTIO_VGA=y +CONFIG_SERIAL_ISA=y +CONFIG_PARALLEL=y +CONFIG_I8254=y +CONFIG_PCSPK=y +CONFIG_PCKBD=y +CONFIG_FDC=y +CONFIG_ACPI=y +CONFIG_ACPI_MEMORY_HOTPLUG=y +CONFIG_ACPI_NVDIMM=y +CONFIG_ACPI_CPU_HOTPLUG=y +CONFIG_APM=y +CONFIG_I8257=y +CONFIG_PIIX4=y +CONFIG_IDE_ISA=y +CONFIG_IDE_PIIX=y +#CONFIG_NE2000_ISA=y +CONFIG_MIPSNET=y +CONFIG_PFLASH_CFI01=y +CONFIG_I8259=y +CONFIG_MC146818RTC=y +CONFIG_ISA_TESTDEV=y +CONFIG_EMPTY_SLOT=y +CONFIG_I2C=y +CONFIG_DIMM=y +CONFIG_MEM_DEVICE=y + +# Arch Specified CONFIG defines +CONFIG_IDE_VIA=y +CONFIG_VT82C686=y +CONFIG_RC4030=y +CONFIG_DP8393X=y +CONFIG_DS1225Y=y +CONFIG_FITLOADER=y +CONFIG_SMBIOS=y + +CONFIG_PCIE_PORT=y +CONFIG_I82801B11=y +CONFIG_XIO3130=y +CONFIG_PCI_EXPRESS=y +CONFIG_MSI_NONBROKEN=y +CONFIG_IOH3420=y +CONFIG_SD=y +CONFIG_SDHCI=y +CONFIG_VIRTFS=y +CONFIG_VIRTIO_9P=y +CONFIG_USB_EHCI=y +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_EHCI_SYSBUS=y +CONFIG_USB_STORAGE_BOT=y +CONFIG_TPM_EMULATOR=y +CONFIG_TPM_TIS=y +CONFIG_PLATFORM_BUS=y +CONFIG_TPM_TIS_SYSBUS=y +CONFIG_ACPI_LOONGARCH=y +CONFIG_LS7A_RTC=y diff --git a/configure b/configure index 48c21775f3..1f932f7eeb 100755 --- a/configure +++ b/configure @@ -581,6 +581,8 @@ elif check_define __arm__ ; then cpu="arm" elif check_define __aarch64__ ; then cpu="aarch64" +elif check_define __loongarch__ ; then + cpu="loongarch64" else cpu=$(uname -m) fi @@ -606,6 +608,9 @@ case "$cpu" in aarch64) cpu="aarch64" ;; + loongarch64) + cpu="loongarch64" + ;; mips*) cpu="mips" ;; diff --git a/meson.build b/meson.build index c0fb5788f7..c5fdb78569 100644 --- a/meson.build +++ b/meson.build @@ -361,6 +361,8 @@ if not get_option('tcg').disabled() tcg_arch = 'i386' elif config_host['ARCH'] == 'ppc64' tcg_arch = 'ppc' + elif config_host['ARCH'] == 'loongarch64' + tcg_arch = 'loongarch64' endif add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch, language: ['c', 'cpp', 'objc']) diff --git a/pc-bios/meson.build b/pc-bios/meson.build index a09ca4d03c..60009bd89e 100644 --- a/pc-bios/meson.build +++ b/pc-bios/meson.build @@ -84,6 +84,7 @@ blobs = files( 'opensbi-riscv64-generic-fw_dynamic.elf', 'npcm7xx_bootrom.bin', 'loongarch_bios.bin', + 'loongarch_vars.bin', ) if get_option('install_blobs') diff --git a/tcg/loongarch64/tcg-insn-defs.c.inc b/tcg/loongarch64/tcg-insn-defs.c.inc new file mode 100644 index 0000000000..d162571856 --- /dev/null +++ b/tcg/loongarch64/tcg-insn-defs.c.inc @@ -0,0 +1,979 @@ +/* SPDX-License-Identifier: MIT */ +/* + * LoongArch instruction formats, opcodes, and encoders for TCG use. + * + * This file is auto-generated by genqemutcgdefs from + * https://github.com/loongson-community/loongarch-opcodes, + * from commit 961f0c60f5b63e574d785995600c71ad5413fdc4. + * DO NOT EDIT. + */ + +typedef enum { + OPC_CLZ_W = 0x00001400, + OPC_CTZ_W = 0x00001c00, + OPC_CLZ_D = 0x00002400, + OPC_CTZ_D = 0x00002c00, + OPC_REVB_2H = 0x00003000, + OPC_REVB_2W = 0x00003800, + OPC_REVB_D = 0x00003c00, + OPC_SEXT_H = 0x00005800, + OPC_SEXT_B = 0x00005c00, + OPC_ADD_W = 0x00100000, + OPC_ADD_D = 0x00108000, + OPC_SUB_W = 0x00110000, + OPC_SUB_D = 0x00118000, + OPC_SLT = 0x00120000, + OPC_SLTU = 0x00128000, + OPC_MASKEQZ = 0x00130000, + OPC_MASKNEZ = 0x00138000, + OPC_NOR = 0x00140000, + OPC_AND = 0x00148000, + OPC_OR = 0x00150000, + OPC_XOR = 0x00158000, + OPC_ORN = 0x00160000, + OPC_ANDN = 0x00168000, + OPC_SLL_W = 0x00170000, + OPC_SRL_W = 0x00178000, + OPC_SRA_W = 0x00180000, + OPC_SLL_D = 0x00188000, + OPC_SRL_D = 0x00190000, + OPC_SRA_D = 0x00198000, + OPC_ROTR_W = 0x001b0000, + OPC_ROTR_D = 0x001b8000, + OPC_MUL_W = 0x001c0000, + OPC_MULH_W = 0x001c8000, + OPC_MULH_WU = 0x001d0000, + OPC_MUL_D = 0x001d8000, + OPC_MULH_D = 0x001e0000, + OPC_MULH_DU = 0x001e8000, + OPC_DIV_W = 0x00200000, + OPC_MOD_W = 0x00208000, + OPC_DIV_WU = 0x00210000, + OPC_MOD_WU = 0x00218000, + OPC_DIV_D = 0x00220000, + OPC_MOD_D = 0x00228000, + OPC_DIV_DU = 0x00230000, + OPC_MOD_DU = 0x00238000, + OPC_SLLI_W = 0x00408000, + OPC_SLLI_D = 0x00410000, + OPC_SRLI_W = 0x00448000, + OPC_SRLI_D = 0x00450000, + OPC_SRAI_W = 0x00488000, + OPC_SRAI_D = 0x00490000, + OPC_ROTRI_W = 0x004c8000, + OPC_ROTRI_D = 0x004d0000, + OPC_BSTRINS_W = 0x00600000, + OPC_BSTRPICK_W = 0x00608000, + OPC_BSTRINS_D = 0x00800000, + OPC_BSTRPICK_D = 0x00c00000, + OPC_SLTI = 0x02000000, + OPC_SLTUI = 0x02400000, + OPC_ADDI_W = 0x02800000, + OPC_ADDI_D = 0x02c00000, + OPC_CU52I_D = 0x03000000, + OPC_ANDI = 0x03400000, + OPC_ORI = 0x03800000, + OPC_XORI = 0x03c00000, + OPC_LU12I_W = 0x14000000, + OPC_CU32I_D = 0x16000000, + OPC_PCADDU2I = 0x18000000, + OPC_PCALAU12I = 0x1a000000, + OPC_PCADDU12I = 0x1c000000, + OPC_PCADDU18I = 0x1e000000, + OPC_LD_B = 0x28000000, + OPC_LD_H = 0x28400000, + OPC_LD_W = 0x28800000, + OPC_LD_D = 0x28c00000, + OPC_ST_B = 0x29000000, + OPC_ST_H = 0x29400000, + OPC_ST_W = 0x29800000, + OPC_ST_D = 0x29c00000, + OPC_LD_BU = 0x2a000000, + OPC_LD_HU = 0x2a400000, + OPC_LD_WU = 0x2a800000, + OPC_LDX_B = 0x38000000, + OPC_LDX_H = 0x38040000, + OPC_LDX_W = 0x38080000, + OPC_LDX_D = 0x380c0000, + OPC_STX_B = 0x38100000, + OPC_STX_H = 0x38140000, + OPC_STX_W = 0x38180000, + OPC_STX_D = 0x381c0000, + OPC_LDX_BU = 0x38200000, + OPC_LDX_HU = 0x38240000, + OPC_LDX_WU = 0x38280000, + OPC_DBAR = 0x38720000, + OPC_JIRL = 0x4c000000, + OPC_B = 0x50000000, + OPC_BL = 0x54000000, + OPC_BEQ = 0x58000000, + OPC_BNE = 0x5c000000, + OPC_BGT = 0x60000000, + OPC_BLE = 0x64000000, + OPC_BGTU = 0x68000000, + OPC_BLEU = 0x6c000000, +} LoongArchInsn; + +static int32_t __attribute__((unused)) +encode_d_slot(LoongArchInsn opc, uint32_t d) +{ + return opc | d; +} + +static int32_t __attribute__((unused)) +encode_dj_slots(LoongArchInsn opc, uint32_t d, uint32_t j) +{ + return opc | d | j << 5; +} + +static int32_t __attribute__((unused)) +encode_djk_slots(LoongArchInsn opc, uint32_t d, uint32_t j, uint32_t k) +{ + return opc | d | j << 5 | k << 10; +} + +static int32_t __attribute__((unused)) +encode_djkm_slots(LoongArchInsn opc, uint32_t d, uint32_t j, uint32_t k, + uint32_t m) +{ + return opc | d | j << 5 | k << 10 | m << 16; +} + +static int32_t __attribute__((unused)) +encode_dk_slots(LoongArchInsn opc, uint32_t d, uint32_t k) +{ + return opc | d | k << 10; +} + +static int32_t __attribute__((unused)) +encode_dj_insn(LoongArchInsn opc, TCGReg d, TCGReg j) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + return encode_dj_slots(opc, d, j); +} + +static int32_t __attribute__((unused)) +encode_djk_insn(LoongArchInsn opc, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(k >= 0 && k <= 0x1f); + return encode_djk_slots(opc, d, j, k); +} + +static int32_t __attribute__((unused)) +encode_djsk12_insn(LoongArchInsn opc, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(sk12 >= -0x800 && sk12 <= 0x7ff); + return encode_djk_slots(opc, d, j, sk12 & 0xfff); +} + +static int32_t __attribute__((unused)) +encode_djsk16_insn(LoongArchInsn opc, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(sk16 >= -0x8000 && sk16 <= 0x7fff); + return encode_djk_slots(opc, d, j, sk16 & 0xffff); +} + +static int32_t __attribute__((unused)) +encode_djuk12_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk12) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(uk12 <= 0xfff); + return encode_djk_slots(opc, d, j, uk12); +} + +static int32_t __attribute__((unused)) +encode_djuk5_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk5) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(uk5 <= 0x1f); + return encode_djk_slots(opc, d, j, uk5); +} + +static int32_t __attribute__((unused)) +encode_djuk5um5_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk5, + uint32_t um5) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(uk5 <= 0x1f); + tcg_debug_assert(um5 <= 0x1f); + return encode_djkm_slots(opc, d, j, uk5, um5); +} + +static int32_t __attribute__((unused)) +encode_djuk6_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk6) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(uk6 <= 0x3f); + return encode_djk_slots(opc, d, j, uk6); +} + +static int32_t __attribute__((unused)) +encode_djuk6um6_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk6, + uint32_t um6) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(uk6 <= 0x3f); + tcg_debug_assert(um6 <= 0x3f); + return encode_djkm_slots(opc, d, j, uk6, um6); +} + +static int32_t __attribute__((unused)) +encode_dsj20_insn(LoongArchInsn opc, TCGReg d, int32_t sj20) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(sj20 >= -0x80000 && sj20 <= 0x7ffff); + return encode_dj_slots(opc, d, sj20 & 0xfffff); +} + +static int32_t __attribute__((unused)) +encode_sd10k16_insn(LoongArchInsn opc, int32_t sd10k16) +{ + tcg_debug_assert(sd10k16 >= -0x2000000 && sd10k16 <= 0x1ffffff); + return encode_dk_slots(opc, (sd10k16 >> 16) & 0x3ff, sd10k16 & 0xffff); +} + +static int32_t __attribute__((unused)) +encode_ud15_insn(LoongArchInsn opc, uint32_t ud15) +{ + tcg_debug_assert(ud15 <= 0x7fff); + return encode_d_slot(opc, ud15); +} + +/* Emits the `clz.w d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_clz_w(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_CLZ_W, d, j)); +} + +/* Emits the `ctz.w d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ctz_w(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_CTZ_W, d, j)); +} + +/* Emits the `clz.d d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_clz_d(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_CLZ_D, d, j)); +} + +/* Emits the `ctz.d d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ctz_d(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_CTZ_D, d, j)); +} + +/* Emits the `revb.2h d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_revb_2h(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_REVB_2H, d, j)); +} + +/* Emits the `revb.2w d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_revb_2w(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_REVB_2W, d, j)); +} + +/* Emits the `revb.d d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_revb_d(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_REVB_D, d, j)); +} + +/* Emits the `sext.h d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sext_h(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_SEXT_H, d, j)); +} + +/* Emits the `sext.b d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sext_b(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_SEXT_B, d, j)); +} + +/* Emits the `add.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_add_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ADD_W, d, j, k)); +} + +/* Emits the `add.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_add_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ADD_D, d, j, k)); +} + +/* Emits the `sub.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sub_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SUB_W, d, j, k)); +} + +/* Emits the `sub.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sub_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SUB_D, d, j, k)); +} + +/* Emits the `slt d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_slt(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SLT, d, j, k)); +} + +/* Emits the `sltu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sltu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SLTU, d, j, k)); +} + +/* Emits the `maskeqz d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_maskeqz(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MASKEQZ, d, j, k)); +} + +/* Emits the `masknez d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_masknez(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MASKNEZ, d, j, k)); +} + +/* Emits the `nor d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_nor(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_NOR, d, j, k)); +} + +/* Emits the `and d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_and(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_AND, d, j, k)); +} + +/* Emits the `or d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_or(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_OR, d, j, k)); +} + +/* Emits the `xor d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_xor(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_XOR, d, j, k)); +} + +/* Emits the `orn d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_orn(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ORN, d, j, k)); +} + +/* Emits the `andn d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_andn(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ANDN, d, j, k)); +} + +/* Emits the `sll.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sll_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SLL_W, d, j, k)); +} + +/* Emits the `srl.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srl_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SRL_W, d, j, k)); +} + +/* Emits the `sra.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sra_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SRA_W, d, j, k)); +} + +/* Emits the `sll.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sll_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SLL_D, d, j, k)); +} + +/* Emits the `srl.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srl_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SRL_D, d, j, k)); +} + +/* Emits the `sra.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sra_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SRA_D, d, j, k)); +} + +/* Emits the `rotr.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_rotr_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ROTR_W, d, j, k)); +} + +/* Emits the `rotr.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_rotr_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ROTR_D, d, j, k)); +} + +/* Emits the `mul.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mul_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MUL_W, d, j, k)); +} + +/* Emits the `mulh.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mulh_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MULH_W, d, j, k)); +} + +/* Emits the `mulh.wu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mulh_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MULH_WU, d, j, k)); +} + +/* Emits the `mul.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mul_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MUL_D, d, j, k)); +} + +/* Emits the `mulh.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mulh_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MULH_D, d, j, k)); +} + +/* Emits the `mulh.du d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mulh_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MULH_DU, d, j, k)); +} + +/* Emits the `div.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_div_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_DIV_W, d, j, k)); +} + +/* Emits the `mod.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mod_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MOD_W, d, j, k)); +} + +/* Emits the `div.wu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_div_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_DIV_WU, d, j, k)); +} + +/* Emits the `mod.wu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mod_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MOD_WU, d, j, k)); +} + +/* Emits the `div.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_div_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_DIV_D, d, j, k)); +} + +/* Emits the `mod.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mod_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MOD_D, d, j, k)); +} + +/* Emits the `div.du d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_div_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_DIV_DU, d, j, k)); +} + +/* Emits the `mod.du d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mod_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MOD_DU, d, j, k)); +} + +/* Emits the `slli.w d, j, uk5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_slli_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) +{ + tcg_out32(s, encode_djuk5_insn(OPC_SLLI_W, d, j, uk5)); +} + +/* Emits the `slli.d d, j, uk6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_slli_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) +{ + tcg_out32(s, encode_djuk6_insn(OPC_SLLI_D, d, j, uk6)); +} + +/* Emits the `srli.w d, j, uk5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srli_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) +{ + tcg_out32(s, encode_djuk5_insn(OPC_SRLI_W, d, j, uk5)); +} + +/* Emits the `srli.d d, j, uk6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srli_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) +{ + tcg_out32(s, encode_djuk6_insn(OPC_SRLI_D, d, j, uk6)); +} + +/* Emits the `srai.w d, j, uk5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srai_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) +{ + tcg_out32(s, encode_djuk5_insn(OPC_SRAI_W, d, j, uk5)); +} + +/* Emits the `srai.d d, j, uk6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srai_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) +{ + tcg_out32(s, encode_djuk6_insn(OPC_SRAI_D, d, j, uk6)); +} + +/* Emits the `rotri.w d, j, uk5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_rotri_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) +{ + tcg_out32(s, encode_djuk5_insn(OPC_ROTRI_W, d, j, uk5)); +} + +/* Emits the `rotri.d d, j, uk6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_rotri_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) +{ + tcg_out32(s, encode_djuk6_insn(OPC_ROTRI_D, d, j, uk6)); +} + +/* Emits the `bstrins.w d, j, uk5, um5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bstrins_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5, + uint32_t um5) +{ + tcg_out32(s, encode_djuk5um5_insn(OPC_BSTRINS_W, d, j, uk5, um5)); +} + +/* Emits the `bstrpick.w d, j, uk5, um5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bstrpick_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5, + uint32_t um5) +{ + tcg_out32(s, encode_djuk5um5_insn(OPC_BSTRPICK_W, d, j, uk5, um5)); +} + +/* Emits the `bstrins.d d, j, uk6, um6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bstrins_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6, + uint32_t um6) +{ + tcg_out32(s, encode_djuk6um6_insn(OPC_BSTRINS_D, d, j, uk6, um6)); +} + +/* Emits the `bstrpick.d d, j, uk6, um6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bstrpick_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6, + uint32_t um6) +{ + tcg_out32(s, encode_djuk6um6_insn(OPC_BSTRPICK_D, d, j, uk6, um6)); +} + +/* Emits the `slti d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_slti(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_SLTI, d, j, sk12)); +} + +/* Emits the `sltui d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sltui(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_SLTUI, d, j, sk12)); +} + +/* Emits the `addi.w d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_addi_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ADDI_W, d, j, sk12)); +} + +/* Emits the `addi.d d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_addi_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ADDI_D, d, j, sk12)); +} + +/* Emits the `cu52i.d d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_cu52i_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_CU52I_D, d, j, sk12)); +} + +/* Emits the `andi d, j, uk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_andi(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) +{ + tcg_out32(s, encode_djuk12_insn(OPC_ANDI, d, j, uk12)); +} + +/* Emits the `ori d, j, uk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ori(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) +{ + tcg_out32(s, encode_djuk12_insn(OPC_ORI, d, j, uk12)); +} + +/* Emits the `xori d, j, uk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_xori(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) +{ + tcg_out32(s, encode_djuk12_insn(OPC_XORI, d, j, uk12)); +} + +/* Emits the `lu12i.w d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_lu12i_w(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_LU12I_W, d, sj20)); +} + +/* Emits the `cu32i.d d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_cu32i_d(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_CU32I_D, d, sj20)); +} + +/* Emits the `pcaddu2i d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_pcaddu2i(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_PCADDU2I, d, sj20)); +} + +/* Emits the `pcalau12i d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_pcalau12i(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_PCALAU12I, d, sj20)); +} + +/* Emits the `pcaddu12i d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_pcaddu12i(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_PCADDU12I, d, sj20)); +} + +/* Emits the `pcaddu18i d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_pcaddu18i(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_PCADDU18I, d, sj20)); +} + +/* Emits the `ld.b d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_b(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_B, d, j, sk12)); +} + +/* Emits the `ld.h d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_h(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_H, d, j, sk12)); +} + +/* Emits the `ld.w d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_W, d, j, sk12)); +} + +/* Emits the `ld.d d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_D, d, j, sk12)); +} + +/* Emits the `st.b d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_st_b(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ST_B, d, j, sk12)); +} + +/* Emits the `st.h d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_st_h(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ST_H, d, j, sk12)); +} + +/* Emits the `st.w d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_st_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ST_W, d, j, sk12)); +} + +/* Emits the `st.d d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_st_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ST_D, d, j, sk12)); +} + +/* Emits the `ld.bu d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_bu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_BU, d, j, sk12)); +} + +/* Emits the `ld.hu d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_hu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_HU, d, j, sk12)); +} + +/* Emits the `ld.wu d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_wu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_WU, d, j, sk12)); +} + +/* Emits the `ldx.b d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_b(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_B, d, j, k)); +} + +/* Emits the `ldx.h d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_h(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_H, d, j, k)); +} + +/* Emits the `ldx.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_W, d, j, k)); +} + +/* Emits the `ldx.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_D, d, j, k)); +} + +/* Emits the `stx.b d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_stx_b(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_STX_B, d, j, k)); +} + +/* Emits the `stx.h d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_stx_h(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_STX_H, d, j, k)); +} + +/* Emits the `stx.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_stx_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_STX_W, d, j, k)); +} + +/* Emits the `stx.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_stx_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_STX_D, d, j, k)); +} + +/* Emits the `ldx.bu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_bu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_BU, d, j, k)); +} + +/* Emits the `ldx.hu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_hu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_HU, d, j, k)); +} + +/* Emits the `ldx.wu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_WU, d, j, k)); +} + +/* Emits the `dbar ud15` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_dbar(TCGContext *s, uint32_t ud15) +{ + tcg_out32(s, encode_ud15_insn(OPC_DBAR, ud15)); +} + +/* Emits the `jirl d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_jirl(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_JIRL, d, j, sk16)); +} + +/* Emits the `b sd10k16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_b(TCGContext *s, int32_t sd10k16) +{ + tcg_out32(s, encode_sd10k16_insn(OPC_B, sd10k16)); +} + +/* Emits the `bl sd10k16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bl(TCGContext *s, int32_t sd10k16) +{ + tcg_out32(s, encode_sd10k16_insn(OPC_BL, sd10k16)); +} + +/* Emits the `beq d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_beq(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BEQ, d, j, sk16)); +} + +/* Emits the `bne d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bne(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BNE, d, j, sk16)); +} + +/* Emits the `bgt d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bgt(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BGT, d, j, sk16)); +} + +/* Emits the `ble d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ble(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BLE, d, j, sk16)); +} + +/* Emits the `bgtu d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bgtu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BGTU, d, j, sk16)); +} + +/* Emits the `bleu d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bleu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BLEU, d, j, sk16)); +} + +/* End of generated code. */ diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h new file mode 100644 index 0000000000..349c672687 --- /dev/null +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define LoongArch target-specific constraint sets. + * + * Copyright (c) 2021 WANG Xuerui + * + * Based on tcg/riscv/tcg-target-con-set.h + * + * Copyright (c) 2021 Linaro + */ + +/* + * C_On_Im(...) defines a constraint set with outputs and inputs. + * Each operand should be a sequence of constraint letters as defined by + * tcg-target-con-str.h; the constraint combination is inclusive or. + */ +C_O0_I1(r) +C_O0_I2(rZ, r) +C_O0_I2(rZ, rZ) +C_O0_I2(LZ, L) +C_O1_I1(r, r) +C_O1_I1(r, L) +C_O1_I2(r, r, rC) +C_O1_I2(r, r, ri) +C_O1_I2(r, r, rI) +C_O1_I2(r, r, rU) +C_O1_I2(r, r, rW) +C_O1_I2(r, r, rZ) +C_O1_I2(r, 0, rZ) +C_O1_I2(r, rZ, rN) +C_O1_I2(r, rZ, rZ) diff --git a/tcg/loongarch64/tcg-target-con-str.h b/tcg/loongarch64/tcg-target-con-str.h new file mode 100644 index 0000000000..c3986a4fd4 --- /dev/null +++ b/tcg/loongarch64/tcg-target-con-str.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define LoongArch target-specific operand constraints. + * + * Copyright (c) 2021 WANG Xuerui + * + * Based on tcg/riscv/tcg-target-con-str.h + * + * Copyright (c) 2021 Linaro + */ + +/* + * Define constraint letters for register sets: + * REGS(letter, register_mask) + */ +REGS('r', ALL_GENERAL_REGS) +REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS) + +/* + * Define constraint letters for constants: + * CONST(letter, TCG_CT_CONST_* bit set) + */ +CONST('I', TCG_CT_CONST_S12) +CONST('N', TCG_CT_CONST_N12) +CONST('U', TCG_CT_CONST_U12) +CONST('Z', TCG_CT_CONST_ZERO) +CONST('C', TCG_CT_CONST_C12) +CONST('W', TCG_CT_CONST_WSZ) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc new file mode 100644 index 0000000000..9b53549edb --- /dev/null +++ b/tcg/loongarch64/tcg-target.c.inc @@ -0,0 +1,1744 @@ +/* + * Tiny Code Generator for QEMU + * + * Copyright (c) 2021 WANG Xuerui + * + * Based on tcg/riscv/tcg-target.c.inc + * + * Copyright (c) 2018 SiFive, Inc + * Copyright (c) 2008-2009 Arnaud Patard + * Copyright (c) 2009 Aurelien Jarno + * Copyright (c) 2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "../tcg-ldst.c.inc" + +#ifdef CONFIG_DEBUG_TCG +static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { + "zero", + "ra", + "tp", + "sp", + "a0", + "a1", + "a2", + "a3", + "a4", + "a5", + "a6", + "a7", + "t0", + "t1", + "t2", + "t3", + "t4", + "t5", + "t6", + "t7", + "t8", + "r21", /* reserved in the LP64* ABI, hence no ABI name */ + "s9", + "s0", + "s1", + "s2", + "s3", + "s4", + "s5", + "s6", + "s7", + "s8" +}; +#endif + +static const int tcg_target_reg_alloc_order[] = { + /* Registers preserved across calls */ + /* TCG_REG_S0 reserved for TCG_AREG0 */ + TCG_REG_S1, + TCG_REG_S2, + TCG_REG_S3, + TCG_REG_S4, + TCG_REG_S5, + TCG_REG_S6, + TCG_REG_S7, + TCG_REG_S8, + TCG_REG_S9, + + /* Registers (potentially) clobbered across calls */ + TCG_REG_T0, + TCG_REG_T1, + TCG_REG_T2, + TCG_REG_T3, + TCG_REG_T4, + TCG_REG_T5, + TCG_REG_T6, + TCG_REG_T7, + TCG_REG_T8, + + /* Argument registers, opposite order of allocation. */ + TCG_REG_A7, + TCG_REG_A6, + TCG_REG_A5, + TCG_REG_A4, + TCG_REG_A3, + TCG_REG_A2, + TCG_REG_A1, + TCG_REG_A0, +}; + +static const int tcg_target_call_iarg_regs[] = { + TCG_REG_A0, + TCG_REG_A1, + TCG_REG_A2, + TCG_REG_A3, + TCG_REG_A4, + TCG_REG_A5, + TCG_REG_A6, + TCG_REG_A7, +}; + +static const int tcg_target_call_oarg_regs[] = { + TCG_REG_A0, + TCG_REG_A1, +}; + +#ifndef CONFIG_SOFTMMU +#define USE_GUEST_BASE (guest_base != 0) +#define TCG_GUEST_BASE_REG TCG_REG_S1 +#endif + +#define TCG_CT_CONST_ZERO 0x100 +#define TCG_CT_CONST_S12 0x200 +#define TCG_CT_CONST_N12 0x400 +#define TCG_CT_CONST_U12 0x800 +#define TCG_CT_CONST_C12 0x1000 +#define TCG_CT_CONST_WSZ 0x2000 + +#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32) +/* + * For softmmu, we need to avoid conflicts with the first 5 + * argument registers to call the helper. Some of these are + * also used for the tlb lookup. + */ +#ifdef CONFIG_SOFTMMU +#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_A0, 5) +#else +#define SOFTMMU_RESERVE_REGS 0 +#endif + + +static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len) +{ + return sextract64(val, pos, len); +} + +/* test if a constant matches the constraint */ +static bool tcg_target_const_match(int64_t val, TCGType type, int ct) +{ + if (ct & TCG_CT_CONST) { + return true; + } + if ((ct & TCG_CT_CONST_ZERO) && val == 0) { + return true; + } + if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) { + return true; + } + if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) { + return true; + } + if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) { + return true; + } + if ((ct & TCG_CT_CONST_C12) && ~val >= 0 && ~val <= 0xfff) { + return true; + } + if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) { + return true; + } + return false; +} + +/* + * Relocations + */ + +/* + * Relocation records defined in LoongArch ELF psABI v1.00 is way too + * complicated; a whopping stack machine is needed to stuff the fields, at + * the very least one SOP_PUSH and one SOP_POP (of the correct format) are + * needed. + * + * Hence, define our own simpler relocation types. Numbers are chosen as to + * not collide with potential future additions to the true ELF relocation + * type enum. + */ + +/* Field Sk16, shifted right by 2; suitable for conditional jumps */ +#define R_LOONGARCH_BR_SK16 256 +/* Field Sd10k16, shifted right by 2; suitable for B and BL */ +#define R_LOONGARCH_BR_SD10K16 257 + +static bool reloc_br_sk16(tcg_insn_unit *src_rw, const tcg_insn_unit *target) +{ + const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); + intptr_t offset = (intptr_t)target - (intptr_t)src_rx; + + tcg_debug_assert((offset & 3) == 0); + offset >>= 2; + if (offset == sextreg(offset, 0, 16)) { + *src_rw = deposit64(*src_rw, 10, 16, offset); + return true; + } + + return false; +} + +static bool reloc_br_sd10k16(tcg_insn_unit *src_rw, + const tcg_insn_unit *target) +{ + const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); + intptr_t offset = (intptr_t)target - (intptr_t)src_rx; + + tcg_debug_assert((offset & 3) == 0); + offset >>= 2; + if (offset == sextreg(offset, 0, 26)) { + *src_rw = deposit64(*src_rw, 0, 10, offset >> 16); /* slot d10 */ + *src_rw = deposit64(*src_rw, 10, 16, offset); /* slot k16 */ + return true; + } + + return false; +} + +static bool patch_reloc(tcg_insn_unit *code_ptr, int type, + intptr_t value, intptr_t addend) +{ + tcg_debug_assert(addend == 0); + switch (type) { + case R_LOONGARCH_BR_SK16: + return reloc_br_sk16(code_ptr, (tcg_insn_unit *)value); + case R_LOONGARCH_BR_SD10K16: + return reloc_br_sd10k16(code_ptr, (tcg_insn_unit *)value); + default: + g_assert_not_reached(); + } +} + +#include "tcg-insn-defs.c.inc" + +/* + * TCG intrinsics + */ + +static void tcg_out_mb(TCGContext *s, TCGArg a0) +{ + /* Baseline LoongArch only has the full barrier, unfortunately. */ + tcg_out_opc_dbar(s, 0); +} + +static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) +{ + if (ret == arg) { + return true; + } + switch (type) { + case TCG_TYPE_I32: + case TCG_TYPE_I64: + /* + * Conventional register-register move used in LoongArch is + * `or dst, src, zero`. + */ + tcg_out_opc_or(s, ret, arg, TCG_REG_ZERO); + break; + default: + g_assert_not_reached(); + } + return true; +} + +static bool imm_part_needs_loading(bool high_bits_are_ones, + tcg_target_long part) +{ + if (high_bits_are_ones) { + return part != -1; + } else { + return part != 0; + } +} + +/* Loads a 32-bit immediate into rd, sign-extended. */ +static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val) +{ + tcg_target_long lo = sextreg(val, 0, 12); + tcg_target_long hi12 = sextreg(val, 12, 20); + + /* Single-instruction cases. */ + if (lo == val) { + /* val fits in simm12: addi.w rd, zero, val */ + tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val); + return; + } + if (0x800 <= val && val <= 0xfff) { + /* val fits in uimm12: ori rd, zero, val */ + tcg_out_opc_ori(s, rd, TCG_REG_ZERO, val); + return; + } + + /* High bits must be set; load with lu12i.w + optional ori. */ + tcg_out_opc_lu12i_w(s, rd, hi12); + if (lo != 0) { + tcg_out_opc_ori(s, rd, rd, lo & 0xfff); + } +} + +static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, + tcg_target_long val) +{ + /* + * LoongArch conventionally loads 64-bit immediates in at most 4 steps, + * with dedicated instructions for filling the respective bitfields + * below: + * + * 6 5 4 3 + * 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 + * +-----------------------+---------------------------------------+... + * | hi52 | hi32 | + * +-----------------------+---------------------------------------+... + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * ...+-------------------------------------+-------------------------+ + * | hi12 | lo | + * ...+-------------------------------------+-------------------------+ + * + * Check if val belong to one of the several fast cases, before falling + * back to the slow path. + */ + + intptr_t pc_offset; + tcg_target_long val_lo, val_hi, pc_hi, offset_hi; + tcg_target_long hi32, hi52; + bool rd_high_bits_are_ones; + + /* Value fits in signed i32. */ + if (type == TCG_TYPE_I32 || val == (int32_t)val) { + tcg_out_movi_i32(s, rd, val); + return; + } + + /* PC-relative cases. */ + pc_offset = tcg_pcrel_diff(s, (void *)val); + if (pc_offset == sextreg(pc_offset, 0, 22) && (pc_offset & 3) == 0) { + /* Single pcaddu2i. */ + tcg_out_opc_pcaddu2i(s, rd, pc_offset >> 2); + return; + } + + if (pc_offset == (int32_t)pc_offset) { + /* Offset within 32 bits; load with pcalau12i + ori. */ + val_lo = sextreg(val, 0, 12); + val_hi = val >> 12; + pc_hi = (val - pc_offset) >> 12; + offset_hi = val_hi - pc_hi; + + tcg_debug_assert(offset_hi == sextreg(offset_hi, 0, 20)); + tcg_out_opc_pcalau12i(s, rd, offset_hi); + if (val_lo != 0) { + tcg_out_opc_ori(s, rd, rd, val_lo & 0xfff); + } + return; + } + + hi32 = sextreg(val, 32, 20); + hi52 = sextreg(val, 52, 12); + + /* Single cu52i.d case. */ + if (ctz64(val) >= 52) { + tcg_out_opc_cu52i_d(s, rd, TCG_REG_ZERO, hi52); + return; + } + + /* Slow path. Initialize the low 32 bits, then concat high bits. */ + tcg_out_movi_i32(s, rd, val); + rd_high_bits_are_ones = (int32_t)val < 0; + + if (imm_part_needs_loading(rd_high_bits_are_ones, hi32)) { + tcg_out_opc_cu32i_d(s, rd, hi32); + rd_high_bits_are_ones = hi32 < 0; + } + + if (imm_part_needs_loading(rd_high_bits_are_ones, hi52)) { + tcg_out_opc_cu52i_d(s, rd, rd, hi52); + } +} + +static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_andi(s, ret, arg, 0xff); +} + +static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_bstrpick_w(s, ret, arg, 0, 15); +} + +static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_bstrpick_d(s, ret, arg, 0, 31); +} + +static void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_sext_b(s, ret, arg); +} + +static void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_sext_h(s, ret, arg); +} + +static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_addi_w(s, ret, arg, 0); +} + +static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc, + TCGReg a0, TCGReg a1, TCGReg a2, + bool c2, bool is_32bit) +{ + if (c2) { + /* + * Fast path: semantics already satisfied due to constraint and + * insn behavior, single instruction is enough. + */ + tcg_debug_assert(a2 == (is_32bit ? 32 : 64)); + /* all clz/ctz insns belong to DJ-format */ + tcg_out32(s, encode_dj_insn(opc, a0, a1)); + return; + } + + tcg_out32(s, encode_dj_insn(opc, TCG_REG_TMP0, a1)); + /* a0 = a1 ? REG_TMP0 : a2 */ + tcg_out_opc_maskeqz(s, TCG_REG_TMP0, TCG_REG_TMP0, a1); + tcg_out_opc_masknez(s, a0, a2, a1); + tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0); +} + +static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, + TCGReg arg1, TCGReg arg2, bool c2) +{ + TCGReg tmp; + + if (c2) { + tcg_debug_assert(arg2 == 0); + } + + switch (cond) { + case TCG_COND_EQ: + if (c2) { + tmp = arg1; + } else { + tcg_out_opc_sub_d(s, ret, arg1, arg2); + tmp = ret; + } + tcg_out_opc_sltui(s, ret, tmp, 1); + break; + case TCG_COND_NE: + if (c2) { + tmp = arg1; + } else { + tcg_out_opc_sub_d(s, ret, arg1, arg2); + tmp = ret; + } + tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp); + break; + case TCG_COND_LT: + tcg_out_opc_slt(s, ret, arg1, arg2); + break; + case TCG_COND_GE: + tcg_out_opc_slt(s, ret, arg1, arg2); + tcg_out_opc_xori(s, ret, ret, 1); + break; + case TCG_COND_LE: + tcg_out_setcond(s, TCG_COND_GE, ret, arg2, arg1, false); + break; + case TCG_COND_GT: + tcg_out_setcond(s, TCG_COND_LT, ret, arg2, arg1, false); + break; + case TCG_COND_LTU: + tcg_out_opc_sltu(s, ret, arg1, arg2); + break; + case TCG_COND_GEU: + tcg_out_opc_sltu(s, ret, arg1, arg2); + tcg_out_opc_xori(s, ret, ret, 1); + break; + case TCG_COND_LEU: + tcg_out_setcond(s, TCG_COND_GEU, ret, arg2, arg1, false); + break; + case TCG_COND_GTU: + tcg_out_setcond(s, TCG_COND_LTU, ret, arg2, arg1, false); + break; + default: + g_assert_not_reached(); + break; + } +} + +/* + * Branch helpers + */ + +static const struct { + LoongArchInsn op; + bool swap; +} tcg_brcond_to_loongarch[] = { + [TCG_COND_EQ] = { OPC_BEQ, false }, + [TCG_COND_NE] = { OPC_BNE, false }, + [TCG_COND_LT] = { OPC_BGT, true }, + [TCG_COND_GE] = { OPC_BLE, true }, + [TCG_COND_LE] = { OPC_BLE, false }, + [TCG_COND_GT] = { OPC_BGT, false }, + [TCG_COND_LTU] = { OPC_BGTU, true }, + [TCG_COND_GEU] = { OPC_BLEU, true }, + [TCG_COND_LEU] = { OPC_BLEU, false }, + [TCG_COND_GTU] = { OPC_BGTU, false } +}; + +static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, + TCGReg arg2, TCGLabel *l) +{ + LoongArchInsn op = tcg_brcond_to_loongarch[cond].op; + + tcg_debug_assert(op != 0); + + if (tcg_brcond_to_loongarch[cond].swap) { + TCGReg t = arg1; + arg1 = arg2; + arg2 = t; + } + + /* all conditional branch insns belong to DJSk16-format */ + tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SK16, l, 0); + tcg_out32(s, encode_djsk16_insn(op, arg1, arg2, 0)); +} + +static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) +{ + TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; + ptrdiff_t offset = tcg_pcrel_diff(s, arg); + + tcg_debug_assert((offset & 3) == 0); + if (offset == sextreg(offset, 0, 28)) { + /* short jump: +/- 256MiB */ + if (tail) { + tcg_out_opc_b(s, offset >> 2); + } else { + tcg_out_opc_bl(s, offset >> 2); + } + } else if (offset == sextreg(offset, 0, 38)) { + /* long jump: +/- 256GiB */ + tcg_target_long lo = sextreg(offset, 0, 18); + tcg_target_long hi = offset - lo; + tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, hi >> 18); + tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2); + } else { + /* far jump: 64-bit */ + tcg_target_long lo = sextreg((tcg_target_long)arg, 0, 18); + tcg_target_long hi = (tcg_target_long)arg - lo; + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, hi); + tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2); + } +} + +static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg) +{ + tcg_out_call_int(s, arg, false); +} + +/* + * Load/store helpers + */ + +static void tcg_out_ldst(TCGContext *s, LoongArchInsn opc, TCGReg data, + TCGReg addr, intptr_t offset) +{ + intptr_t imm12 = sextreg(offset, 0, 12); + + if (offset != imm12) { + intptr_t diff = offset - (uintptr_t)s->code_ptr; + + if (addr == TCG_REG_ZERO && diff == (int32_t)diff) { + imm12 = sextreg(diff, 0, 12); + tcg_out_opc_pcaddu12i(s, TCG_REG_TMP2, (diff - imm12) >> 12); + } else { + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12); + if (addr != TCG_REG_ZERO) { + tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, addr); + } + } + addr = TCG_REG_TMP2; + } + + switch (opc) { + case OPC_LD_B: + case OPC_LD_BU: + case OPC_LD_H: + case OPC_LD_HU: + case OPC_LD_W: + case OPC_LD_WU: + case OPC_LD_D: + case OPC_ST_B: + case OPC_ST_H: + case OPC_ST_W: + case OPC_ST_D: + tcg_out32(s, encode_djsk12_insn(opc, data, addr, imm12)); + break; + default: + g_assert_not_reached(); + } +} + +static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, intptr_t arg2) +{ + bool is_32bit = type == TCG_TYPE_I32; + tcg_out_ldst(s, is_32bit ? OPC_LD_W : OPC_LD_D, arg, arg1, arg2); +} + +static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, intptr_t arg2) +{ + bool is_32bit = type == TCG_TYPE_I32; + tcg_out_ldst(s, is_32bit ? OPC_ST_W : OPC_ST_D, arg, arg1, arg2); +} + +static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, + TCGReg base, intptr_t ofs) +{ + if (val == 0) { + tcg_out_st(s, type, TCG_REG_ZERO, base, ofs); + return true; + } + return false; +} + +/* + * Load/store helpers for SoftMMU, and qemu_ld/st implementations + */ + +#if defined(CONFIG_SOFTMMU) +/* + * helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, + * MemOpIdx oi, uintptr_t ra) + */ +static void * const qemu_ld_helpers[4] = { + [MO_8] = helper_ret_ldub_mmu, + [MO_16] = helper_le_lduw_mmu, + [MO_32] = helper_le_ldul_mmu, + [MO_64] = helper_le_ldq_mmu, +}; + +/* + * helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, + * uintxx_t val, MemOpIdx oi, + * uintptr_t ra) + */ +static void * const qemu_st_helpers[4] = { + [MO_8] = helper_ret_stb_mmu, + [MO_16] = helper_le_stw_mmu, + [MO_32] = helper_le_stl_mmu, + [MO_64] = helper_le_stq_mmu, +}; + +/* We expect to use a 12-bit negative offset from ENV. */ +QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0); +QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11)); + +static bool tcg_out_goto(TCGContext *s, const tcg_insn_unit *target) +{ + tcg_out_opc_b(s, 0); + return reloc_br_sd10k16(s->code_ptr - 1, target); +} + +/* + * Emits common code for TLB addend lookup, that eventually loads the + * addend in TCG_REG_TMP2. + */ +static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl, MemOpIdx oi, + tcg_insn_unit **label_ptr, bool is_load) +{ + MemOp opc = get_memop(oi); + unsigned s_bits = opc & MO_SIZE; + unsigned a_bits = get_alignment_bits(opc); + tcg_target_long compare_mask; + int mem_index = get_mmuidx(oi); + int fast_ofs = TLB_MASK_TABLE_OFS(mem_index); + int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask); + int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table); + + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs); + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs); + + tcg_out_opc_srli_d(s, TCG_REG_TMP2, addrl, + TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); + tcg_out_opc_and(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0); + tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1); + + /* Load the tlb comparator and the addend. */ + tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP0, TCG_REG_TMP2, + is_load ? offsetof(CPUTLBEntry, addr_read) + : offsetof(CPUTLBEntry, addr_write)); + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2, + offsetof(CPUTLBEntry, addend)); + + /* We don't support unaligned accesses. */ + if (a_bits < s_bits) { + a_bits = s_bits; + } + /* Clear the non-page, non-alignment bits from the address. */ + compare_mask = (tcg_target_long)TARGET_PAGE_MASK | ((1 << a_bits) - 1); + tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_TMP1, compare_mask); + tcg_out_opc_and(s, TCG_REG_TMP1, TCG_REG_TMP1, addrl); + + /* Compare masked address with the TLB entry. */ + label_ptr[0] = s->code_ptr; + tcg_out_opc_bne(s, TCG_REG_TMP0, TCG_REG_TMP1, 0); + + /* TLB Hit - addend in TCG_REG_TMP2, ready for use. */ +} + +static void add_qemu_ldst_label(TCGContext *s, int is_ld, MemOpIdx oi, + TCGType type, + TCGReg datalo, TCGReg addrlo, + void *raddr, tcg_insn_unit **label_ptr) +{ + TCGLabelQemuLdst *label = new_ldst_label(s); + + label->is_ld = is_ld; + label->oi = oi; + label->type = type; + label->datalo_reg = datalo; + label->datahi_reg = 0; /* unused */ + label->addrlo_reg = addrlo; + label->addrhi_reg = 0; /* unused */ + label->raddr = tcg_splitwx_to_rx(raddr); + label->label_ptr[0] = label_ptr[0]; +} + +static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) +{ + MemOpIdx oi = l->oi; + MemOp opc = get_memop(oi); + MemOp size = opc & MO_SIZE; + TCGType type = l->type; + + /* resolve label address */ + if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { + return false; + } + + /* call load helper */ + tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); + tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg); + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A2, oi); + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, (tcg_target_long)l->raddr); + + tcg_out_call(s, qemu_ld_helpers[size]); + + switch (opc & MO_SSIZE) { + case MO_SB: + tcg_out_ext8s(s, l->datalo_reg, TCG_REG_A0); + break; + case MO_SW: + tcg_out_ext16s(s, l->datalo_reg, TCG_REG_A0); + break; + case MO_SL: + tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0); + break; + case MO_UL: + if (type == TCG_TYPE_I32) { + /* MO_UL loads of i32 should be sign-extended too */ + tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0); + break; + } + /* fallthrough */ + default: + tcg_out_mov(s, type, l->datalo_reg, TCG_REG_A0); + break; + } + + return tcg_out_goto(s, l->raddr); +} + +static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) +{ + MemOpIdx oi = l->oi; + MemOp opc = get_memop(oi); + MemOp size = opc & MO_SIZE; + + /* resolve label address */ + if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { + return false; + } + + /* call store helper */ + tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); + tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg); + switch (size) { + case MO_8: + tcg_out_ext8u(s, TCG_REG_A2, l->datalo_reg); + break; + case MO_16: + tcg_out_ext16u(s, TCG_REG_A2, l->datalo_reg); + break; + case MO_32: + tcg_out_ext32u(s, TCG_REG_A2, l->datalo_reg); + break; + case MO_64: + tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_A2, l->datalo_reg); + break; + default: + g_assert_not_reached(); + break; + } + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, oi); + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A4, (tcg_target_long)l->raddr); + + tcg_out_call(s, qemu_st_helpers[size]); + + return tcg_out_goto(s, l->raddr); +} +#else + +/* + * Alignment helpers for user-mode emulation + */ + +static void tcg_out_test_alignment(TCGContext *s, bool is_ld, TCGReg addr_reg, + unsigned a_bits) +{ + TCGLabelQemuLdst *l = new_ldst_label(s); + + l->is_ld = is_ld; + l->addrlo_reg = addr_reg; + + /* + * Without micro-architecture details, we don't know which of bstrpick or + * andi is faster, so use bstrpick as it's not constrained by imm field + * width. (Not to say alignments >= 2^12 are going to happen any time + * soon, though) + */ + tcg_out_opc_bstrpick_d(s, TCG_REG_TMP1, addr_reg, 0, a_bits - 1); + + l->label_ptr[0] = s->code_ptr; + tcg_out_opc_bne(s, TCG_REG_TMP1, TCG_REG_ZERO, 0); + + l->raddr = tcg_splitwx_to_rx(s->code_ptr); +} + +static bool tcg_out_fail_alignment(TCGContext *s, TCGLabelQemuLdst *l) +{ + /* resolve label address */ + if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { + return false; + } + + tcg_out_mov(s, TCG_TYPE_TL, TCG_REG_A1, l->addrlo_reg); + tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); + + /* tail call, with the return address back inline. */ + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (uintptr_t)l->raddr); + tcg_out_call_int(s, (const void *)(l->is_ld ? helper_unaligned_ld + : helper_unaligned_st), true); + return true; +} + +static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) +{ + return tcg_out_fail_alignment(s, l); +} + +static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) +{ + return tcg_out_fail_alignment(s, l); +} + +#endif /* CONFIG_SOFTMMU */ + +/* + * `ext32u` the address register into the temp register given, + * if target is 32-bit, no-op otherwise. + * + * Returns the address register ready for use with TLB addend. + */ +static TCGReg tcg_out_zext_addr_if_32_bit(TCGContext *s, + TCGReg addr, TCGReg tmp) +{ + if (TARGET_LONG_BITS == 32) { + tcg_out_ext32u(s, tmp, addr); + return tmp; + } + return addr; +} + +static void tcg_out_qemu_ld_indexed(TCGContext *s, TCGReg rd, TCGReg rj, + TCGReg rk, MemOp opc, TCGType type) +{ + /* Byte swapping is left to middle-end expansion. */ + tcg_debug_assert((opc & MO_BSWAP) == 0); + + switch (opc & MO_SSIZE) { + case MO_UB: + tcg_out_opc_ldx_bu(s, rd, rj, rk); + break; + case MO_SB: + tcg_out_opc_ldx_b(s, rd, rj, rk); + break; + case MO_UW: + tcg_out_opc_ldx_hu(s, rd, rj, rk); + break; + case MO_SW: + tcg_out_opc_ldx_h(s, rd, rj, rk); + break; + case MO_UL: + if (type == TCG_TYPE_I64) { + tcg_out_opc_ldx_wu(s, rd, rj, rk); + break; + } + /* fallthrough */ + case MO_SL: + tcg_out_opc_ldx_w(s, rd, rj, rk); + break; + case MO_Q: + tcg_out_opc_ldx_d(s, rd, rj, rk); + break; + default: + g_assert_not_reached(); + } +} + +static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGType type) +{ + TCGReg addr_regl; + TCGReg data_regl; + MemOpIdx oi; + MemOp opc; +#if defined(CONFIG_SOFTMMU) + tcg_insn_unit *label_ptr[1]; +#else + unsigned a_bits; +#endif + TCGReg base; + + data_regl = *args++; + addr_regl = *args++; + oi = *args++; + opc = get_memop(oi); + +#if defined(CONFIG_SOFTMMU) + tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 1); + base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); + tcg_out_qemu_ld_indexed(s, data_regl, base, TCG_REG_TMP2, opc, type); + add_qemu_ldst_label(s, 1, oi, type, + data_regl, addr_regl, + s->code_ptr, label_ptr); +#else + a_bits = get_alignment_bits(opc); + if (a_bits) { + tcg_out_test_alignment(s, true, addr_regl, a_bits); + } + base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); + TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; + tcg_out_qemu_ld_indexed(s, data_regl, base, guest_base_reg, opc, type); +#endif +} + +static void tcg_out_qemu_st_indexed(TCGContext *s, TCGReg data, + TCGReg rj, TCGReg rk, MemOp opc) +{ + /* Byte swapping is left to middle-end expansion. */ + tcg_debug_assert((opc & MO_BSWAP) == 0); + + switch (opc & MO_SIZE) { + case MO_8: + tcg_out_opc_stx_b(s, data, rj, rk); + break; + case MO_16: + tcg_out_opc_stx_h(s, data, rj, rk); + break; + case MO_32: + tcg_out_opc_stx_w(s, data, rj, rk); + break; + case MO_64: + tcg_out_opc_stx_d(s, data, rj, rk); + break; + default: + g_assert_not_reached(); + } +} + +static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args) +{ + TCGReg addr_regl; + TCGReg data_regl; + MemOpIdx oi; + MemOp opc; +#if defined(CONFIG_SOFTMMU) + tcg_insn_unit *label_ptr[1]; +#else + unsigned a_bits; +#endif + TCGReg base; + + data_regl = *args++; + addr_regl = *args++; + oi = *args++; + opc = get_memop(oi); + +#if defined(CONFIG_SOFTMMU) + tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 0); + base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); + tcg_out_qemu_st_indexed(s, data_regl, base, TCG_REG_TMP2, opc); + add_qemu_ldst_label(s, 0, oi, + 0, /* type param is unused for stores */ + data_regl, addr_regl, + s->code_ptr, label_ptr); +#else + a_bits = get_alignment_bits(opc); + if (a_bits) { + tcg_out_test_alignment(s, false, addr_regl, a_bits); + } + base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); + TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; + tcg_out_qemu_st_indexed(s, data_regl, base, guest_base_reg, opc); +#endif +} + +/* + * Entry-points + */ + +static const tcg_insn_unit *tb_ret_addr; + +static void tcg_out_op(TCGContext *s, TCGOpcode opc, + const TCGArg args[TCG_MAX_OP_ARGS], + const int const_args[TCG_MAX_OP_ARGS]) +{ + TCGArg a0 = args[0]; + TCGArg a1 = args[1]; + TCGArg a2 = args[2]; + int c2 = const_args[2]; + + switch (opc) { + case INDEX_op_exit_tb: + /* Reuse the zeroing that exists for goto_ptr. */ + if (a0 == 0) { + tcg_out_call_int(s, tcg_code_gen_epilogue, true); + } else { + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); + tcg_out_call_int(s, tb_ret_addr, true); + } + break; + + case INDEX_op_goto_tb: + assert(s->tb_jmp_insn_offset == 0); + /* indirect jump method */ + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, + (uintptr_t)(s->tb_jmp_target_addr + a0)); + tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0); + set_jmp_reset_offset(s, a0); + break; + + case INDEX_op_mb: + tcg_out_mb(s, a0); + break; + + case INDEX_op_goto_ptr: + tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0); + break; + + case INDEX_op_br: + tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SD10K16, arg_label(a0), + 0); + tcg_out_opc_b(s, 0); + break; + + case INDEX_op_brcond_i32: + case INDEX_op_brcond_i64: + tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); + break; + + case INDEX_op_ext8s_i32: + case INDEX_op_ext8s_i64: + tcg_out_ext8s(s, a0, a1); + break; + + case INDEX_op_ext8u_i32: + case INDEX_op_ext8u_i64: + tcg_out_ext8u(s, a0, a1); + break; + + case INDEX_op_ext16s_i32: + case INDEX_op_ext16s_i64: + tcg_out_ext16s(s, a0, a1); + break; + + case INDEX_op_ext16u_i32: + case INDEX_op_ext16u_i64: + tcg_out_ext16u(s, a0, a1); + break; + + case INDEX_op_ext32u_i64: + case INDEX_op_extu_i32_i64: + tcg_out_ext32u(s, a0, a1); + break; + + case INDEX_op_ext32s_i64: + case INDEX_op_extrl_i64_i32: + case INDEX_op_ext_i32_i64: + tcg_out_ext32s(s, a0, a1); + break; + + case INDEX_op_extrh_i64_i32: + tcg_out_opc_srai_d(s, a0, a1, 32); + break; + + case INDEX_op_not_i32: + case INDEX_op_not_i64: + tcg_out_opc_nor(s, a0, a1, TCG_REG_ZERO); + break; + + case INDEX_op_nor_i32: + case INDEX_op_nor_i64: + if (c2) { + tcg_out_opc_ori(s, a0, a1, a2); + tcg_out_opc_nor(s, a0, a0, TCG_REG_ZERO); + } else { + tcg_out_opc_nor(s, a0, a1, a2); + } + break; + + case INDEX_op_andc_i32: + case INDEX_op_andc_i64: + if (c2) { + /* guaranteed to fit due to constraint */ + tcg_out_opc_andi(s, a0, a1, ~a2); + } else { + tcg_out_opc_andn(s, a0, a1, a2); + } + break; + + case INDEX_op_orc_i32: + case INDEX_op_orc_i64: + if (c2) { + /* guaranteed to fit due to constraint */ + tcg_out_opc_ori(s, a0, a1, ~a2); + } else { + tcg_out_opc_orn(s, a0, a1, a2); + } + break; + + case INDEX_op_and_i32: + case INDEX_op_and_i64: + if (c2) { + tcg_out_opc_andi(s, a0, a1, a2); + } else { + tcg_out_opc_and(s, a0, a1, a2); + } + break; + + case INDEX_op_or_i32: + case INDEX_op_or_i64: + if (c2) { + tcg_out_opc_ori(s, a0, a1, a2); + } else { + tcg_out_opc_or(s, a0, a1, a2); + } + break; + + case INDEX_op_xor_i32: + case INDEX_op_xor_i64: + if (c2) { + tcg_out_opc_xori(s, a0, a1, a2); + } else { + tcg_out_opc_xor(s, a0, a1, a2); + } + break; + + case INDEX_op_extract_i32: + tcg_out_opc_bstrpick_w(s, a0, a1, a2, a2 + args[3] - 1); + break; + case INDEX_op_extract_i64: + tcg_out_opc_bstrpick_d(s, a0, a1, a2, a2 + args[3] - 1); + break; + + case INDEX_op_deposit_i32: + tcg_out_opc_bstrins_w(s, a0, a2, args[3], args[3] + args[4] - 1); + break; + case INDEX_op_deposit_i64: + tcg_out_opc_bstrins_d(s, a0, a2, args[3], args[3] + args[4] - 1); + break; + + case INDEX_op_bswap16_i32: + case INDEX_op_bswap16_i64: + tcg_out_opc_revb_2h(s, a0, a1); + if (a2 & TCG_BSWAP_OS) { + tcg_out_ext16s(s, a0, a0); + } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) { + tcg_out_ext16u(s, a0, a0); + } + break; + + case INDEX_op_bswap32_i32: + /* All 32-bit values are computed sign-extended in the register. */ + a2 = TCG_BSWAP_OS; + /* fallthrough */ + case INDEX_op_bswap32_i64: + tcg_out_opc_revb_2w(s, a0, a1); + if (a2 & TCG_BSWAP_OS) { + tcg_out_ext32s(s, a0, a0); + } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) { + tcg_out_ext32u(s, a0, a0); + } + break; + + case INDEX_op_bswap64_i64: + tcg_out_opc_revb_d(s, a0, a1); + break; + + case INDEX_op_clz_i32: + tcg_out_clzctz(s, OPC_CLZ_W, a0, a1, a2, c2, true); + break; + case INDEX_op_clz_i64: + tcg_out_clzctz(s, OPC_CLZ_D, a0, a1, a2, c2, false); + break; + + case INDEX_op_ctz_i32: + tcg_out_clzctz(s, OPC_CTZ_W, a0, a1, a2, c2, true); + break; + case INDEX_op_ctz_i64: + tcg_out_clzctz(s, OPC_CTZ_D, a0, a1, a2, c2, false); + break; + + case INDEX_op_shl_i32: + if (c2) { + tcg_out_opc_slli_w(s, a0, a1, a2 & 0x1f); + } else { + tcg_out_opc_sll_w(s, a0, a1, a2); + } + break; + case INDEX_op_shl_i64: + if (c2) { + tcg_out_opc_slli_d(s, a0, a1, a2 & 0x3f); + } else { + tcg_out_opc_sll_d(s, a0, a1, a2); + } + break; + + case INDEX_op_shr_i32: + if (c2) { + tcg_out_opc_srli_w(s, a0, a1, a2 & 0x1f); + } else { + tcg_out_opc_srl_w(s, a0, a1, a2); + } + break; + case INDEX_op_shr_i64: + if (c2) { + tcg_out_opc_srli_d(s, a0, a1, a2 & 0x3f); + } else { + tcg_out_opc_srl_d(s, a0, a1, a2); + } + break; + + case INDEX_op_sar_i32: + if (c2) { + tcg_out_opc_srai_w(s, a0, a1, a2 & 0x1f); + } else { + tcg_out_opc_sra_w(s, a0, a1, a2); + } + break; + case INDEX_op_sar_i64: + if (c2) { + tcg_out_opc_srai_d(s, a0, a1, a2 & 0x3f); + } else { + tcg_out_opc_sra_d(s, a0, a1, a2); + } + break; + + case INDEX_op_rotl_i32: + /* transform into equivalent rotr/rotri */ + if (c2) { + tcg_out_opc_rotri_w(s, a0, a1, (32 - a2) & 0x1f); + } else { + tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2); + tcg_out_opc_rotr_w(s, a0, a1, TCG_REG_TMP0); + } + break; + case INDEX_op_rotl_i64: + /* transform into equivalent rotr/rotri */ + if (c2) { + tcg_out_opc_rotri_d(s, a0, a1, (64 - a2) & 0x3f); + } else { + tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2); + tcg_out_opc_rotr_d(s, a0, a1, TCG_REG_TMP0); + } + break; + + case INDEX_op_rotr_i32: + if (c2) { + tcg_out_opc_rotri_w(s, a0, a1, a2 & 0x1f); + } else { + tcg_out_opc_rotr_w(s, a0, a1, a2); + } + break; + case INDEX_op_rotr_i64: + if (c2) { + tcg_out_opc_rotri_d(s, a0, a1, a2 & 0x3f); + } else { + tcg_out_opc_rotr_d(s, a0, a1, a2); + } + break; + + case INDEX_op_add_i32: + if (c2) { + tcg_out_opc_addi_w(s, a0, a1, a2); + } else { + tcg_out_opc_add_w(s, a0, a1, a2); + } + break; + case INDEX_op_add_i64: + if (c2) { + tcg_out_opc_addi_d(s, a0, a1, a2); + } else { + tcg_out_opc_add_d(s, a0, a1, a2); + } + break; + + case INDEX_op_sub_i32: + if (c2) { + tcg_out_opc_addi_w(s, a0, a1, -a2); + } else { + tcg_out_opc_sub_w(s, a0, a1, a2); + } + break; + case INDEX_op_sub_i64: + if (c2) { + tcg_out_opc_addi_d(s, a0, a1, -a2); + } else { + tcg_out_opc_sub_d(s, a0, a1, a2); + } + break; + + case INDEX_op_mul_i32: + tcg_out_opc_mul_w(s, a0, a1, a2); + break; + case INDEX_op_mul_i64: + tcg_out_opc_mul_d(s, a0, a1, a2); + break; + + case INDEX_op_mulsh_i32: + tcg_out_opc_mulh_w(s, a0, a1, a2); + break; + case INDEX_op_mulsh_i64: + tcg_out_opc_mulh_d(s, a0, a1, a2); + break; + + case INDEX_op_muluh_i32: + tcg_out_opc_mulh_wu(s, a0, a1, a2); + break; + case INDEX_op_muluh_i64: + tcg_out_opc_mulh_du(s, a0, a1, a2); + break; + + case INDEX_op_div_i32: + tcg_out_opc_div_w(s, a0, a1, a2); + break; + case INDEX_op_div_i64: + tcg_out_opc_div_d(s, a0, a1, a2); + break; + + case INDEX_op_divu_i32: + tcg_out_opc_div_wu(s, a0, a1, a2); + break; + case INDEX_op_divu_i64: + tcg_out_opc_div_du(s, a0, a1, a2); + break; + + case INDEX_op_rem_i32: + tcg_out_opc_mod_w(s, a0, a1, a2); + break; + case INDEX_op_rem_i64: + tcg_out_opc_mod_d(s, a0, a1, a2); + break; + + case INDEX_op_remu_i32: + tcg_out_opc_mod_wu(s, a0, a1, a2); + break; + case INDEX_op_remu_i64: + tcg_out_opc_mod_du(s, a0, a1, a2); + break; + + case INDEX_op_setcond_i32: + case INDEX_op_setcond_i64: + tcg_out_setcond(s, args[3], a0, a1, a2, c2); + break; + + case INDEX_op_ld8s_i32: + case INDEX_op_ld8s_i64: + tcg_out_ldst(s, OPC_LD_B, a0, a1, a2); + break; + case INDEX_op_ld8u_i32: + case INDEX_op_ld8u_i64: + tcg_out_ldst(s, OPC_LD_BU, a0, a1, a2); + break; + case INDEX_op_ld16s_i32: + case INDEX_op_ld16s_i64: + tcg_out_ldst(s, OPC_LD_H, a0, a1, a2); + break; + case INDEX_op_ld16u_i32: + case INDEX_op_ld16u_i64: + tcg_out_ldst(s, OPC_LD_HU, a0, a1, a2); + break; + case INDEX_op_ld_i32: + case INDEX_op_ld32s_i64: + tcg_out_ldst(s, OPC_LD_W, a0, a1, a2); + break; + case INDEX_op_ld32u_i64: + tcg_out_ldst(s, OPC_LD_WU, a0, a1, a2); + break; + case INDEX_op_ld_i64: + tcg_out_ldst(s, OPC_LD_D, a0, a1, a2); + break; + + case INDEX_op_st8_i32: + case INDEX_op_st8_i64: + tcg_out_ldst(s, OPC_ST_B, a0, a1, a2); + break; + case INDEX_op_st16_i32: + case INDEX_op_st16_i64: + tcg_out_ldst(s, OPC_ST_H, a0, a1, a2); + break; + case INDEX_op_st_i32: + case INDEX_op_st32_i64: + tcg_out_ldst(s, OPC_ST_W, a0, a1, a2); + break; + case INDEX_op_st_i64: + tcg_out_ldst(s, OPC_ST_D, a0, a1, a2); + break; + + case INDEX_op_qemu_ld_i32: + tcg_out_qemu_ld(s, args, TCG_TYPE_I32); + break; + case INDEX_op_qemu_ld_i64: + tcg_out_qemu_ld(s, args, TCG_TYPE_I64); + break; + case INDEX_op_qemu_st_i32: + tcg_out_qemu_st(s, args); + break; + case INDEX_op_qemu_st_i64: + tcg_out_qemu_st(s, args); + break; + + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ + case INDEX_op_mov_i64: + case INDEX_op_call: /* Always emitted via tcg_out_call. */ + default: + g_assert_not_reached(); + } +} + +static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +{ + switch (op) { + case INDEX_op_goto_ptr: + return C_O0_I1(r); + + case INDEX_op_st8_i32: + case INDEX_op_st8_i64: + case INDEX_op_st16_i32: + case INDEX_op_st16_i64: + case INDEX_op_st32_i64: + case INDEX_op_st_i32: + case INDEX_op_st_i64: + return C_O0_I2(rZ, r); + + case INDEX_op_brcond_i32: + case INDEX_op_brcond_i64: + return C_O0_I2(rZ, rZ); + + case INDEX_op_qemu_st_i32: + case INDEX_op_qemu_st_i64: + return C_O0_I2(LZ, L); + + case INDEX_op_ext8s_i32: + case INDEX_op_ext8s_i64: + case INDEX_op_ext8u_i32: + case INDEX_op_ext8u_i64: + case INDEX_op_ext16s_i32: + case INDEX_op_ext16s_i64: + case INDEX_op_ext16u_i32: + case INDEX_op_ext16u_i64: + case INDEX_op_ext32s_i64: + case INDEX_op_ext32u_i64: + case INDEX_op_extu_i32_i64: + case INDEX_op_extrl_i64_i32: + case INDEX_op_extrh_i64_i32: + case INDEX_op_ext_i32_i64: + case INDEX_op_not_i32: + case INDEX_op_not_i64: + case INDEX_op_extract_i32: + case INDEX_op_extract_i64: + case INDEX_op_bswap16_i32: + case INDEX_op_bswap16_i64: + case INDEX_op_bswap32_i32: + case INDEX_op_bswap32_i64: + case INDEX_op_bswap64_i64: + case INDEX_op_ld8s_i32: + case INDEX_op_ld8s_i64: + case INDEX_op_ld8u_i32: + case INDEX_op_ld8u_i64: + case INDEX_op_ld16s_i32: + case INDEX_op_ld16s_i64: + case INDEX_op_ld16u_i32: + case INDEX_op_ld16u_i64: + case INDEX_op_ld32s_i64: + case INDEX_op_ld32u_i64: + case INDEX_op_ld_i32: + case INDEX_op_ld_i64: + return C_O1_I1(r, r); + + case INDEX_op_qemu_ld_i32: + case INDEX_op_qemu_ld_i64: + return C_O1_I1(r, L); + + case INDEX_op_andc_i32: + case INDEX_op_andc_i64: + case INDEX_op_orc_i32: + case INDEX_op_orc_i64: + /* + * LoongArch insns for these ops don't have reg-imm forms, but we + * can express using andi/ori if ~constant satisfies + * TCG_CT_CONST_U12. + */ + return C_O1_I2(r, r, rC); + + case INDEX_op_shl_i32: + case INDEX_op_shl_i64: + case INDEX_op_shr_i32: + case INDEX_op_shr_i64: + case INDEX_op_sar_i32: + case INDEX_op_sar_i64: + case INDEX_op_rotl_i32: + case INDEX_op_rotl_i64: + case INDEX_op_rotr_i32: + case INDEX_op_rotr_i64: + return C_O1_I2(r, r, ri); + + case INDEX_op_add_i32: + case INDEX_op_add_i64: + return C_O1_I2(r, r, rI); + + case INDEX_op_and_i32: + case INDEX_op_and_i64: + case INDEX_op_nor_i32: + case INDEX_op_nor_i64: + case INDEX_op_or_i32: + case INDEX_op_or_i64: + case INDEX_op_xor_i32: + case INDEX_op_xor_i64: + /* LoongArch reg-imm bitops have their imms ZERO-extended */ + return C_O1_I2(r, r, rU); + + case INDEX_op_clz_i32: + case INDEX_op_clz_i64: + case INDEX_op_ctz_i32: + case INDEX_op_ctz_i64: + return C_O1_I2(r, r, rW); + + case INDEX_op_setcond_i32: + case INDEX_op_setcond_i64: + return C_O1_I2(r, r, rZ); + + case INDEX_op_deposit_i32: + case INDEX_op_deposit_i64: + /* Must deposit into the same register as input */ + return C_O1_I2(r, 0, rZ); + + case INDEX_op_sub_i32: + case INDEX_op_sub_i64: + return C_O1_I2(r, rZ, rN); + + case INDEX_op_mul_i32: + case INDEX_op_mul_i64: + case INDEX_op_mulsh_i32: + case INDEX_op_mulsh_i64: + case INDEX_op_muluh_i32: + case INDEX_op_muluh_i64: + case INDEX_op_div_i32: + case INDEX_op_div_i64: + case INDEX_op_divu_i32: + case INDEX_op_divu_i64: + case INDEX_op_rem_i32: + case INDEX_op_rem_i64: + case INDEX_op_remu_i32: + case INDEX_op_remu_i64: + return C_O1_I2(r, rZ, rZ); + + default: + g_assert_not_reached(); + } +} + +static const int tcg_target_callee_save_regs[] = { + TCG_REG_S0, /* used for the global env (TCG_AREG0) */ + TCG_REG_S1, + TCG_REG_S2, + TCG_REG_S3, + TCG_REG_S4, + TCG_REG_S5, + TCG_REG_S6, + TCG_REG_S7, + TCG_REG_S8, + TCG_REG_S9, + TCG_REG_RA, /* should be last for ABI compliance */ +}; + +/* Stack frame parameters. */ +#define REG_SIZE (TCG_TARGET_REG_BITS / 8) +#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE) +#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long)) +#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \ + + TCG_TARGET_STACK_ALIGN - 1) \ + & -TCG_TARGET_STACK_ALIGN) +#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE) + +/* We're expecting to be able to use an immediate for frame allocation. */ +QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff); + +/* Generate global QEMU prologue and epilogue code */ +static void tcg_target_qemu_prologue(TCGContext *s) +{ + int i; + + tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE); + + /* TB prologue */ + tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE); + for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { + tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], + TCG_REG_SP, SAVE_OFS + i * REG_SIZE); + } + +#if !defined(CONFIG_SOFTMMU) + if (USE_GUEST_BASE) { + tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base); + tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); + } +#endif + + /* Call generated code */ + tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); + tcg_out_opc_jirl(s, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0); + + /* Return path for goto_ptr. Set return value to 0 */ + tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr); + tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO); + + /* TB epilogue */ + tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr); + for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { + tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], + TCG_REG_SP, SAVE_OFS + i * REG_SIZE); + } + + tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE); + tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_RA, 0); +} + +static void tcg_target_init(TCGContext *s) +{ + tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS; + tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS; + + tcg_target_call_clobber_regs = ALL_GENERAL_REGS; + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9); + + s->reserved_regs = 0; + tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_RESERVED); +} + +typedef struct { + DebugFrameHeader h; + uint8_t fde_def_cfa[4]; + uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; +} DebugFrame; + +#define ELF_HOST_MACHINE EM_LOONGARCH + +static const DebugFrame debug_frame = { + .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */ + .h.cie.id = -1, + .h.cie.version = 1, + .h.cie.code_align = 1, + .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */ + .h.cie.return_column = TCG_REG_RA, + + /* Total FDE size does not include the "len" member. */ + .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), + + .fde_def_cfa = { + 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ + (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ + (FRAME_SIZE >> 7) + }, + .fde_reg_ofs = { + 0x80 + 23, 11, /* DW_CFA_offset, s0, -88 */ + 0x80 + 24, 10, /* DW_CFA_offset, s1, -80 */ + 0x80 + 25, 9, /* DW_CFA_offset, s2, -72 */ + 0x80 + 26, 8, /* DW_CFA_offset, s3, -64 */ + 0x80 + 27, 7, /* DW_CFA_offset, s4, -56 */ + 0x80 + 28, 6, /* DW_CFA_offset, s5, -48 */ + 0x80 + 29, 5, /* DW_CFA_offset, s6, -40 */ + 0x80 + 30, 4, /* DW_CFA_offset, s7, -32 */ + 0x80 + 31, 3, /* DW_CFA_offset, s8, -24 */ + 0x80 + 22, 2, /* DW_CFA_offset, s9, -16 */ + 0x80 + 1 , 1, /* DW_CFA_offset, ra, -8 */ + } +}; + +void tcg_register_jit(const void *buf, size_t buf_size) +{ + tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); +} diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h new file mode 100644 index 0000000000..d58a6162f2 --- /dev/null +++ b/tcg/loongarch64/tcg-target.h @@ -0,0 +1,178 @@ +/* + * Tiny Code Generator for QEMU + * + * Copyright (c) 2021 WANG Xuerui + * + * Based on tcg/riscv/tcg-target.h + * + * Copyright (c) 2018 SiFive, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef LOONGARCH_TCG_TARGET_H +#define LOONGARCH_TCG_TARGET_H + +/* + * Loongson removed the (incomplete) 32-bit support from kernel and toolchain + * for the initial upstreaming of this architecture, so don't bother and just + * support the LP64* ABI for now. + */ +#if defined(__loongarch64) +# define TCG_TARGET_REG_BITS 64 +#else +# error unsupported LoongArch register size +#endif + +#define TCG_TARGET_INSN_UNIT_SIZE 4 +#define TCG_TARGET_NB_REGS 32 +#define MAX_CODE_GEN_BUFFER_SIZE SIZE_MAX + +typedef enum { + TCG_REG_ZERO, + TCG_REG_RA, + TCG_REG_TP, + TCG_REG_SP, + TCG_REG_A0, + TCG_REG_A1, + TCG_REG_A2, + TCG_REG_A3, + TCG_REG_A4, + TCG_REG_A5, + TCG_REG_A6, + TCG_REG_A7, + TCG_REG_T0, + TCG_REG_T1, + TCG_REG_T2, + TCG_REG_T3, + TCG_REG_T4, + TCG_REG_T5, + TCG_REG_T6, + TCG_REG_T7, + TCG_REG_T8, + TCG_REG_RESERVED, + TCG_REG_S9, + TCG_REG_S0, + TCG_REG_S1, + TCG_REG_S2, + TCG_REG_S3, + TCG_REG_S4, + TCG_REG_S5, + TCG_REG_S6, + TCG_REG_S7, + TCG_REG_S8, + + /* aliases */ + TCG_AREG0 = TCG_REG_S0, + TCG_REG_TMP0 = TCG_REG_T8, + TCG_REG_TMP1 = TCG_REG_T7, + TCG_REG_TMP2 = TCG_REG_T6, +} TCGReg; + +/* used for function call generation */ +#define TCG_REG_CALL_STACK TCG_REG_SP +#define TCG_TARGET_STACK_ALIGN 16 +#define TCG_TARGET_CALL_ALIGN_ARGS 1 +#define TCG_TARGET_CALL_STACK_OFFSET 0 + +/* optional instructions */ +#define TCG_TARGET_HAS_movcond_i32 0 +#define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 1 +#define TCG_TARGET_HAS_div2_i32 0 +#define TCG_TARGET_HAS_rot_i32 1 +#define TCG_TARGET_HAS_deposit_i32 1 +#define TCG_TARGET_HAS_extract_i32 1 +#define TCG_TARGET_HAS_sextract_i32 0 +#define TCG_TARGET_HAS_extract2_i32 0 +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_mulu2_i32 0 +#define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 1 +#define TCG_TARGET_HAS_mulsh_i32 1 +#define TCG_TARGET_HAS_ext8s_i32 1 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_ext8u_i32 1 +#define TCG_TARGET_HAS_ext16u_i32 1 +#define TCG_TARGET_HAS_bswap16_i32 1 +#define TCG_TARGET_HAS_bswap32_i32 1 +#define TCG_TARGET_HAS_not_i32 1 +#define TCG_TARGET_HAS_neg_i32 0 +#define TCG_TARGET_HAS_andc_i32 1 +#define TCG_TARGET_HAS_orc_i32 1 +#define TCG_TARGET_HAS_eqv_i32 0 +#define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_nor_i32 1 +#define TCG_TARGET_HAS_clz_i32 1 +#define TCG_TARGET_HAS_ctz_i32 1 +#define TCG_TARGET_HAS_ctpop_i32 0 +#define TCG_TARGET_HAS_direct_jump 0 +#define TCG_TARGET_HAS_brcond2 0 +#define TCG_TARGET_HAS_setcond2 0 +#define TCG_TARGET_HAS_qemu_st8_i32 0 + +/* 64-bit operations */ +#define TCG_TARGET_HAS_movcond_i64 0 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 +#define TCG_TARGET_HAS_div2_i64 0 +#define TCG_TARGET_HAS_rot_i64 1 +#define TCG_TARGET_HAS_deposit_i64 1 +#define TCG_TARGET_HAS_extract_i64 1 +#define TCG_TARGET_HAS_sextract_i64 0 +#define TCG_TARGET_HAS_extract2_i64 0 +#define TCG_TARGET_HAS_extrl_i64_i32 1 +#define TCG_TARGET_HAS_extrh_i64_i32 1 +#define TCG_TARGET_HAS_ext8s_i64 1 +#define TCG_TARGET_HAS_ext16s_i64 1 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext8u_i64 1 +#define TCG_TARGET_HAS_ext16u_i64 1 +#define TCG_TARGET_HAS_ext32u_i64 1 +#define TCG_TARGET_HAS_bswap16_i64 1 +#define TCG_TARGET_HAS_bswap32_i64 1 +#define TCG_TARGET_HAS_bswap64_i64 1 +#define TCG_TARGET_HAS_not_i64 1 +#define TCG_TARGET_HAS_neg_i64 0 +#define TCG_TARGET_HAS_andc_i64 1 +#define TCG_TARGET_HAS_orc_i64 1 +#define TCG_TARGET_HAS_eqv_i64 0 +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_nor_i64 1 +#define TCG_TARGET_HAS_clz_i64 1 +#define TCG_TARGET_HAS_ctz_i64 1 +#define TCG_TARGET_HAS_ctpop_i64 0 +#define TCG_TARGET_HAS_add2_i64 0 +#define TCG_TARGET_HAS_sub2_i64 0 +#define TCG_TARGET_HAS_mulu2_i64 0 +#define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 1 +#define TCG_TARGET_HAS_mulsh_i64 1 + +/* not defined -- call should be eliminated at compile time */ +void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); + +#define TCG_TARGET_DEFAULT_MO (0) + +#define TCG_TARGET_NEED_LDST_LABELS + +#define TCG_TARGET_HAS_MEMORY_BSWAP 0 + +#endif /* LOONGARCH_TCG_TARGET_H */ -- Gitee From 1d21568eaf11f35e5cc8d96eb7d8ddd0b3b77430 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 05:48:46 -0400 Subject: [PATCH 10/29] Modify smbios option lack and Modify the maximum number of CPUs supported by the virtual machine. Add smbios option support for loongarch. The number of virtual CPUs can be greater than the number of CPUs of the host machine. Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- accel/kvm/kvm-all.c | 2 +- qemu-options.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index decc77b472..b69fef27f0 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2503,7 +2503,7 @@ static int kvm_init(MachineState *ms) soft_vcpus_limit = kvm_recommended_vcpus(s); hard_vcpus_limit = kvm_max_vcpus(s); -#ifdef HOST_PPC64 +#if defined(HOST_PPC64) || defined(HOST_LOONGARCH) /* * On POWER, the kernel advertises a soft limit based on the * number of CPU threads on the host. We want to allow exceeding diff --git a/qemu-options.hx b/qemu-options.hx index 6eaa529d4b..eaf16a68e0 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2480,7 +2480,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios, " specify SMBIOS type 17 fields\n" "-smbios type=41[,designation=str][,kind=str][,instance=%d][,pcidev=str]\n" " specify SMBIOS type 41 fields\n", - QEMU_ARCH_I386 | QEMU_ARCH_ARM) + QEMU_ARCH_I386 | QEMU_ARCH_ARM | QEMU_ARCH_LOONGARCH64) SRST ``-smbios file=binary`` Load SMBIOS entry from binary file. -- Gitee From e5f741545f0c184c29b07d6904cc6ea196061c32 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 05:57:27 -0400 Subject: [PATCH 11/29] rename kvm_msr_buf with kvm_csr_buf. Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- target/loongarch64/cpu.h | 2 +- target/loongarch64/kvm.c | 564 +++++++++++++++++++-------------------- 2 files changed, 283 insertions(+), 283 deletions(-) diff --git a/target/loongarch64/cpu.h b/target/loongarch64/cpu.h index 10facb3b73..078556a22a 100644 --- a/target/loongarch64/cpu.h +++ b/target/loongarch64/cpu.h @@ -200,7 +200,7 @@ struct LOONGARCHCPU { VMChangeStateEntry *cpuStateEntry; int32_t node_id; /* NUMA node this CPU belongs to */ int32_t core_id; - struct kvm_msrs *kvm_msr_buf; + struct kvm_msrs *kvm_csr_buf; /* 'compatible' string for this CPU for Linux device trees */ const char *dtb_compatible; }; diff --git a/target/loongarch64/kvm.c b/target/loongarch64/kvm.c index 404a605eb6..b5c655812b 100644 --- a/target/loongarch64/kvm.c +++ b/target/loongarch64/kvm.c @@ -31,7 +31,7 @@ #define DEBUG_KVM 0 /* A 16384-byte buffer can hold the 8-byte kvm_msrs header, plus * 2047 kvm_msr_entry structs */ -#define MSR_BUF_SIZE 16384 +#define CSR_BUF_SIZE 16384 #define DPRINTF(fmt, ...) \ do { if (DEBUG_KVM) { fprintf(stderr, fmt, ## __VA_ARGS__); } } while (0) @@ -101,7 +101,7 @@ int kvm_arch_init_vcpu(CPUState *cs) int ret = 0; cpu->cpuStateEntry = qemu_add_vm_change_state_handler(kvm_loongarch_update_state, cs); - cpu->kvm_msr_buf = g_malloc0(MSR_BUF_SIZE); + cpu->kvm_csr_buf = g_malloc0(CSR_BUF_SIZE); DPRINTF("%s\n", __func__); return ret; } @@ -111,15 +111,15 @@ int kvm_arch_destroy_vcpu(CPUState *cs) return 0; } -static void kvm_msr_buf_reset(LOONGARCHCPU *cpu) +static void kvm_csr_buf_reset(LOONGARCHCPU *cpu) { - memset(cpu->kvm_msr_buf, 0, MSR_BUF_SIZE); + memset(cpu->kvm_csr_buf, 0, CSR_BUF_SIZE); } -static void kvm_msr_entry_add(LOONGARCHCPU *cpu, uint32_t index, uint64_t value) +static void kvm_csr_entry_add(LOONGARCHCPU *cpu, uint32_t index, uint64_t value) { - struct kvm_msrs *msrs = cpu->kvm_msr_buf; - void *limit = ((void *)msrs) + MSR_BUF_SIZE; + struct kvm_msrs *msrs = cpu->kvm_csr_buf; + void *limit = ((void *)msrs) + CSR_BUF_SIZE; struct kvm_csr_entry *entry = &msrs->entries[msrs->ncsrs]; assert((void *)(entry + 1) <= limit); @@ -767,144 +767,144 @@ static int kvm_loongarch_put_csr_registers(CPUState *cs, int level) (void)level; - kvm_msr_buf_reset(cpu); - - kvm_msr_entry_add(cpu, LOONGARCH_CSR_CRMD, env->CSR_CRMD); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRMD, env->CSR_PRMD); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_EUEN, env->CSR_EUEN); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_MISC, env->CSR_MISC); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ECFG, env->CSR_ECFG); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ESTAT, env->CSR_ESTAT); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERA, env->CSR_ERA); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADV, env->CSR_BADV); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADI, env->CSR_BADI); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_EEPN, env->CSR_EEPN); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBIDX, env->CSR_TLBIDX); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBEHI, env->CSR_TLBEHI); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO0, env->CSR_TLBELO0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO1, env->CSR_TLBELO1); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GTLBC, env->CSR_GTLBC); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TRGP, env->CSR_TRGP); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ASID, env->CSR_ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDL, env->CSR_PGDL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDH, env->CSR_PGDH); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGD, env->CSR_PGD); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL0, env->CSR_PWCTL0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL1, env->CSR_PWCTL1); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_STLBPGSIZE, env->CSR_STLBPGSIZE); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_RVACFG, env->CSR_RVACFG); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_CPUID, env->CSR_CPUID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG1, env->CSR_PRCFG1); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG2, env->CSR_PRCFG2); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG3, env->CSR_PRCFG3); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS0, env->CSR_KS0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS1, env->CSR_KS1); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS2, env->CSR_KS2); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS3, env->CSR_KS3); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS4, env->CSR_KS4); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS5, env->CSR_KS5); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS6, env->CSR_KS6); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS7, env->CSR_KS7); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TMID, env->CSR_TMID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_CNTC, env->CSR_CNTC); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TINTCLR, env->CSR_TINTCLR); - - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GSTAT, env->CSR_GSTAT); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCFG, env->CSR_GCFG); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GINTC, env->CSR_GINTC); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCNTC, env->CSR_GCNTC); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_LLBCTL, env->CSR_LLBCTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL1, env->CSR_IMPCTL1); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL2, env->CSR_IMPCTL2); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GNMI, env->CSR_GNMI); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRENT, env->CSR_TLBRENT); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRBADV, env->CSR_TLBRBADV); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRERA, env->CSR_TLBRERA); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRSAVE, env->CSR_TLBRSAVE); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO0, env->CSR_TLBRELO0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO1, env->CSR_TLBRELO1); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBREHI, env->CSR_TLBREHI); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRPRMD, env->CSR_TLBRPRMD); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRCTL, env->CSR_ERRCTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO, env->CSR_ERRINFO); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO1, env->CSR_ERRINFO1); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRENT, env->CSR_ERRENT); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRERA, env->CSR_ERRERA); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRSAVE, env->CSR_ERRSAVE); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_CTAG, env->CSR_CTAG); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN0, env->CSR_DMWIN0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN1, env->CSR_DMWIN1); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN2, env->CSR_DMWIN2); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN3, env->CSR_DMWIN3); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL0, env->CSR_PERFCTRL0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR0, env->CSR_PERFCNTR0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL1, env->CSR_PERFCTRL1); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR1, env->CSR_PERFCNTR1); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL2, env->CSR_PERFCTRL2); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR2, env->CSR_PERFCNTR2); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL3, env->CSR_PERFCTRL3); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR3, env->CSR_PERFCNTR3); + kvm_csr_buf_reset(cpu); + + kvm_csr_entry_add(cpu, LOONGARCH_CSR_CRMD, env->CSR_CRMD); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PRMD, env->CSR_PRMD); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_EUEN, env->CSR_EUEN); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_MISC, env->CSR_MISC); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ECFG, env->CSR_ECFG); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ESTAT, env->CSR_ESTAT); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERA, env->CSR_ERA); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_BADV, env->CSR_BADV); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_BADI, env->CSR_BADI); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_EEPN, env->CSR_EEPN); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBIDX, env->CSR_TLBIDX); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBEHI, env->CSR_TLBEHI); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBELO0, env->CSR_TLBELO0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBELO1, env->CSR_TLBELO1); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GTLBC, env->CSR_GTLBC); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TRGP, env->CSR_TRGP); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ASID, env->CSR_ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PGDL, env->CSR_PGDL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PGDH, env->CSR_PGDH); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PGD, env->CSR_PGD); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PWCTL0, env->CSR_PWCTL0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PWCTL1, env->CSR_PWCTL1); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_STLBPGSIZE, env->CSR_STLBPGSIZE); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_RVACFG, env->CSR_RVACFG); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_CPUID, env->CSR_CPUID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PRCFG1, env->CSR_PRCFG1); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PRCFG2, env->CSR_PRCFG2); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PRCFG3, env->CSR_PRCFG3); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS0, env->CSR_KS0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS1, env->CSR_KS1); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS2, env->CSR_KS2); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS3, env->CSR_KS3); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS4, env->CSR_KS4); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS5, env->CSR_KS5); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS6, env->CSR_KS6); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS7, env->CSR_KS7); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TMID, env->CSR_TMID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_CNTC, env->CSR_CNTC); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TINTCLR, env->CSR_TINTCLR); + + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GSTAT, env->CSR_GSTAT); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GCFG, env->CSR_GCFG); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GINTC, env->CSR_GINTC); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GCNTC, env->CSR_GCNTC); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_LLBCTL, env->CSR_LLBCTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IMPCTL1, env->CSR_IMPCTL1); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IMPCTL2, env->CSR_IMPCTL2); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GNMI, env->CSR_GNMI); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRENT, env->CSR_TLBRENT); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRBADV, env->CSR_TLBRBADV); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRERA, env->CSR_TLBRERA); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRSAVE, env->CSR_TLBRSAVE); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRELO0, env->CSR_TLBRELO0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRELO1, env->CSR_TLBRELO1); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBREHI, env->CSR_TLBREHI); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRPRMD, env->CSR_TLBRPRMD); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRCTL, env->CSR_ERRCTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRINFO, env->CSR_ERRINFO); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRINFO1, env->CSR_ERRINFO1); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRENT, env->CSR_ERRENT); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRERA, env->CSR_ERRERA); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRSAVE, env->CSR_ERRSAVE); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_CTAG, env->CSR_CTAG); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DMWIN0, env->CSR_DMWIN0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DMWIN1, env->CSR_DMWIN1); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DMWIN2, env->CSR_DMWIN2); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DMWIN3, env->CSR_DMWIN3); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL0, env->CSR_PERFCTRL0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR0, env->CSR_PERFCNTR0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL1, env->CSR_PERFCTRL1); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR1, env->CSR_PERFCNTR1); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL2, env->CSR_PERFCTRL2); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR2, env->CSR_PERFCNTR2); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL3, env->CSR_PERFCTRL3); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR3, env->CSR_PERFCNTR3); /* debug */ - kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPC, env->CSR_MWPC); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPS, env->CSR_MWPS); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ADDR, env->CSR_DB0ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0MASK, env->CSR_DB0MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0CTL, env->CSR_DB0CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ASID, env->CSR_DB0ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ADDR, env->CSR_DB1ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1MASK, env->CSR_DB1MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1CTL, env->CSR_DB1CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ASID, env->CSR_DB1ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ADDR, env->CSR_DB2ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2MASK, env->CSR_DB2MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2CTL, env->CSR_DB2CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ASID, env->CSR_DB2ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ADDR, env->CSR_DB3ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3MASK, env->CSR_DB3MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3CTL, env->CSR_DB3CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ASID, env->CSR_DB3ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPC, env->CSR_FWPC); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPS, env->CSR_FWPS); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ADDR, env->CSR_IB0ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0MASK, env->CSR_IB0MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0CTL, env->CSR_IB0CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ASID, env->CSR_IB0ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ADDR, env->CSR_IB1ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1MASK, env->CSR_IB1MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1CTL, env->CSR_IB1CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ASID, env->CSR_IB1ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ADDR, env->CSR_IB2ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2MASK, env->CSR_IB2MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2CTL, env->CSR_IB2CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ASID, env->CSR_IB2ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ADDR, env->CSR_IB3ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3MASK, env->CSR_IB3MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3CTL, env->CSR_IB3CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ASID, env->CSR_IB3ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ADDR, env->CSR_IB4ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4MASK, env->CSR_IB4MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4CTL, env->CSR_IB4CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ASID, env->CSR_IB4ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ADDR, env->CSR_IB5ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5MASK, env->CSR_IB5MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5CTL, env->CSR_IB5CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ASID, env->CSR_IB5ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ADDR, env->CSR_IB6ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6MASK, env->CSR_IB6MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6CTL, env->CSR_IB6CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ASID, env->CSR_IB6ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ADDR, env->CSR_IB7ADDR); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7MASK, env->CSR_IB7MASK); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7CTL, env->CSR_IB7CTL); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ASID, env->CSR_IB7ASID); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DEBUG, env->CSR_DEBUG); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DERA, env->CSR_DERA); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DESAVE, env->CSR_DESAVE); - - ret = kvm_vcpu_ioctl(cs, KVM_SET_MSRS, cpu->kvm_msr_buf); - if (ret < cpu->kvm_msr_buf->ncsrs) { - struct kvm_csr_entry *e = &cpu->kvm_msr_buf->entries[ret]; + kvm_csr_entry_add(cpu, LOONGARCH_CSR_MWPC, env->CSR_MWPC); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_MWPS, env->CSR_MWPS); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB0ADDR, env->CSR_DB0ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB0MASK, env->CSR_DB0MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB0CTL, env->CSR_DB0CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB0ASID, env->CSR_DB0ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB1ADDR, env->CSR_DB1ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB1MASK, env->CSR_DB1MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB1CTL, env->CSR_DB1CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB1ASID, env->CSR_DB1ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB2ADDR, env->CSR_DB2ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB2MASK, env->CSR_DB2MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB2CTL, env->CSR_DB2CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB2ASID, env->CSR_DB2ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB3ADDR, env->CSR_DB3ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB3MASK, env->CSR_DB3MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB3CTL, env->CSR_DB3CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB3ASID, env->CSR_DB3ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_FWPC, env->CSR_FWPC); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_FWPS, env->CSR_FWPS); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB0ADDR, env->CSR_IB0ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB0MASK, env->CSR_IB0MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB0CTL, env->CSR_IB0CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB0ASID, env->CSR_IB0ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB1ADDR, env->CSR_IB1ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB1MASK, env->CSR_IB1MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB1CTL, env->CSR_IB1CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB1ASID, env->CSR_IB1ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB2ADDR, env->CSR_IB2ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB2MASK, env->CSR_IB2MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB2CTL, env->CSR_IB2CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB2ASID, env->CSR_IB2ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB3ADDR, env->CSR_IB3ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB3MASK, env->CSR_IB3MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB3CTL, env->CSR_IB3CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB3ASID, env->CSR_IB3ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB4ADDR, env->CSR_IB4ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB4MASK, env->CSR_IB4MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB4CTL, env->CSR_IB4CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB4ASID, env->CSR_IB4ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB5ADDR, env->CSR_IB5ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB5MASK, env->CSR_IB5MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB5CTL, env->CSR_IB5CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB5ASID, env->CSR_IB5ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB6ADDR, env->CSR_IB6ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB6MASK, env->CSR_IB6MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB6CTL, env->CSR_IB6CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB6ASID, env->CSR_IB6ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB7ADDR, env->CSR_IB7ADDR); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB7MASK, env->CSR_IB7MASK); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB7CTL, env->CSR_IB7CTL); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB7ASID, env->CSR_IB7ASID); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DEBUG, env->CSR_DEBUG); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DERA, env->CSR_DERA); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DESAVE, env->CSR_DESAVE); + + ret = kvm_vcpu_ioctl(cs, KVM_SET_MSRS, cpu->kvm_csr_buf); + if (ret < cpu->kvm_csr_buf->ncsrs) { + struct kvm_csr_entry *e = &cpu->kvm_csr_buf->entries[ret]; printf("error: failed to set CSR 0x%" PRIx32 " to 0x%" PRIx64"\n", (uint32_t)e->index, (uint64_t)e->data); } @@ -935,147 +935,147 @@ static int kvm_loongarch_get_csr_registers(CPUState *cs) LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); CPULOONGARCHState *env = &cpu->env; int ret = 0, i; - struct kvm_csr_entry *csrs = cpu->kvm_msr_buf->entries; - - kvm_msr_buf_reset(cpu); - - kvm_msr_entry_add(cpu, LOONGARCH_CSR_CRMD, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRMD, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_EUEN, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_MISC, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ECFG, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ESTAT, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERA, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADV, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_BADI, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_EEPN, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBIDX, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBEHI, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO0, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBELO1, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GTLBC, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TRGP, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGDH, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PGD, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL0, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PWCTL1, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_STLBPGSIZE, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_RVACFG, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_CPUID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG1, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG2, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PRCFG3, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS0, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS1, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS2, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS3, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS4, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS5, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS6, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_KS7, 0); - - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TMID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_CNTC, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TINTCLR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GSTAT, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCFG, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GINTC, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GCNTC, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_LLBCTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL1, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IMPCTL2, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_GNMI, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRENT, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRBADV, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRERA, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRSAVE, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO0, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRELO1, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBREHI, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_TLBRPRMD, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRCTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRINFO1, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRENT, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRERA, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_ERRSAVE, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_CTAG, 0); - - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN0, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN1, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN2, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DMWIN3, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL0, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR0, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL1, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR1, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL2, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR2, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL3, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR3, 0); + struct kvm_csr_entry *csrs = cpu->kvm_csr_buf->entries; + + kvm_csr_buf_reset(cpu); + + kvm_csr_entry_add(cpu, LOONGARCH_CSR_CRMD, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PRMD, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_EUEN, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_MISC, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ECFG, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ESTAT, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERA, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_BADV, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_BADI, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_EEPN, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBIDX, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBEHI, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBELO0, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBELO1, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GTLBC, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TRGP, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PGDL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PGDH, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PGD, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PWCTL0, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PWCTL1, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_STLBPGSIZE, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_RVACFG, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_CPUID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PRCFG1, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PRCFG2, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PRCFG3, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS0, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS1, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS2, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS3, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS4, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS5, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS6, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_KS7, 0); + + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TMID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_CNTC, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TINTCLR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GSTAT, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GCFG, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GINTC, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GCNTC, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_LLBCTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IMPCTL1, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IMPCTL2, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_GNMI, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRENT, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRBADV, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRERA, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRSAVE, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRELO0, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRELO1, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBREHI, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_TLBRPRMD, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRCTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRINFO, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRINFO1, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRENT, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRERA, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_ERRSAVE, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_CTAG, 0); + + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DMWIN0, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DMWIN1, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DMWIN2, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DMWIN3, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL0, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR0, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL1, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR1, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL2, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR2, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCTRL3, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_PERFCNTR3, 0); /* debug */ - kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPC, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_MWPS, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB0ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB1ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB2ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DB3ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPC, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_FWPS, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB0ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB1ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB2ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB3ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB4ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB5ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB6ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ADDR, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7MASK, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7CTL, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_IB7ASID, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DEBUG, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DERA, 0); - kvm_msr_entry_add(cpu, LOONGARCH_CSR_DESAVE, 0); - - ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, cpu->kvm_msr_buf); - if (ret < cpu->kvm_msr_buf->ncsrs) { - struct kvm_csr_entry *e = &cpu->kvm_msr_buf->entries[ret]; + kvm_csr_entry_add(cpu, LOONGARCH_CSR_MWPC, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_MWPS, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB0ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB0MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB0CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB0ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB1ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB1MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB1CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB1ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB2ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB2MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB2CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB2ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB3ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB3MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB3CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DB3ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_FWPC, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_FWPS, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB0ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB0MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB0CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB0ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB1ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB1MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB1CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB1ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB2ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB2MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB2CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB2ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB3ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB3MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB3CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB3ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB4ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB4MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB4CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB4ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB5ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB5MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB5CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB5ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB6ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB6MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB6CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB6ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB7ADDR, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB7MASK, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB7CTL, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_IB7ASID, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DEBUG, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DERA, 0); + kvm_csr_entry_add(cpu, LOONGARCH_CSR_DESAVE, 0); + + ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, cpu->kvm_csr_buf); + if (ret < cpu->kvm_csr_buf->ncsrs) { + struct kvm_csr_entry *e = &cpu->kvm_csr_buf->entries[ret]; printf("error: failed to get CSR 0x%" PRIx32"\n", (uint32_t)e->index); } -- Gitee From 4513c4f499acdd239a7590900b0669065b3c1362 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 07:04:10 -0400 Subject: [PATCH 12/29] code cleanup for loongarch kvm. Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- linux-headers/asm-loongarch64/kvm.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/linux-headers/asm-loongarch64/kvm.h b/linux-headers/asm-loongarch64/kvm.h index a24375ee59..799af75940 100644 --- a/linux-headers/asm-loongarch64/kvm.h +++ b/linux-headers/asm-loongarch64/kvm.h @@ -72,15 +72,7 @@ struct kvm_fpu { * * Register set = 0: GP registers from kvm_regs (see definitions below). * - * Register set = 1: CP0 registers. - * bits[15..8] - COP0 register set. - * - * COP0 register set = 0: Main CP0 registers. - * bits[7..3] - Register 'rd' index. - * bits[2..0] - Register 'sel' index. - * - * COP0 register set = 1: MAARs. - * bits[7..0] - MAAR index. + * Register set = 1: CSR registers. * * Register set = 2: KVM specific registers (see definitions below). * -- Gitee From 751c393f44e1d14f238c2b8fdadb159c282c7ed4 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 07:16:34 -0400 Subject: [PATCH 13/29] Support TPM. Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- hw/loongarch/acpi-build.c | 44 +++++++ hw/loongarch/larch_3a.c | 53 ++++++++- hw/loongarch/larch_hotplug.c | 16 ++- hw/loongarch/meson.build | 1 + hw/loongarch/sysbus-fdt.c | 183 ++++++++++++++++++++++++++++++ include/hw/loongarch/larch.h | 1 + include/hw/loongarch/ls7a.h | 5 + include/hw/loongarch/sysbus-fdt.h | 37 ++++++ 8 files changed, 333 insertions(+), 7 deletions(-) create mode 100644 hw/loongarch/sysbus-fdt.c create mode 100644 include/hw/loongarch/sysbus-fdt.h diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index 6ba637be53..682e016be2 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -58,6 +58,7 @@ #include "hw/acpi/aml-build.h" #include "hw/loongarch/larch.h" #include "hw/loongarch/ls7a.h" +#include "hw/platform-bus.h" #include "hw/acpi/ipmi.h" #include "hw/acpi/ls7a.h" @@ -474,7 +475,40 @@ static void build_ls7a_uart_device_aml(Aml *table) aml_append(scope, dev); aml_append(table, scope); } +#ifdef CONFIG_TPM +static void acpi_dsdt_add_tpm(Aml *scope, LoongarchMachineState *vms) +{ + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev); + hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS; + SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find()); + MemoryRegion *sbdev_mr; + hwaddr tpm_base; + + if (!sbdev) { + return; + } + + tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0); + assert(tpm_base != -1); + tpm_base += pbus_base; + + sbdev_mr = sysbus_mmio_get_region(sbdev, 0); + + Aml *dev = aml_device("TPM0"); + aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); + aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + + Aml *crs = aml_resource_template(); + aml_append(crs, + aml_memory32_fixed(tpm_base, + (uint32_t)memory_region_size(sbdev_mr), + AML_READ_WRITE)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} +#endif static void build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) { @@ -500,6 +534,10 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(dev, build_ls7a_osc_method()); aml_append(sb_scope, dev); + +#ifdef CONFIG_TPM + acpi_dsdt_add_tpm(sb_scope, lsms); +#endif aml_append(dsdt, sb_scope); build_ls7a_pci0_int(dsdt); @@ -633,6 +671,12 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) lsms->oem_table_id); } + if (tpm_get_version(tpm_find()) == TPM_VERSION_2_0) { + acpi_add_table(table_offsets, tables_blob); + build_tpm2(tables_blob, tables->linker, tables->tcpalog, + lsms->oem_id, lsms->oem_table_id); + } + /* Build mcfg */ acpi_add_table(table_offsets, tables_blob); { diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c index 3194a822cc..6c2602050e 100644 --- a/hw/loongarch/larch_3a.c +++ b/hw/loongarch/larch_3a.c @@ -52,6 +52,7 @@ #include "hw/rtc/mc146818rtc.h" #include "hw/irq.h" #include "net/net.h" +#include "hw/platform-bus.h" #include "hw/timer/i8254.h" #include "hw/loongarch/larch.h" #include "hw/loongarch/ls7a.h" @@ -65,6 +66,8 @@ #include "sysemu/device_tree.h" #include "qapi/visitor.h" #include "qapi/qapi-visit-common.h" +#include "sysemu/tpm.h" +#include "hw/loongarch/sysbus-fdt.h" #include @@ -1235,6 +1238,19 @@ void loongarch_machine_done(Notifier *notifier, void *data) { LoongarchMachineState *lsms = container_of(notifier, LoongarchMachineState, machine_done); + + platform_bus_add_all_fdt_nodes(lsms->fdt, NULL, + VIRT_PLATFORM_BUS_BASEADDRESS, + VIRT_PLATFORM_BUS_SIZE, + VIRT_PLATFORM_BUS_IRQ); + + qemu_fdt_dumpdtb(lsms->fdt, lsms->fdt_size); + /* load fdt */ + MemoryRegion *fdt_rom = g_new(MemoryRegion, 1); + memory_region_init_rom(fdt_rom, NULL, "fdt", LS_FDT_SIZE, &error_fatal); + memory_region_add_subregion(get_system_memory(), LS_FDT_BASE, fdt_rom); + rom_add_blob_fixed("fdt", lsms->fdt, lsms->fdt_size, LS_FDT_BASE); + loongarch_acpi_setup(); loongarch_build_smbios(lsms); } @@ -1562,7 +1578,31 @@ static void fdt_add_pcie_node(const LoongarchMachineState *lsms) 1, FDT_PCI_RANGE_MMIO, 2, base_mmio, 2, base_mmio, 2, size_mmio); g_free(nodename); - qemu_fdt_dumpdtb(lsms->fdt, lsms->fdt_size); +} + +static void create_platform_bus(LoongarchMachineState *s, qemu_irq *pic) +{ + DeviceState *dev; + SysBusDevice *sysbus; + int i; + MemoryRegion *sysmem = get_system_memory(); + + dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE); + dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE); + qdev_prop_set_uint32(dev, "num_irqs", VIRT_PLATFORM_BUS_NUM_IRQS); + qdev_prop_set_uint32(dev, "mmio_size", VIRT_PLATFORM_BUS_SIZE); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + s->platform_bus_dev = dev; + + sysbus = SYS_BUS_DEVICE(dev); + for (i = 0; i < VIRT_PLATFORM_BUS_NUM_IRQS; i++) { + int irq = VIRT_PLATFORM_BUS_IRQ + i; + sysbus_connect_irq(sysbus, i, pic[irq - LOONGARCH_PCH_IRQ_BASE]); + } + + memory_region_add_subregion(sysmem, + VIRT_PLATFORM_BUS_BASEADDRESS, + sysbus_mmio_get_region(sysbus, 0)); } static void ls3a5k_init(MachineState *args) @@ -1784,6 +1824,8 @@ static void ls3a5k_init(MachineState *args) object_property_set_link(OBJECT(machine), LOONGARCH_MACHINE_ACPI_DEVICE_PROP, OBJECT(ls7a_dev), &error_abort); + create_platform_bus(lsms, ls7a_apic); + #ifdef CONFIG_KVM if (kvm_enabled()) { kvm_direct_msi_allowed = (kvm_check_extension(kvm_state, @@ -1835,11 +1877,6 @@ static void ls3a5k_init(MachineState *args) fdt_add_pcie_node(lsms); - /* load fdt */ - MemoryRegion *fdt_rom = g_new(MemoryRegion, 1); - memory_region_init_rom(fdt_rom, NULL, "fdt", LS_FDT_SIZE, &error_fatal); - memory_region_add_subregion(get_system_memory(), LS_FDT_BASE, fdt_rom); - rom_add_blob_fixed("fdt", lsms->fdt, lsms->fdt_size, LS_FDT_BASE); } static const CPUArchIdList *loongarch_possible_cpu_arch_ids(MachineState *ms) @@ -1986,6 +2023,10 @@ static void loongarch_class_init(ObjectClass *oc, void *data) mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000"); mc->default_ram_id = "loongarch_ls3a.ram"; +#ifdef CONFIG_TPM + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS); +#endif + mc->reset = ls3a_board_reset; mc->max_cpus = LOONGARCH_MAX_VCPUS; hc->pre_plug = loongarch_machine_device_pre_plug; diff --git a/hw/loongarch/larch_hotplug.c b/hw/loongarch/larch_hotplug.c index 7bce957124..bb3e9826b2 100644 --- a/hw/loongarch/larch_hotplug.c +++ b/hw/loongarch/larch_hotplug.c @@ -32,6 +32,7 @@ #include "hw/loongarch/larch.h" #include "hw/cpu/core.h" #include "hw/nvram/fw_cfg.h" +#include "hw/platform-bus.h" /* find cpu slot in machine->possible_cpus by core_id */ static CPUArchId *loongarch_find_cpu_slot(MachineState *ms, uint32_t id, @@ -327,7 +328,8 @@ HotplugHandler *loongarch_get_hotpug_handler(MachineState *machine, DeviceState *dev) { if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || - object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { + object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU) || + object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) { return HOTPLUG_HANDLER(machine); } return NULL; @@ -346,6 +348,18 @@ void loongarch_machine_device_pre_plug(HotplugHandler *hotplug_dev, void loongarch_machine_device_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + LoongarchMachineState *lsms = LoongarchMACHINE(hotplug_dev); + + if (lsms->platform_bus_dev) { + MachineClass *mc = MACHINE_GET_CLASS(lsms); + + if (device_is_dynamic_sysbus(mc, dev)) { + platform_bus_link_device( + PLATFORM_BUS_DEVICE(lsms->platform_bus_dev), + SYS_BUS_DEVICE(dev)); + } + } + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { loongarch_memory_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) { diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build index 81ee99a028..47d886ddd4 100644 --- a/hw/loongarch/meson.build +++ b/hw/loongarch/meson.build @@ -9,6 +9,7 @@ loongarch_ss.add(files( 'ipi.c', 'apic.c', 'iocsr.c', + 'sysbus-fdt.c', )) hw_arch += {'loongarch64': loongarch_ss} diff --git a/hw/loongarch/sysbus-fdt.c b/hw/loongarch/sysbus-fdt.c new file mode 100644 index 0000000000..f750ad6b67 --- /dev/null +++ b/hw/loongarch/sysbus-fdt.c @@ -0,0 +1,183 @@ +/* + * Loongarch Platform Bus device tree generation helpers + * + * Copyright (c) 2014 Linaro Limited + * + * Authors: + * Alex Graf + * Eric Auger + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include +#include "qemu/error-report.h" +#include "sysemu/device_tree.h" +#include "hw/platform-bus.h" +#include "hw/display/ramfb.h" +#include "hw/loongarch/sysbus-fdt.h" +#include "sysemu/tpm.h" + +/* + * internal struct that contains the information to create dynamic + * sysbus device node + */ +typedef struct PlatformBusFDTData { + void *fdt; /* device tree handle */ + int irq_start; /* index of the first IRQ usable by platform bus devices */ + const char *pbus_node_name; /* name of the platform bus node */ + PlatformBusDevice *pbus; +} PlatformBusFDTData; + +/* struct that allows to match a device and create its FDT node */ +typedef struct BindingEntry { + const char *typename; + const char *compat; + int (*add_fn)(SysBusDevice *sbdev, void *opaque); + bool (*match_fn)(SysBusDevice *sbdev, const struct BindingEntry *combo); +} BindingEntry; + + + +static int no_fdt_node(SysBusDevice *sbdev, void *opaque) +{ + return 0; +} + +/* Device type based matching */ +static bool type_match(SysBusDevice *sbdev, const BindingEntry *entry) +{ + return !strcmp(object_get_typename(OBJECT(sbdev)), entry->typename); +} + +#define TYPE_BINDING(type, add_fn) {(type), NULL, (add_fn), NULL} + +#ifdef CONFIG_TPM +/* + * add_tpm_tis_fdt_node: Create a DT node for TPM TIS + * + * See kernel documentation: + * Documentation/devicetree/bindings/security/tpm/tpm_tis_mmio.txt + * Optional interrupt for command completion is not exposed + */ +static int add_tpm_tis_fdt_node(SysBusDevice *sbdev, void *opaque) +{ + PlatformBusFDTData *data = opaque; + PlatformBusDevice *pbus = data->pbus; + void *fdt = data->fdt; + const char *parent_node = data->pbus_node_name; + char *nodename; + uint32_t reg_attr[2]; + uint64_t mmio_base; + + mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0); + nodename = g_strdup_printf("%s/tpm_tis@%" PRIx64, parent_node, mmio_base); + qemu_fdt_add_subnode(fdt, nodename); + + qemu_fdt_setprop_string(fdt, nodename, "compatible", "tcg,tpm-tis-mmio"); + + reg_attr[0] = cpu_to_be32(mmio_base); + reg_attr[1] = cpu_to_be32(0x5000); + qemu_fdt_setprop(fdt, nodename, "reg", reg_attr, 2 * sizeof(uint32_t)); + + g_free(nodename); + + return 0; +} +#endif + +/* list of supported dynamic sysbus bindings */ +static const BindingEntry bindings[] = { +#ifdef CONFIG_TPM + TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node), +#endif + TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node), + TYPE_BINDING("", NULL), /* last element */ +}; + +/* Generic Code */ + +/** + * add_fdt_node - add the device tree node of a dynamic sysbus device + * + * @sbdev: handle to the sysbus device + * @opaque: handle to the PlatformBusFDTData + * + * Checks the sysbus type belongs to the list of device types that + * are dynamically instantiable and if so call the node creation + * function. + */ +static void add_fdt_node(SysBusDevice *sbdev, void *opaque) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(bindings); i++) { + const BindingEntry *iter = &bindings[i]; + + if (type_match(sbdev, iter)) { + if (!iter->match_fn || iter->match_fn(sbdev, iter)) { + ret = iter->add_fn(sbdev, opaque); + assert(!ret); + return; + } + } + } + error_report("Device %s can not be dynamically instantiated", + qdev_fw_name(DEVICE(sbdev))); + exit(1); +} + +void platform_bus_add_all_fdt_nodes(void *fdt, const char *intc, hwaddr addr, + hwaddr bus_size, int irq_start) +{ + const char platcomp[] = "qemu,platform\0simple-bus"; + PlatformBusDevice *pbus; + DeviceState *dev; + gchar *node; + + assert(fdt); + + node = g_strdup_printf("/platform@%"PRIx64, addr); + + /* Create a /platform node that we can put all devices into */ + qemu_fdt_add_subnode(fdt, node); + qemu_fdt_setprop(fdt, node, "compatible", platcomp, sizeof(platcomp)); + + /* + * Our platform bus region is less than 32bits, so 1 cell is enough for + * address and size + */ + qemu_fdt_setprop_cells(fdt, node, "#size-cells", 1); + qemu_fdt_setprop_cells(fdt, node, "#address-cells", 1); + qemu_fdt_setprop_cells(fdt, node, "ranges", 0, addr >> 32, addr, bus_size); + if (intc != NULL) { + qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", intc); + } + dev = qdev_find_recursive(sysbus_get_default(), TYPE_PLATFORM_BUS_DEVICE); + pbus = PLATFORM_BUS_DEVICE(dev); + + PlatformBusFDTData data = { + .fdt = fdt, + .irq_start = irq_start, + .pbus_node_name = node, + .pbus = pbus, + }; + + /* Loop through all dynamic sysbus devices and create their node */ + foreach_dynamic_sysbus_device(add_fdt_node, &data); + + g_free(node); +} diff --git a/include/hw/loongarch/larch.h b/include/hw/loongarch/larch.h index 62e2830e27..81dcb78f4a 100644 --- a/include/hw/loongarch/larch.h +++ b/include/hw/loongarch/larch.h @@ -103,6 +103,7 @@ typedef struct LoongarchMachineState { void *fdt; int fdt_size; unsigned int hotpluged_cpu_num; + DeviceState *platform_bus_dev; OnOffAuto acpi; char *oem_id; char *oem_table_id; diff --git a/include/hw/loongarch/ls7a.h b/include/hw/loongarch/ls7a.h index 686af763a0..fc78083bef 100644 --- a/include/hw/loongarch/ls7a.h +++ b/include/hw/loongarch/ls7a.h @@ -121,6 +121,11 @@ #define INT_ROUTER_REGS_CORE2_INTISR 0x50 #define INT_ROUTER_REGS_CORE3_INTISR 0x58 +#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000 +#define VIRT_PLATFORM_BUS_SIZE 0x2000000 +#define VIRT_PLATFORM_BUS_NUM_IRQS 2 +#define VIRT_PLATFORM_BUS_IRQ 69 + typedef struct LS7APCIState LS7APCIState; typedef struct LS7APCIEHost { PCIExpressHost parent_obj; diff --git a/include/hw/loongarch/sysbus-fdt.h b/include/hw/loongarch/sysbus-fdt.h new file mode 100644 index 0000000000..340c382cdd --- /dev/null +++ b/include/hw/loongarch/sysbus-fdt.h @@ -0,0 +1,37 @@ +/* + * Dynamic sysbus device tree node generation API + * + * Copyright Linaro Limited, 2014 + * + * Authors: + * Alex Graf + * Eric Auger + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + */ + +#ifndef HW_ARM_SYSBUS_FDT_H +#define HW_ARM_SYSBUS_FDT_H + +#include "exec/hwaddr.h" + +/** + * platform_bus_add_all_fdt_nodes - create all the platform bus nodes + * + * builds the parent platform bus node and all the nodes of dynamic + * sysbus devices attached to it. + */ +void platform_bus_add_all_fdt_nodes(void *fdt, const char *intc, hwaddr addr, + hwaddr bus_size, int irq_start); +#endif -- Gitee From 76e33ba42ed689980d89d5c8329564b37029670a Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 07:25:52 -0400 Subject: [PATCH 14/29] kvm csr save and restore optimization. Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- target/loongarch64/kvm.c | 547 +++++++++++---------------------------- 1 file changed, 153 insertions(+), 394 deletions(-) diff --git a/target/loongarch64/kvm.c b/target/loongarch64/kvm.c index b5c655812b..6885ec6c9c 100644 --- a/target/loongarch64/kvm.c +++ b/target/loongarch64/kvm.c @@ -95,19 +95,165 @@ int kvm_arch_irqchip_create(KVMState *s) return 0; } +static void kvm_csr_set_addr(uint64_t **addr, uint32_t index, uint64_t *p) +{ + addr[index] = p; +} + int kvm_arch_init_vcpu(CPUState *cs) { LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + uint64_t **addr; + CPULOONGARCHState *env = &cpu->env; int ret = 0; cpu->cpuStateEntry = qemu_add_vm_change_state_handler(kvm_loongarch_update_state, cs); - cpu->kvm_csr_buf = g_malloc0(CSR_BUF_SIZE); + cpu->kvm_csr_buf = g_malloc0(CSR_BUF_SIZE + CSR_BUF_SIZE); + + addr = (void *)cpu->kvm_csr_buf + CSR_BUF_SIZE; + kvm_csr_set_addr(addr, LOONGARCH_CSR_CRMD, &env->CSR_CRMD); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PRMD, &env->CSR_PRMD); + kvm_csr_set_addr(addr, LOONGARCH_CSR_EUEN, &env->CSR_EUEN); + kvm_csr_set_addr(addr, LOONGARCH_CSR_MISC, &env->CSR_MISC); + kvm_csr_set_addr(addr, LOONGARCH_CSR_ECFG, &env->CSR_ECFG); + kvm_csr_set_addr(addr, LOONGARCH_CSR_ESTAT, &env->CSR_ESTAT); + kvm_csr_set_addr(addr, LOONGARCH_CSR_ERA, &env->CSR_ERA); + kvm_csr_set_addr(addr, LOONGARCH_CSR_BADV, &env->CSR_BADV); + kvm_csr_set_addr(addr, LOONGARCH_CSR_BADI, &env->CSR_BADI); + kvm_csr_set_addr(addr, LOONGARCH_CSR_EEPN, &env->CSR_EEPN); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBIDX, &env->CSR_TLBIDX); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBEHI, &env->CSR_TLBEHI); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBELO0, &env->CSR_TLBELO0); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBELO1, &env->CSR_TLBELO1); + kvm_csr_set_addr(addr, LOONGARCH_CSR_GTLBC, &env->CSR_GTLBC); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TRGP, &env->CSR_TRGP); + kvm_csr_set_addr(addr, LOONGARCH_CSR_ASID, &env->CSR_ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PGDL, &env->CSR_PGDL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PGDH, &env->CSR_PGDH); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PGD, &env->CSR_PGD); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PWCTL0, &env->CSR_PWCTL0); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PWCTL1, &env->CSR_PWCTL1); + kvm_csr_set_addr(addr, LOONGARCH_CSR_STLBPGSIZE, &env->CSR_STLBPGSIZE); + kvm_csr_set_addr(addr, LOONGARCH_CSR_RVACFG, &env->CSR_RVACFG); + kvm_csr_set_addr(addr, LOONGARCH_CSR_CPUID, &env->CSR_CPUID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PRCFG1, &env->CSR_PRCFG1); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PRCFG2, &env->CSR_PRCFG2); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PRCFG3, &env->CSR_PRCFG3); + kvm_csr_set_addr(addr, LOONGARCH_CSR_KS0, &env->CSR_KS0); + kvm_csr_set_addr(addr, LOONGARCH_CSR_KS1, &env->CSR_KS1); + kvm_csr_set_addr(addr, LOONGARCH_CSR_KS2, &env->CSR_KS2); + kvm_csr_set_addr(addr, LOONGARCH_CSR_KS3, &env->CSR_KS3); + kvm_csr_set_addr(addr, LOONGARCH_CSR_KS4, &env->CSR_KS4); + kvm_csr_set_addr(addr, LOONGARCH_CSR_KS5, &env->CSR_KS5); + kvm_csr_set_addr(addr, LOONGARCH_CSR_KS6, &env->CSR_KS6); + kvm_csr_set_addr(addr, LOONGARCH_CSR_KS7, &env->CSR_KS7); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TMID, &env->CSR_TMID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_CNTC, &env->CSR_CNTC); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TINTCLR, &env->CSR_TINTCLR); + + kvm_csr_set_addr(addr, LOONGARCH_CSR_GSTAT, &env->CSR_GSTAT); + kvm_csr_set_addr(addr, LOONGARCH_CSR_GCFG, &env->CSR_GCFG); + kvm_csr_set_addr(addr, LOONGARCH_CSR_GINTC, &env->CSR_GINTC); + kvm_csr_set_addr(addr, LOONGARCH_CSR_GCNTC, &env->CSR_GCNTC); + kvm_csr_set_addr(addr, LOONGARCH_CSR_LLBCTL, &env->CSR_LLBCTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IMPCTL1, &env->CSR_IMPCTL1); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IMPCTL2, &env->CSR_IMPCTL2); + kvm_csr_set_addr(addr, LOONGARCH_CSR_GNMI, &env->CSR_GNMI); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBRENT, &env->CSR_TLBRENT); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBRBADV, &env->CSR_TLBRBADV); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBRERA, &env->CSR_TLBRERA); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBRSAVE, &env->CSR_TLBRSAVE); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBRELO0, &env->CSR_TLBRELO0); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBRELO1, &env->CSR_TLBRELO1); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBREHI, &env->CSR_TLBREHI); + kvm_csr_set_addr(addr, LOONGARCH_CSR_TLBRPRMD, &env->CSR_TLBRPRMD); + kvm_csr_set_addr(addr, LOONGARCH_CSR_ERRCTL, &env->CSR_ERRCTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_ERRINFO, &env->CSR_ERRINFO); + kvm_csr_set_addr(addr, LOONGARCH_CSR_ERRINFO1, &env->CSR_ERRINFO1); + kvm_csr_set_addr(addr, LOONGARCH_CSR_ERRENT, &env->CSR_ERRENT); + kvm_csr_set_addr(addr, LOONGARCH_CSR_ERRERA, &env->CSR_ERRERA); + kvm_csr_set_addr(addr, LOONGARCH_CSR_ERRSAVE, &env->CSR_ERRSAVE); + kvm_csr_set_addr(addr, LOONGARCH_CSR_CTAG, &env->CSR_CTAG); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DMWIN0, &env->CSR_DMWIN0); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DMWIN1, &env->CSR_DMWIN1); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DMWIN2, &env->CSR_DMWIN2); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DMWIN3, &env->CSR_DMWIN3); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PERFCTRL0, &env->CSR_PERFCTRL0); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PERFCNTR0, &env->CSR_PERFCNTR0); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PERFCTRL1, &env->CSR_PERFCTRL1); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PERFCNTR1, &env->CSR_PERFCNTR1); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PERFCTRL2, &env->CSR_PERFCTRL2); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PERFCNTR2, &env->CSR_PERFCNTR2); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PERFCTRL3, &env->CSR_PERFCTRL3); + kvm_csr_set_addr(addr, LOONGARCH_CSR_PERFCNTR3, &env->CSR_PERFCNTR3); + + /* debug */ + kvm_csr_set_addr(addr, LOONGARCH_CSR_MWPC, &env->CSR_MWPC); + kvm_csr_set_addr(addr, LOONGARCH_CSR_MWPS, &env->CSR_MWPS); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB0ADDR, &env->CSR_DB0ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB0MASK, &env->CSR_DB0MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB0CTL, &env->CSR_DB0CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB0ASID, &env->CSR_DB0ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB1ADDR, &env->CSR_DB1ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB1MASK, &env->CSR_DB1MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB1CTL, &env->CSR_DB1CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB1ASID, &env->CSR_DB1ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB2ADDR, &env->CSR_DB2ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB2MASK, &env->CSR_DB2MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB2CTL, &env->CSR_DB2CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB2ASID, &env->CSR_DB2ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB3ADDR, &env->CSR_DB3ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB3MASK, &env->CSR_DB3MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB3CTL, &env->CSR_DB3CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DB3ASID, &env->CSR_DB3ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_FWPC, &env->CSR_FWPC); + kvm_csr_set_addr(addr, LOONGARCH_CSR_FWPS, &env->CSR_FWPS); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB0ADDR, &env->CSR_IB0ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB0MASK, &env->CSR_IB0MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB0CTL, &env->CSR_IB0CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB0ASID, &env->CSR_IB0ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB1ADDR, &env->CSR_IB1ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB1MASK, &env->CSR_IB1MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB1CTL, &env->CSR_IB1CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB1ASID, &env->CSR_IB1ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB2ADDR, &env->CSR_IB2ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB2MASK, &env->CSR_IB2MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB2CTL, &env->CSR_IB2CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB2ASID, &env->CSR_IB2ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB3ADDR, &env->CSR_IB3ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB3MASK, &env->CSR_IB3MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB3CTL, &env->CSR_IB3CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB3ASID, &env->CSR_IB3ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB4ADDR, &env->CSR_IB4ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB4MASK, &env->CSR_IB4MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB4CTL, &env->CSR_IB4CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB4ASID, &env->CSR_IB4ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB5ADDR, &env->CSR_IB5ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB5MASK, &env->CSR_IB5MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB5CTL, &env->CSR_IB5CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB5ASID, &env->CSR_IB5ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB6ADDR, &env->CSR_IB6ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB6MASK, &env->CSR_IB6MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB6CTL, &env->CSR_IB6CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB6ASID, &env->CSR_IB6ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB7ADDR, &env->CSR_IB7ADDR); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB7MASK, &env->CSR_IB7MASK); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB7CTL, &env->CSR_IB7CTL); + kvm_csr_set_addr(addr, LOONGARCH_CSR_IB7ASID, &env->CSR_IB7ASID); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DEBUG, &env->CSR_DEBUG); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DERA, &env->CSR_DERA); + kvm_csr_set_addr(addr, LOONGARCH_CSR_DESAVE, &env->CSR_DESAVE); + DPRINTF("%s\n", __func__); return ret; } int kvm_arch_destroy_vcpu(CPUState *cs) { + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + + g_free(cpu->kvm_csr_buf); + cpu->kvm_csr_buf = NULL; return 0; } @@ -936,8 +1082,10 @@ static int kvm_loongarch_get_csr_registers(CPUState *cs) CPULOONGARCHState *env = &cpu->env; int ret = 0, i; struct kvm_csr_entry *csrs = cpu->kvm_csr_buf->entries; + uint64_t **addr; kvm_csr_buf_reset(cpu); + addr = (void *)cpu->kvm_csr_buf + CSR_BUF_SIZE; kvm_csr_entry_add(cpu, LOONGARCH_CSR_CRMD, 0); kvm_csr_entry_add(cpu, LOONGARCH_CSR_PRMD, 0); @@ -1082,399 +1230,10 @@ static int kvm_loongarch_get_csr_registers(CPUState *cs) for (i = 0; i < ret; i++) { uint32_t index = csrs[i].index; - - switch (index) { - case LOONGARCH_CSR_CRMD: - env->CSR_CRMD = csrs[i].data; - break; - case LOONGARCH_CSR_PRMD: - env->CSR_PRMD = csrs[i].data; - break; - case LOONGARCH_CSR_EUEN: - env->CSR_EUEN = csrs[i].data; - break; - case LOONGARCH_CSR_MISC: - env->CSR_MISC = csrs[i].data; - break; - case LOONGARCH_CSR_ECFG: - env->CSR_ECFG = csrs[i].data; - break; - case LOONGARCH_CSR_ESTAT: - env->CSR_ESTAT = csrs[i].data; - break; - case LOONGARCH_CSR_ERA: - env->CSR_ERA = csrs[i].data; - break; - case LOONGARCH_CSR_BADV: - env->CSR_BADV = csrs[i].data; - break; - case LOONGARCH_CSR_BADI: - env->CSR_BADI = csrs[i].data; - break; - case LOONGARCH_CSR_EEPN: - env->CSR_EEPN = csrs[i].data; - break; - case LOONGARCH_CSR_TLBIDX: - env->CSR_TLBIDX = csrs[i].data; - break; - case LOONGARCH_CSR_TLBEHI: - env->CSR_TLBEHI = csrs[i].data; - break; - case LOONGARCH_CSR_TLBELO0: - env->CSR_TLBELO0 = csrs[i].data; - break; - case LOONGARCH_CSR_TLBELO1: - env->CSR_TLBELO1 = csrs[i].data; - break; - case LOONGARCH_CSR_GTLBC: - env->CSR_GTLBC = csrs[i].data; - break; - case LOONGARCH_CSR_TRGP: - env->CSR_TRGP = csrs[i].data; - break; - case LOONGARCH_CSR_ASID: - env->CSR_ASID = csrs[i].data; - break; - case LOONGARCH_CSR_PGDL: - env->CSR_PGDL = csrs[i].data; - break; - case LOONGARCH_CSR_PGDH: - env->CSR_PGDH = csrs[i].data; - break; - case LOONGARCH_CSR_PGD: - env->CSR_PGD = csrs[i].data; - break; - case LOONGARCH_CSR_PWCTL0: - env->CSR_PWCTL0 = csrs[i].data; - break; - case LOONGARCH_CSR_PWCTL1: - env->CSR_PWCTL1 = csrs[i].data; - break; - case LOONGARCH_CSR_STLBPGSIZE: - env->CSR_STLBPGSIZE = csrs[i].data; - break; - case LOONGARCH_CSR_RVACFG: - env->CSR_RVACFG = csrs[i].data; - break; - case LOONGARCH_CSR_CPUID: - env->CSR_CPUID = csrs[i].data; - break; - case LOONGARCH_CSR_PRCFG1: - env->CSR_PRCFG1 = csrs[i].data; - break; - case LOONGARCH_CSR_PRCFG2: - env->CSR_PRCFG2 = csrs[i].data; - break; - case LOONGARCH_CSR_PRCFG3: - env->CSR_PRCFG3 = csrs[i].data; - break; - case LOONGARCH_CSR_KS0: - env->CSR_KS0 = csrs[i].data; - break; - case LOONGARCH_CSR_KS1: - env->CSR_KS1 = csrs[i].data; - break; - case LOONGARCH_CSR_KS2: - env->CSR_KS2 = csrs[i].data; - break; - case LOONGARCH_CSR_KS3: - env->CSR_KS3 = csrs[i].data; - break; - case LOONGARCH_CSR_KS4: - env->CSR_KS4 = csrs[i].data; - break; - case LOONGARCH_CSR_KS5: - env->CSR_KS5 = csrs[i].data; - break; - case LOONGARCH_CSR_KS6: - env->CSR_KS6 = csrs[i].data; - break; - case LOONGARCH_CSR_KS7: - env->CSR_KS7 = csrs[i].data; - break; - - case LOONGARCH_CSR_TMID: - env->CSR_TMID = csrs[i].data; - break; - case LOONGARCH_CSR_CNTC: - env->CSR_CNTC = csrs[i].data; - break; - case LOONGARCH_CSR_TINTCLR: - env->CSR_TINTCLR = csrs[i].data; - break; - case LOONGARCH_CSR_GSTAT: - env->CSR_GSTAT = csrs[i].data; - break; - case LOONGARCH_CSR_GCFG: - env->CSR_GCFG = csrs[i].data; - break; - case LOONGARCH_CSR_GINTC: - env->CSR_GINTC = csrs[i].data; - break; - case LOONGARCH_CSR_GCNTC: - env->CSR_GCNTC = csrs[i].data; - break; - case LOONGARCH_CSR_LLBCTL: - env->CSR_LLBCTL = csrs[i].data; - break; - case LOONGARCH_CSR_IMPCTL1: - env->CSR_IMPCTL1 = csrs[i].data; - break; - case LOONGARCH_CSR_IMPCTL2: - env->CSR_IMPCTL2 = csrs[i].data; - break; - case LOONGARCH_CSR_GNMI: - env->CSR_GNMI = csrs[i].data; - break; - case LOONGARCH_CSR_TLBRENT: - env->CSR_TLBRENT = csrs[i].data; - break; - case LOONGARCH_CSR_TLBRBADV: - env->CSR_TLBRBADV = csrs[i].data; - break; - case LOONGARCH_CSR_TLBRERA: - env->CSR_TLBRERA = csrs[i].data; - break; - case LOONGARCH_CSR_TLBRSAVE: - env->CSR_TLBRSAVE = csrs[i].data; - break; - case LOONGARCH_CSR_TLBRELO0: - env->CSR_TLBRELO0 = csrs[i].data; - break; - case LOONGARCH_CSR_TLBRELO1: - env->CSR_TLBRELO1 = csrs[i].data; - break; - case LOONGARCH_CSR_TLBREHI: - env->CSR_TLBREHI = csrs[i].data; - break; - case LOONGARCH_CSR_TLBRPRMD: - env->CSR_TLBRPRMD = csrs[i].data; - break; - case LOONGARCH_CSR_ERRCTL: - env->CSR_ERRCTL = csrs[i].data; - break; - case LOONGARCH_CSR_ERRINFO: - env->CSR_ERRINFO = csrs[i].data; - break; - case LOONGARCH_CSR_ERRINFO1: - env->CSR_ERRINFO1 = csrs[i].data; - break; - case LOONGARCH_CSR_ERRENT: - env->CSR_ERRENT = csrs[i].data; - break; - case LOONGARCH_CSR_ERRERA: - env->CSR_ERRERA = csrs[i].data; - break; - case LOONGARCH_CSR_ERRSAVE: - env->CSR_ERRSAVE = csrs[i].data; - break; - case LOONGARCH_CSR_CTAG: - env->CSR_CTAG = csrs[i].data; - break; - case LOONGARCH_CSR_DMWIN0: - env->CSR_DMWIN0 = csrs[i].data; - break; - case LOONGARCH_CSR_DMWIN1: - env->CSR_DMWIN1 = csrs[i].data; - break; - case LOONGARCH_CSR_DMWIN2: - env->CSR_DMWIN2 = csrs[i].data; - break; - case LOONGARCH_CSR_DMWIN3: - env->CSR_DMWIN3 = csrs[i].data; - break; - case LOONGARCH_CSR_PERFCTRL0: - env->CSR_PERFCTRL0 = csrs[i].data; - break; - case LOONGARCH_CSR_PERFCNTR0: - env->CSR_PERFCNTR0 = csrs[i].data; - break; - case LOONGARCH_CSR_PERFCTRL1: - env->CSR_PERFCTRL1 = csrs[i].data; - break; - case LOONGARCH_CSR_PERFCNTR1: - env->CSR_PERFCNTR1 = csrs[i].data; - break; - case LOONGARCH_CSR_PERFCTRL2: - env->CSR_PERFCTRL2 = csrs[i].data; - break; - case LOONGARCH_CSR_PERFCNTR2: - env->CSR_PERFCNTR2 = csrs[i].data; - break; - case LOONGARCH_CSR_PERFCTRL3: - env->CSR_PERFCTRL3 = csrs[i].data; - break; - case LOONGARCH_CSR_PERFCNTR3: - env->CSR_PERFCNTR3 = csrs[i].data; - break; - - case LOONGARCH_CSR_MWPC: - env->CSR_MWPC = csrs[i].data; - break; - case LOONGARCH_CSR_MWPS: - env->CSR_MWPS = csrs[i].data; - break; - case LOONGARCH_CSR_DB0ADDR: - env->CSR_DB0ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_DB0MASK: - env->CSR_DB0MASK = csrs[i].data; - break; - case LOONGARCH_CSR_DB0CTL: - env->CSR_DB0CTL = csrs[i].data; - break; - case LOONGARCH_CSR_DB0ASID: - env->CSR_DB0ASID = csrs[i].data; - break; - case LOONGARCH_CSR_DB1ADDR: - env->CSR_DB1ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_DB1MASK: - env->CSR_DB1MASK = csrs[i].data; - break; - case LOONGARCH_CSR_DB1CTL: - env->CSR_DB1CTL = csrs[i].data; - break; - case LOONGARCH_CSR_DB1ASID: - env->CSR_DB1ASID = csrs[i].data; - break; - case LOONGARCH_CSR_DB2ADDR: - env->CSR_DB2ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_DB2MASK: - env->CSR_DB2MASK = csrs[i].data; - break; - case LOONGARCH_CSR_DB2CTL: - env->CSR_DB2CTL = csrs[i].data; - break; - case LOONGARCH_CSR_DB2ASID: - env->CSR_DB2ASID = csrs[i].data; - break; - case LOONGARCH_CSR_DB3ADDR: - env->CSR_DB3ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_DB3MASK: - env->CSR_DB3MASK = csrs[i].data; - break; - case LOONGARCH_CSR_DB3CTL: - env->CSR_DB3CTL = csrs[i].data; - break; - case LOONGARCH_CSR_DB3ASID: - env->CSR_DB3ASID = csrs[i].data; - break; - case LOONGARCH_CSR_FWPC: - env->CSR_FWPC = csrs[i].data; - break; - case LOONGARCH_CSR_FWPS: - env->CSR_FWPS = csrs[i].data; - break; - case LOONGARCH_CSR_IB0ADDR: - env->CSR_IB0ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_IB0MASK: - env->CSR_IB0MASK = csrs[i].data; - break; - case LOONGARCH_CSR_IB0CTL: - env->CSR_IB0CTL = csrs[i].data; - break; - case LOONGARCH_CSR_IB0ASID: - env->CSR_IB0ASID = csrs[i].data; - break; - case LOONGARCH_CSR_IB1ADDR: - env->CSR_IB1ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_IB1MASK: - env->CSR_IB1MASK = csrs[i].data; - break; - case LOONGARCH_CSR_IB1CTL: - env->CSR_IB1CTL = csrs[i].data; - break; - case LOONGARCH_CSR_IB1ASID: - env->CSR_IB1ASID = csrs[i].data; - break; - case LOONGARCH_CSR_IB2ADDR: - env->CSR_IB2ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_IB2MASK: - env->CSR_IB2MASK = csrs[i].data; - break; - case LOONGARCH_CSR_IB2CTL: - env->CSR_IB2CTL = csrs[i].data; - break; - case LOONGARCH_CSR_IB2ASID: - env->CSR_IB2ASID = csrs[i].data; - break; - case LOONGARCH_CSR_IB3ADDR: - env->CSR_IB3ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_IB3MASK: - env->CSR_IB3MASK = csrs[i].data; - break; - case LOONGARCH_CSR_IB3CTL: - env->CSR_IB3CTL = csrs[i].data; - break; - case LOONGARCH_CSR_IB3ASID: - env->CSR_IB3ASID = csrs[i].data; - break; - case LOONGARCH_CSR_IB4ADDR: - env->CSR_IB4ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_IB4MASK: - env->CSR_IB4MASK = csrs[i].data; - break; - case LOONGARCH_CSR_IB4CTL: - env->CSR_IB4CTL = csrs[i].data; - break; - case LOONGARCH_CSR_IB4ASID: - env->CSR_IB4ASID = csrs[i].data; - break; - case LOONGARCH_CSR_IB5ADDR: - env->CSR_IB5ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_IB5MASK: - env->CSR_IB5MASK = csrs[i].data; - break; - case LOONGARCH_CSR_IB5CTL: - env->CSR_IB5CTL = csrs[i].data; - break; - case LOONGARCH_CSR_IB5ASID: - env->CSR_IB5ASID = csrs[i].data; - break; - case LOONGARCH_CSR_IB6ADDR: - env->CSR_IB6ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_IB6MASK: - env->CSR_IB6MASK = csrs[i].data; - break; - case LOONGARCH_CSR_IB6CTL: - env->CSR_IB6CTL = csrs[i].data; - break; - case LOONGARCH_CSR_IB6ASID: - env->CSR_IB6ASID = csrs[i].data; - break; - case LOONGARCH_CSR_IB7ADDR: - env->CSR_IB7ADDR = csrs[i].data; - break; - case LOONGARCH_CSR_IB7MASK: - env->CSR_IB7MASK = csrs[i].data; - break; - case LOONGARCH_CSR_IB7CTL: - env->CSR_IB7CTL = csrs[i].data; - break; - case LOONGARCH_CSR_IB7ASID: - env->CSR_IB7ASID = csrs[i].data; - break; - case LOONGARCH_CSR_DEBUG: - env->CSR_DEBUG = csrs[i].data; - break; - case LOONGARCH_CSR_DERA: - env->CSR_DERA = csrs[i].data; - break; - case LOONGARCH_CSR_DESAVE: - env->CSR_DESAVE = csrs[i].data; - break; - default: - break; + if (addr[index]) { + *addr[index] = csrs[i].data; + } else { + printf("Failed to get addr CSR 0x%"PRIx32"\n", i); } } -- Gitee From d9c0bf488f4178ad2545374437b306a06c278482 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 07:33:26 -0400 Subject: [PATCH 15/29] address space code cleanup on 7A virt-machine. Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- hw/loongarch/larch_3a.c | 16 +++----- hw/loongarch/ls7a_nb.c | 49 ------------------------- include/hw/loongarch/larch.h | 1 - include/hw/loongarch/ls7a.h | 71 ++++++++++++++++-------------------- 4 files changed, 37 insertions(+), 100 deletions(-) diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c index 6c2602050e..6eaa53d74c 100644 --- a/hw/loongarch/larch_3a.c +++ b/hw/loongarch/larch_3a.c @@ -88,10 +88,8 @@ #ifdef CONFIG_KVM #define LS_ISA_IO_SIZE 0x02000000 -#define LS_ISA_MEM_SIZE 0x40000000 #else #define LS_ISA_IO_SIZE 0x00010000 -#define LS_ISA_MEM_SIZE 0x01000000 #endif #ifdef CONFIG_KVM @@ -626,8 +624,8 @@ static struct irq_source_routing_table *init_irq_source(void *g_irq_source) irq_info->ht_enable = 0x0000d17b; irq_info->node_id = 0; - irq_info->pci_mem_start_addr = LS_ISA_MEM_BASE; - irq_info->pci_mem_end_addr = irq_info->pci_mem_start_addr + LS_ISA_MEM_SIZE - 1; + irq_info->pci_mem_start_addr = PCIE_MEMORY_BASE; + irq_info->pci_mem_end_addr = irq_info->pci_mem_start_addr + PCIE_MEMORY_SIZE - 1; if (strstr(lsmc->cpu_name, "5000")) { irq_info->pci_io_start_addr = LS3A5K_ISA_IO_BASE; @@ -1551,8 +1549,8 @@ static void fdt_add_fw_cfg_node(const LoongarchMachineState *lsms) static void fdt_add_pcie_node(const LoongarchMachineState *lsms) { char *nodename; - hwaddr base_mmio = LS_ISA_MEM_BASE; - hwaddr size_mmio = LS_ISA_MEM_SIZE; + hwaddr base_mmio = PCIE_MEMORY_BASE; + hwaddr size_mmio = PCIE_MEMORY_SIZE; hwaddr base_pio = LS3A5K_ISA_IO_BASE; hwaddr size_pio = LS_ISA_IO_SIZE; hwaddr base_pcie = LS_PCIECFG_BASE; @@ -1650,7 +1648,6 @@ static void ls3a5k_init(MachineState *args) create_fdt(lsms); DPRINTF("isa 0x%lx\n", lsmc->isa_io_base); - DPRINTF("ht1lo 0x%lx\n", lsmc->ht1lo_pcicfg_base); DPRINTF("cpu_name %s bridge_name %s\n", lsmc->cpu_name, lsmc->bridge_name); @@ -1800,9 +1797,9 @@ static void ls3a5k_init(MachineState *args) memory_region_init_alias(isa_io, NULL, "isa-io", get_system_io(), 0, LS_ISA_IO_SIZE); - memory_region_init(isa_mem, NULL, "isa-mem", LS_ISA_MEM_SIZE); + memory_region_init(isa_mem, NULL, "isa-mem", PCIE_MEMORY_SIZE); memory_region_add_subregion(get_system_memory(), lsmc->isa_io_base, isa_io); - memory_region_add_subregion(get_system_memory(), LS_ISA_MEM_BASE, isa_mem); + memory_region_add_subregion(get_system_memory(), PCIE_MEMORY_BASE, isa_mem); if (!strcmp(lsmc->bridge_name, "ls7a")) { /*Initialize the 7A IO interrupt subsystem*/ @@ -1950,7 +1947,6 @@ static void ls3a5k_ls7a_machine_options(MachineClass *m) m->alias = "loongson7a"; m->is_default = 1; lsmc->isa_io_base = LS3A5K_ISA_IO_BASE; - lsmc->ht1lo_pcicfg_base = LS3A5K_HT1LO_PCICFG_BASE; lsmc->pciecfg_base = LS_PCIECFG_BASE; lsmc->ls7a_ioapic_reg_base = LS3A5K_LS7A_IOAPIC_REG_BASE; lsmc->node_shift = 44; diff --git a/hw/loongarch/ls7a_nb.c b/hw/loongarch/ls7a_nb.c index 5a500fbd5a..5a231e6f01 100644 --- a/hw/loongarch/ls7a_nb.c +++ b/hw/loongarch/ls7a_nb.c @@ -108,7 +108,6 @@ static const VMStateDescription vmstate_ls7a_pcie = { .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(dev, LS7APCIState), VMSTATE_STRUCT(pm, LS7APCIState, 0, vmstate_ls7a_pm, LS7APCIPMRegs), - VMSTATE_UINT32_ARRAY(regs, LS7APCIState, LS7A_REGS), VMSTATE_END_OF_LIST() } }; @@ -153,47 +152,6 @@ static void ls7a_pcie_realize(PCIDevice *dev, Error **errp) qemu_register_reset(ls7a_reset, s); } -static void pci_ls7a_config_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - hwaddr tmp_addr; - tmp_addr = addr & 0xffffff; - - pci_data_write(opaque, tmp_addr, val, size); -} - -static uint64_t pci_ls7a_config_read(void *opaque, - hwaddr addr, unsigned size) -{ - uint64_t val; - hwaddr tmp_addr; - - tmp_addr = addr & 0xffffff; - val = pci_data_read(opaque, tmp_addr, size); - - if (addr & 0x3c) { - DPRINTF(TARGET_FMT_plx" val %lx\n", addr, val); - } - return val; -} - -static const MemoryRegionOps pci_ls7a_config_ops = { - .read = pci_ls7a_config_read, - .write = pci_ls7a_config_write, - /* Set to access 64bits data, because default to 32bits*/ - .valid = { - .min_access_size = 1, - .max_access_size = 4, - }, - /* Set to access 64bits data, because default to 32bits*/ - .impl = { - .min_access_size = 1, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, - -}; - static AddressSpace *ls7a_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) { return &address_space_memory; @@ -205,12 +163,9 @@ static PCIBus *pci_ls7a_init(MachineState *machine, DeviceState *dev, LoongarchMachineState *lsms = LoongarchMACHINE(machine); LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); PCIExpressHost *e; - SysBusDevice *sysbus; - MemoryRegion *iomem = g_new(MemoryRegion, 1); PCIHostState *phb; e = PCIE_HOST_BRIDGE(dev); - sysbus = SYS_BUS_DEVICE(e); phb = PCI_HOST_BRIDGE(e); phb->bus = pci_register_root_bus(dev, "pcie.0", pci_ls7a_set_irq, pci_ls7a_map_irq, pic, @@ -220,10 +175,6 @@ static PCIBus *pci_ls7a_init(MachineState *machine, DeviceState *dev, DPRINTF("------ %d\n", __LINE__); pci_bus_set_route_irq_fn(phb->bus, ls7a_route_intx_pin_to_irq); - memory_region_init_io(iomem, NULL, &pci_ls7a_config_ops, phb->bus, - "ls7a_pci_conf", HT1LO_PCICFG_SIZE); - sysbus_init_mmio(sysbus, iomem); - sysbus_mmio_map(sysbus, 0, lsmc->ht1lo_pcicfg_base); return phb->bus; } diff --git a/include/hw/loongarch/larch.h b/include/hw/loongarch/larch.h index 81dcb78f4a..b8f28e330e 100644 --- a/include/hw/loongarch/larch.h +++ b/include/hw/loongarch/larch.h @@ -64,7 +64,6 @@ typedef struct LoongarchMachineClass { uint64_t ht_control_regs_base; uint64_t hpet_mmio_addr; uint64_t smbus_cfg_base; - uint64_t ht1lo_pcicfg_base; uint64_t pciecfg_base; uint64_t ls7a_ioapic_reg_base; uint32_t node_shift; diff --git a/include/hw/loongarch/ls7a.h b/include/hw/loongarch/ls7a.h index fc78083bef..63a070296b 100644 --- a/include/hw/loongarch/ls7a.h +++ b/include/hw/loongarch/ls7a.h @@ -39,44 +39,33 @@ #define ACPI_IO_SIZE (LS7A_ACPI_IO_SIZE) #define ACPI_SCI_IRQ (LS7A_SCI_IRQ) -#define LS3A5K_ISA_IO_BASE 0x18000000UL -#define LS_ISA_MEM_BASE 0x40000000 -#define LS3A5K_HT1LO_PCICFG_BASE 0x1a000000 -#define HT1LO_PCICFG_SIZE 0x02000000 +#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000 +#define VIRT_PLATFORM_BUS_SIZE 0x02000000 +#define VIRT_PLATFORM_BUS_NUM_IRQS 2 +#define VIRT_PLATFORM_BUS_IRQ (LOONGARCH_PCH_IRQ_BASE + 5) + +#define LS3A5K_ISA_IO_BASE 0x18000000UL #define LS_BIOS_BASE 0x1c000000 #define LS_BIOS_VAR_BASE 0x1c3a0000 -#define LS_BIOS_SIZE (4 * 1024 * 1024) - -#define FW_CFG_ADDR 0x1e020000 -#define LS7A_REG_BASE 0x1FE00000 -#define LS7A_PCICONFIG_BASE (LS7A_REG_BASE + 0x30) -#define LS7A_PCICONFIG_SIZE (0x100) -#define LS7A_INTERNAL_REG_BASE (LS7A_REG_BASE + 0x100) -#define LS7A_INTERNAL_REG_SIZE (0xE0) -#define LS7A_REGS (0xE0 >> 2) -#define LS7A_UART_BASE 0x1fe001e0 -#define LS7A_UART_LEN 0x8 - -#define LS_FDT_BASE 0x1c400000 -#define LS_FDT_SIZE 0x100000 - -#define LS_PCIECFG_BASE 0x20000000 -#define LS_PCIECFG_SIZE 0x08000000 -#define MSI_ADDR_LOW 0x2FF00000 -#define MSI_ADDR_HI 0x0 - +#define LS_BIOS_SIZE (4 * 1024 * 1024) +#define LS_FDT_BASE 0x1c400000 +#define LS_FDT_SIZE 0x00100000 + +#define FW_CFG_ADDR 0x1e020000 +#define LS7A_REG_BASE 0x1FE00000 +#define LS7A_UART_BASE 0x1fe001e0 +#define LS7A_UART_LEN 0x8 #define SMP_GIPI_MAILBOX 0x1f000000ULL -#define CORE0_STATUS_OFF 0x000 -#define CORE0_EN_OFF 0x004 -#define CORE0_SET_OFF 0x008 -#define CORE0_CLEAR_OFF 0x00c -#define CORE0_BUF_20 0x020 -#define CORE0_BUF_28 0x028 -#define CORE0_BUF_30 0x030 -#define CORE0_BUF_38 0x038 -#define CORE0_IPI_SEND 0x040 -#define CORE0_MAIL_SEND 0x048 - +#define CORE0_STATUS_OFF 0x000 +#define CORE0_EN_OFF 0x004 +#define CORE0_SET_OFF 0x008 +#define CORE0_CLEAR_OFF 0x00c +#define CORE0_BUF_20 0x020 +#define CORE0_BUF_28 0x028 +#define CORE0_BUF_30 0x030 +#define CORE0_BUF_38 0x038 +#define CORE0_IPI_SEND 0x040 +#define CORE0_MAIL_SEND 0x048 #define INT_ROUTER_REGS_BASE 0x1fe01400UL #define INT_ROUTER_REGS_SIZE 0x100 #define INT_ROUTER_REGS_SYS_INT0 0x00 @@ -121,10 +110,13 @@ #define INT_ROUTER_REGS_CORE2_INTISR 0x50 #define INT_ROUTER_REGS_CORE3_INTISR 0x58 -#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000 -#define VIRT_PLATFORM_BUS_SIZE 0x2000000 -#define VIRT_PLATFORM_BUS_NUM_IRQS 2 -#define VIRT_PLATFORM_BUS_IRQ 69 +#define LS_PCIECFG_BASE 0x20000000 +#define LS_PCIECFG_SIZE 0x08000000 +#define MSI_ADDR_LOW 0x2FF00000 +#define MSI_ADDR_HI 0x0 + +#define PCIE_MEMORY_BASE 0x40000000 +#define PCIE_MEMORY_SIZE 0x40000000 typedef struct LS7APCIState LS7APCIState; typedef struct LS7APCIEHost { @@ -136,7 +128,6 @@ struct LS7APCIState { PCIDevice dev; LS7APCIEHost *pciehost; - uint32_t regs[LS7A_REGS]; /* LS7A registers */ MemoryRegion iomem; -- Gitee From 6112f11fa9dcd0f2d63784da4c29c9716e16a590 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 07:38:26 -0400 Subject: [PATCH 16/29] Fix irq routing and fpu option to compat with kernel v6.4 Fix set irq routing and enable fpu for kvm to compat with kernel v6.4 Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- target/loongarch64/kvm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/loongarch64/kvm.c b/target/loongarch64/kvm.c index 6885ec6c9c..b6711da91b 100644 --- a/target/loongarch64/kvm.c +++ b/target/loongarch64/kvm.c @@ -107,6 +107,9 @@ int kvm_arch_init_vcpu(CPUState *cs) CPULOONGARCHState *env = &cpu->env; int ret = 0; + kvm_vcpu_enable_cap(cs, KVM_CAP_LOONGARCH_FPU, 0, 0); + kvm_vcpu_enable_cap(cs, KVM_CAP_LOONGARCH_LSX, 0, 0); + cpu->cpuStateEntry = qemu_add_vm_change_state_handler(kvm_loongarch_update_state, cs); cpu->kvm_csr_buf = g_malloc0(CSR_BUF_SIZE + CSR_BUF_SIZE); -- Gitee From c015d9ff735ddcfa64dbcf45dfbb6bbd5a0ac019 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 07:41:14 -0400 Subject: [PATCH 17/29] Support vfio config Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- configs/devices/loongarch64-softmmu/default.mak | 9 +++++++++ .../loongarch64-softmmu/loongarch64-rh-devices.mak | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/configs/devices/loongarch64-softmmu/default.mak b/configs/devices/loongarch64-softmmu/default.mak index fcb7e45dd2..b4994d8a6c 100644 --- a/configs/devices/loongarch64-softmmu/default.mak +++ b/configs/devices/loongarch64-softmmu/default.mak @@ -152,3 +152,12 @@ CONFIG_PLATFORM_BUS=y CONFIG_TPM_TIS_SYSBUS=y CONFIG_ACPI_LOONGARCH=y CONFIG_LS7A_RTC=y + +#vfio config +CONFIG_VFIO=y +CONFIG_VFIO_PCI=y +CONFIG_VFIO_PLATFORM=y +CONFIG_VFIO_XGMAC=y +CONFIG_VFIO_AMD_XGBE=y + + diff --git a/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak b/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak index e7b5bdc8e9..696ee9b72f 100644 --- a/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak +++ b/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak @@ -153,3 +153,11 @@ CONFIG_PLATFORM_BUS=y CONFIG_TPM_TIS_SYSBUS=y CONFIG_ACPI_LOONGARCH=y CONFIG_LS7A_RTC=y + +#vfio config +CONFIG_VFIO=y +CONFIG_VFIO_PCI=y +CONFIG_VFIO_PLATFORM=y +CONFIG_VFIO_XGMAC=y +CONFIG_VFIO_AMD_XGBE=y + -- Gitee From 82b9f21ca56487543497bf2d34c56c3e574a7d65 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 07:49:06 -0400 Subject: [PATCH 18/29] pass to make check. With this patch, when running make check command, qemu passes to compile. Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- hw/loongarch/apic.c | 4 ++-- hw/loongarch/ioapic.c | 4 ++-- hw/loongarch/iocsr.c | 20 ++++++++++++++++++-- hw/loongarch/ipi.c | 4 ++-- hw/loongarch/larch_3a.c | 3 --- target/loongarch64/machine.c | 7 +++++++ 6 files changed, 31 insertions(+), 11 deletions(-) diff --git a/hw/loongarch/apic.c b/hw/loongarch/apic.c index d6ba2a2cec..67994d201f 100644 --- a/hw/loongarch/apic.c +++ b/hw/loongarch/apic.c @@ -64,7 +64,7 @@ static int ext_irq_pre_save(void *opaque) struct kvm_loongarch_ls3a_extirq_state *kstate; int ret, length, i, vcpuid; #endif - if (!kvm_irqchip_in_kernel()) { + if ((!kvm_enabled()) || (!kvm_irqchip_in_kernel())) { return 0; } #ifdef CONFIG_KVM @@ -112,7 +112,7 @@ static int ext_irq_post_load(void *opaque, int version) struct kvm_loongarch_ls3a_extirq_state *kstate; int ret, length, i, vcpuid; #endif - if (!kvm_irqchip_in_kernel()) { + if ((!kvm_enabled()) || (!kvm_irqchip_in_kernel())) { return 0; } #ifdef CONFIG_KVM diff --git a/hw/loongarch/ioapic.c b/hw/loongarch/ioapic.c index 3de0ed88da..60abff8554 100644 --- a/hw/loongarch/ioapic.c +++ b/hw/loongarch/ioapic.c @@ -253,7 +253,7 @@ static int kvm_ls7a_pre_save(void *opaque) struct ls7a_ioapic_state *state; int ret, i, length; - if (!kvm_irqchip_in_kernel()) { + if ((!kvm_enabled()) || (!kvm_irqchip_in_kernel())) { return 0; } @@ -297,7 +297,7 @@ static int kvm_ls7a_post_load(void *opaque, int version) struct ls7a_ioapic_state *state; int ret, i, length; - if (!kvm_irqchip_in_kernel()) { + if ((!kvm_enabled()) || (!kvm_irqchip_in_kernel())) { return 0; } length = sizeof(struct loongarch_kvm_irqchip) + sizeof(struct ls7a_ioapic_state); diff --git a/hw/loongarch/iocsr.c b/hw/loongarch/iocsr.c index 60daafd6e1..13d356d806 100644 --- a/hw/loongarch/iocsr.c +++ b/hw/loongarch/iocsr.c @@ -95,6 +95,11 @@ static int kvm_iocsr_pre_save(void *opaque) IOCSRState *s = opaque; struct kvm_iocsr_entry entry; int i = 0; + + if ((!kvm_enabled())) { + return 0; + } + for (i = 0; i < IOCSR_MAX; i++) { entry.addr = iocsr_array[i]; kvm_vm_ioctl(kvm_state, KVM_LOONGARCH_GET_IOCSR, &entry); @@ -172,8 +177,19 @@ static void iocsr_instance_init(Object *obj) { IOCSRState *s = IOCSR(obj); int i; - LoongarchMachineState *lsms = LoongarchMACHINE(qdev_get_machine()); - LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + LoongarchMachineState *lsms; + LoongarchMachineClass *lsmc; + Object *machine = qdev_get_machine(); + ObjectClass *mc = object_get_class(machine); + + + /* 'lams' should be initialized */ + if (!strcmp(MACHINE_CLASS(mc)->name, "none")) { + return; + } + + lsms = LoongarchMACHINE(machine); + lsmc = LoongarchMACHINE_GET_CLASS(lsms); init_vendor_cpuname((uint64_t *)&iocsr_init.iocsr_val[IOCSR_VENDOR], (uint64_t *)&iocsr_init.iocsr_val[IOCSR_CPUNAME], diff --git a/hw/loongarch/ipi.c b/hw/loongarch/ipi.c index ade182abcc..59186f1def 100644 --- a/hw/loongarch/ipi.c +++ b/hw/loongarch/ipi.c @@ -25,7 +25,7 @@ static int gipi_pre_save(void *opaque) int ret, i, j, length; #endif - if (!kvm_irqchip_in_kernel()) { + if ((!kvm_enabled()) || (!kvm_irqchip_in_kernel())) { return 0; } @@ -67,7 +67,7 @@ static int gipi_post_load(void *opaque, int version) int ret, i, j, length; #endif - if (!kvm_irqchip_in_kernel()) { + if ((!kvm_enabled()) || (!kvm_irqchip_in_kernel())) { return 0; } diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c index 6eaa53d74c..f83bd37501 100644 --- a/hw/loongarch/larch_3a.c +++ b/hw/loongarch/larch_3a.c @@ -1435,9 +1435,6 @@ static void ls3a5k_bios_init(LoongarchMachineState *lsms, if (kernel_filename) { lsms->reset_info[0]->vector = load_kernel(); - } else { - error_report("Please specify at lease one of -bios and -kernel"); - exit(1); } } } diff --git a/target/loongarch64/machine.c b/target/loongarch64/machine.c index b69bca6a9b..dea6a7034c 100644 --- a/target/loongarch64/machine.c +++ b/target/loongarch64/machine.c @@ -15,6 +15,10 @@ static int cpu_post_load(void *opaque, int version_id) CPULOONGARCHState *env = &cpu->env; int r = 0; + if (!kvm_enabled()) { + return 0; + } + #ifdef CONFIG_KVM struct kvm_loongarch_vcpu_state vcpu_state; int i; @@ -48,6 +52,9 @@ static int cpu_pre_save(void *opaque) LOONGARCHCPU *cpu = opaque; struct kvm_loongarch_vcpu_state vcpu_state; int i, r = 0; + if (!kvm_enabled()) { + return 0; + } r = kvm_vcpu_ioctl(CPU(cpu), KVM_LARCH_GET_VCPU_STATE, &vcpu_state); if (r < 0) { -- Gitee From a747905e4012e5cb40a22985e0be20a518979b23 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 07:51:55 -0400 Subject: [PATCH 19/29] fixup can't find cpu type. Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- hw/loongarch/larch_3a.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c index f83bd37501..5e271f339a 100644 --- a/hw/loongarch/larch_3a.c +++ b/hw/loongarch/larch_3a.c @@ -547,7 +547,15 @@ static char *get_host_cpu_model_name(void) fprintf(stderr, "read err...\n"); } close(fd); - buf_p = strstr(buf, "name"); + buf_p = strstr(buf, "Name"); + if (!buf_p) { + buf_p = strstr(buf, "name"); + } + if (!buf_p) { + fprintf(stderr, "Can't find cpu name\n"); + return 0; + } + while (*buf_p != ':') { buf_p++; -- Gitee From ab18a2706d39178471317be046339834a0dd5791 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 07:53:36 -0400 Subject: [PATCH 20/29] fix smbios type4 info for numa support. Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- hw/loongarch/larch_3a.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c index 5e271f339a..b1501e0ea6 100644 --- a/hw/loongarch/larch_3a.c +++ b/hw/loongarch/larch_3a.c @@ -1211,8 +1211,14 @@ static void loongarch_build_smbios(LoongarchMachineState *lsms) uint8_t *smbios_tables, *smbios_anchor; size_t smbios_tables_len, smbios_anchor_len; const char *product = "QEMU Virtual Machine"; - ms->smp.cores = 4; + int nb_numa_nodes, smp_cpus; + smp_cpus = ms->smp.cpus; + nb_numa_nodes = ms->numa_state->num_nodes; + if (nb_numa_nodes == 0) { + nb_numa_nodes = 1; + } + ms->smp.cores = smp_cpus / nb_numa_nodes; if (!lsms->fw_cfg) { return; } @@ -2004,6 +2010,10 @@ static int64_t ls3a_get_default_cpu_node_id(const MachineState *ms, int idx) { int nb_numa_nodes = ms->numa_state->num_nodes; int smp_cores = ms->smp.cores; + + if (nb_numa_nodes == 0) { + nb_numa_nodes = 1; + } return idx / smp_cores % nb_numa_nodes; } -- Gitee From d3dbb4f5e3fd19759bde6cdaeca4f4c59e99c065 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 07:55:12 -0400 Subject: [PATCH 21/29] Fix smp.cores value The smp.cores should use the default value passed from qemu start command, and the argument is cores_per_socket. Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- hw/loongarch/larch_3a.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c index b1501e0ea6..8fc79546de 100644 --- a/hw/loongarch/larch_3a.c +++ b/hw/loongarch/larch_3a.c @@ -1211,14 +1211,7 @@ static void loongarch_build_smbios(LoongarchMachineState *lsms) uint8_t *smbios_tables, *smbios_anchor; size_t smbios_tables_len, smbios_anchor_len; const char *product = "QEMU Virtual Machine"; - int nb_numa_nodes, smp_cpus; - smp_cpus = ms->smp.cpus; - nb_numa_nodes = ms->numa_state->num_nodes; - if (nb_numa_nodes == 0) { - nb_numa_nodes = 1; - } - ms->smp.cores = smp_cpus / nb_numa_nodes; if (!lsms->fw_cfg) { return; } -- Gitee From 774f3ba213cfe402a9b1703b3880f124e7f2f94e Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 08:00:52 -0400 Subject: [PATCH 22/29] Add lbt support for kvm Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- hw/loongarch/larch_3a.c | 4 ++-- linux-headers/asm-loongarch64/kvm.h | 10 ++++++++- target/loongarch64/cpu.h | 10 +++++++++ target/loongarch64/kvm.c | 35 +++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c index 8fc79546de..2affc50486 100644 --- a/hw/loongarch/larch_3a.c +++ b/hw/loongarch/larch_3a.c @@ -348,8 +348,8 @@ struct kvm_cpucfg ls3a5k_cpucfgs = { CPUCFG1_IOCSRBRD, .cpucfg[LOONGARCH_CPUCFG2] = CPUCFG2_FP | CPUCFG2_FPSP | CPUCFG2_FPDP | CPUCFG2_FPVERS | CPUCFG2_LSX | CPUCFG2_LASX | CPUCFG2_COMPLEX | - CPUCFG2_CRYPTO | CPUCFG2_LLFTP | CPUCFG2_LLFTPREV | CPUCFG2_LSPW | - CPUCFG2_LAM, + CPUCFG2_CRYPTO | CPUCFG2_LLFTP | CPUCFG2_LLFTPREV | CPUCFG2_X86BT | + CPUCFG2_ARMBT | CPUCFG2_MIPSBT | CPUCFG2_LSPW | CPUCFG2_LAM, .cpucfg[LOONGARCH_CPUCFG3] = CPUCFG3_CCDMA | CPUCFG3_SFB | CPUCFG3_UCACC | CPUCFG3_LLEXC | CPUCFG3_SCDLY | CPUCFG3_LLDBAR | CPUCFG3_ITLBT | CPUCFG3_ICACHET | CPUCFG3_SPW_LVL | CPUCFG3_SPW_HG_HF | CPUCFG3_RVA | diff --git a/linux-headers/asm-loongarch64/kvm.h b/linux-headers/asm-loongarch64/kvm.h index 799af75940..3687a358fa 100644 --- a/linux-headers/asm-loongarch64/kvm.h +++ b/linux-headers/asm-loongarch64/kvm.h @@ -77,6 +77,7 @@ struct kvm_fpu { * Register set = 2: KVM specific registers (see definitions below). * * Register set = 3: FPU / MSA registers (see definitions below). + * Register set = 4: LBT registers (see definitions below). * * Other sets registers may be added in the future. Each set would * have its own identifier in bits[31..16]. @@ -86,7 +87,7 @@ struct kvm_fpu { #define KVM_REG_LOONGARCH_CSR (KVM_REG_LOONGARCH | 0x0000000000010000ULL) #define KVM_REG_LOONGARCH_KVM (KVM_REG_LOONGARCH | 0x0000000000020000ULL) #define KVM_REG_LOONGARCH_FPU (KVM_REG_LOONGARCH | 0x0000000000030000ULL) - +#define KVM_REG_LOONGARCH_LBT (KVM_REG_LOONGARCH | 0x0000000000040000ULL) /* * KVM_REG_LOONGARCH_GP - General purpose registers from kvm_regs. @@ -168,6 +169,13 @@ struct kvm_fpu { #define KVM_REG_LOONGARCH_VCPU_RESET (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 4) +#define KVM_REG_LBT_SCR0 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 1) +#define KVM_REG_LBT_SCR1 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 2) +#define KVM_REG_LBT_SCR2 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 3) +#define KVM_REG_LBT_SCR3 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 4) +#define KVM_REG_LBT_FLAGS (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 5) +#define KVM_REG_LBT_FTOP (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 6) + struct kvm_iocsr_entry { __u32 addr; __u32 pad; diff --git a/target/loongarch64/cpu.h b/target/loongarch64/cpu.h index 078556a22a..ab88658e47 100644 --- a/target/loongarch64/cpu.h +++ b/target/loongarch64/cpu.h @@ -55,6 +55,7 @@ typedef struct CPULOONGARCHFPUContext { uint32_t fcsr0; uint32_t fcsr0_rw_bitmask; uint32_t vcsr16; + uint64_t ftop; } CPULOONGARCHFPUContext; /* fp control and status register definition */ @@ -167,6 +168,15 @@ struct CPULOONGARCHState { struct { uint64_t guest_addr; } st; + struct { + /* scratch registers */ + unsigned long scr0; + unsigned long scr1; + unsigned long scr2; + unsigned long scr3; + /* loongarch eflag */ + unsigned long eflag; + } lbt; }; diff --git a/target/loongarch64/kvm.c b/target/loongarch64/kvm.c index b6711da91b..0eaabe3943 100644 --- a/target/loongarch64/kvm.c +++ b/target/loongarch64/kvm.c @@ -1295,6 +1295,39 @@ int kvm_loongarch_get_pvtime(LOONGARCHCPU *cpu) return 0; } + +static int kvm_loongarch_put_lbt_registers(CPUState *cs) +{ + int ret = 0; + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + + ret |= kvm_larch_putq(cs, KVM_REG_LBT_SCR0, &env->lbt.scr0); + ret |= kvm_larch_putq(cs, KVM_REG_LBT_SCR1, &env->lbt.scr1); + ret |= kvm_larch_putq(cs, KVM_REG_LBT_SCR2, &env->lbt.scr2); + ret |= kvm_larch_putq(cs, KVM_REG_LBT_SCR3, &env->lbt.scr3); + ret |= kvm_larch_putq(cs, KVM_REG_LBT_FLAGS, &env->lbt.eflag); + ret |= kvm_larch_putq(cs, KVM_REG_LBT_FTOP, &env->active_fpu.ftop); + + return ret; +} + +static int kvm_loongarch_get_lbt_registers(CPUState *cs) +{ + int ret = 0; + LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); + CPULOONGARCHState *env = &cpu->env; + + ret |= kvm_larch_getq(cs, KVM_REG_LBT_SCR0, &env->lbt.scr0); + ret |= kvm_larch_getq(cs, KVM_REG_LBT_SCR1, &env->lbt.scr1); + ret |= kvm_larch_getq(cs, KVM_REG_LBT_SCR2, &env->lbt.scr2); + ret |= kvm_larch_getq(cs, KVM_REG_LBT_SCR3, &env->lbt.scr3); + ret |= kvm_larch_getq(cs, KVM_REG_LBT_FLAGS, &env->lbt.eflag); + ret |= kvm_larch_getq(cs, KVM_REG_LBT_FTOP, &env->active_fpu.ftop); + + return ret; +} + int kvm_arch_put_registers(CPUState *cs, int level) { LOONGARCHCPU *cpu = LOONGARCH_CPU(cs); @@ -1326,6 +1359,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) return ret; } + kvm_loongarch_put_lbt_registers(cs); return ret; } @@ -1352,6 +1386,7 @@ int kvm_arch_get_registers(CPUState *cs) kvm_loongarch_get_csr_registers(cs); kvm_loongarch_get_fpu_registers(cs); + kvm_loongarch_get_lbt_registers(cs); return ret; } -- Gitee From 34db66abd782303635fc4db49630d0105b7dd471 Mon Sep 17 00:00:00 2001 From: lixianglai Date: Mon, 29 May 2023 08:44:26 -0400 Subject: [PATCH 23/29] Modify the ioctl command of kvm. Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- linux-headers/linux/kvm.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 3875127a37..15628a0e26 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -2226,10 +2226,10 @@ struct kvm_loongarch_vcpu_state { __u64 core_ext_ioisr[4]; }; -#define KVM_CAP_LOONGARCH_FPU 165 -#define KVM_CAP_LOONGARCH_LSX 166 -#define KVM_CAP_LOONGARCH_VZ 167 -#define KVM_REG_LOONGARCH 0x8000000000000000ULL +#define KVM_CAP_LOONGARCH_FPU 800 +#define KVM_CAP_LOONGARCH_LSX 801 +#define KVM_CAP_LOONGARCH_VZ 802 +#define KVM_REG_LOONGARCH 0x9000000000000000ULL #define KVM_LARCH_GET_VCPU_STATE _IOR(KVMIO, 0xc0, struct kvm_loongarch_vcpu_state) #define KVM_LARCH_SET_VCPU_STATE _IOW(KVMIO, 0xc1, struct kvm_loongarch_vcpu_state) #define KVM_LARCH_GET_CPUCFG _IOR(KVMIO, 0xc2, struct kvm_cpucfg) -- Gitee From 0d84fd4cc8eb14fcc7cff4180ddb9390c040562a Mon Sep 17 00:00:00 2001 From: Tianrui Zhao Date: Mon, 19 Jun 2023 09:34:02 +0800 Subject: [PATCH 24/29] Add usb-storage config for loongarch Signed-off-by: Tianrui Zhao Signed-off-by: Xianglai Li --- configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak b/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak index 696ee9b72f..15fc2d00f9 100644 --- a/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak +++ b/configs/devices/loongarch64-softmmu/loongarch64-rh-devices.mak @@ -147,6 +147,8 @@ CONFIG_USB_EHCI=y CONFIG_USB_EHCI_PCI=y CONFIG_USB_EHCI_SYSBUS=y CONFIG_USB_STORAGE_BOT=y +CONFIG_USB_STORAGE_CORE=y +CONFIG_USB_STORAGE_CLASSIC=y CONFIG_TPM_EMULATOR=y CONFIG_TPM_TIS=y CONFIG_PLATFORM_BUS=y -- Gitee From 8e6cf94fd83fe5ff5764830d5e65b95bb4a93415 Mon Sep 17 00:00:00 2001 From: Tianrui Zhao Date: Mon, 19 Jun 2023 09:38:16 +0800 Subject: [PATCH 25/29] Add loongarch into QEMU_ARCH_VIRTIO_PCI to support qdev alias Signed-off-by: Tianrui Zhao Signed-off-by: Xianglai Li --- softmmu/qdev-monitor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index 01f3834db5..ece96121d3 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -60,7 +60,8 @@ typedef struct QDevAlias QEMU_ARCH_HPPA | QEMU_ARCH_I386 | \ QEMU_ARCH_MIPS | QEMU_ARCH_PPC | \ QEMU_ARCH_RISCV | QEMU_ARCH_SH4 | \ - QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA) + QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA | \ + QEMU_ARCH_LOONGARCH64) #define QEMU_ARCH_VIRTIO_CCW (QEMU_ARCH_S390X) #define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K) -- Gitee From 9bc49f29ced2eba765f3aaf027bb8d84f0768934 Mon Sep 17 00:00:00 2001 From: Tianrui Zhao Date: Mon, 19 Jun 2023 16:38:29 +0800 Subject: [PATCH 26/29] Fix host architecture macro of LoongArch to HOST_LOONGARCH64 Signed-off-by: Tianrui Zhao Signed-off-by: Xianglai Li --- accel/kvm/kvm-all.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index b69fef27f0..10af4170d9 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2503,7 +2503,7 @@ static int kvm_init(MachineState *ms) soft_vcpus_limit = kvm_recommended_vcpus(s); hard_vcpus_limit = kvm_max_vcpus(s); -#if defined(HOST_PPC64) || defined(HOST_LOONGARCH) +#if defined(HOST_PPC64) || defined(HOST_LOONGARCH64) /* * On POWER, the kernel advertises a soft limit based on the * number of CPU threads on the host. We want to allow exceeding -- Gitee From ec0785debe3485e1d1a2c286e7dde10d95ded6d3 Mon Sep 17 00:00:00 2001 From: Tianrui Zhao Date: Tue, 20 Jun 2023 16:34:43 +0800 Subject: [PATCH 27/29] Fix LoongArch KVM header macros Signed-off-by: Tianrui Zhao Signed-off-by: Xianglai Li --- linux-headers/linux/kvm.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 15628a0e26..3875127a37 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -2226,10 +2226,10 @@ struct kvm_loongarch_vcpu_state { __u64 core_ext_ioisr[4]; }; -#define KVM_CAP_LOONGARCH_FPU 800 -#define KVM_CAP_LOONGARCH_LSX 801 -#define KVM_CAP_LOONGARCH_VZ 802 -#define KVM_REG_LOONGARCH 0x9000000000000000ULL +#define KVM_CAP_LOONGARCH_FPU 165 +#define KVM_CAP_LOONGARCH_LSX 166 +#define KVM_CAP_LOONGARCH_VZ 167 +#define KVM_REG_LOONGARCH 0x8000000000000000ULL #define KVM_LARCH_GET_VCPU_STATE _IOR(KVMIO, 0xc0, struct kvm_loongarch_vcpu_state) #define KVM_LARCH_SET_VCPU_STATE _IOW(KVMIO, 0xc1, struct kvm_loongarch_vcpu_state) #define KVM_LARCH_GET_CPUCFG _IOR(KVMIO, 0xc2, struct kvm_cpucfg) -- Gitee From 47747a0a652d72ba953c9829fb1d4657e4141fbb Mon Sep 17 00:00:00 2001 From: lixianglai Date: Wed, 23 Aug 2023 07:10:25 -0400 Subject: [PATCH 28/29] Fixed the issue where qemu specifies the boot order Fixed the issue that the device path of bootorder in the generated fw_cfg was abnormal because the PCIeHost device did not initialize the memory space of sysbus, which caused the QEMU boot order to not take effect. Change-Id: Ifde4c8b8432c5c8748c1b38a3c33bafef4f24083 Signed-off-by: lixianglai Signed-off-by: Xianglai Li --- hw/loongarch/larch_3a.c | 14 -------------- hw/loongarch/ls7a_nb.c | 28 ++++++++++++++++++++++++++-- include/hw/loongarch/larch.h | 6 ++++++ include/hw/loongarch/ls7a.h | 2 ++ 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/hw/loongarch/larch_3a.c b/hw/loongarch/larch_3a.c index 2affc50486..1a4e982b74 100644 --- a/hw/loongarch/larch_3a.c +++ b/hw/loongarch/larch_3a.c @@ -86,12 +86,6 @@ #define TARGET_REALPAGE_MASK (TARGET_PAGE_MASK << 2) -#ifdef CONFIG_KVM -#define LS_ISA_IO_SIZE 0x02000000 -#else -#define LS_ISA_IO_SIZE 0x00010000 -#endif - #ifdef CONFIG_KVM #define align(x) (((x) + 63) & ~63) #else @@ -1618,8 +1612,6 @@ static void ls3a5k_init(MachineState *args) ram_addr_t ram_size = args->ram_size; MemoryRegion *address_space_mem = get_system_memory(); ram_addr_t offset = 0; - MemoryRegion *isa_io = g_new(MemoryRegion, 1); - MemoryRegion *isa_mem = g_new(MemoryRegion, 1); MachineState *machine = args; MachineClass *mc = MACHINE_GET_CLASS(machine); LoongarchMachineState *lsms = LoongarchMACHINE(machine); @@ -1799,12 +1791,6 @@ static void ls3a5k_init(MachineState *args) &machine->device_memory->mr); } - memory_region_init_alias(isa_io, NULL, "isa-io", - get_system_io(), 0, LS_ISA_IO_SIZE); - memory_region_init(isa_mem, NULL, "isa-mem", PCIE_MEMORY_SIZE); - memory_region_add_subregion(get_system_memory(), lsmc->isa_io_base, isa_io); - memory_region_add_subregion(get_system_memory(), PCIE_MEMORY_BASE, isa_mem); - if (!strcmp(lsmc->bridge_name, "ls7a")) { /*Initialize the 7A IO interrupt subsystem*/ DeviceState *ls7a_dev; diff --git a/hw/loongarch/ls7a_nb.c b/hw/loongarch/ls7a_nb.c index 5a231e6f01..f11b855a71 100644 --- a/hw/loongarch/ls7a_nb.c +++ b/hw/loongarch/ls7a_nb.c @@ -162,17 +162,41 @@ static PCIBus *pci_ls7a_init(MachineState *machine, DeviceState *dev, { LoongarchMachineState *lsms = LoongarchMACHINE(machine); LoongarchMachineClass *lsmc = LoongarchMACHINE_GET_CLASS(lsms); + LS7APCIEHost *pciehost = LS7A_PCIE_HOST_BRIDGE(dev); PCIExpressHost *e; + SysBusDevice *sysbus; PCIHostState *phb; + MemoryRegion *mmio_alias; e = PCIE_HOST_BRIDGE(dev); + sysbus = SYS_BUS_DEVICE(e); phb = PCI_HOST_BRIDGE(e); + + sysbus_init_mmio(sysbus, &e->mmio); + + memory_region_init(&pciehost->io_mmio, OBJECT(pciehost), + "pciehost-mmio", UINT64_MAX); + sysbus_init_mmio(sysbus, &pciehost->io_mmio); + mmio_alias = g_new0(MemoryRegion, 1); + memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio", + &pciehost->io_mmio, PCIE_MEMORY_BASE, + PCIE_MEMORY_SIZE); + memory_region_add_subregion(get_system_memory(), + PCIE_MEMORY_BASE, mmio_alias); + + memory_region_init(&pciehost->io_ioport, OBJECT(pciehost), + "pciehost-ioport", LS_ISA_IO_SIZE); + sysbus_init_mmio(sysbus, &pciehost->io_ioport); + + sysbus_mmio_map(sysbus, 2, LS3A5K_ISA_IO_BASE); + + phb->bus = pci_register_root_bus(dev, "pcie.0", pci_ls7a_set_irq, pci_ls7a_map_irq, pic, - get_system_memory(), get_system_io(), + &pciehost->io_mmio, &pciehost->io_ioport, (1 << 3), 128, TYPE_PCIE_BUS); + /*update pcie config memory*/ pcie_host_mmcfg_update(e, true, lsmc->pciecfg_base, LS_PCIECFG_SIZE); - DPRINTF("------ %d\n", __LINE__); pci_bus_set_route_irq_fn(phb->bus, ls7a_route_intx_pin_to_irq); diff --git a/include/hw/loongarch/larch.h b/include/hw/loongarch/larch.h index b8f28e330e..3f4fdd946b 100644 --- a/include/hw/loongarch/larch.h +++ b/include/hw/loongarch/larch.h @@ -40,6 +40,12 @@ #define LOONGARCH_HOTPLUG_MEM_ALIGN (1ULL << 28) #define LOONGARCH_MAX_RAM_SLOTS 10 +#ifdef CONFIG_KVM +#define LS_ISA_IO_SIZE 0x02000000 +#else +#define LS_ISA_IO_SIZE 0x00010000 +#endif + /* Memory types: */ #define SYSTEM_RAM 1 #define SYSTEM_RAM_RESERVED 2 diff --git a/include/hw/loongarch/ls7a.h b/include/hw/loongarch/ls7a.h index 63a070296b..05edee6030 100644 --- a/include/hw/loongarch/ls7a.h +++ b/include/hw/loongarch/ls7a.h @@ -121,6 +121,8 @@ typedef struct LS7APCIState LS7APCIState; typedef struct LS7APCIEHost { PCIExpressHost parent_obj; + MemoryRegion io_ioport; + MemoryRegion io_mmio; LS7APCIState *pci_dev; } LS7APCIEHost; -- Gitee From 0a8a7bd27b57e555e1df54c051d8e073f0d995f9 Mon Sep 17 00:00:00 2001 From: Xianglai Li Date: Tue, 30 Jul 2024 14:11:25 +0800 Subject: [PATCH 29/29] Add bios for loongarch Add UEFI bios for loongarch virt machine Signed-off-by: Xianglai Li --- pc-bios/loongarch_bios.bin | Bin 0 -> 4190208 bytes pc-bios/loongarch_vars.bin | Bin 0 -> 389120 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 pc-bios/loongarch_bios.bin create mode 100644 pc-bios/loongarch_vars.bin diff --git a/pc-bios/loongarch_bios.bin b/pc-bios/loongarch_bios.bin new file mode 100644 index 0000000000000000000000000000000000000000..d6330c6f0532effe458726efa18222166a444839 GIT binary patch literal 4190208 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 z5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI z5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI z5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI z5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI z5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI z5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI 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

QTQo+|HZ@ByG_EXr==mhtmuge;4Xri(alK&~ zi0bBMHgOcojD<^9;OX+`FWC0DZUSF(hwIF;oEr`71Uq!lus0NlwQiC!Mkl*K`@hM z8hSLtQ@IlX07C1*Ny|!!ov!)+LLYZJ^^V1>;#iFJZXfof$n#_J$s8fg-1FbB$55rH z(;QS#sQNk#hEg7{r-suhkfoe>9o4#229>Y-)FC9Sml{Eot?EsTBj;PPM%vHhU|E3| zBvdf{fFc~(FUoB3SIlqAFj7DN+GA8o36+RfH>pPMy_Mana|s#p92G#-c8*7H=P@>J zq(7h_8ip!SZN+6(y_A?EVa~eILqB&B$|Q^~*POIk=EtXj%FET@qkNhK13Rf8jjd&h zWRWU3(Uk5Ki+JQn5aT2YI8~i{HB14+o`kog1Ph?*5{=yx!SvTZRW09`)K0nlW*Fy+ z=X3PeSxHSyPN{X@D26UC#5`E=YR^oFvxaTdW*q#15b^i=e}d>nImrO5$(+#r-MZ|I zz;{$Q*Gb6V<)c$^@~7`{>gX`NLvK+2$HWAuSmVq9?Jbm!N=bJpqz|PTC zQx-J@GT?rkfGgV*+SPy1z=W4>49q)}6e9qme$Z}QvSd!mq2bSC%J$n(fngvmfMuWo zWo8htocelxocE4IhuwPP)3zZ|PLc}uurg&iHvU)xc~n6Of>)9RWn%PTgJ2d|s0E3d z46^6xz?eY?P8JZ;&_q9WK7W{I;%Oz|2LsTTdrDNkQdgOw_`3AJT|pj`|8fwozT_am zXfil%@jl1Cny@Vz7J_^`bJec~5bDvCIMA-zvBrUUu)*zeBsHX?PTr70C6i)%+KW_1 z_=g?@qCN|fy*xiLXK~QY--?CNZ{SpdV>@Ye8-z>ldcx*^YFzXb?7R_XHGPrtoFhkn zeg2F-K(MNX$7WTW6hz#-&hXj;Xa2aKxD`r zu&O|MPv#S`U#Xq5426kXkt!nvyjNJ^jTA)b;NP+LQw{n3S(2{!X|0=I>IpCS)d#OH z*9rLA^wUXsIwxVHmTBf0+$De2K?9v8W)SXi!pv8+jue#Ih3B+7e514qBROpGxV>~% zz30nnr4tZEmnae!TMxLP)4moJH)46e2qr9&&_0K{FDj8%o{E_x*XL9i+WQdNVtW~m z=eAr>@$bi0;$g{UzRdzT%-Q-Fh>SXXI#io_?3sF91Oz}#%}Z7#)H@LcuusZJ_UTI^ z4g2+7n#0B2RGtBA^s7-6q?5;d+sj3{`Vb^h5C1#GR@hJK#*Rkfa{l>h*s}`K(IG*W z-D7kzWjU`!2oELxAEi7RjOHBv!jLYjLOyq~JC05pjLs`7-4aOtLex>kp%Q6ov5?$B zK+7in#rVF$U1Yj1_qBzLBQL%$y@yF-TOI-!hk@FZCBj!JPybeY>+xxc&>~o zF=3j;)t;aTHVkc#O2!lvgui@sJ<{#>AJzXAv0sQuOlbYa!69=vf*)q~Blyk)2vW5N zBi)^MRwRQ@E*T9-V$fy=>Eh!B)`nQP`qqlp1Al;{%~ofWsdsmZvK{j;=L#iCpE=Y} zqp%)A?-H+yjKyAwyyn_4lGZv~F*K=X%gmkbmi4LHrP7k~j@fxt0F8NG`}N+Os18n~ zJ+N_&I3?n?F86!54s-!NqxwmO-m#GtzUMke;3!LjVy=R%0{>Ce>>7_p$M|P8vwDg! zu0fK-5}B`|MEf!+I73u>5q`-_ia6svY|A0M3{S_%SWvv?c}1LP__I#9XL>Q65X8Tj zV1lnn9#R*(0o?KSx59-i4AKGfs8x*74U3;XjNzdMJ{!izpIXbiZ7|7Ktz_2!eP^}^ zNUbZ9|AbO0O1-4raACft?7GnJ?zH%2j`rAS51E`t>#I(YCq159tENpNr)w7Q6P{BIz!Hcn&E$O>r5iB+e3Qo4Adm8j7AWEInbED!(1XFdJo8UXX}!)Eb9s^l@Zi!mw|`v4cS^r@92ceb zM2L+8QI7`vAv-fX{5B%?f3IWWuur9CBG6s(yo4>&#mo*|rKy9XG>o(&xUB)9zPI|p za$%nm^k7kJIZD5ANyNFm>0QofW@bW7XnG)jy%?wCc2qNye;%&r8$TgiV{U)L;4&Vu zA>h95S)?)#DEd-k7A0F>9+{gsH}hjY`4oKuOi5j!ez~Cu6W{z=>T=ZQ9S907O{t0b z6ORvtrAup!`|Wqt;XwWqgu=JXK>J{ygNu`l_uc3}wFp&y7fsiCKA9zaUd!6Yr4IRT zfcargHXU|nV;Sx)ShR{&a<7CH(|wavbTymL@T^?-PpvtYrMxa3MADh)uq33+~+b2UaPG;$LaPBsUsuVVkCqfJ?%o_@r zj!qQ-eou*|wDiJOmZXz+Ekoi#9!JX~%b|8ob&~keog;MPCq}@I#j)bK8XK6?HRn`j z;`A$OG9h(zE%YpE8T)?Smm+OTs6YXYS%BqPvcu(}s@g@8uASJbsmwo%lFBjAD<-AY z-Iu=OiY*5-qv5tjimEdLGx!8Paxuv5>9*!WhH4v8J!=`N5Ctb>aE!jjF>)MQ)nNDc^m~Pe zre!BOZqwCdE{|fMs7flK!YOTI7~p=9_(hB%mCu4wea%IgB&!Ni37IT?k>Aca!T+g1 z;yRWPS-1cpzz4j8zIu=k#hgetp%8bHibomOFk^o!7Dv2Mu2_IK9#IQGL|JLo&jY+k zS@HW(eJQzWx9aLeDqbZ>Eg@brdIqw@d=UHuX_2`NHegbmdx2Q_JL$)+CC3Z)*70aB zNpKJmGPe>y<8kw0B0U^{GE1hHZWe|jr5!oT!`7up4fvs zNE%Tjr!({-W9X$R84agypQ*gg6JVC-Flp*v`a0Jz7nn^M67-|{biX)z?S8n_Q1R*4 z>~f>0T;t2?>yoF>Knt2W`kO?1v)+ko+k$6M73N*ctJH6rUjK-iL}i4aNKlWKbam{wwS?9YiE%M)p9cU2 zX~0Ad{DAPA#gx8CDpnar%R`%b3*k${oi@F;S3D;+N0!Nl4NQTN4=Sjt_c}PDc%&^{qW__d^XQLkBK6o^fhw8? zkC-Kpv{IE#sdy1UFfeO!oAP)x=VWP(4z9=SX`B9dt&et_X%(n+Om=oF_rvnHISz-bYDbem{7W!A5Asm86)K19q?=XsRH7y|qW-1OR61`jT?)y% zPp{3Ku@}n+c{%c2-Dug2!o0To6Q%J&wTdr33Hk% zmM6Z=D38mxjU(CIA7YOQ;9%;Ib7hpAh4bOUzPC)kE->bMNiH?qL!#`?Ox*JURfzFGA4yEf1d8CtvMv;UIPb=#FwDtRFyT^2b|I5p0e$3uhdi#_$a~ zvhirQVxitMld7yt{L%t4Hy`L;!q;m&0ER3KeD{(7WuZB2XjinOnPZorugmohCg{h_ ztHu>$)PnAC5OAYhhd>RbfTLIDjOm&@MBulQR*Dzsfoo}gBid38GC@k;h`;qaTOmX= zURBzW6C0;7#O2bvmdWaqE@}f>VN0=_Vtm|s z_Gl;K=3;Py2|cR{>?w=Vo`_O!9CJwEBh`8Ola^g0n`a$w<)(Pa0#R4v;=$BPS4TLS zhRf4FbF|A%tX@NuVw_(v_Jz3;%~E1mFiKbKZ58M=r4yOgefu}NDj+vCU6s>bJ7_F2 zMF@sm@>{JK`B)x?a2Rg+eUheU*zWa@&Q9a91{fXbKSt4ji#8;hjxc80Nw^Kb>V3~=YE z7Mna}=D)YrKRfugL-hMQ9^I*|VAZq`bi(!2^j{P{V%Q&>#rKav1DW>(lAKKu%flx6 z25|MN{1NVVdf+?&r2x#ym4xpJ_6ohFr7E#RrZFbeK4 z4#Pup>dMsAizH5(3KPw|KEaqxQ~^+8Uz$7NF-C zA%^5cmOx(4Ub)npGMW*(;WUT+iX4g|8eTs1h-S2hCU;iPX>ptnbp#VSgN{yxa-AbO zjoX0Q`sS)P$DLOPFiy+!?X^yvfGtB@Q^+&vnW~xK8R^9$0WYnL=duEBi$93^*S1l; z))RnvbgF*vW4=fx8sp>jT7_QbW*VGWbBIaX)nspu9^^S?_(4N^O^vuZ$XQ^)>zv$h z5UwkNz07kKBF(GiL9S{}`RGqQa5hcmo@Bia`Z~FC)J|AGn>|cd$Hc%yxpSiEx+goD z<*@t`&+z{*V1L)NdN$lt@&if`21@@GZ$QOO=xh1y%^{h8Mexq!G!Qx6snHtlHN)O{ zx!TmrMx3TVLp5cn(TxG?F7`SA+43;9tYsGF)~1xZ5uHX{)>;=SAcd7yPQT(K{S*K< z%FQhPuc7(U9k!tGX{f6;VZLGw%3M7Oo54&Ja{!PnO;wn%_@=HsRiD}zU}S9a)Uexm zxN!O(<$UPbn55jrOZotX-3+0RA_s4b*$2b9zfpHU;4jLi_A zM>0X%*-%LC!X9znl)PSUT3qMa^XkA%-85yZhErN>9ACh{1@;^ovIF3>v@dmxhAgjc zun?8k-;|4J#2Ua9i-;;z*`tBIt%ld%E77>&CrxuxQL2FQp%roWv!|kYVXk@KHg*wy zj||Nfw9r`0p-{Nt%&eLT4x?T-ZR=Pvt73CCr5Y7o_q3auDV!;z7fW;Wm9@4a%tyQUp{ld{qTI58(@$RnZb4USHcnR<0M(mfJh>=B-I|gQVi)#V{eMuQXC0@ zc#PzEEx0z`wKgx3HVwyIMW>#o-IJ9Xxe(1;NfpNIwHFP(qpY)A{N zA~fv${Q-ja2DJHBqMujNwx0fRP2oZw=@#R@GJu?bqdo98#WN(!GaSP(jfvmy&b-*@ z*8Z139#h!bEybi_96$x)*D|ME_Lk)rm~~Tymr^>g64cq5!?)}=;oGN2d;F<_wKA?SisQ zm~@PB+ByH9SF*1dKwhEvP^HC|?OKTTnm?s~!@wu{j z|B+pX$1D{6mgX{v%axe$T_r-L5|t74UHEQdJ>l^kD=yo z4ZF`S&4a;cMpnCFXF`XxAH9~liHvm}>7}H>uo(Z`fB1h58YOP#Sk6@`yFuRX#ZeTO zaCMN4>s!Lf(FU!inPQN~b*%Z7WUr4c+#~ZW#>TRJ=k>sbh$7GTN*5u=Tg!4?X3pKH ztjI8Fe0-sEVEYxAS<>l#wws+-Gyq7?aFRg`PP|l#*(X;p0x$1+cP0EYJFL%oYBZ9W z~uH?_te<3`48emcMuwec?4>hD{Mo||H&zpP|cPXz0^2%t3 z_xdNeV;(Shtsb=LDOU}8dSC!MTy=S)JDC%ne(zcLq`AjDSV7=u&D1*bM-mc$8^hsb zx+~E9NVWX;w|+OfqYrj6GgsKRJ%632Z|0ip5q*kTtI_)(I{)44xvNvUez|5&yizy0 z_F|CM;mcMpVk7#uc_tAC86Y&G%3R=eZeYw|xKcHLL~&Jw)9?rA0pNaQXIh!g?l(OD z{Rz$x55|8r61}qLfPwmxzS!0ZaUvu6IE_CR(UDpgOGh#jN8sVdS7-HY&Pv4Quqihowq4(j-O%|1J{C zx&VWb_CIcv*}+Mp@gfV&<93;#k0MsoMb5#s3AL9HAP=USW5p);)ltM(jq+jl`59Dog<*Z){ylWc8?SQ5&Ok^ zVp~yJTYI@iK%?DZDZ5QsxTJrACoTi%u%b8A}u zbgm<$4E^Uw${=d{Chz&765<$!Y3eWo_XJJJ!iWGNyeVuW;wxF>`JJ^?R4~fa1Hy@LmmsufMOBWs7J*5 zaip1!$Rxn~CC!17Lq+Nd9SD*Rz^L9h62MIyekUxJa{5oq;X$D05F)XE5rv+as7ZvS!+E;D@;+-aso|7hWHM!8QW-nL1Kst%sfn049R z`Jdf=Y+bojhLPfkX7|^ynO6vKy0bgqh&HzQ?%fE-Em9k<4R0O!6b+l0AF)b;$2&Ge zM(|cjyq|Is(xqMo?r9)Tj8$lD{jbVI3T#SEP9vO}Zx3&-^YV1iS^>RT?RYOsEnNcm z>-cs8fUfJV$?a*+yEfcJWUoSYGv!0)tyMLw)0|@Y;e5Rs{2%AMTp#V1SZulZF}==~O(i@VhDd=upPQC(pApo8gq! zILfG1F+F(7Vd30oWR3bDkc@a0`}^s_}`ZojlX@iW@i&qY^Y{$jE3EU=0L4l79*%kYJK{ z(S9;WuF^OndbIBBWPIq{KK7qe@;fZ|71_kiB%SxA_`Xcn5-bfZWN1`?0PM=6@x&HX zTHpeF8lr2m>tN`MWH@}t_kaX~UK`T&p_`5|O%OeR-vUp~KW+1GhQ1pmi+~TPy+mPTSf6C)V>@`XzRW)MSdpwk<>2kuEG7r*@rmhi*}r3_YIt@ioA|YFQm>ooDop z!4hm2#;`0+j+?}!L0&}g!K4ttrb!U*FJ4Bt zORM`E3LRmVk_m>``Jq~V?bn#0vy1wzX3%e3MmMbm?_@CFfop3*F{Mu%E7Y^vib?Hq zE>Ybpw7Jy!^I;CT6)`RJ*@&gu$>9tI9jKmUUV+U ze$APSjfS3n@MBbCgCc2b!O}%tG^kNA3>w5}}c3#fySv{)fpU5n2?vh9dJlYM=zY+epttcA*pd zQUTk>uEK%&_e>nCEutoaQNi!9+H7$R?6_<84APAxF|}%%eX)l7rBd!Nto*_+@+h$| z?5FnTcuN_$_TVFU&woGKXV5KMonMmcF$vF|BtL9?#KgPShe)D&nAqw2Y|zbHHfVk) zraUaC$yr7DxdK7;00CTvp>jK!J!QLg`_Q3CV53-`4+pMal;BtIe47pc)q>x^pibrf zV~98No8p58fcrTjgI8QkU$9Xrd$8r{`yMU4>=aGeIfA2)td!gbRCIJmKKuRAq_q6P+GHofNr%{B4*4lJ8sK`Tf^T)>RQAM1C@yF7CnP`(V@#hJTw&t!xwXu(UwhSyW=kQYsPyYdLmMZ74vQ*d3E*ipk=$-#TIpu z-Mc~=Faw{ULCDK3;=+DGNQhwT6?G?`NB=KUy92RgeZflje1MUEBq_S6sOIXnXxy6*mR0Jea-*+XK4lNQ9 z;LY+4#}tAYez;kTcUzgApAE8G^B$jYOw14J{EJ3frC*+)rcWsHW1JKQ$5~QQ3k6g#l3y{| zfc%&~Xk$1j1UeBs-DA*hk}BH-<(y{V6&~Qg6#_Gv48YyuxG>hF%nDxbmi_n}v2K$- z(|wQm%*~T&`y!&D1a2Pmkk!^<_HY3!BQK;1`b1+Tp1WPsA5-8Wbt4XQ3R7_SYHx|^ znSF!Jm&t8UZaxqipxS31cP9%4hk6^Qvqx|o;lB>&pmt@H!}i-I65+15pBOOER|p*G z@$q*+{!|-3TuHh-gl#s)%G&I0xt~sxPPSCL@whRH7@ubEr|d{G5EXUBCeH9iafG#s zA*%51AL%{VKVg;`!TveG49)b=Ivq6Mua?LLqU=Efn;|^H$_LlF4x0>_-iV>~ZNHQS zbA$cfQz*ON(3nHcpvQJQ2l7~TOz*uOmMVE6N0y!^LjLN)#{)knp-flF>yc<}1%7IU zKR)?8V5aHh+P43eQ2)_DBHG-*Y@E7|FP%_}nnhH5n0la{Y2Q9}s3<~?CkFP%M>h(Q zt)e!YLGE%-1WX(AMs}-ck3tTr1sCyNUKu^3}rBSzs7V z=;?&G5D;&7xw?1wicGxal8ZA?W>i&M9hnYqZY@{&sf z92>?7mY9myMEw_s;$WlvawlNFts?$_$@`o_c><7&fpxR1Vhmb#>Ki9}*5PkOD9!Q! z-fEC$eSC$9$xg_*Bh=cA$1s$J@+IQ1rBo-qlME~Tvy%)BI`y7?xP$%7n^yLLB1QGu`sfNv1=MTDc;axdIYZaFvku{l|M*UwVoU`td15Iqrn6mTgDuD!LIZvtC0DUwjd&;Jvx`O-Of|R z?7k&zF$b%z5%@g0)8Cay0tCgUp4+hD%r64QTwNCkPBnKL7s*Vus%>rx1}ep zSGY(MVNEAlmt=IyK^2y-A10E2$$V6;^hRUW$0r3LB?Z4 zYdEG$itOV?q@_vcS-}@lhaDCMtk2#i)gjDbRyAR|#bYO|HUXb`a2QhA&RG$qNA7)F zY;$xFl2xAUZ{Q*EZ^U67@HiRNnO>|RJ8*ZWpPSaEWH&YqDCviH_o=mB_2l;0aqD-R z_zo0V0glzZtMVW7GT$wIL&6b(TnF*(3zvkVSzzsNE$i{vxJ~!fX&m;0dIe*S2QOOw z;EoBp(~^2rxQW2;Vp(Fq^E_M2m5utw8Zu9mu|*UkgUFe*>{m#R;36x2*x|IFea*PI zv+;itb-Up$M-a20(frkL+Kh|ghDmUz=WWNx`9DO#-xvJ}B@I)pL}^`kHwK-YbY)6? zZM45T3&9Dn*-~Abew9mc*BON2IV2>}Vq2W?FX@zWypwDp_Vj#9=M(ab482M4#ID1o z(_Ge-P`Np;tg%tAk)M;z)(bc)>I6kE`dMEHrx`ojZd)8T z=G=AS4>v6zXjn2ax?%MKtx;)a4}i1&IDsYZOg05{Zs$f+C3WUrv%`T9k<*uEjf11+ zoRkK?nPHl1G5GOq2Ni|;a`9@SpVzot+T)@TG{pbx^km^k%EYnov7vUPabBCs1TB2T zcdhdp*84<4ej%IG$;#usXRGb)rXBU8Lrkc}{FFr)*K4Rye%5blm@IqnpuBH!Hw;D~ zXLWVq;%cDsZzwL>Iv(xkGNJcAw;MRn5IzV;KAD<#ar8CqSr5^?o>HvRO^4jA7w0oX zT8NWhvY>R2Cjs z@Y(e@Z!`t~Dj19_E}#uPrGg5eFk~Jo--&Q)8ZvWG@@r@ib^9S0+kh$<)Dopreb$q; z@769f1XAmtPA+wxmaRa$Y+i=}I%C+KVy6JBi_3V4IL&uDuTP9HTNDlLArxVsV4u9@ z5E*sURBGEDXlKNEJn}A8L+0gdsEp20S+UjnKITEX8zD0l4_sr=?-^EK?fQ0T&Sk&6 z#&v547(%+-!;P+gf7xI%Qv&xWStTE)jRMEKE>j@mEu)LMCVbrV+D-zzDFmZD`ClAQ zg7qs~7}Hw4-io2iK#VQF)u;H|BV64AMo_ll9Mdy0D3YK&0wKGT3UUJ|_J*5xO%GXN zKo3XQIg*Eel{S5=(&w>|A84ejr?SajV1+H?u7#anNC{BuVl-NB+H}{{PfVyik!`0C zS5(8PE<)m2^4nntO)(*BaWV@CrfS&Z_m!+|#0a(4UWyliQAUo%AO_H>YU3c~qE7WB z4$Rz1=%Hf!3-hkLDPK7_!SP2qF{zZeOqE1K<>__?Bi8IlpS3joqF}5^n+K1J><`7T z-rrZ|b*0nGFWr>$OD)_5>SJ|yo`!nU_-!ng6|TmUqyW`-ntrQi>W%7s~*)i)pyQIJ?lO^-7ic zgHKU6$Vir}F+=gQGF|7EL)NM4lERAU!@L?LMLcwNe;S?imlMy`-u+~A@*i7}Q|wly zHPv!hZO#(~h2u+U_P)U5%#5T&j>(59EP;X2h9n}Lb~t2uvj7~=xYu!Du({Or~|FrSViynKFB(V z5DDupV}TJ8VCX4>@)3aFSgvgA4=atoV3v?;Tn*_Yk|i;(s0Yc-fYt-L2em&_}n zd{7sr(5#XH7(K!ILZn?Dq8{?9p>zx686%}ZC^!7&O~D=J=*3(6;ybvVPk!?__(Xu8 zFoWEAD?FH4a(@q{%Z0Z2$>SCOWQ+`*LPfo9;&7MD=2In@{K4dvmU}n{H%5;R+Ehj{ z^GyF2Owy>s2NMHs5cBotPIlk#vZS2ER9^v=4PtDy6rhn&o+I}CuVZJ zo5^=>R&=1IfcF@pi*^A7OJtcDU~9e3Box^ya$F2Y^N?7^NJlm-bxAPqS= zHfUHw z=Im$Zh+i&j4WmJi85l-V#JJG`^3;5Tl?G7;i_Mq29uMCtdd(w4bU|1TqYfynAyO6R z?rN)8i7*$Rlerg~brW(!`0&6wzitZOE~nakjpHo~vS^vrDM=D!_;thv@Y5fqQbMtH zRi{BD6f=Om!bh1tIc7z@sPTNnc}oAbRTV_dKyb9?c4Z{%{7vEjDPF~~Qcpt6g1u{# z5}KuV$t?BmM9(Ew`Y8Bj>7Sg-ix@}r+Nm@F3K&f{*O^AvAW%tKAL5Wp9RtcZ5{4N! zWe~4!NJC&v*es|O6uglYo3=)Zod%c8d|G_xY%{TGZrgr32Anb)7mt@K2n=fv`IA=ALrvA^~AV&khx) z@&`RwEgTIuc=r(XeLA0rX?hIkNjzS4oF>QOC94J`<#8D#*g{{%{KotMY9*fw(M3O z6e2FM5LucyQbiw;&?9=q92zi=vye!3M=*-qhtW>Ygq~j&J1g%DQ-SmlfVaFh`dSf3ZyTA z9lI&%w+%7Jmys`Ue9W4X#%+|jd5_|tsGasto|zaspHF)qi;lw}=D{=a`LQ14u!1BY z5alrcOGg4^vK+YH>alc2_rtQ`0>7|oMA#NoTZ|-i>}`{tenCkXH@(<+tl684zVAGP zo!GUW@c5VIX~6;4RTm8$PKTnJIcFpsc9atQ{3dKCNSnh&s>;$!T3K08YvAtKBw2Gh z^L6iBY)V4~_L{Tho-%SrS+7H8C7Ot+?V8k(f>Q-Eu7Ps^BX6_t} z2&0vtFnmzz;~v@MgSh!17Q(M5F4;8+WNsJTsfY|40phCM^tiin0a_Do65>z- z5?Wz?t(wk}j3@t{G?z)H0~2rdpzMD0j}PW1rP)x1xc)uT;uk}Xf1qi@i&10|h@I2A z|7JfX7Ozt3!h-!{-}AbTds3gs+4_TbjjL^1#~!kXj&Qd^K9FQlI?8ggfbPO-AxUNJ zEKk!L8s@j428{|0EQ?;}8*i>fedtA&k^c_o9YvIN1W&(0C9PX|LXwRJawd-Pjdpa; zjfAQ(C?ZgEwyw6%h+M(DI=StXJ#2p3`z+7W2L!XfM;9}F4xw?ZK+%08NlzLxjJCUx za@;JifekX1ruc+kFCb4bjO?a~8e29B7T1hfhVEtsedU@bVAxtnCFdq-s@asFoeUp{ zjX#l^7W4(OdB%Iyksy#HE*ubLzPWpRrogm_^=9$)ec#%rI4Bj~xl@3=K3-?3h=sE0 zXMj7hfk1BA17LiVb>>~=RQVYg^4Ol)sR4>5)C(wO|`rE&(sCp_gu4h7=iowd^MgHP*DsJ zWABX!dm}+%Fun%WfzE{-NKg0J(i+Pxxfl*-jO0`sLA7;_xv@N%q4o+qg~7blQzTAi zCAE^UyL8tgO%b67EH3Yq(BAi2_70|q-ildR?roWj&Z0_d*f&KEUXR>uN!5IuWZj;Q zxY23Pu-s{wQdmh#5S{HzkLDtZIpwGq6NPw`WDn%%v$(sG-f*dHwobG+Uwf+I5vP$Y z?DeN9m9yEMs6}9#;yjUIez|ogSyn z3ZkvG^HspNjVPA8tO>)sv`T2J^(%yf$>WY8WknWi@4{VOPzE z`I-P39LlGiQqDUD0l7>PbmH>4@hQRVgb8J$^Kn|^4GJRDV!HYo3+d?2F#(7DtUg}u z<;n)fuMXCvAqi8sJ*f~U^j+aiQ}V-DWdP)#3C_nFr4{)j@W?-+MWBaog<(;fKS@J8 zQ+c^I_cvA?oO@(OOz)CKB7G_;ds9Qf^Py}d6;#l-bgmw758me%|uj_3O(SRElkD; z=uoWVO{grx76K(h2tFnw_`)V0ac$sBQ5AJg1&4D}gNYfbq+O`VY3fKk0Zw zX93NZ-Dj7JCj@BI_QC0y!Gzt1lsXeQ0(BcU{il~j^E5YCy?8hU?%T-7wp`3QKrR>l z?a%!(UVK1aCGEUIKBsNJb&TfV(*1HQRzrGt@+M}|`tk_iYyoXJn(nD}C|X(qb-!Ju z4e!7!Qo&vDHt6(v-1&l3KppG2lUbv+loH7F`NQL#E}Hr+zCa;SWJD0Dt-vPlFgA^p zPbffckxbe?BT#qwI(d7>&rvsUe1R5jht*(U`P5ZPc;y!#L24qLu;RM!n z-febvrj||)xjm89u~8B?PcgWA=n*2;)jl75;JSpl%S6<6qV6{|+olsv62OOxdBxRO zeu}(C$C~xa$INmY3eP1^o1}{_WYdb71>H?3pAsjoLT*j?s03PizBlTBK;^TAO1<9} zp>g*}w1snUdilez-v%I9j;h?)$Lfre6%;Cs#qaN@zb84e&9x*!bnt9-36=4JJ6J!CHgB@^E&H8+_zPznN=dcj;Jll4m z*h|J_S7@cyvTG>meG|c`&7@2>v(`yRH-ABUH9oXq4ds1{q803``{nJ_fL8c`TglzD zjW957hdlsXEQln)0;w>TmdoZdJjj5OYk+^H;OeX2u@5WU&uMa*wkKu8`AQ7U+Dh|M ziUuT0McnaAXOmM$XHofKiIjvkr?MygTvAQkSJebJtSe6SA_2BM0bT=8Y0z$l3^`9% zuAIDCA{Y0UWGi4#MD~mK;rrj~aUYAI#mqRsvmOs~Ulqmi{s_ z;-gYXgk=h5dz&p|t#zbKwpNZg;-mdCi@Jy(YM+g|UL8!G{^xHs$Uu(>nuF$XesF4| zqMPESXmzqYuP5QB2-qpr;`c(6>*Q6eA^E?ni~5d&_mPfaysdvG>7nYpDWIOzh-_Kw z1U|;de36bPkMR0EZ@ll7fB^wv7N|!5{bZ`|6=t|)PD^SKbGZ(fCVn&T-z%aZ-8Vqe z(XH3@o$nd1pF;+?8TI91)C`Es)+pqe;PjV=PRFGP`PQoMIwMRp6NNiPf~!1hem|>- zwzh6TcIFJ;Q09v6yLKn3gj`S9h_U*;lyB|=KWO_ziLjYYy*oHLkS~+oIj&uCc+|>odU#CN(Po z|6AlLX#o(T? zlf4gJmW-sN!K>-PA;V4flVw|?&(O@;*=ZKbd`U@AkIvW3RRi1z$CZ zdt_v+s}x#&EK;ci25Irdx?l9{rXF1;&^duZj~{Mi>xy+Pt)oeXiC|pYZwl)|2WE*# ze7w)80bUsqCnokk2`5Y@L*p!HVxB2YSZ1hmKcdqo?-FILY7$kzS;n(W>TIF5I z&1JaFD%ENV!BGq>z4uUbsVmF)+_^Q+9|6Z!uTn~edgR@7W3esY<>3)P%qhQz^1dRG zxE7&zAwh>N^g#M7G?a%l_S>MLhO>ppDU_j=Tz!JA#bmb9MtI8qxrnZNW2 zreb?P^R%xXA3m~=uX2DD*0dRan6f}-m3kb5IKiZVqY5&76ebA#w2_C-pf`E)I=Wr_ z79hAGR}?=p`3Td&kpErg#9dD^RI{I4#2Jp1A=zNk z0Bk%w{o6zd`OWY!ui&&i`PRHz>fC`f^%kO8Dd<8)huzb7`xc3K7Kd*7kL#2=KvJV^ zGIjv_+jBJ0R2r*xraP&;UBzX#y$in{#diMag19>)(Xch#b^gN^&X&>@bYPd~W8cKw zpkR)|j{L^eg2io)c}RoT{${Ld?`?yURR&Odl;v8_N0cqx-clGBxH?2*U)*d&-C7$jd6RQZ5o9j3zerpIT08r-llY9pc`gA1i`nXD3 z0=V7dBm={Klf-v-Zdz>AadsxCx2=7x1B%vc^p7J^*0OLiwEHg=&F{se+!Bsb)9q^( z8qLDe;sL(;E=jJWj_6{KBjRFK%k(>>8rMQZisT!3_2splA;e65sn2*Rm9Sa+J)WFA z515cWQ@41CkTC_C>1_-%3#3PPB)~gSvUYlpC#J~{^;xa;W6LBOCh;3j^^do-t+LZA zp?yD5P|yA^8IDo76lB9hqzjQdxl+$|xcxc_Bkge@J+}(4Yc1H-Tj5IYUXHfpkjYhj z7{TLpycp>e0xP65@B6DMp!Q6J`Jeo5qei0Hfo)9r9qDAsr52P|VsbMuLVM(+#F2g^ zEtWX#x4?F$VT}<|n?;G>3ca&}(^}+o#D2wz2D37haj=r?Fz`fV8T2J49z^`v;ql$| zVc2u1<$k4&Ok4_tu>FQ8JYFL<#EiO9=nm#M8L7Sre%V0j>+_};vjXe$JDh`+=gEBa z)T%xx5f(gf_-aIik~ZyRT+MVtaf zQiorS&7^n@x*c0qSf0D{g@mVdE2hv8i5UpGc=c?H%C-Bh;1;USkImvSzvBMfJ9%N$ zYSbeXa;Ok22z>AIsZew)C|{GaD-iK^=irXFppe7Bu}X$%ew61-q$O%FxX*l#HP?nk zx@lo?EVw%5_Nci6Wd~gVm(19t{X-M{H#;bD1{MrZ8Ou!tYy#XQpol zv7hvuJrp?-Z6>#Xnyszw-f12SQoQQ28+s1Ajseg6f$Ksb0-De+Om_k*3)GQnA(9|B z{{I@Gu8J_lf7fN3lhVlQ0jom=&@YN*5I^8e4FPe{3UZ-#_| zg)$8cMdJh}MG*s+Q=FM+jh~+Mv3yWwJ(9LS-xE-}o z^v8sQohb1RuP1EZZRe7%gC1(K$7w1hu=uXu2!jixx?3zq^8~XG4+hF_ zRwp+)mZ!0q-3Ojh#tVweUau>ug0qrkav-te%xrCn;=O)+^KOs_tEith zNY>gcu9?GrD}^-ts&^A&Ii`tq8X(`x5b-^%Y8lhne9ASv`=~UqZ}YxU4t| z$ie0+PB2;9Q*HXL!Y8WoSCDx;F-?%G5}!=MyJ2_JhmEG|cPpLV%YgQYi2hzR09-35 zA@!t-XZ}~>bBiK17oHt6=}uabiLbEqXT@FC9%g&!5I03Zrs=!Xym@>5AQ$8@xH>5% z1x~C(zY-Bnlk%Is@pD$^9+eToU>@uWj|>vbxQd>)SsX^R0 z=D5iFbi8>&Dg1g=$`fH7Q}eyByEev{~j3!@pHQk3Dj&}k{)T&sNj6w*`7j{#!= zt7WvZON0WsZ?m0R(t4h(cneSU*j=wB_rA`r_qwueH!|qN<4lq(!x1dsz;b7_vCKeZ zyE?s=VJkQ2@eE7CQ2sjYE#zKlb;wwmRp;XTLwL<~wrn)I_?oWD!?9CZbt0=)ZhEA~ zvv9PdovbvfMAD*F;R7>-SpI{HQz;d5uIsW1^S`I2P-Kx3$w(H&WnP$^z)K{Gtm;NB zebV_hJ%3HD31#*YG(rehLFMo{77U+){#kRq%g>)mDF9Y}sb9^-IqCIO@wK(O zUloK9OC*tflTLnx`iikJl{Cn=ZUZMJ42B<*#N;{L?9DNBJY1wqKNHI%4v?f zpUv7UHwNiAw_XrS!y~50wPPy=Bc{@EbysW%gEh1S=@WBEdm&%{GkJj+#nq1{q+!A| zM{eIF4T=oqlCw1O=4@fm4G$ySk4;v^567v4_cmq*S?1j1J&@7RKv#4KCWwj&9$a;k z+xZl>cx?v>{uDE#P520p0^{RV1F7FA>ooW)^vNfOl%%~2gg;leMa3j5a)Q7 z+Snq_!X(@p`RLAOPwiHNcP4w>2|YSN^FznNjdi_$%%6KjP>j}-SX{20vFa^5psIC> z50(K<^JwDCUz2^#3k(wPlFPMz7)1FL9;#{q z1WNn+iTYoOh)OzYDoUQS@kpAkD8PaW4HTcOAdJXN*~z&{FLqlcvfEl5$93mI;aVgb zg5Ao%;Lkfu3cTtJ$J61#efJ{~p@4u(#Al9i!sk#qEzLS00c2cVl@eHSnHV&qWL-doB+(9sp1uQJy zRs_)MM05QPB-*v69dAgLo2tH z-nfDHD(aji>tEqXNgIdQaZiFtwTSu5AR~>dDJ{fs8aPs+?s|F)x&%&{?l%;lLDxUy zQk+Y-23H>@9m^yCEL?^J~x zjd8s{u_tH1G6eRO8;%$VqT5lLNTYz^PTIxP(T%un;gH7cgF|XF41R3LtxP78Z zr!=c(obnB8u>M>oN4%q4MWT5ROX?QUH@}-tQA;pOvP=AF{hF8VgnE2T7r1swfQ~SC z#z`voelDpnSlsu;T}#zkd8ntM`Ki@Eva%^USp*Tmd;P2*#!Wj7Di-Q5r3TqA)r5jX7EGu76hOWjoYl3k*M(p}M@ICn|an=#$jpn}QSu$fG-plUjeY9cVdZj`of4OIa=a z!Pk5Xc?v(aT(1G50TS_izWj|2lkx#kZmRZU{G~x<8GdSM9M|uYv7wQ1{*Q5U^W$UG zJpfOWfe{x*cB~aL0@4PJKu^eV>?Kx;|HqFdvZMq}E8EDn4_5dlbvM#1?I7=Um_XFU zFhWxagIwfV%lBuSBSy<2>kRohssE0q3!`I7+_%i8PH$R7;p7!Cv!-=Dzc7WC2cPKJ z)s9nHpNbF28o)7y;(?ae+U*`J@{Z!-7l53?-itr6YnR9fSAKM44t?(?^#q2Xzx#56 z$aI-jW|X)d15rUvRyP(-k zJLwlS2nAvVOA`T~xf;_6#MGFt+k)U^qzCK=eHHO+H|Y;nw;}1kI-DVkUdRJRefZ7z zsSCz@@A5}`+@Ox>h9==R-YNC$>gr=}l%P=G1(`D+i=PHL!m*6+BAJyp&Q4kS8h8@u z5KTINIv7%5Z69fzOo$|Qw_capbB6BuGwE{%d5)R%+Gf_Zw1f@;QP9o>P)>2e?GR;G zNzQ4%iXJTVR#Txs6<3d=jFCFCohYFlyZ=_}6gGK`35;RF{869$lFQR2M@c>0t)Kn) zZQ{U9e(s?5VgTxb0H-sWXe(iz-B23qE55#YwT!mf@aIfEgyU9||3RPmtA%{ky$ ze8`4QifEr7cY_Y~p-urDKy7YQxrz%y3^hXz1z!Fsn(u#q$&5`NYs9>)wdI~AbMX-Y z1HNqmsb5W>z?K=dEqLmCu6Sm7$bvWu)Ruz;wvuao%;K2XHG1+y<1%-_A%rE_{hi|` zSUBvGUhAK{Q0Z1Twq;B7OD_NGBdhsbZ=G004MTb76$sxO#0jT6KVLMLW@EKwXX$q1 zBf5UmH5Ts+5B3h^S&A6VAI==Vhz*u^UA^wuonMrqM;luoy&KOhXr&cgda&0xoihId zt4-t+?oYpZQTt78-EG9-F(NYbi}ttCo(%#f2C)^6<+J7XYehUF@Cm0m`)Fiyq=ZX* z^@9_BiXw;pkodhgZjtSgAA^{z3P_LFn9db#Sw}%v-&HP;?-buGj>GSN9Pbodo&^=} zJkNhiec6gCfZu!tz;~UHsm$;XCd^h&#rRcL+&8Xgo%u+%@C-2$=N6l~qJr+)`Q=A( zF`^qbh)OzP8qyh?1-?m|phFUsz}Af4^BJJ_vFwO8nJch;yU{c?d}-uAo7fzFpnCQI z4Pav>gwwB3BaO~g`Yiq@IMxS`D%O`tm^JdqO})HO+?MQl8*j7s zwa$dN_T9w&fToo^xV@_X(@;xx*84;%$D5L)4oM@%SmbwC(zoJGEN^(|r{t+W&7Tnk z#bDFrFk^^0#a}p~q^fcaYjqm36_t4S>e1_)Hq;GKnn5AJZus~cJy;1=f-uHEvxnwg zjNrNZalLevV|3laEXNg+zRp|B=~rH|9wzzi z7RGL*x*A6?S-EHJ+dnIvFZnU{Zb6y`!XX@Hm+VofS{$*E_t2W-zUKl~U08_`>teM$ z_j2bo1?`a&5AV4%`IUZL24uv|ORO1^j%Vf(QG333SKa|g7VC@l(p^evG&!dcn~8`* zrO1@<{7o13I7)Tdd|T884+19L(V*^WNgoj!i}yX>DlB4N?b?|O@bXg4&=f_27?|jM z986eiZAN99l2~LTtm2}#c(lg zsO)R_(tebFOMppcVPv++L0&_1{E;&bc!|M2ky|<|v41rs&SHi|ui;PNV*S6Tdgj0t zO;+feNJYxJ^J)}Oaq!hbXglDnpV@>lvj>4aS_(8MKy?qTa@9igLIgcj6|3NQ$dEyC z_!fWz?(C@NZRrdlT7efTLtOOw|KO@e~qQ8gwDn8Io4)hh8XM)kRycsNbS#GKj`Ee&vp`#L9p*+HR8 zo)Kx>hT61BALwK1^M0V68nk)$6a0$su0i3wK&bakwzvOdgw`|bFA@+#6kb_Fu}XJr zsgqO5?++vxbxv}{=37V7*vmRED6IgD7SUOMP>G9pAKTa}#>u&qsIYt*i)0L=;I0ZC zpRY7cuhiIcmD?Y7I_us+x_j}=NtKg9;vCj`MbbNPnHe<(9^UQ+!g$n;H|`g@o8_gQ z07{kD3-DS;ZEP4?rcARVlh4(`$#rPNhOB=(`oBf&foaND0KcQXo)s2t0|VbzmeV6l z?(QZEVA2zUg+?=8wP($J0{^#3oF=*SP@T+n?bNDeoDQ^z2$fJ-&`N7EWk-7$Q|~$P zAY9&f56hQpD~h{|H1_9M-i87hgZf}#X1|F$qtfln#EY{!*d2~POCz%)$#z}2bucN` z&vWcS^Mbm@I(Ei%vGa>&aZTeVAsQkgFL7G4=R0_W1mrN#4gy)%GW087_1_CI$9EXj z6p!xijce_*;_VA$xW-0c<{%grnm=;Oj^QjlJp*ayyLK>h;YmUag&EYi%uvvm+G8HG z11NW_3^vy_OxY!Sg&dqz_lHr1;NV7Wjw!jLV5YDL;`{n^6E+GA~%UL8FFll|%9 zR@d>khwEP%di&PoF9Yw+&XGrTi9OQmh_1!0M-`Z zBaZ%Hx}cLnIP1`D%U{&(SPNH@=A!L$Lq6!7>50q}X<{1to>T;sQP?2FJJZ6AfQeZ# zSR9+O3?XMBHnKz_5smwwT~+3`&OaLC4TLuIl#!Yubqh0$33inu>Gr7*wwq1n#P3;~ zMxA)fQNBKESY0kl@6wzeDm^!r`Jo))0JjU)(imJP8`vuST z4y3e>tS2zDIBFOVf=qQ&JuhsF7X}IV&1;Oh||(>(L?1a#a^Y~7=(YgDQ-w=0rnm7*zSjC z2GBUWAuwN47rd(x>a(ZrH7gw?l-58!x~K;OMms-r5BB0lX5D9OyQi6qaDeAZ>{1M8 z$R*CVF_=*u)e;r!-XCM+w?}hl>&`W*lTO}IQA3oEqhkqS=NYu)m1DlIKZC9<0&Zq|X3GmIG!$Y&Uuy|Q|?)+0j3#pRMiK3JM z{Rd|@w}4FL@=YxHrC?6jCAbH%jwBqM?Jm^iVAgZB1}$I(Rv?eIQ0gOhR{+32;`&{* zYdTAj_B>VA(^NiRLg+ed+IM!%uxLa%?XS_q;o;SxAao-Brp^z%S7)WI3GZKIc<`GQ zT{E**NaJDnEs9V@dW*$Y5bE{$+`U8$1_LKaaQXaXuch?VM5DpkB1w_GBl9uzJ$-!u zowvP-f|G3W=6&HrFM2~g$LyUY*9RJZGwH87vIwr&Am`ajoZjb!=Ko;Hbfc75x`~s~ zlEm!}&vnPA`6ZU_6#L#QGwd`r^+Vc`7m$OpNm0DM_4yIYtz%=|ZJpOY6IB6k_IJXm zFM9z;)b)P_*!7h=BWTf(Ikl*M+ri!}Bz#&>9C;_w z-me)WbRib-+~b5;4#Y>1%9vMU89P}iFI8Gbx^5)>8s-h zLPh%_HFJsT5c>7K%PM=&V& zPZ%4==aTI`xi6}=c`pI$7V0GF@at**J0n`&F6!UaK6gtV9TxoLkB2QFry@)tI zot-JMk!};=ifj?Jvyiqnue?^e8*s>uL}N0RdmqN0ywu`|2q0IoT0s%xgPbQhgJ4Ri z7oR?;d;x9zh@nY^*$!~ufTZzFD-&9A)Pre+TD|jbOPfXtcO=77xvc+giR7;O8`NO$ z+|w=gD{a;-^5`lxU+PBcD?kr^l>pWHJ;BwOo9bx$X(^32ip+ajcapT||0ZQ~JaK!H z>^iAKbm;pg2L(sg!&l55Y&C`~21q|O&R;;|o$Y6!514>&sNY*VQNP(M2M9cjnyuHG z{wgU*thXP&S^kEkKWAB_pYsv90>A+&xau5NK$WWcWeYl)I3KbS1^-=+WVP4S42U9h z_b#6>bV*2;1!ejfJ+j1~N4nH7rw5QL{+Y6nfjkmqKYKek&bqQ}x*e#o2^h7^ z)TLu|=H%fSB*hB@$Xm&z+R3ItNZr{G50}=WezdK0g$?)XoA|PHEXAbqnGx*YPu4Ms zzpC)6H?#^j-v$|067~eWWGM-_;pop2Z>7#gDgf#C^g4uX`tM}X?PhwS>g<}fB<8B= zM3-5nwv@;-m>bbV&QbzCi7kK`9B^>1gE)RhNfrSC366v5cB4XxtYitOp-2g$D&A^p zRw|c!V~TJvjqws6ofkUYG|!vrEN6NcYo5!DTHF{;0ZYH^kY(Vb?r@cB=R)L$zlr#O z4Q5SFgtF(`6T6k4PL|Lyp5uzxttR>D*jjOa86f2+@JNC99b9D@6K-IIQ2Vq_JjA>=XosklU?v!fC+VMJ{l|rrxKp&pHV2 zb%7QYTmE002GxY94UjX^avb0kmcM-$7)HUGOOc3mfa#Az>| z;OYpxMN?n2bBZsVz#gq$7$0P3KsJ3K@)09xyE=mr!A^aq7h^Nce&juMGp5@yNL5EG zpJZ%i%ka0UDeEbuzClzj z3P=katX#vWHEsU`3A{T{O6zl#&%^;y3jTR!pFxGZXU@!PzVEDqc#)nwwvWOAC-R^FoUno zJlX2`q+r*934B#Nr^(;**X&qX&z!Ful8GwgGIbKh59IQqqCVWJYzS|@oqmTYs~(f7 zktnrQ@!%_I4zH58w0nMVktlVRc(lQkmiOvDfz?jo@FxRXj>H%Vls|CmyMU#*i}PsH zflp31Zn`XERC>k5D!GYm`M0wTrr5c)OJ@a-Z>3?sV>8FSua|vtC44Ax(kwaMsfQmw8stg@a*+S4rSLz{gB_AOnF$s}ZxT~Uy+3=ebu zTP|3p8`qCs^;|-E^JeD?x=F)i~Ggdwts`WAN1so?kZZK z(HmCDWK)PSEj?}72Wp5dwU8X6goSrV>dYQJbhWtn!)0eoLvIQC<((Xph!!8q*pjXf za?GE1;+Ki{0~!>Lc8r{DB=~p3>KxY;5C^=BYCx(<>{n5ryngW(z$|-d3L1P&P71|0 zH5l5QAeFF|u2<;2stXde?1N$lV^HF=h3JorCdUL8*>CE&E0zSFXKOZqUfyuU--<#~ zTahAvDklu^Ph@|dYOCP?4ES(1S_!+Q6u|BQZSc$~)E`*~oi+EP>WFm$=Mi(&bYEMQ zCzzVTE8aL1E)1smzEJ_Vpf2(x4cqOm;M(ry?*e}OHsXDW1JX4$18G5@VQsb<0!Obb zDdYeW%NAX{f>7@nI$mvcVP631t_FiI8i!rj*^_D{{dK2hId_{wh>)NA+OCQy;;~rn@i*=>rdUY%_iLW5y^;o?;mF!j$RgIlpuR35vPY~i_(k` ztTsrdw5D1_RaA2|rilT!<{u4&irtN!Wl27D&W32BMMJELCL{i zWzkZP{i8XR1_Eh_;BK&;s{J>+lxay*lXw3pqNVubKus2BZdTTLJbLZVRX}vNw{J?ZpB8O#W{;OoPH6f@v|%*h)?~Yo|m6P zph>(n<$x{CrYF5^dlw#V0FfujCG6Qri_24r;|hC156TJt?;SR%^F}!wea(wtDmu@;b8P*~3^-zHp7} z^_Jg~)4y1)SpFA|jI9X%@k@$HP2p}A^7ZSc19Lyjy@*&T6%<=RnNbtDJP*2+6qhP^ zbg2Ksj{3QSf0@1Ljb2DZ8PnnIY0B>Rg}wWpLvwKc7eS zW`5DkmaH8-MM#&c0JUHG^04I8h75=wLz2kQQ~)I$d9a5G379SD5PSXGCKrixzezE z-6<9RnYNucVuy*nxkDYiw&eu`;8A3Tf`(cBX>FX~ZEZ^cDS@D}`W3PCO|D}7{#P_G zr+}s8(}H2Zw1?_8!fh+o-?>&(l?)8&KGV@VU|I|hzLgD7Aka&kEL{nD7#g_}E|qdl zBFK?w$f)(6yBgGnUUJ)4ci~Xr2+hC)I-_RxE77K#(js7qe%kKLY}|Gnk$a#RctkK{ zV^KfEG9w0TJx(2;XgUc!ZmiGAuJRKB$l4tq>4Dff50>hgp#7V~^!FTdK<=cvbZ>G~ zRiK>Xzl^yYiK+K2*cTKJ+7{2Y*(;;jpBlleNrLR{p)@@ksjbxYL!UXxk7tPTt}%^B zsVW@XPp_q4SkvRv=~r%9JOBnJFU)Vh)kpue#}v1cVAgzyHpWj>NxKU%HDAHNBJUv` zuIH*bXR$KAOUVuGjH3zWkaNtzNrfY{D-yvSR6^V8-o^Iq`M#{si?Y7zwvd{T!ebl1 zL|eDCIl5+Ec?CWNkpd=yUA+=?zlA$)onAk|Yn30#7%KPc9#3?il{mwVcXu=Eai7UI zxpcbAtWu-Qd*9q^DE{&6ZXbY37WZnHX2-=m)x@(Fs0AvzHDi7R;2^|$3ro!TG72Xa)uGNS0op2%nMbvOMP2Ewc};!H!|J}YP)^na_wQLxQkCqfn7G!vOHQNP&dKxi)Amb)$dUXe{CLq9JL1an zL7W<%QcmGoh-E_}VF^N_UM674H)E<0zX+a#X5Vock+yyeeA_F!Y{JFfB4aKn-q72J zUDq4STILj{@t(v3+X{Y?m+m^?C(}ql*+tGF$2qoHjU&O_r<|@F83=Q)ucwBBACMY# z=B0+uG^C&4AH)nKBL!2nd8!_ufA|gcUc!$QHKC;(DlHWTIy2!Q5?HA{qs;*2zco3( zB4gC65w(louSH{YxV@|ijd<7}-ax>VOdc(z$k)u?JuodyhjiLcHi}60?emY{Ek`Ua z88Uz>wMPg$=HC0HzcfAtN4Rx&BD1wcI7=UJFE43i;lDl$f?dpWB*bW?JP+s>Z##>j zyGK`IGHF{1HabC0i!T0}xa5CbRNh zuZ`E}6btbqmLfWQy;t) zW{774(GtcWb?Za2T=`rGl77^YroR=BdN7il16r5yBPwwVKts^ zg%04u(}WZ#RYx6G!~BRi{{8sw|fcC&d3<+LjNRVNHJP)!J*XZW=>Dc zt%ItixVoA^?&o`}GnOf@_ZnmLDNCAV`56Ek?^IJEB^~GI2^>jQ!5JTzw-JYOe+qGi zS*2k>$ph*qf0qHFXF_q;YM=Pi0PIo?{vQoNcgS^slz*QmUcEb&cHI76c6^JyHV{LZ z3DpOnEQhf=9utN=+Q*k^)b!@V-uALwOuyKV?8J z4yQ5yP=h}y(Y~H%7dw42L=47_Qo@W<^^mEK&jLOZg|puNjUzrNPymh=UHUpNfMHV; z#}=UK>qfl#dC7yvB3zMV?)6%R)g=tr(VC_sE`q7e#mKv5(37I~8Dz8U2j!aNz2xVfei>{`<}NeHF{zMNb@<fc9oiI;Kly1 zO#%`@zz@R7CE8{>L$$g{+0kyM0T?lBSw+FQYPW`;fN?Lv&{wu^StIv0FVJ4=l`<-` zh0LvviF!fR6{?Xmk24mwf<3CY=(QTLjl9A`z+!(}5cGNTa16B_OBOMtuAup-rM()4 zJ@eBVbLambF}G?xJ9gpmp_-$oH@~OcgIPm!2e+*nlq2P8Tq0gVWNE8v*1qpkhSdT9 z8diAMp+`Xb9)w19j|gsU$gSB6ki?2nM0&Pk%=qRnq+`!*HLt(w&`wuzJeL#5DcMWP zLD6yl6O6+Rd73$O4X&snN!ucB^l2JMKT2aFcV+w%jMqLlI3ts|{Z0B?zXy^w&P2i( zO(Lzz3#~RQWhOf-uX&Hdd0Wv5x2WIa#cLlIbkN`Gre{9WHbjg)# z9=~*W?k)ZL>-;0r*W_#mzJ3(mC-Lfcy@UgGy6163qTcV#e-n#^&b%i#K$(_*{t25=I z`}rnApj%m3>Io&{zc5D+T5%B)5Z-Ix03V~mQAP#YC&Oup#3I$I+K||5$I14N07Cni z$-N|%34P;l5oq7;Z5*I^@l7E9P)d7p!vM>?Eos7IvD+Bt9MA~F!+lOO_aA;1m`=Yl z0A|CdVK6pm?iL`MGnU1}j+`=K08`3RY5?VREYv|iKVyEvEu<=fli|`^s?@1n{jn#R zP8jszO29kyeKuPX=*J3!Egx~oNc4<{xt}e9uCEI!nCGtT9knOPe`a+s0}_0BTee>i z^BqN2v=N;|V0rEwuL&+=){@4AmU~#DV{W*}$byxBK?SqBCF?Hk-uDb!WeitjP;%9a z#ly|2W6 z6W(qyG(`0_`F4R-hNu_aDWZ<4QJ2z3tT1eQi5Oo2KZ;Hq`Pk{&AGtkKIctsqZW>WT zX%T->8&te;iRae1b>3->`@2@QH*eIR8E&!hlp-&0(C>z)@!A7R&bD08A#2(~JrW&0 zsNDduQR3!sjZT*!?NOAt-+v6-F6qr81lZDANrOG#Diip?>sOQB(x1 z>N!3cJL9JSab_4D1gzt)$NqMnNZF#S26n?onkAgkdF)GXljbk=f*v!D?l$R z`o6(~iR!5yY6oU+llMST#$<9(U+@TN7kY&45kufzJs-gzxVBnm&`+c|$0sHQQa;G7M++Kd+;BxU zr>BvbyK)}li*I)@UcRi#%M$+pvvv!Uu%bLr3mxz)xfZA2+b2kdrXC}oJWV~vG5B50O!=N!$JV|^qv{Zd~B~lD%_cgwW_iFfRXY`Br(G1h zYBt(kj8l22R?aOf4w}gu_m|wO@w*R3Ak3 z!%xOwHJ%2JT8);-{#0)nOstK8%E7jFmy zFd2RlKy}ob!HMf4IyGj3wIS?aAX6y2zY>^7T7XHU8qE~JDVRv)LU|__3U3DRw2>Pv z>EJ(KNBW1E27-~r)*EFF2@LHz45gwHYqtym%1`-a3yg_2VwsHM8w0gk zJAVFbi!tqhfO%5c#?40j=iJns?WIAgkRKMj>Yk!+skxt~34m(N!n)oG60BgSnYJfY zFOMfKv^OkY*b}>ej5Tz%PcK~qCkkc_6PmK5PjIio6%iT}UaaWOWl`zF7srf;|AWe4 z&LkA~wg_dVvf>vwoDRQ#;lQ1|7^6MM-;ML@=DRMdG{GctN-&%=Su&FK=3R!zdcod9 z1`lNv!KBja^48|)Z+b$6#}Gh|E}I{knYda;C%AT4YelsWa%vkSH$GW|8{CymwQ+IV z`0G=^`t8QQl^d#61S&YV;w^hzG!|R?pZ1hsVh%(8(Od-9Q>8AiT8dndz*6)B^q93U zL_m(rwE)y@R_Ok(1NYAd>~y(uf0#OwH-%#TB3l}<36y$2g|Lqv``u<~G>V~Q?E4eX zT3#k~4(=jUl{}cbhg&2J4;|MjTk$$8A(I3bq@jq5sG^lFXbNw;ChB7FI>|@&0DH7JLq+ z|CyD81~$Insic7Fs>3jXTkzUj6pM!PeHRdEybOGHFM zfIgjG5px#CFmQbH#j(*ib@F$gYDnNhKswDuSQ<*0wv$y-!JnbHw0+50d#?TfFMxN=*}&Roy0e{ zt-WO0K#DoC+y}Z~$8OX@z+qkA%y*j>Vq2Cfxpb&rnQebp5Q`&mN9d~ z^Ey>X?-3Z`;gDaKR^xM`yuD_&XXcPfD7>A8bOHV3DQK1RV6YeuU;Rme?3cfc&1rZS z#z#jLD#?$1tAat%qyjS-q$!b!Uu3nSpB{VYckgy~y3UhcXk+vY`VVKdGk_6kXrQ@P z^~Lf2$GmW0B!h8NFbRd1@_UO zC7dsaN^{lvgYltrr7%TlMu{ANc}2?akW%~|fUk>J+CU?8jv(42*%pC`Z(`p1fw}8^ zRu!)xRHJWXo)CXuggODIEMgFi<{>0YOzq7@VgC=&ux18+^gk$De|}SE^+6J;Ly>dU zLiE_+(pdGQBu|E9>dov%DIg`oN|IIK)1*+DL9Ou0?8l1i=lo)s_%3=v{64j0dssGyK?wEk}&F*$}+?Vyco6q){d21DXOps1zxn7kA8~$ye=$ttlZ$gh@jtOWShz&YZ82atVb7E zkNNIG?N=1?X?EreD1zOaB6r1o>ny&!ZkxWns*XXQcDoKK{O~({+*^c}_6hHW`EOl= zQ(y@ie@RH>;K!pa60bOrRxbX1OM@k!d7sHZHT4xl*&ZNvPKi8wJ2H-R4}Xu2zxDuc z^*?p2JK%18N>dygc~l5-+_f~YOP~KWK}BtzzklA1q&6n3+(7#{9HeaYv84$*Ln2y} zg1?9?W{WNVKbm)G2X(#sI;5C(v`5tx@v4E3d(k;uTtm?)KP->rL1?L?f=(V+eA-+P zrCqTaH=ZZws>z?`mzhDc6JF~2A1EZ2sY$^NGEDK@%`h94b%5c_olDUh&%Nd4Hq~>* zpO*g}yudYfJ+Ew#IXG?~=p3@;)>442sPsaC_RZbmy%OgtJzpZpBlBDskRW;r(!=lt z@YBXofDDIsvbPi~x!=Dp^yeqY9Wo=KY-uCN(?mDPUNNLXzenoBUA6Z?{a4LysV+&h z#rl1v2EDws35t>ZLoxNotv)yZZ1F@J?V~9kw1NWjp2*1H6n%Z%c}-OhFTOLIty5A; zR{{5H#hfdpA}7#88_j7h{^s@pM+s!~RoXLQ$^xYAOGElX1q=~Jm>E3+4W0%W(R#D4 zkqq5xHp6M_v#k#;|C>_GA~#9G21X7gavq7ng1eLk>viy-)q3o#5Md#k%b08X^))>$ z{z8*BAoV>#XBF5lk81G;^8?Z^uII4(ZV}`0SXoYg-pbBafe1JCU>NT^f$w#&T^DqZ z$M0$hR3&ZkFrkrv;4ATRJhR8pd-CBbs=P{1;u)mf>e3|7uRFy#T)nzvGIzO4C^aW~ zJ4pIu8lY!d8`eE$Q3|wex~+ifuJDAwdL>%7NK(U%5+}|XvsGbixEKI?I(_L=d@A1o z!)80v5NIP{-@MSu!GF^SlHnhGK%!>^FRZbWhDV5P*x;j2zZZ$?#2_D!=KPJ+p~3in z<>!Tpwwr15q*n*Gn0H2@z5KXx1AG5P z@fE%bDv^xlcahA$jxXkU*0C_tW26qw!LbT}X^kT9367^L^ zm9|a2`kVF>2tw|Fow1Lp5!$MJ_;mZ=VJvm9oV!1=1#JviN<`^$wxvUt++4MT0!N~n zFfZ=hWHn7-Eh=53=wGTvZ49T&WaHpB zm&jQu!Rou{?@0Xwa?Gf(Vr_%yX@a4FdydhgZroYr1w3*AoLP~(;|L<#mdN6$5U?B& z0IU7bAuIZjaUC^8r*x{SauvMDVYJ6W7zm#L-*!#$+^3?Kls-{<`piB*v?aVl*yW{B z-7KZqxh{Z5)0&nQkB;QBQyIdBM$h==vEw0EeZD`uGns7Y|Qh^R!(3d>B90@p|#(=MobciB) zwt~obr|K0~AE%%4W?UxV?Z{D@0Fk4(D);F5J`fD=w~%zOZnh!U8z}wJ>ME zDNUcdp{Y#TWq{xmQekE;ua1(mEuLo>Xr7w+N+v}KC7WhO=&fHh?2JDHO6&TrkN`M9 z$G;(i#*uiTHRkwqeP208D-%6WWORNYAFQwbY@cy@|7Xvej)RNUWIwR;hc_a zS|vD-+yQ_<&z9QdyI=Sd$8tZ_^8t>q!6TtUD}xM~KM$-@Sl!h!`qosHBb1ZXGQ|rq zuuH$av29;klR-DB6ud&*DGaN~{3ey9Om{L2zX|_q3y@yGBOgCmocDjQ(k&R*^YAHS z*BkEZivEV!>j>BI6Wix$zU!199@74&6I^mq zo0{9q(Y#9O3}2HH_FxNJH&{IXl#`^(0Cj5#kI)6n?Nqy|4XJpuw_b%OITttD`Pob3 zxfW3xToH^A6!`%Zcg!;3A9?NhV5%CZTggtNj2T>iAKc`63+@|$0<>T%gv@{fO6(15*!-6c#bg&N zlMyfl0JWKc)tb>>l|%o@Q|%U~!AwSRg3B$Sdsu8* zL~>6A$C%kQI808nFr}*55^CsakZH24xJ(|u#olcjgkmP4)e>C zVY{zBx$6trw}w&ZFWJkt$JH^ygr5L#%k`N_!5YH2MHw*b4_lbn)ZOx*FGNB{T}tNe z;aZtQxO0$AE_IZ%Ass@`na?3u1aw{Q=PNma(;$e#Fbr`6oUR!iAI3RKT{B)UU(KYa z1G6sCK{>JZk1nA62>^~wA=Pf@Bg;7vR?E_@MA3#H2L~1>yn_LBP}XwyywkaGhzGcq zwkClf;lu;|EC&Z#!UnkzURRKNqx4Q}?=JdCI{6K!*!a|;%j%*}Mi`@}Z9A(G^>m(| zv>YE)6HZy5C5)Und#sQ;tH;m%!peLi3-(fP;6Yj(J5F%VlowSa)!fG~W4$1&^*M%V zy?$RI_xuEJ6L}c}9pb2+nBKWbo{Tcd6()an_>xXPKrC0!4VaH-T0-L(02YNjp{Kn4 zN~1!*kag8uu1~EtUtkNMCZ>~ zgIct5;f~_y$0PQXg+vi^!tXCW=z{irLD@cvQLY;Lj?24xE<^BuoBL*Q*@k?=77Q zm>5Ew*%CM%Sh2pBxvRXX=yYf8Pzwf|(n~lxow?tKUzgk1Jfs=>Oun3Ua zYScpyG9CxeK7DGgknyG6D6&@igRxTMQE|6J=wh2hzW;^GO=+94@vFo$n#2@X2)y$& zd4IdYNZp%}C)$_X9egzQ+B8+UW|cQM?wj1hGh;L*mV^usDY>IPQV-m6LfmE4-#m*A z8H zQqlDr_J${=NTvLUo5OFLQ3GZa`gU8%4SLe&R_dG$60}PQ?0c}p_Y2BTT0YcK{#`Iv z)#deQ>Xq;^fh*xEc7Zu#t#1x0bmC}O@$VBstLf@S=Ax<0VBZC26<2+1!%&(3e>b8y zobD`n19|?I`s7cxayEW~Y;nwHKe!TBYWy7)W)G%LG-Tt01NmhDH}OH2-rD?L{o%FO zrF2QLbLa&EZ>jft((r2pbn_EUIMxoQqhmV0RPJYKKX13MPn|yVOWb!W6Wzh!^3#k{ zy4QfYZ0Ky|&v2$SpA3 z!twwFHGrckVG#J8t6dIQ>wq0^HORT`XS-=oH=8d_$HMc`oQXWd6Rv@`LzJ3GI{yYo z8w3}4wA@O`I`~1dT%v-1VGMc_Wvfdz+Dwr>CiKCNlsu#>P4wTi4d^|IA}>_9Xe|3E z8%E|JKC^j)*W*4;?2KV+Yu>HE)jU`y#s=z4C!rr6n{ysfZla;}zNh3K)46?d4u66- z7&Qw@>CyDf?zsVNy|Q9i>?YElOAs>_oSfj6i${G7h3Kc=DBaL?szl1nk@C1B+C9ei z=G#D-A^GAM$I}dyh{S*v(+8F{)JQ~l?k>Uq96CQ!yp7hYBddith$x}mPRStnc8^7TzSFD6 zPk6Xg)+Lp1P<8>W9iulxO-tdUHlS*=+RLg}?TZC7{z z4V!}3B-7w|ZIIwwQsdZNBT#tn(wc3rZ>Lbn7%ja|Z;u|?oulU**IW1d@w8_A9sZ;% zAo3KAwwli5Q7JJ(m?s*?c4qFx57;nDMKL$EVPd%GLg|Yc4?n*oIHu_4N9cS2(j{(y z`?vcZ) zw#CZHep0)25!u=6@3>5b&@ehpyv!C(l+-haNEM=24!;lYa{Asr+(&P7%@5#L!OPYN zwe`nYB0A`^{jdGm#vz5D`M+NyMDfC4M@IQWWqyS^;wn{>W1bg%E5G{A6a7l$gVkzt z3XmAuR0r7Sw1Vp{ehgdypBmpdrw-*z)G7Sf3(FBrOc7-KpqaI~$GW)>VyIg7B{HJU zOKwNbF=tcN061-5_EW}nv0$FnZUkKD2e^M6n;Wg0lXoL3AWrCJ3d0&`@rf#fl^f@) z0mqS_0Y&qlN)9?pbHf_rM#hHk-iVY2_U0#F1vEXwo3xbD1hko60EJK8zSj4?(r0z> zUZ%6UZJ_1L+yrCKhA??19<xjlj`h93}&6#p>MV>%!xBe?1B9%+iC+-@v32b zZWQrj^NpHkcN9mb?BjixyH>n`QSWP@eeipo*rpjd;hhdj)c1UNuOK{uW^N#j8reULsO-);h)7lL;E zpn0_=weXK0TDw@HLHCzO(i^xBXGS%%xMFGfYs&!oQ(Y$YPwvDDugsP4C_bgnwZA-T zd%V=N%h}XDPLN~dDJTuP&rb>^P}s9%Tr?NJ69+0G2l7SM69lvQ^-g%hdUaOO2OmG4 z*KfR6?C{1OeZhSa6RG_|S^3VBvphi+q^Db%(9mx4DoHQMM)M9c z;U_$EZG?d8jgOCCy?lb;mX=?bWq1!Yc}OfiV)O757+vfxUeDjdK>i8OFqE-Gh>r5$ zz#k5+VCIb`U&h~Laec6A=7XU3kJPds|8*r3ui!Eamar)cA zS}DQr4AIe0uZo9Xu~*B+g4Ko+s%-zu4KHCoXH9`(%b8!?HAKzG=$w429;q&yhIO!k zjE^N)qBZR>RK5h3rkNEYS(v-|6&VfBQxlZj9}~K+FpC15W;RsW?_R|r)=LLc=RI}7cJEE5=W3>H1=cvrQl2n3T=X2eG*f~RK~IOS%K4P zb7>iqC1NQau+t2_F~34-gs`aZi2kdB3hl9gW(l?CnsLK=OFeOIXE;U3EPSr~~wi`PGcpU1JV;*>d1v3;QqYTF-W?1iZvMWA6Ffa2G=zcN2Ds|6Jxf{V7#w6JOMpz z;mTt*Z*ngs^lwLHkcpqvZ0YcFq;)%bZU^dFv|>KDm}k;Brxxo)uGmRb5O=A6GRL^f zDlBO(ntn#i^?k(Y!Jt^SYi&5{42fVbNZ%b8%Sjnn3JTggpLs%pwcS$@4=uC81qH*6 zh!jqzhm`G0@4E07n!ZW*RCbPOXwVP-i#n>tnlIgFYVNeyD@I$!zA-W>^Cx2?dm^%W z{*)r(*J+*L>k6akB>}CY2H}MGtWufOB~TP+H%Kx5v#v`IMNApQ4xpbffWJZOzhuUn zs=1I?Ibv=nycc$qp37S_1w6qJtsxM1NT7u(9h}l+kn=|!*A{>=ozSggjZ0v|R!VRc zw_iguuc9{K)ft5nLQo_c`#5Rf+q4@yo6NaI+Xw0YP~qqag3^dkem&JhQ595Z ztQo?sKYtHe9DG9(FX=xi#p3MHTjOx&PnTqdoEKBw#%Kb5!NQ4px8@=2a?%3pAw$%I zD|<&7TSgzXE3qH*MEb}NQRCpqq}puTqDrvF!4~1{1~B%Z{IWbRvXu-HK;-(Wi2Udg z%9$)EFdcvC8>}W<@RYW*Wuwg$Xbl_kxua z&^Ib2f?mmpdY?{AWeag^X*sG96#2Oa@t!%+1q;*#?@ffw)1N?l!zvaQd&tAtE-4^F zZnJVUi=8@FTFGbN9x}}4<|80<9!7W~7p%HI{6?ipl&9W!y4QUC5ybJU?zX)&ac13t zW?$XFW$9}P7A(qpI{jVT0~NxN613Nwqe~0-7B-+@PEMA@HvU@JsCJrN3|vyPn#QG9 zx_Y&AP@e23#C9Ub?*^roW0JjneIb@OUGU~A2<5t~K!b~s@OU)SaI7KLX#q(@(-xFm zMCcXcim7M_F(Z*qK6v!+ooCyhyX_yb$>pNq>y0YXY)7z9?qOb>vy1AlTQAbWN#LxK zucO3r{4vv@?JGD9h}VosjO z$`TTT#I@h69~V!T=og^%-k|Ofeg3g(Nlr}!gjy=W9ikxIgJ#4&bF?>67=v2KshJ~! z6O@Ag)tvYM&<=h-gh-Jm=Z(|7sDiU?I%7dC9&A&@$GxWhNn?EQkZ*g_!SX=mL8%%J zZNNnm_C2~ z9^ZI?>volA(y05Vy4O((5>M|VhIaQJLu%D`EAztZ85~>sY&tU;AmN6KY{NR`H}JKX8scc?`f-KT%oYsD=k(PNMH`V)a3}63{a!Qc2Nd4e zoS09Vb%LboVfHZ|5T^#J=9M*V_O7x;X`2$mGSbco(J64;m9Mx^*9GGUYa&cqeh6)Q z8D}ZoC>cG1{i9phxBy(nZK(1}lYOSo6ABcs*V=UIx&53|Vff!{APu@lNhU+{9TT4g z6yg8_1t)#?Uxea1*{jf`l#peDaA{LLzX5p5i{CC@@+UYMeUHe-LeK zd^%;b+l`1*fp*n z({@UW1+z8yr?FBCGYSgD;pVYQFy+47`D=bOU|M;8!tRQM@KxP&@Y&LMsIUgzp-V(L z^!p6D|J<#a{Kp;@yF$QjtisB>Y3v4CIhZO5)WwO+Tj3Zb77&7YW9F)GHE6<4*%Jga z0b-Ua=jr7N=c8@{#UcqFPtxl@=ADvuUc#zCC!R`dN$J0a@o|t#d9{2~(pjZ&SXicC zWqAk_KcZ(-im&r3!Jn!*GtN!obV_);l1``V5}&Dn5%AFw3=lCl6`^5R|NCa+K z-HG5Lwq>vIp!6c+8h<92cssAMS^%L|_Vn2#V}YuaX*^8YARHhu`wH698k0Lj7W$Db z*;UqdbeL=JHE-oEw230L5o_qH-Gu{{7um$G0!zCg%FqpIZ%l#dye=7)O%Eta+kr^V3H z6;@2d;Cv_3YBv$U8Oj50+0Iyev%({WKdEV^qe1ruNhU8cYz8~-n%!!FA=KAp)$6 z=&-$JMkABrc#@4CzYGJ&3r!n#yHv@t3v8vA=p*j>>FmzRIm_|4P#;B=k!K+|*fL)F zH!)OerBvFusNbpLn{BLkK+20TaS-1OWxr=pFR78moFtw^6&$v-|+zz$FP z$ZW2N%gOLl;+Jw+#~js1CO$1W9=YTD_kAjDsO4$k0F=05LH1?k%p;_&@&F(*P}ieE z{xvNh75KD9Es4}8e5!E!jRa9W0VbWd3d;maCM|xCEowlUPt|pz{DKnrQ1IW25L|MH zyy233iLn_DM|VL!Ihg5TM`zbg17QoJ9LgJVN)vS#w-p?4F+l4A2P8LRh-?QccWV=K z*TEn8$HnPeA$$x=cH@zMLoNPY{5EMVqkktSr6PV%BQIJ#-t`!>Vw^Lw%?oQ2Jdpvm zE*PTMWR@Sk8KL85l@9$Z$`8F=5(wrevmUeW#gBw=0**v;$B9_yv6l-6X%tdoc!| zm1Tp(BXD7tO_tWu{t74|q=`NVmvTDWjkBeUn$fns})a`EY%-Lh8LiY`pRh=IgL`mi$r)cS35?OxuX z1c{Go1sS7I;)F~`>*iPZ+5(BehM>^pT0~7ozUU@J%F7Nx?j|7=2IR4>eQ|iJ(;UUa82ordD+zvvWz~Ie|qiSr>O9DhXkb z+mE`ZF))Vj6Y;6}Jx0aY$HT}QRRAUhdfZZ+pa$_`f1r2%OxhSQ#bGxNbV>$^v4xNP zw;RE;TpDw+fS(?c_b;iaTT66XE&<1pHV^LW-L7AL(YP;lZoxx+PCls%0gE<(4ZZ0w{&9qN8Pcub`rv zbrMn3My_Zv;oygW65vGo(eUHsM3_O01vw9>SVq%<&AH4oF$<%XxC$%06>0P(4BpY= z)gdAvoJIWQnwN~ir@vt<&I^BVI(FPixhs*vG*Slj@+wQm`!Y>YxRlHWjPZ~0m0@-U zf@Y2XW-0yl>a!E%#Y`f>um>DO1aau|GljILLdk`+1v_8($oG{KY|Lap-a;=k{%77_ zU4BYJ*J<5DVa(f6FLm{nG_ZL)LO%LxAk1NqwHaD{!aCIz>#LgYKl1#W^HbHZQAI#; z?QQo2YtAC@Bm%4?3DtRCEUqpeIMzh0$b!nraPd)-wLw9rNb?`%wEzlRt~UNR5%{KA z^f~IhxWU!a{6vyOH?fn>rChD8qB`OI;gYMg%g{228asesV9)0j+9$I3hxks79k(&T z{sibHeN4aS-EfH|1+~QNBlS``-q4a#rsQ!Lz1+J@zS-*b)obPha8qkliR}zf!%0?O zUX}i?HJ*cY3cMvG=uZD|(G;G5OUX#yeVL1wXc{zF9MY+Z%luD4IU$xs@iY5|U~Gs1 zG(jcBA#$burL%8l*TebZJKfLY3oyA^d*l-&Y~&1fAM4YwCZ}?au5TQ*EZL2UC@vPGSm#O~CY=;5XW3v!$YVMvl{2R6B5#e_*GD!}>ZIJ{)> z-jLRna+zfr@*D7OX)q+sIW9=qtc>8B1I1NRg$ZP4k!Ov@N)SG{iCfiA>qVe)w_AqO zI@DJJpMk*|t0ELF3bByK|4V~yx929oZXWRg)tn>rxI8ITM_j%Jb3vi}J`k zo(Ex)*CEP*3+Hd$wSIEY(6l^Wtj$W5$^sqeM=%gJuoNEy4ePdkI<}){rKA_=XhSzZ z?_+TCfSAG=7w8mY%$EQ>U;vjz_Fje#iIA%mx4v@Fx$=W7xn<;?_0=JU2=MccK;oEz zVJGUnuP0fl;RZJ@)nG6z6TNCB2XfU=pu)T7G55_mwayuZ=95B0VSO?cps{cgs623M zTIf7!#^v5;6Totax$exDJ3)&uI!_zc{-tuk*mzA^>!IdBMHB1=4}+o!xM5Xt40eb+ z_Z)uBn;YP1lcq=(a%b^Ab-0RUgH12zMTLg!e`Uds4a^SOeIg{Q`jNQ@PSH-XAC_v% zN)BQxD2eqHbEI=s%ry;DFR>YK02+p6sCojhRL;`SljaPgXt(H>^mUTI_$g_963A5z zBv91a3PoKd#q9RAA_wS?XmQL*y`~K=L%>t!Ami21 zPvle1C6b+F5r=ddyG)gko=+fF8@yJZHlV{BY5Px`ebc$Yl_T27I1tyQfX%JtM_F$F-Z@)erqFM-%R@pgPaIL;2 zNS?(@w{!BgIrqr8zPE~Xx#nu3Lm3&C6V3p-!SGYafi=pIPJY6n=A_Hop?2jxTSWAK z?peZ0u9ZdB(8{r{c3e#x9y}{51360$fF3gqc>Xh2mErPSN(&|{eg3wae=Y+_c~Iz8 z7OUS+?u4V<fFmYesY5IZF{na8lWZmL>r({tBb>l1y6xvfTa~4+x?ed&4 zjPP_d)e?Bh@U$McvC)V~O}}A#ne4dPT0c*6bRnC_L4gCEb5*`{IBw~)Rji;sCe}L^ z(k2wBMnzJp>-qIKo7vAm={L;g1;X^~f*lT=Um(7A7}q3NY0p{f169baUNvdZ0P+E< z0#gf^;4yUbCb%r>9O6c~{$~_NLt~W5TRiv!C{W(8g8`LbJOevz)`mwTNU(93A}Cgj zsXS_UrlRVkr?I zmHw+>Pk4psV@N8l|ADIifD#%Je-Gvw@&R3Z6GuZE&$TrI-w0q0gR9n-(gAKFjI=y~(U|9Z&p4Yque)(INP;~9j8u2ALA zca3Cj&~n&$qjW3a@TRNA;9Qzw!~&& zL&^o$IV@CS8AC(eui+9u+>p@c#3`QGV)``9!sT)LE1)#!{@Q8aK=6t?q>vG6AgIfsjuO-Em_S>3c@s%f)DcOdesM5&1=aN?r2k8 z)3=md#pFJspT_jX{e#f76rMu3#a`SH-EO;v4s+3(Ai0=xvfN6dekr)>7vfcB6`GSk z9!Hy@)2#*e5-=0EO``)7RZ1NEj*8(({_&E@s&+4aRR0)=Q8QtLf>Alu^0o9H9)CvkK76-8X~%ES z5isrLFg8`6!AqZ-A=<>rIT%?xS%Tz#QC`88$lafjd@9`~yD?8$*qUhWhMl`MH!<#} zJSVv-4&J9-t|r`urGrqQ1-)WD2pdNXjT@m&kYgaR`LG$KDw9>mcT*V0}?+qyEXkJ>y-kVj0m9W zgZ0Az@_bE9Z-;Xv94SxyIjHC`k6e2HOEBqpJiUjw?2k?m2-+^~TAl#yLTm?s?uFwL z(a%7d5e@dhBOckMmjnpbPI}9E3oIKMyl{KeKr-9=QhXFn9MHZDQ`-zEMUUE2055_m zUkGt#$!h&ruD)3FQDS6VRPynwRWYrM4N2olEa0RJcJU{|WD!vEP{RXt%1*vG-itKV zxFG7IVo01dPE##lY3Au;@Lw(}eEF&R`T4>-gpg3V!@4OIo7tj@>qmlZk)BAGgY5i} z)1Cv^cXjrx*e91}rluJ>AZ;uLR8sA{NN6ow#Qe&}D{4x^>XMTEU919J#-lvY-sv^3cjwN^m!;(^a1Ts2E*2`6=?Hj!RDFA(Y2@3{qKJKz z3fzqV?1=`_(f(r*fy-dKS?N54&@d!f0pK-;zB$fEb0x>SVSZX&rw-DQvzR*fp=cdY z`g#%pC`lHllSVMGf7~zVhp=Jgsn0MC-4Djah=NBe%R_!~>oFauB4kCSb2+ ztwd^=M-Ikdm{lM{@zAyUw;ttfWTondCQ{%=8iu94Qu@$m`Bl-3hY2v>s#Hu(^`|U3v&|D)a$VhwV-kic>P7xFS~ORCAwfN zrJe&N|7GH8UT=E}>hoAhN}S4#ToinFZzIxOket%305bH() zwvk8oXz=S-Uc+AOJ;^)|ns&Jo4ORf5lEP;43DkpvdDg|p+|%db#Up1$C%Ub?aD~IE zCRuAu;s{5(p|*GrqejDX?;Eugxck^To#!501sn{FGMqGa701c~yBs6#+HZvm&_$AFy%_bpNnl^LK#sba#UDGIka)1`DW!|1!f&H1Qj%im%h> z=?fcPb%_bN18&Ydj+ zIewo;_uwt*==~Cy$JnF8{F5XJuUeG3Hbu68jlD zOy+f~Xs>SL>Dm*vfp^=5f($3n~XNUf&vW4h{-*>xHiYqhlDoFSe8KZ|3KgPwz|IaR0 z&M+!G_mNt#(JXe4yjwnrB6{mlrE<%xGl)n(MB4okgDN5Z+ZfOft7Y!1C75lgcO6}N zlaPmLx_{>C6->ZCP*)GxQXt<1XiKVjeqzwsoYXK=<1dXNl58FpT zwarHS<@75HH(;QtuQZ8#_B3;>i<8N07>Gc!`Dbe z5!ixD;`&Bn%h&x5L%1sW(_BwXr;lDZzjD<7{>SXENeGC)3W@9fW`sCkf+6F%qp&e2 zN5`QJ9O_<`L+}c+B1deoCN@ko*lrS;ko$a3W~-QJr~cgI{gGikp9!7=3&kk<@*F8( zl|t2IDR1h_Vrnsmy7Vb_!c*Q(cLbd+Xgl$WR516B8y-oe=@ewW?%i@;E=WXP4vdi; zPD6u8x4*BDGdv&*TmpIWa5OcG>%cZnQ@z#Bfca@z4vH)pY!T=Aka>|()>hsEeUHvo zaQ1Ohi`;^^@)eit7Sd#*mjbdai)9-gluaq7D{;KjCva?CUY@rV&cKexFWQbOm`l^{AxVbgp6nFfE)tVyDM_}OH7t1rlg2`>mKd|BrH}6mMI2t? z`h`-1{%s6v9xP%>Vkc^sk|1Yzx_n{$zddGA~qV(It5+=Jln%7 zV@Seu^>3~VSe+ZP3yY7hOU_t2yGsr%knW2R(<6Z!HiNNtR>`#X%_?YO9dfJf=Fr z3$I2;SSZ}6K+TqCJ7dZn!#ZL~NmzBMEbLOT z^C0Its1~q=gk^Vko@%xfOw@rXqZ?T=MX!Gqmue{RN!r$S=2w^yotaxWYy9GxILA0S zt-Kyev(N3CWVEvu>9>TPA+pt04=@Hpko+2hTff+Y(x>LhXQze)Yi8D(0~tnT-8HvG_s`J76gMc%ROW&OJvHeK>r2Cm6T0G39zl9Vb^_34bb z{Tai&{WWHdG*$|IHo@l`EFTq|^ZRgb@QWw#~sYDzx$PYF_>}Ai|b4lu%lv4GoIk z(DOzMTf`7$5QvYTi6~z)G8$olJ2_{mwSSkBYtbY?jw@f1tAYO3u1GJcg#A5)h_$rI z=VJai1R`-8H(<8>T*@Y4pJU%6WH-6N3a%z;QImP6J%Xw+p)%~1k+a0@(3I9574be{ zJ4U*M&ZD1b0+9+6A26QPwX^?)N;%7bz@|sBOY#Z+YoC)>xfjU+MJyD#C!q`fiA`tU z!HL&A&5_Jvd<0j1^MLU-I1%$Ct8;3pfen#YN6~+eyM2z%$m;##GD#%A7IjUv%K!){ z{*V+*##gL$cvObkLYh+r`JztX*IMV;UUST0w902~3`w2uMcj8uJ=Koj#GdU|fT35T zO)sh|m#Wdl-vCkS#!MBHcz$ZV(= zIne$|du285)p6t8xHy;{6+%w#0O)e!{#0Qhc=#&-j}T0>sg9?5#uV6Y0r=ei@6k7u z;0@U_3$5^`b+e9T+;o+$Y@R~oj@P_)&>q<_?hk`BSCPto>BaCB@TGARwFlSm&<1Tv zwXSx|A9~#P_PLZL>Ninr_Q`i)3+jH2dwZFhw1E>_wNbm`6Jhh^XEEG&hJQq>OF@|f zw=$N)med9C!zA(W*&nwNL-0)JDU5OE0DO+(7UK9ow6@!lj{(4qsVNxXr{!MMsijt< zF;4|?Mcxu1vbwZt&{?LKZm*hcdaC6`!|eJ{`zEUGZiIH?Htxk(q>VH+(g3PLRr_2= zqR8)((EKQJTg1mWSQ}9x6?1O9ZyrE|$HrDFpLXxp)S|xi5%KU5;^WABgxh;`8s$?# z$u&YG`o1Bmx0Q2Sh9vg12;H<@rxJ{RP!miJ|5&4RB1HH3Fqru2l{>y}nzAoD|7Bb; zu47(QAk0Eel^Fz8$Fjwr!8l?{ZM+gTv`+td*$umfQn$3LnKAYr=!@ndw(=81GNqc& zuUo0JW^?zJS_rC;hR&EdZa--gI4li@4^(gB=h0Jo8i)DG7oYma-CqUyB939w=Nze1 z_f;zIh|vUBj>TV#W4@dkkX*Ut!OBK&``(0e0i1qdEbfRnsX(=^vx7Z^~qY0xh7a+NR%u;VH>TLt;n$eBGk4z?THSKxaA7YmsRKO=W=TflW=_lR za`B;QqHmEj^U9eQA?r=H5i|597=6wo0+k4B7xoTC`PWJ-Nll8K$vld}(fU?s-L9D* zT0gr<0r7KXu$F!3K|E*R(JbQYl%UTEbt=dPR6>_x7|^I@l2t^(%uenF{NYGvT}}cC zT*0=VftCTf9<;dj8{MAsmmn986=0| z9(%JPfk39X<5%=850c)e%_85rIev?9Q&|9$d#i00@C%}zL>%ZD60t`4g=r*LQ2auv zAY(`r5w8Ju$wL?>`1>RS`@*nDap8Hu*JKE5w#S{h3jHHvJj2svban zDC**fA!05!niMlN=bQwz_Ftc4G@(f!!_%s_$eYo&Yb zV6qTgMlPM=$fyA#FoT7;j8bjze^IH8Z-<^QgUrdf%Q#o-hFfR?n#47KKG$Tw9Xrkf zUp`75s9bTLA2ko>~S9Q_R> z&iZJl#HhP!k?(?4IqRv@V%aS2H)MQ1iFdK|bOQGfosSlZ0E%uoG2n}r5{k7p~SwbX60jV{4%I`X$wK_A2GS_u5iQ zquy49pJH!b#hSeMAL}gA2;`?EKHaXwL-hXD!}zYf%R+#wmkfNmnPO=rymkPcKy|Dux-R4Ra!}6i9{Jl?TL0QV!r(!jumiOgfvj;&2kb|0CtCI z9DyZ>1=jv6g-NWr9o)A;D_P@6{da|W`Q96;2Y+Echr_2)q=r3{z+j_$fqvS6hHWQo z+ZbsX$;QnbLKYBW9jBAB@xB1q<$Oz@V-RB&_&~-Yz`UhDb=oEO$#NYwXykRsZ+#BU zx@&6KW^MD&YeDx>;n-52=Xa7N+Ye=gY=K&iG1I4YsF^)~V))OysWD=+EV^IyIV*ad z>vwv=l2%MIq43iIcKzLPE04IAwlOYGkZ)4B`Z8t?)< z&BXf$i)RO$IuQUxK)S!|`a*stM8uyg<-ESrCP`_P8w|e!%j@ zEGSoc+ZO5X6T}u5C2DZR$S~(E??k(HZqoK;mLl0INVVvQqMn@&Lnz^Zhmw6-=jHYBfijgQz=U?^YaB^77de2~oarTVxZ2o}BLztsFSGsa?-09d0NL zrXd74usp>5u{q&URpj5-EeUaA0ym?QPhKyitxTOVWM0#(B`4P&Eip)X7>IM;1AOu} z_!H8Bp@BZ%__J=;P#O;<{-9%-g_aa$56xY0*3d(&iAdTYjuI?#@ku+Mq_>zyR7d@j zL0uNdJ;UY^6{57$#l+VVnTPKcPnVMSt6E=MCD zmTL8b!W}IUpe0M@r7Q)6Q7`4#+^4|E43sxG zt@3oqmcoBKVg|374Ni3nh52sCOv)dVWE2IFult3fe^{{vBf7#XcPBKejj#^Yzb8G@ zM2cT}xg3GqMyx_+?Aji3GE7mzjsY93marD8PVKqTr$Vxo&qLTH{pmVr{wFmf?nVn6 zh5z>BwUGCg=;IqrSgzUK%&r44=8hZYDT5b^mnhC@$~>HIm#o2enNU(r$y8Abco)vD zW}@JH2$)=Sc5S-R2%FZVQI{`<{}&7^wAxy)S>8FDdP<=G)LnnYpDw_t*|FHmM!PKa zkrkvy73fB!dsM}UZuMrps z>hrh_V4@TdzyIt^n62sQvZiJn@}7`j9TVA}b@!?Wv+IFcBeaNn=~pP&SmbBVh}+mi zf_-%^=tEGcd&XY#x5Ur%ywmlo7LDbNn`BVsFbzwUMDZ6Y$gaEathZL3$%0BMO<*|p z(dDKxUiEZZ;9dVDglv@q#(cuXT6WtZLd^@gpGHlv-AR#ObB0 zj3{$5Et&bA%40}{5bOfBia6sF!~KYT20^X=1%01>AzN8Pg&zIy!$oHNoLPt#m=J!&nsSe-(|IvDi80Ty+B9? z2v^pOKiB(y)!;z!g*e2b2+CTqb+ctT_(<~cHxnRwsWqzHtqKDfw;v{hAqIx_EPdDN zg>-Fy0>xp^rywjwj~$A?k!w2O#T5()ViJqRDMjGncA9v*|#w|t#@ z(2OsMJ@X>NO+DPD`(H`V-Bm-)-gs0-Zl&E;40)HY*UgjMX&?tTRX}*~8b3SfSn4Puf#bp(9LxE-VlfkA-U zlglA5gg3s4!|Dky^g?8mW@YPV`z2CJmU{OVRIjp=AU+RYC2z_$uyQTZE(|Xh+_0ZP za_ql$0fJbQ$gr>*RM2r%LDIp@FpL!ccR!6q0+lnfC}NapYU4COL@9)n)YW5e!GhlM z+Dq6T%8nKjO)Kyml88hkz70z zMScQ#myt|)i@4`Rwp%|%AJuRtTr_PWb^Mr$Z++0+4uL8>Pf85>Htow;yHdWJC}q5o zjxhs8{N{*AO&U;z`?QnXnJ{Ebd9$YxVOzLL`L-+-vfKe1RHRRGSIAnA-^*r_oX02T z$SzM7N!VdsJsj#b8Q4jmRjQfl;Ht?mlyLQJk~8Me)#o$DLQMpn0rOaW)4WsR_{ah8 zx3XLX=OL2lDt5vuR>C{fNExGh11>ls-eW z_vfK~p-M0{t{eilhUgDX3nHa%q}NKaJ3}Ox(MS4EjN2dzWTIPNywP^_?rW)>I{b^7 z@*_9ZDkE{k!3f3hAlTn1|D%M4BDr_AmUU)=QArdH8Jj>NA0x11vmgXxy!`DQyDEiy z#dI6SZzQ@w7;zBB!-(h(GHsdJR*y9GZe6N;Zna*f&)(w7QNkX=MyMI{iwY2fp78FL zJW@Mj8k*PI_Uv@a9xi(`X5^nuQ%z=E%6iFyk7SLzKX(t;J>($VORzG%s;1M-+pWjo zI%CNz@rmXawjup@DY zf|bz)WDXcr{cNhfDiDiYOz>IvCfCUA;`e1GK0oTA(H+uI>I#LlNxwDf%OPmv}3Q7p=4B<1hCy^2wfu zk!xqalXX-w%oBRF*MdTQ5`$0akHP$9wtMry-`u~Yf5Ja@b8W(g4n}Ks5b4MkyM8O8 zr&x8-r0w23&>x0|;gY)2;ummE} z1<1)rvu%?WYHpH`BDe5rjjHsGl3SNsYL?L*B)|0L@qj#e2Vag~bEB5eRV)>K@?|KEI@oxg+wX z;9SpkNdGDTjC!C!V@!8Vy=Es=;z3W2o!vl`YWzhND>dcZyck2zUw{iAXsfVw18xh_ z*S~#Z%-TV1f^PiwO>4h1P97U_Fmsyu1zYL%k-VlvN^5PthDpXTkYIe-E|V+q1jU_# zry%`_Zclp2X%ShlM~DO^8jWD{Q%p7h3{tiQIW`qUD5IOnS0#A5DVgDg?F#-$;?o6| z%5spV>0jnGLbs=pm#k!A`y=|4<@b`QNq9RUc9;F^WBr`MlSGckVcR!4g9_qZBkBp1 z_qT5vCnf-tZb>{Bjjdx$i-WxeKrW1>kZiU(gMtuEO+5M>&OWVq z&FY3d_bs)m!aKf9Jhs%VAAKwvx--h9rq_?XP+R?3s{xR~Ub+&E<(l~kt;-NQPNHN* zA7chiCnD8Xs!!5PjXQzHIzfD&elX8SdR@C+Ltmpa1ChHU13mJ1p>)YCED2#D&oLr# z{KZc?uT_;C`GJ=opcrZALu;*IYH6S<2QF+JN`ysE(~t?!pSt?YM@}%Qn1}{A^_Bql zu`PxRUo6@ zMQv=m9n&^5%7|E_kdpu5H;WBBy+n0kEYMvq7i^urb&9(k{g(kP(6a4mHLtDl;Wd)? z!CY4NFm#nFgF}M5l}DRz%_4^Mmx{VLJQUWO9T7s)1ILgt|o~qf^^QQQrv=7P469 zMDr*WWz;;y){2YcG|^Emf2=KaN*-pm`6XfKg?AMz%9!P0Wn7uTyXm&Pb4(mp*I2fe zL_uvIZm{kda?+1Gy04E7&KYV^e>l;=d`s0^N)ex59Bv_!07A1ivD2ZIwsWmV1*;Su z`ncNZg+UfW-8&0w{?HMqHO;g6mXDxWvsc@chqw~5I42if>H%Pdzj!deu?h+5M=@5+ z+O-l%`wdM7(A&@rOul?93F9ZDG5`@(wxxY`{{y8HPb%~Z9Fx0~3Ns3=IToICwkHxi zo!Z7;Hji{lE?WFEUHx%M5AS={; z7NCi6XT2_EAizrxBB9{oG5#Y*G2JMQXNvaI@>qj3o^#T6XX8Ff3Q@$jGz)C(ZzQ<5 zyxNNt=XXpaA)>$1;l<>uwQM*%MN}N($~ojlDnDk|eljL{_kg0Ktn{vwttZl$ukqU# zDW7j`Pj>EIcdct*@RE2#xmjUwzZtV-xj3Yoefd5^%h1v&fAoCq8I41 zl1OpNzC_4#T2C`$#Jv{n&YYEQz)Yg0mwL0MlBUr-=5z14JNrUK%kP*m8!4wy))OK{gMswx5p@L+owON>YHg(6EbK)tpG3~^NbTf#HAWMKh!D|n%9Kqp6cjP zA2}XgD=C7r0zn_54^3^f0NN3K?(o4II||~;F9v_!Ozu-Er7PlxMEzvr#0()#Cgn(B zE{BG`zSH5SNrCd{d;D(nnWGSNIY63O70h`K-JkM&gQ)URqfm7k*BKR6`$}SS(-$eL z@!-Cri4%FHt}?QX0H2wSc&kra4f~0PJEqeR3N#}837xZeUhIklF&mm!f1GCvbL=WO7>TGHJ)q% znWacDgcHw0bjo?2VBudX7F05l@*}TfM^VjdV{yn8wZ*AldiM%iImuyR{NG=p6o>Ie z57y(r9k^x53k{WXZTF|Yu-`6}LVg_7Q?r)CV|f!)20=^lTlss$y!}NKq{KU6YdSBg7V8cp69M!V@RqaOKfm#|{TZTVi6G_!XR>4j z`1l!9^o5gn>PYm32GHz(Zfr*OhRlE?K7Eztmlx3yB1x#9h~Bjb$39k5nvyg_g!FFk zgLTunQ6c$$ZZtC3bb=17Yvj&syAG|J$Qvx}CjG2SuXl8>)B}_^K4UnKgsBWr?0ja? zpdGy4t#gvJI<{u9hx_m;ogj~BBzcC&*%@KWdDiLx9Mw^j0q;0t9eOf5Y};8$Ul#kR z@ksAb9y#v!;5`ZF13iJ-nUt%p>t#(Qq(REajfHs2KKgh^(ZzN$E6vbhm;{J8cVsiB z*vimIXf?!1Pv&9%MlE;;M!F@bezrgL#mxOhD>v!QuDTgdD zr1R|{LZeAe`bZHpUC#kB#sb5yF;ItU)q#Lgu*1K>^(ty~^IV=?Xc9qT%`C#c7+;%K4_%Z0 zoRL(A`vZ~@I^Czvb=%^gp*Ne?UZ_ARPlfl|=l~aKR}EkY6GOxQfQ5B;^%U7>f}%A9 zydVuFCVhj>9U`fMJGFpb+I<38F9Fl1Mn{V4|9F^ z%TD=m%Vv6noIpnW^MQPMyJ0UjtmPO-e#Lw^=9SyvAi%xTi1gCUe~H)lj8YXv)ITow zAXa1H1YPDF-DjSduLG>C*X6#L?Aq>R=6XlIl?bEc-+jqRC27E%bxzjqvAfE~>ued^ zoJFJJ$m!~Zee_B6K6kyv8!r1{s1)9-`z)CV3J@xAXb)FD|G*p?SEl3H;A_y_da$&# zTsL_eP17#k#Yed^F_vUBG`KX2LT5NLzCpJ(@t1*%v)cy}VMu@0Evv?it`ebBXdKyPt%cy+0QsR>B9U(;;EnqMzt zHBZqcZ|xUW_bvxuTXp=(efVOg1y4cO*r9-T@?%$4ttju#uuuW#NU-mq#2pSrESF1P z*%qBdxUTjXeZetayrY^1r*PW%o}g(D&}?q`RBF0(n@y5nC}ACp)WA5v?uTO!1Z zm`5SfjpFAeU+)1JqSx8pGo&K}%Raolxd)6K@Gy@rOz9h%&8;Sz- z6{WeEbBP4XxesJ5ju{xoFVn>6eQ9bi@|Ns8Q; zRZ!u?kn&1O)04~6vv8>vSVG45c-ScD_7f#jwtB55&@F?9oQgB_iSTa9eS?a4loFEN zarfwZ0vW^4BxZ#aWrvlfkS& z0edOtN`|QC=8%JF@;)Byjp}z;Dnjc)XBUme%T;m{pER`%Nqu4UFUCILK;HWOF28Y(?ytM4LVKYbu6c6G z-r|KCWy!W*TmJl;&9LLSxA&EwI$wLsT*ykAdqjO~lhL=^4LHpEl&|`1+`zLjd7|4F z2Og5dp2e)lU0D0#$Lo4busR%Nmmv+!!KfJy3hg*CoED{Vb{)tzInu@9ts zV`H5>%rpe&9LfD-&)!h@zRD9&L8rE0BpUC5g;m4G>&U8*yP&IPe4 z|H>#~3!%uC@2wf|_z5)T2B{X=&7CiUHDx|+J#xIv$lB?&nkO21c(nO`RkaG;vY7Q; z9Bco$XO1pj+|+%KlQ%ldwDTxm;AxGCBDOHa!fgMR=rbAVrMiOXb#{@<|EB>dP= zg#}P$^xP0@A6h^J(n<4PxGoxyTY4hP%$Qc=dI+|mX3f3wIg*e8R|`{68B&JeD|K44%r(Tb&+2UO@));x~is^y@pGlH{YS7TENl}T}} zJe8}{lqO@4I}H&itur(IJ(S$SK!2QalSv36x~fc(Pzu0g@F`lhd@A~Di1HEXfBa0W z_LzUl<0>l0q#e2f)Xi(?`lu3okGyB-Xn??owzKy}tI{YJcIbU6CVQ6D?-^S%xzye~ zCFyr;yl~kw+)p(`BL!GL-^^`AD9lPK;3b@aYu63RCvKVbh& z=6z!x&xbd|eG~Hsp8FI4z64|?14eOsvwGZdCk%D@Gl2r}g5{3x&E$I8Wd+JR~`+x2}- zLfw9HORvqK_cYsSPIgME@(3vu{G;jhy;R1s2P4iG9qWNoC-a7&W+f!xD{(T6%~WJ= z*6M$L3x`$qL7>Rn_*G)NIEAT-V1jkT)CPsK_9L&ErOt7D z@}~Iy(O97r*`TG}s$A7igPQ~YD- zQrZ-MYha0n-mzAwcxU4;FqNzpXRUP-zPnUz(lGP+PMUSKDw)0%q&MwrT}Ux6^9dqQ zB(2|=ZimB4Dr<>V50$i-xLrGQ{`YCljz}R-{5MjSOef{HZ+PMwr?nK@0(*v?s!U-~oJ3@o`s^k$%i6@fjVp-7IXk8n}oz?4s7=*tgX$I}H zO7V@GJ}cb)kbX7lf!Y^$#IP6?0eD&ZFBo0iZ{NrYvKbc z&ge4smxVV27=2FqUx`9@J(MrwoGtIbh_jBS%TAhrQfNnh^EK5$=UWV~!Cni~8{k|g zMPmFztso4{n?w*Z0A%=(J0h)<UZL?k|~Wlz#JB);TbW=D26c(n~`<5#1A-UD(7qFTw{+4jVjO6%e=3G1sm- zDVkKQNxsE25WdO2m84p{C)r}l^$#`oDb>x6WVlc{el(FOSKjtWQ!p*rjR>qezO|?3 zz)tUZ52E^4!E2U*((8ZDjML$8-L|V!EO~V+%9{T=zIAXm^d|D2p@_-SQvw2g@-ew| zU%;jtw91HP4Hhk5Q%$Bs!{VaNF90zp2VI~xmfqN-c?E=-*Gbv2(5e_aV?qsE3|n+D|v417LFB z7fcTKr_!Yx%9%4Nsk`U$`7axD%mSN0Eh5ebIKh5PPv^5=HR^(F3^C;LYCH3m#q57uW z-tTu?&1!bYs>%6P-ezt<7_dcGw$BE!9>;O*Jnp2(|GCS+O3=o;iX5JZjXNsY);`W+ zID71?G@+b*qH!d#9IP%LkC^VBBi~FHoB*PNDVo{8yFBO%@Tz(YY%c%pssyib+Wud4 zq*#XiLD^a-@lwj9-Q>5pyGaUYLR->Ags!RA975E%YZlo>7%umBw;TPXuaz+;o}X{a zg8q1Yg!q|Dn_bL+G~#}V2O-vX!ZTP+h@HJQa)>ib)}wy%mQtZZJalMtTY0Cv((h{NTr=%v4SD< zQg#@f^WIzgvOok-due3!fH0>omOwQS%5GbJQL;oa7dOZ3skhraxt7QCatSywnOjS> zD3EA8o=;|V-T@K6kFyQctgsVXoR*;hc?&OsN`aW?j{?4?bU_h* z-=$QTP;+>T_gD$}FeQCNTUgD}(V*rpd^6<>0o)EMGw2EEDE#yusaEEt+yloI%#tsZ zr4aqHayCX{gTj;y{QK5_wx;YlOK?NXwoxqq`rM^G$7DoePSel8`lUNiVX4AObpet% zhZ4`ne14*=M_G7%9*qzu7tEM8xety4@FFlCOdjAC7g*r9VP7F*^|hL%1~ZX{pnPd%VL*ITtN=aK@*0wyzM99|j~B#%5D$RW{gzxJ?@bKTd%GON(8nXS zYNTXpaxp#eo`VA$%l*Mt-7G;j5>6oFq3WoV5?u#V(WvyFN_9@Zc%uZeCf7TIXSXqJ zIMMTpQvMCO|7f62hf0puXD%?V>EcO<8Qh|`T zI!cN?`=;{o3`El%H-0C!@IF8?p!dtZc${uZdjz2iS4-<^BqdeUXbO{XXi-$~oFU)P zbD^GXtpk!7V+ZD?Y5QDXjSM&iAf$plxN?UjgCN}%Pa|yat>1{DMn2&0xK++?3<3>; zxoXS8o*idG0&pyw$d=_P-*k_6Fzbvz_U*)`e*t*S*^UVW5BQ67gV?*66SLmFbbr%e zo%MbIJeSOiY^tmmnNC`wDomDh9a9o0$(KuCYvEtoNa_%-+~qMj43v#jHq=-lqx)Jb zvHEGR&se`+h@BKWEjwHZd8un_(fbM{Hr%=G(6}7>6inu|4bQIeoV*xf_JBxnp18TV zBRTtK9LH{%nBBH@bwo_hVqK!)?;U&jwnO9rwcFo>OU>mLy9qOWK@SCxJ-HnuBFJ_ALZQh9vTNw? zAIKFKq_4o6#I-BaR-?(`t+$^qoqp8m8}_4|b6JchN+6PQ>wnANnDObP@TPP#aewZ= z1NMrY5CxpZjtV8amcu1IcvBn!h{0CnzcF1c2XRY~LO;UFC;-e;U&AnZKwk?^VAfNP zzr%o#oN}jjQj{I+&%PzZW1}ocNG5+(PMaErnwAsRQ7yu)1k&rGd(yS#b665y0wNXK z)NyDz$BcP&UlIWyHG1CE9CFdD$|@i(Ot4R}SeJnSw&3T#qjw7C5MMzCbi(;XoEf93>Q&pn0B!w8SqDk zM;Sj>;?gKWXgy_W=;V@y%T#PO694#|_IF+7O9&Wd0q_*t?y-Y7lh$!oJ_Mc{02^mO zGmrCu19h&6ju?7&*Qc0lV;%nOt%ZldVp%-*a<|nzO=3;qKz&3kJ(or77aIA>oRUjA z=>{zJtgRMyp$NIb{^Y=Nm>4ifv>a-&C}CjIo(Gr zOtWp&{CaFB(=Z;T@gY{1fuD6O`-@jn)4Q7B+eb(NO)bb_)*p{@O5F;sW(70~V{^P% zh3B<`4PmAwsXduUNn#LR0G@;mG@TJkED_~>Z;PkcYC_{>@D6f^MF7X{y4ydZPuV$@7FiJ6 z_s}uXn@ep?^1w_fz}RpaSYB480E6=kCl|PT<2C&)HuaZGJ zDMrmssH+3p0}w+SJ7pD~l@$txcW;6lJE*w|Nhhc*jrQKS(H_QjDE7*#A2E3)Ex6XZ zT0(JI#`{CFEJsLgQYhw|@S0)hGiv}%dMps0(6{8~ZOhsKRzMGN{=i|g^0O3$9CQrU z)ih|WBh|Aewqpm&alDkRr9C5%>GmCteR6{_yUs0@fQ~t|^X)v~W@5YrfQ{=JqO>ox ztq2|3pYCykO#R|lsjVQI=2! zQWV)2McRG6Hv4AU+Jf!uGIQPd&W*QEQwno?b32T}Aw851Bd&)~`|7zyg^(b9 zP^c+IP^{zg^ugTp`w0z_OTSEc1bmS4?cU>v*$ zu+Z6Z=SvtV^xX-7I|`bO0bCPzZL9->1?A%d`#o@ei2>)1t_EM!@?d@y4m97UG$IYH zIfJ||B)1rpxhGF~meQm4im$38vh%q?JZ*@S@CZNzAgRBy7C4FJV9;`yl-V_f_5wil zjgwdmaAC-=jooGRYiE;B@%<6Rf5#AtQg(96m9^g%QKrEy#lJ+HyGR=_S`)-YSNMyP zwh^5TOnge}#h={US1E^YaDde2ItvP znUqQJ=oy#OZ*B_L)r#$20Y%`7<7QCO{w&0Hl4jlqK6K4Cc?CescwP4$ToLUjZiKeG zMd&S)schR)9l!LtRRf}Az68H$W6g>V=F}J1QT?*vebUyr2ud?&C`G4@+s?s^8{0{!$z2Wpyv7LpeNG0lh&M@X2<|k zXo;6&n9rR+EC&p75_H)OfD^(fEZ$=P*U@QNCS@?;z(iK2F#2N)aM9=MrFSm`_+sk5 z+2cb1EL^94?yfT~vWzuL4Iqb!4ZBZ|81j-r`*)cOrEh6_rhyEaRdkb0i zhe%17yE>yAb~`_&w9$sSPXYyp)ty=+OWR;pz#*R*<6`C)x%*eot@A3g%i>6+eIncr z+`Q1@455`wwFmz74=Y!d7*c-0R^kt>7>>Hnmh3sSSy^m63y{;Lt3f#1!F|@yh=!s8 zTsV~Nog5Q4Rw(2yNc;@u!tP)f#&wqImGINE0sTFf^iAI#(D zJFk?8IVz9P%3`skbI@6k3Qn%Fbf5yEl?Zv96<*s!4kfe^rAwHmB|dR=rTiCzf~N`` z$n;GsfBc3e?h|WM==@F^|J#fyJ+LYO>+?gd;B4s7J`#QvQnQ$W2b?EEVdl85RBdW# zL)m=L^v@&TU_IFs5luDB2FA>7EP@1>uBq`yV3z>AuImnj)|J&m%whSd3t*ZeTETpz z;sKC83nCxta1pfB3QZ+f8N;=mB_#Nq7t)*%|5|ZiG3Rw~+l=$9zy26(Pt) zXJV|fS1zsV#f4h}&mlbkc5-tEd*kRAGNu<)+~mcW2g)#TYct2mSPj(S+KQ)U#XZoY zpOMJ+PQCFLry`L%keA746i;TSnU5k5qF8P4eHg~h% z%Ao&6uaZvb&O!9(D4T#5WPwmBdL`tNsg1F& zG-SABfYbL$YUmA}hMaF2cHO0ur3RIE8eUSpULo&<8KxE?S<$8KpbDA zd!C)+NOTXrKU~EQ{qIGZDaMkJi1p?)M++hj3MEFlc7%vNHu^HIH_-8*90~i7}Gp@_SQ0nm}tLy+4iN2cQ zR7Io&OGUco@GPC$5N(W`t2}SZ32-w8`%3XzYD{B9mU88LmRM>Cb{7ZMUxKx)0;puU z`}qxEYO{%6{~Iys+n_FdzVs8N<2i0vUGXT8Cwl^kuWc~$9VXBk!7r!nJPWy#(dy$P zGfZc@AIBegnm#kH7Spyy}FyrCK(M$km3LW#cT5UIJKRQa2p>{5*{QDh}_xwx)c#g2<>u1=shdl{=_5M!~bewBVaYkEI0b@N`M zHo#ugfA$Y|#{&YO!F&*p8cEv2DwQVa*lmWxn8u~YicTPq3#W_y=Zq?M76|{|U9aSN z5@QStAl4P}!Ym`PPyHhT4mK#xY}$T@o96F);_ZcDp2~bNC%Ih0F`y~wk7D=CmiG2) zMyg$CsV03Swlr<`xHw84lf$jVC_vygaqqYi1e;x0sRhhRV(i6nfso)u-YU6;*0lo^ zo1|D*$kcU-|KLj=Q&(>oQ|OgCy2|pCC7j=w)GSX`ip|39U<7tF??_+**F7w-c!hCr z!dnkzTW)V*Y^rr@n#!qQ^l^+c_B`k5)L$>)FlD2qxeAQmcOinqr-BITk^&+|;L}wv z9q(x~1wCtNJ+=TEv=#R2WG2b$3(C8IruDh-={1bjqp18Q8E8`{w$Caa2W^|jDCn*# zeec9-{L{4gnK|T2kh1uAgKprKrkN3r9vL}_7@OVEC03}CI+IY%YZD^6SAhQjRaMLD z@&CL9eE~o!r-$>9J@Hwl`|GN5AK>%WS*4td%jfh`pcF#TSkM566Kpv{i}mx1Lk7@u ztNS;Lm-7%s05+q!i|vT%+zV7DmBtmmj_ECtwF4k5&2Q5jyH?6RuQp@!hdcOfF$RrMyL}pk-j%nh&eZ+B`EqW|Qm_XeMd5Nh4(fpi=v)K|* zUp0!iHnZ{l+*0W&Awi@-(ttNhk0y|^pp^JdDr($%9j0mp&jexheGVhgq*35?gOS$B zLbx^g7DMM^S0%Oe?{@YEncYXX>3oht7GJyaf%d_dEoFTyB*nG3h(i2a4%1vGX4MYe zAeB(7k<@Wr0#|DbEmH6WM}slB$z)_i@<>X^&vTyp={^m0!KY@k`~Nxkm=`Ms1Y{xQ zN!=6;Bg-Z)>NEk!TNa%NgQSab=-EXtqRoALa>JzU!9FM0)P zyS~HtFZPiLvoorwu~mqIvQE8Rr$9}CsP{5*=?y9q%#NCLrvOyK(s($uMK-Hi`rIQV zIf9#EpRjaF_NK<-VXH);2G?IU;5DqniYusvDk5D@Fyco_=pZwFO>Jjt$21YDgHs4# za;rRKI-GcPDYSzU$gEOYfc0`LdA=2RqhgD{=hOlMrUKBTpS9raF=SYpNl6Q2#CIy+ zA^jYWDxr)V=D}&szr07k4H=c@HX_Qsuq0mm+Uh(>L>X`bg2^#)oGrQtQgzFswG8#( zDSZ^`Suf?PhSvM&`Jn~;`*e0je@|yT;FFY-^gFS9voA211V%9eGmcZv|B@P8?2dRo zt^fTfDemtBR^A8|1de|e58@(Kmyuhs|026X{1q_|MbqQq27lhujAK}VKfw{Dsn*I3 zMT86gJ{`L(d=n8bE@zti3|8X}-&b2o+%J#2^4%9N`I7C!oI- zItlL?e3l3-v{Za7apS6DY~x2ME7?pZHPZAwOq8(Iy7a+@f)qJnrh9F6KfbhsbmzMnAu;E3&GZ{w!YG z3sJcqy3;TnMcpPY`e&iJHToh#0=TDsXLOJ(L-4GYBe<@H&#^ainfw=a(h2DKgh>yH zYt2uXe0Aua$5X|($}A)7_mf)*-vJK92TD ztn*@0+3ZFzJ+kYZZEmbZ7Z(0sv^`%|%(@WGymmyNIU=xsIT0&!7>mzlA=HYx-8H2e zxp3bPy7#U|Xv7`rV~g;f-H~BS`?z4;4Zji_IppM8aK#>55BcKtCUDTG^_*aC;2PIK zNN3Q$i}Z&CMiuy#t8UbC3Pgzhya*7!%&g z+54~3*U_Tmq&%F-wx)e=oy(a+6pG0mAa5Fo;(S#_;a+-2>|&JCbV7I-iUMyn`Sr@N z`RiAb+!s>%=4*k?G5UX@kd8nqqZ5Is6Denv?{IJKD z;v%Ib2+h>^Q)8APutUAu~hxRt)zNSaCobn@>2gF`rczd7Th5~8Tp^? zps`wuSY>f%tvUOP3!XwF5n!2~v{sh#od#V%aCzJpUGPL2k2F8$v~waY@E>rZJlHZg z|HOSm8y*Bz@NDX?TRfv$QOtw8ct{R2(Tc^?vlkaZhpJTzuO()u>?tW>{|{25U>A*$-zbtEEp zW(&R21+>Gta`k5d;ap_D1jm{C4~lW0wqTYHO6Ua~4PtF=$hkvYc%7SH0yx+R&T$M&is|HPKa z1i+lHbKFEeQ~Mo3Q;I!JDt-ubwp9-^n~2qH{JjU+p}TNV06{>$zZf=*MX5UHoIQ*aRI`}=|KvC}$a(rwgBZo=xwso){Dx+vX&b*gWegwNRPo$=T|4S^XYpBoR*44BbHsjQ2{f1!5M)gI21Y%pWs@W%-4c)}M zWvAtuk)-p=EKeR*nX3NDodrm%B{T)|_Bbo(CVhHNT<#TjP}NT@M?T zM|2R?T1!f&935orpde&x5zJtQMN>3o;JJt0wvE8s&9=m+>(Tna)+qEeOFqo7W^IBe zEHm0!@0k)j--vR}Uj)mBsjYQhj-+57i}osBn^LcL`%?>i?#MbQCEAIXzhlGnj5`gx z!+H2RXT>zj_TligxK;R%3p?f8uJvxKnK<+-1}8nskKz6H40Y)*?1v#>hgRo{XJFT) z`zNnZyZe?c)rVr{XpYZCCcBO}b~)mFn|@LJq~?uKqEMbTOP|I6Fnio3oW`>R(doui zhhSUcj`!1oat{XCGk5#e#=zoL1az?Kdj1s}Y?YAYv0#O9{O|-m9$rA_|G_vCUVD)t z%+pFak*%`m+dbzH2lTOV@~1mm7?|^jFEP38Ro7+oq5+|_Hj58^>__4Nx-Ml;LnMej z^;ELv9!tJoft-)wygS$Lw4k4rQX;Zi0+PmS-jrWXF0&4jf3wWfd`5KxUlO~Y!9*st zhKPnNXFJg^Cz4U~*F~e&Fw5H`tYgAWrd?V4Tk1>}G>RKnZT1;|Jj-r#Xt%x!Vba|% zHugeR6rl>J_Nl8^kChBR-1VI^DUT7`K|Mgjv4Fz<-6$KAA`_%`lGeLVh_x%!o5N|j z`a@#PA)0DyC9!M)5=du}1ZMtUfJ}euf*s6aAU1_8nsq`4D`1VX{hj$IXx6Vm6KH{E z7~bL-TLmf{u|0`tyn) z?=IGqcA{MZ$@Sz@`IJvYn`@m&xeZ++Z-_7i@anQkAo$xbVp)2omk)h6?A~0~ zJ+jm4U8k9DBeYzp7Ir$Er2>sDvD)KK#B(RY%OLVH^(LWcdMSu>rj0>c;YaG$UpJJL z4B0wRYh+UKf-AvnNWrg*sNtl*znUbTMU>fEK&hP0c$-(FAG9TEFF9r-vu?ZyI8y-2 z1uFILb~RlR(-Q5Vv?)Qz!bDNH3^s+7dDvY}4xZ=}px8F%I3X1F&iB zjwAlMfClhjT2sBgaXDC(a}7oWN@2n;GAXD)=FCoTjcs?K{T&25<7$y$6~?w&y3(gK zv5w_f(pe-X2}X;S#OLl)P9orf$Z^goBDN3L@iJ#DS*I*(LF&)4xp@O%FptjBqgDTX)`YnB2Ch%U5L z8JS8u9Vgz{jy#F1r<4&x&Cj^rB%9SrmX)9qUqXN{&so5gj%fkW0r^(1m`>*2g7?uj zBE9$MU5GSKn|$dp4&r~oE1W0uzA4rgXxO1x(0pn3M=6V0_wZ(YSWqASIq6`X)5iL= zyT4k$Iz<;~*Rd}RuN2IMy|z@yz8Bzk!pG-X*c@=IIsIRJn4Y)UO((`>O1BZm9yzeL z&^{MXXV?Q*pmeVL%xgvW!t|TxDKYHTTtI??aLqD-^q*SD-!>-x7;#r=6Q@rqW4b(B z9r>_fafDqSq9v{jUoBh=bl&~tV?d6$rSt^A3E&mvz3IUWQ+PDsF)9QO`;99CL$CMz z-xk}c73`quP~_px%wFn)MxRS(X<*M$0OqWdZ?rj&c5!7^PE5WJ3J{-ELmMnQKNe*J z7zQTqdf!f)3mz1OeUfGE#*kP?ow_zS1zXAm1ZoTI=;fz(Z zh!%Sw|I`=yP+{-FT*;f!Zs>=8Agj4ju2OFltloXT#W-%3kg zqgk^-Q?6^Jh*SNtNR=@2`$fo1s{q&oXm+|WJF|k%bOJSYxmsTEI!BI32jJLY+kNGR zp!nS}3k-?23v0Guxj<>d3lnfSl8)2d%Io8l>^RNv1z26+Ek?Y%zK3O|&E;{_!{mMX zPuYi-;TKJgCb;}%!Kvt{xKe9Z>{7!X|CcgxXFEb4UQ(W>@~evgx1Tzz&OnFRv&&Gp zEU4YX`RmMlA{s?Uutps6vuB_lr3sMk<^`&QbwM?)O>TzolpPB`O3Nbwp~8~ndoS>P z4=2v)26l>Q>h6Dmx(Z!;NCU}UO@k!?B%Tjc`kiQSU)Zp!ko(Q_HsjI!W z4Nc3qq|=)PvO!r`cK`{s0#aws^bh6#T-wGuEpR~TY2XY1r*$SOiw*R$>K~~X>37VeO(E{Y{g4VAm@l?zNh>K^hPVeJF z$485{5{ddOp*S23bVyWOv!UvT1Od{1;!$dlJ5BMU@6$+<@x^K(dh@HghjG7h4|uV)MiwaZ6B$ zf!dX`)CTJQ$z0~)gYQWvB1lO~$=Dy05{oZL(ITLn<>7LD>8DgcuCB1`=hzv;0l1Dx zG;)feJdvm|_~%;~W|Aa^;zQG38uHwTqMl32+&=Nga_DDKBe;CJang1HEJx0y*N;iJNF1okXq|@U0JAjbB_h_uuQ4W`B;C2IL7By#D zTLruPoZfA}?@E!Psg3;U+XK)N5rvcT8F2fS(5*#xahT2mx)uKMc!Y1=69W->2i0b+ zTp1v1e$nuVi`hd&Z9(cc!vKA< zh7y=xAXKZ>xTzejfTgOz%hRlbw;dlntH0s#A&7KJ^2qG4GLUyCAb|MCs_=q6RZ5Z8XJir zp!6GG12$BJ`g?R8*)o8+H;R>h>n{$1Ng!tLF)lv#^(qbITTbL+HhoJhks#Uw4@%6w za~IY`!1bEYL>zk_ft9&%AcHSDI)5Yk#(H30a^IVrWos$h$(5TNl|xFhjF9$I(7Yul z!qNdlL(Yp`69i#49zHzp96^6SqnV?ZEx=GmIT@P;53z%)>_+AX0Aew`E-Nsy**Y9i zckBTAVK29WWpswft1qG2(-9B>VgV_Se0cB2X0aJM5z4N94CklWpZuWetMHv9{vTsc zbQn4fJO`We_3TdwI=2OUU}gGRU)+|V z^>M6r&2iB-;78CGs{mN5W)`IRy~L-Gap)j*Dz3yZdO+q?B)WfwK&lvwBZsT}ktxBN zoWY+lH}E(u*2c|XmUc;jYPS3;gdW@(W2dM=5U7E?r$iFc$S-8QMch1n@{qD-_%?Mn z@iYeblzx3%f`xHD<%c+wSECGDFZZR)ymiD@@Y-RbrZ z2#@>~TE2<(3)x>*g6t%|!!h@`NO8XB&*U8=0dktx7kQ$1w629oSbbLr&ed@P_U_?n za~(fxg!T|}nP0Olz868Y2xq#WKVu7-wYZ{jx6J$(pj}J#Zp2ov$4L=Y<-&>Cc1ShR zBisoGfiIw21(Q8FQ=dAoh2Mvu@aiJC_>G~rSCrMA(y`95|%PT1iXeM=)58q?u}rzA+PEe+Fo?)KWd65?Bq zo}V`e##g1omg>0$T*X>@yrW^shyZ@fm%;E?+Kt9qjvCC$lY*OQ8h(ZX!+38Y3{kl# zaA@sj)1nj~vh4$#cwmbL3)VXXR~>O{q@T2*U|f_zoD|KB;K^g*n2_ZqBWiO|ufQ7m ze8|H#bx%Gkq@bfhHcpEo(;;UG+fi?xDWSo)=wN+3{|8qTqCsrTA8#|7?IB)HB3(#K zT?QEUG5N0)lSRDtjTNKnx*FU7%C(u%c}$YnTQ4_(_Ftr5;Q;j06=ErOf3I9$?yQ9F z*Tl>+w8!|pO0`E50MxZl9V=lC>1XAC$GE#;y`QX;Cfbe=1&v&e)3~9NR7B?UC5XpM z_-W{;upc5tby#Dpm7dlx>k^~o9;wa_;a?phjFu9OKAn0!fCMYyj@UtV9s*pZID0>Y(81T^j0dFDIwI@Vt&qB%O6W*|cjU#Ye$RLGq_DS&gl@#xUy z>Zm{cm}Tzmo#Qb;G572#FiyCd;%f$Tk_7w8Hu?=i(Tlwsi>STzzY=3wu};*FgdyHXNyHTA>F+6wX!bwV!=mI zCu3pd#--M$@A|jcUG>lP+fp@Sf>Plmp9)X7gyj+g-|*Qs_P}Pw?Y^>3aW@UnEtg4H zDTm6J;TD|kV;$sQU2Trcu+m3laj&0al<0kNASGS}0GIk*R3& zdh~JFGDj#jtg)%44AM7V}dj}r1?mPtBJ z$uq#H#3El`@~T!i&!`u>7rInd@L!a~kA#QHyf8j7OQTbcZPoH6BS73CHp|uS&o>W; zcT4k%sPoDXX8Dg9K=HttAe>ffy> zE|GeKfK8w@WZe9@k4iULc^~`CzKbVJ)O<$~}G`?yL zzT$~{QcK{RAP{m2l7}#Jh@4ujm5pE;)O0z#za{OELPF!I17y1?_YJl(bPN(q!k$e8 z9?ksWu+gKu1g5d70b@W>Lwo)O6LgNd@}-Y99bB6bhM24o#+I1IO zv2rA8&jV&pfYBAjokD*KkUFoRmqLaIw-}f?c4|?bTE)&x3B-V5Cs0)Ta#Dr&{X$5B zYSLb^b77#cR?)ciJvJ8^=?8-ZkL7@Q26`!bHqxqr)gQWAOL@GQRU5cVKY|qQEGXikI>O|FFyVUj;q>*J{#xn}Q&*%{y-I8L$yhVm zCEyt%$^I5ueMHiS{&J9N*HM`$f0#RuemNgqPztHb1ro9vp=49UsRc=e;em*mH)mSwvGXN41BBTUeW+8X}|K1%(1x-}C(0$7(w>wMSUVi=F;zqfpI%1aJ`l)z>$=vy8ULwk_tW#$TCnY`^XM;S5APt{Gm-}x zeBq0_BLp80pT!iDf*FTl10F$kB=cS;j=gfN7$KhHpO;*oOG>y($@l*9*TrMtd7lq{ zhX=&9f$I zfArM|-i*?RvmAZUXfX+H`{gB;&eE*!ocv|2L|g9RH-DtZ&&;hPbkGTOMHeRCXE=QN zCvg^j3#i7^XU}9-DIdh7h(6~a(#>k+zp@dd_CtmPUT0dJNlJ3MmTea@%JRYM$Ra!3 z{K|4d0=Re*sMQH&WxwcDV}_WVx;Ii$YPGxR2yHuUsliw`BJc-q>l1lhvI7#MDZb~h z$K=hBLk6H6lsAx_4k@YPyD(QaX1jlg4pkU~|;q-0cS6MnJ2SBg(p-U}{{5!tTIy zqRot9dGHH#a8EkpbrNC??@u5SQe`%+hY(e3t~f4Ugvj7fBSzS>G_I#D*#R(-iL18d zINf?(VEe&iehP%lz`HKhF=V2G3%nDbHLnL&k-k#q@vn-dfFzqZ$aUBVTC0_XC)w{u zBp>zD;;J)gAz$C!-|%HA3#I^$Vo}pzizjY4W%4u}K=#USd%B49y!~?%=E$zF45;t_ ziv~1fHEiZtoX=>EtQOhjWJe$Ir z_X@IZQme{tFEcxyU$TLKWL22vTqk*kEET1}OFxB#QZ9NbwE-4i5Ha~>j*+%g-2aru zM3+DB9vjG(%Iig9Ctvhie8#}zel7EH4~AmOGZz!rkShp?Dphi7*1AVk>L|2^s%8`N zBDsr(n?7I&dH70M-)%i}Uod-x8U}2$&+KO+AaU6I{EV=Y;ialG+!51_SAi zDt&ld?JyGX${AOHiG5pv7#t)ORV>0|n!ChDR$KxZQkD?H1kef(0OxK-aXRx~FU$Q| zSwhjQQq{ZjO*|82yrwmzRc%!cp;Hm|_=Tu7p-L_?wi^svVU9D!3vO0rwLcuDUnb@4@h`$Do$~0+WgF zO@wl7mCT#psqy6Hw}rurwnqr^6TtbQ1Nk1!=ZMa+LpV4EpkQ6i+-nHzzuGNyitlZ~ zn2a};H^#_=6ktu9Cp*0!DLf!-#GX~}dK@2TS^GWbe9c?mfc%0lkuP!;F5l># z*|%)R0)I+lfp{7);JJQ*^u&Lf(5}K-uv&Qa!kkJ<;_9V|LfpG!oY zb%qH-@#aXdYd;dC)+ffwN6+BH8RW9L$zSFG&DA~v1^4&Bd^xIB^iblbm+8sc&n7Zs zCZQ;dMcnF^2&-8gp8YxwOpNjr;tn1{0D^4smF8%KZ94x_^-2{NAj(nj3QILii2F8gV+q>$mnS-dN=!XGlZ2TiSog(}kgc_;QQHZPkXZ|1k& zfEwaQ@y3fM*)X4W474-7Ct#d+CHpbwfKbu!UG4`q-cVj?Bt6LgU#82xdOa$;lJB(h ze0@qnOR>B4a$FWQB}5bw*km3UdB{nik`_J5T)W}HWDY$CFvpdzz6DY`u33wH?RtzS zH!Tr>nc!AE2TN4;zgaxxk!vvH-s{4n?FtnZBU+++B;Vlw2jjd$g(^ZGMySO$24x?* z5a*A06r#(i@W3zX)xkSiOl)|2kq$TV{3d+kWas|Mb8-C&UJ?@p608%!4!n#KYFgOK zKJo3QGC2$fT~&{`LV=ymUU+3_4IOx#bVKj4xPl}cAmq7VSZXouvFu6ywfaDOSGT6S zTl*u7`zSL<%}ntqOe?8ea*FqROX-Ua^=T_EpeVB`3apB6>;A#Blb9Q=QE)8R90fJ6 z#NIpx@1EC!L-i4GAHqSo)gKPbX{|7pd2QE!gn7N(J(YJQp)im4hEI4~KZ$H=6?xw+*hgVPN3cG)7vW)hN1QDv~4N%F-Wd#MmkbiZr}vRI10?ii|MY z;e$l?{t&R3s~qGC`E|gJ zsK!07U@dE7T#!A~(qfm~xzdJL*^Hn02W?6l63Rw-+Fc=Zkkq6B4CB+%mhBR=Gng1) zvIxCTo~s~BA8|~Pz4}(i7k(&RbN%B`FJi>dFe7btzfJnlVPZHS-G|NOp*Hc9DR&q4 z)?onC{SdwZTH5z~cfB#q6$rjbGBjihMO_EDF|Kl-W>cT|G7fpYTkRkr+dY{j&Yq^} zcQWukfGUr)(3bHZCl`C~Kb|aL0Mht}rdc@7u92Sfc60NWn#xlsE4?0@5mP0` z23P})`X3{EGhSy?8hCNrt|$adh&So>y=%-)xpgck7|Il*EA|H@54otHZlB(WdRqg~;HrjrJOr>0>$JCngD-aw|tp;-!4K3N;d-?oZ2701@ znXy#f>=v4qb?ZYb^Zz^a8UN7f-LZ42^K0rkuMK~+a6{{x_A|fUBj{ZyrHR7F&YlJ# zOBa~Bkc%FB;k3d@udhwpYIdgwM|9Ay{&j@!_7!eb4RXmM@60OeTxFn}jtu9c>Nc+~l(~~frS)JAD{B?MVvAaEBBc{!;=rke> zk!4q?cH(<0jN5Qg-0I6QXDP zA+LNK4E2|isT=nO8NUwd=2v=d0AKzP+VbEDgZtCXSq(mIn?-=e5^fnLf?Dz2Zn($- z9?B^(DX#r|L{x^ds*;}jEnTl;FQU3QL%u2OfHQTXeLb;cBOMp6ipwUD{BRiJ!^`2zMN}iRR^|*tgMJAg%)VliLCd=}%BqM^) zc-7d^nX&<8*v`Wr=>mBqNJNEUd(#+!1+`GNHNovogm5M>HQ=MH!!Bz6_vAp6vnS`t zx<404qFa{Jv19}EiN}t3K7JjhhFL7S2nRFt)tW)ZG9tI(4G1!+oh$l5j2(67UMEmO zXGt-Gg36Z$#dK+2z_LdQ@A$VfTARbiJe4koYkdbxZY`LR-*T+rV8>V(nHQptAt2?n za{O979ZhZ`;M~orr!ZGG-ZUSfBKm;!oT!gvqu|+Er|nf)WOe%qgMlmPuCR2bRC`ff z=AyhE_?;)JmYoB+W_|0U*?tHP_<~O3OvYXhuwMO5Z@$25sM#4bHAOEya|y?X@D#D5 zS1NfePlL`!q4-b@jKfi81Le6BG$lC6FlW>5!0GD#w<3T;p%!RG2aND0-r zS}w2gev8sIYLR8Fq(Y@9;>l@#gJt>a;wPcnKc4BHdKR>FZh5cSb}5Ok@)n={ABt+h!K$JSIy%8h4q(3NUEOrhBIrly;2XA2jy? z3VCCb2_pfwI&h->jk-!bWAau*lp8;emS;Y^Hf?>pl%>qyB}bczPZL((sJUw(-tsr^ z!#pMLNk$|CWLU0nYMa{5(Pfef&_1Def56w$wSn#J-Bra1cKjsG`y^N-Xyj7rYo);67CzCdqfurDg?mn)C z&ESTt-EPMr-Oh_RE?z6&gzGK=vMgwD1Mp7XP;I%Qp+ePTTL~QvSNWoyV*I58&O`n@Q>A>*SEE~`_j#1O*M?b3Gya2;4XR6-yzu7wSQ2Bh~vb>IEwvE@GGogLL0 zPJ5s3@GXJ*Sdc{K>MRCr)=#Kda$gddcZA12G$V_+_nI|8%vPQ$9BWYML_OeM`Y{rBL)y+;1q z??(I7NGa^zM2WRq24YH75^k;^`I|5aGkc&EPzP*n=1d6Q`x>EjlZ#0sFDK#y+g+=u zh)W7N4b^O2PiB@oxHtQyF)cN`4$jJ(L-nGU#$|NB@pZemY(c8^BJVkJiKCN=Pc*C* z3zl*8x;htq2sX(gnOyI+5OzVh@@!V$L8RJgC_oRqk>)Z!)A}8Ewk!Z+RLuE5`C7!4 znLE4HM6UW{kZwz>0LzJw4KHDOw;J8YXtnFpnffeN=Jcc#G5)}R=`dVm&La^XQFd!W zDyQx58oiWBda^WI?=^m5;)0MgV`4%^ej4_9lW5nHC@(VSay~AKfy63bAIFpkgF3Vu zm180}5VzT>TFY$o;1jt-wPytk!iFwP;kVsvk^%bn*f2Fq!waA z=m)?eM~XUh(w*@A3+#CDzcD{Prbv1cBjrgZkcw&u34y=CNy@Q3p;wpft!y+&VlFzm zKpbXGWD$sYWAkZu-jyG<0E`7M1%#x!f_4&lAW~FFi~ex!OOl^G)-(~sAAG@+R%X7`mXc)# zOD~XU+3l2F>UysNI=?d0x3K;^tfDV&z@9BnaR`z_LC%`s%c>PPAp)dEdb1d2?&k(3WF$&#fIC!-W3=dZ=f0LcP(CZV6M| zNzSz}2)9}GznGZU=b{M(a(vrVeS;o4{ZRdN#Vt^vnx)kJBN`1h$vpaB$2(CCh)S27d%2br4_>;%G!$Ol{V9|xZV`u zhITbuG-abs&-=Q{Y1FT9m^_uF&RG-$rQ;`zu39!wVC;gPhR8P3{l10Qonrcue|O&z zR1LgY17?D|0-TC(dMx=sQSXGE-LDk?Qiphv*!j| zM%w&b(Nc8)$14~1?HOxMT!y+U_lG71WQA6>@YfV_HHfALx5n+{zE@E0l@?ue8f$^~ z9V>d{4WMQ%?Jw1RT8EgL?a*-TnXQW1mD>x4i&Pn=R2F9HIkK)7Lb-}|Voc@uXlOa9 z#)jf)E(s4D2tx?QGp|?2Qu)K^1C}t%6&`2Fxg(e@ynC>_pa4T7EMb~l=-&75>r(7J z@1WLXTmx%S66w~%O1vCs+`LMS-t7MAZek-%?nd5=TK0}!9Q&|uaaYP zgNjg^mx=NR8+boNN>%KklL24u;?Lgazdjs{GO&a19D>$rm1c3+X&&r1fyuU$jy{78 z-Z#4505OnQWG41O$*gU}^1O>%I**Gi{U>tZ9rhhv+r)n0MxEbyqbX?T?o~;ex{Hh$ z>4T~*TS?FU-&8gG4T>7F!%!CxbD9z9jyr%vVRr=%4m}KQ4PLAtxId!I=lHIO_caC! zM*D$%j1hQMht5*f+Ap{fKrrzW+HQgL3rzb}Dgg-O#){u0?ax=J0RHL%O_lS^&PZBC472wRRnW~o@tloe|t}v-Gg@zO9LnrYr$U@mGN{OMU-J*9j zvA<+hF)?v$;bO%l)XLK8I z%dfFje*Sz4( z{w;#l171=E%$#jHRj4KnuFI2uYUZ7-IP`j_kj`U?KBYO%87BmGxo?68;F*=Q859g_ zd&LnZtjYAS)#xjmXfTP1M+3!7Cv6T42e5GMx8Od-Nz-l6al(^YsQS*t@KN=Ts&gsx zs%>T=?P?W#`bgVWk@o=>GdQ-UXDYG0{4?NFZ{*L=DdSbgt^uE%dvqXmJ+u!p5)cVL zFJB(c0b`U$`m#KqFBLs!dYL}s)7nVm15h)=oR%!JM3Sj*R3g?DJ43FUbNphu`kcU4 zN*L6hPZi0>+EH!->QA8-^3;6m!>HW9;MfNXmiOAUm8KMuOB4>|%;S69H)xRk!yQkLzCKr0uRVo!V)cSO5yK)x9v&`rBi`*`mbqjm3p(xUSpyM_EEpfc zNdCCALW7v(;U;JepwJrT?}AY&$Zw3JPDTM}v{Ul3@z@?c*`ls50~W0__DQgw9H$r$fuUtB(>!=ABUiv9n1(*39G(Dxkwwi|X?#L% zY0&R#h@CHtHdYFd%%~P^Gu;8jq-mg}HzLo(zp3|t6d2HEJ1?7S(8Pk7Ps=dH)*eun zmgp`^_`*v5m1!Qecno%9XgGEOQB=mA`InPYLbh6a;H>Sh%7ixpvG2I1PmyXSa^gyQ z890nM&1q&n;2$C|K=%WrdR~%eavox2GOo5G7|qz)B{3~2XoT5 z=hBzCMu%CH;NIGSN*TVkt=qxHwUmtZ#uVEd8PifHhzHxMXeA}e{~=Kec_|rjN^9{v zle5zNg(`-MuIy`^`=D%THFK3{(joT7hlyr0FIR-V&JrJ}rw+u?Z}2qy)fCM`t96#U zdSP}uz}}P7d#v*T7#Og8++%k1?Xd}y;y93|S3g5>t84W{QL+?*QD+MMO$I(x)y$51 zeq^3}XC-mEO8>4jL2cLrp}MyjQe!DrwD~6heqmaHN^+}Ozmt2X_JG{r1<<@V{G+-` zRlFK>rFdoR5;X`488K<$fil75_Wq!?FnrUr7X&qYZPA|qPQkT+om*49F>9Ozrt^@# zPTK<>CD5z18+{z6oS3MTYq0oocl5VptJZc2MkKV>fB7yabGlP6`K*U{dK2$Qg`*ok zWp}Cx*O-X8j%G5B8Uf2}bNi#Zf`x|bwfnxB*2|h-w`6re!pgsC;Q;#%D%uV+&zBIE zxWOWDs`kbFQq9JjB_JH zXef+X{v$fJItWT$C2%2&SE{&}R(QP|kpsU|J-6 zg#~pXVPSz77*J*!jy>>wHt?*@LXqX6Lru0|UzNolB8pOpf6C}s?=sI{TH*I45tI7N zrgIVq(-uuJ&hIA$VHAR*6cBfNIeNq{%kVfLJIpvNjJ&k@I4m*M8_?DbVUY zahc#q2PsYHLTi~P$(tieX)9W>?v!Lfmqdvxn5%QOl$FQeBiR$NHHXlB(gF91vGRr_ zBYUp0`82BaQWp*BQoyVWr^yl+;e_UTM-Q@6ZgnwoR%_LtTnzbs+u)X2-ND9y5ix;p%%Q0^hl6>!`f zk(g*5Znmb!M+!@%+Z~V-ethf~=^S#+rAC3x{xoR3;wql6W`EDoU6CxGmVYiQ)87Pc zJuOCyisRi-dl`^z{ft~`#?6+s8`@Sc{FA&%F6Z;$!{%xA6|@@?@MZJX6D%LO(CQT4 zW+$M{oU6l5EALDI83;c>N9<1c9RPSlCp45Tu95ThWUGEIa>xk$9Fs>s+H+REgm}C_ zM6*36P4c%{ZvJ1j*(>V_TGB7xTZ`?(MUShJxLaQ`_v@Jzf z0^Fv?{(m{)aQhN|HLDmH=3ZaVxiwrR%C0%BV&f@;P|jAejIO_Bn_E;7+8#G;4svWf z3Hjay{a#Lcyy05eeGD+VsrM{{Ua}iB39+N)QnMcRUylF|JC9#=!K%nEmQM#G8xNfXGowbZ z1z_OZZhM|nih^z%0prx_X8K;F1DG1k`z8zDr*Wy6V?kQs1t^);!;WlpZO>5gwj}d* zK3l4;Z%YO-!_k;Vl=i(e!a`F>v{43 zD92o=qLD^sBUprWlJjVPZrHr2clC``Xq`)^^V<5_gwE$0XtJs7al3SgIPj-IJaKNG;Tob{6kK#6TpmRlN)*zvWjZ7{DI2|5{@O zt?IRtHPMOHDNr}36uE+B8{ap#BPgu`_>T_N6;whe0W^XtRh*1L8s#q|iW(|A?!lnc z1Ys|TTW}wL&^Ky^;Xd{xuBKfva#W*0VFL^c@fESAXFU{>lqY^>R7}Q>YVU8fD9%&= z?HLOi?b1G3nbFxh^V*UPv9;WmB_@@A%sMSLHyU<)=+i#J_%qK!?VdOv0(HpguAbDY znzEjGbx091T+V9~^DRfx-qA7N(~5rA(~t7G`r>Qyn{RZ?W@^hCBHBz8IvKXDA9zLN zrM{hA!XpgSzH5Ke)gb_{7i~}_yq4xF7cnf?vGe&mA*_yL0GOeeQ_0ojYt*a<4HVyY z3}QtX8}h$WStC&ZgclQHW00py(|YS`QL9}lE4AhjW=O|?>8e0j1-7b5b;7`vgnhbs z1wJy)S&|OVdm1*d^ZmgT4-gGmYXju~=#dC5IsyyOZl32|M|UiT=mXco{C;J*uRA)F z4XqSST@L#%KLzWrJ9PwjDluaGHFqA*z+}ETA-pz=FL2$w%hpvvf4ELWOFg_hw-p{E zGd@R#8F~!tqu7#9R&4_;<}L)@7-jitk#3cg8V+)hIq`BMOVTxK|*+_!`tJ zyw*opKyfO^^ig$SGG^`ju;GgG zz>Ac5C#rD)(ud70&9KF6gL23=#PqPl33(6lYxX9}f($a?aX>N46dGHSUGrx{&-Lp4 z`(%c${zIz3&sJu+ZF#^)dOoS@usaY8(KHd(iR}m>$1A1f@ZJ(nGyrwnTy0&ex~wX( zywKoRDc*Q3D{?ixOzpuR2}vE+&i*V?M7`Xt;!oZ?`PwzPCkMsc`ckp%MyOlqC=WV^ zs}GJ2l-lYo@||LwR$e8CIF>37n;5&QMHfN+HZP;>vPW$OqrU4hN{Vor7GnQEsg7$p zJNYo0-dxim(sqzyEo6t^&Eu{ig~ZKhKH_S4dv>$}Z-7xFU>s^HFONV?Y>XzDD426E z>IqIs8N*a3D{H^24<$VJA1Vg{m({R~mImoJ7(K76HdhkaPUegz=G}!gaMI@}Co>GT zKxd7M_~ll}G;qCLmM>AX(Z43IW#z^<0A4U7w{7nqP&knhp!Z|(BG&Wl0FLOzu>3rspY5L(AG!qAh%D>VrJMTZmEq!ZeS_S0_n0aZb!}tbc>BHT2f>Gi0 z+N9ot@kDap=g_Ih5$l`z#eTevT!H5;fsL!-WnkJBQ6B7_94KX-W@R|wkV@x)6&EzH zu@vku0u^p?0fB4R44?_%CqIWYPK$^{yCfhbU(^T&TGFUBkWLe-W#OX13mSvDEuMrc zDxHJR!R!f-c>MMeWoiBIcL#p?<4huz3?%NLlRr;KkTa0PDo(RU$A%jE z!NO%g>-*Xx;N25#pREFu%??BuuwEicVwKCA7$n6_%NlZ)AD*(=WK!=wHZS)6RcZp# zOt5E0;m58$J`em^3aC#dkjcJB@!0MD?a=iLNBqeW(;Gb2o7q-h;bV2!{Cp3eP^8g<;R;46$F?YYA^SIpb9~n4$2`JO(2|LLEpTg^KG-K=6--|H*%o zf|69S6zZZO@MpQglO})myy(CR4*if7mlO*4UM=-ldJve6*>E1{J7rC{R<=wfRf01ZrEqIXn^QD>m~ zagdD{M^Vo`=%g9`b>!Ml@nnnWHNMRygZSJHjwi}-S%(ykXF(zUWud7PSg01NZdI(fXlHDI?16iPl*uauz1|BJ3sVF4@jb= zk)>oUx&RzUY7Kw$1W03SX9f{BC{TE!)PkHjN}oBCxJs%t?!6#u)cZ^Z6S_5tsCK)@ z!MG2f06GJ;CZk3ev~Y{2)5Dp-UI1Nn&lN&5OLCcB01ZD2{0NdtpBNb*ON(|j7VAjf zrMHnBZKlO7rv{97oOXS}_++MOqCPP9$F#36_$+iYdGj)K+4zByQKGbxdbq|3xsX*5 zu&@ zqhQEI7YG0^K+wN>urWfuF;elx@YE@wZ^c;R5+&*^2yGhw$iX=b4;qEA$nZWj-hsYi za^zqV(cQ4*!6%z8D6{JFv?-pyvxm~IebE~@m!A#Wqx%pP(efLEjn4}pf$qc{nV1BH z(PVd9Z%k>o{x4D3H)f{;E1HqZHv|A9N)9v|AShTAGQX!BiOK}%np06u59W|7@cK_+ zgGQ4O14eqSY=;;kgp}_i_$BtQRJ&4mP-FDrFXeIRVdrL-A`#15AEXsF#4UO8^mMw`bmP8#C3` zA73B!$B~K9_!OChvbzhnw{Ej`01?0hez6&jK)FcYWLZT}Kk~9H7|!%LTQZpKS&xJ( z4OvwueMvAIVIAN;Md6Hu!sOHWOi-yo7olDKn?#R>IaSlX>S}Xl$(J0u~EP(wochx^>iMd0YUI~-_s&LVw z#?^L0%mDCRr4X;UP!!U#-qv9HA6wu=5q>%gVvRU^reiG?x+-Dtb`*fT>*#_2p<4#K zBdVfG3JBhCpv6r{I>@h47q8#?60!v8{=@ z7KX(`%cRY{5Q1@Q%a#j+Uq^s-1c?1Rk7To!9tgfaHETe|vhOYZ<|Lr)15;uINB754 zW)W);mM3tET}Yu`u3`Hk)b?F^9{9hI!UCv1Al&)|xZyc=n2< zpp9LGYo1#`iN(X^P^{YG@Ux$8Jf0?VxX*Z9%;)Vm=C4992o&kQ>sjaaEPzqnqK|-H zQ#z|HCqRF1*LkIaC0uZzwk;!R*Lw9qCDhsZL4Pz=UXcwf>)CJ9EVw76YB-dPJSxnT zp9VPxPbn4<0Uyp~=-I;bqdYTcPV!pkF zI&&?20wm1cs~SyDRI$j+nbuuTfXpg8RaK_sO4DKIv65x}3^5~G+@>Y7R3i=r=tZqks)Cf2 z&&~DpNN6qtALw_GT;G=@kT?lB%Cso=mL$1V`XO>7x5~p?SCtcHZaM z@1k4?tuyXD;PuRK&oZ(neUMuz)&UU3?}~XHWyP28fi}}7=oC^aJf=!lwkF~rpa>c+ z>v%HGf}}2_5@QWYn1c2d`XwuY!SOg{(wARFLGE^D?v6bdc=wNyi6BtliBp^|M=zz5=N zmWZ2qBwS8lO$^}b9KTwCbP!6TCHRaM#u=(S z?>&bQUo&3MlTW<>j}vO=W2oT~T)P!p7&h5<(%wZ4q_?%jx~RI)Z>q|lWE>iBY!fdB zaLok3maP96*{??I3A6L<*N=o(#ZLj0n!K<_9^fjG50FB74MtE6x=kn#psiz?ATcva zLE+0|xz^|M8Z{(6d`vAe!q>L02`o4xOJ$PmwlQxo1LhQ-d2ymX%s6#VYurXAheJk` zSDWosdvKI!f|Oy%yy{#b4I1E{KJOl?+P3R-+~zu zVncC;9^{p|RmOqX*T|*7JMo?4H5_Orb(wLv*wRkI#|LBrs4fBL<*9|vKV8NlXU!xb zHaeMbYc^@&mELzm)fmGsfspn<=tP{e?W(u=-&<=hFxAH^kP{M{v!}*lg(LnIm4ew1gv1}{1V0+0 zmm8xAU6p*nqYxUC(u6~42-hgPnn{NUIEL_B>cEe&UP{6YN(W~T;Gx(!Y>!Zz^q$oW zi+|ZWDk*!z21sjg$egzN>%t?1cI~0lxw}a=Wt4Q~No3y9S;hC)&ad%|L~Dtmc3%YK zMJu2ww1C`FI`~KcV2feHPbP7}Z<^D_l74Czk}H+bWOYs)`_&&uYI|rX(>#%AqFQpn z?z50C3hiOw+?0M{1&-LD8FSVfKlVuckbv~&^&3n1!u;6HA#;@-Kf2M9h!Kp=Rs=6@ zhIWoQwcFw;7qJK6i+C~PCfIrqCvc^LRmYJjcWz8(xyrj2ZFd8~=`yqLL|)8eGb}e& z?Hhv(bpUlb5+~+;UZdKaui9gZRE{AIA3jWs)o67uDwl$Bz_urm)r0|W(#N&BE}@p+ zB$$2TsD$ph=KqHeFl?3{Lwx;SeNf*P5W$ULTVtu^#U6*nrA08_rWDzLzL~7WN@Q@jm&1*RgQzpA!|Ji2r^~Z&x$y3Hd_(bLu8+0r zitg4sPPLNlge!I=Vi;<50f4G+21FtQM^EfpWmg54Sbh`dgPMR|k|SG%Dp7Kk6yCWi z<|<_L)2_ZYBj&q~f`mes6PeS?|5!HC0$uq>-c>I-$4#wzYFYna+P^pXDB9O3_DbC01Ftb}xwslQLIV1re^xSCf2d0NtiYb~RRcYS38ItytBbczbkAlgA?xBN<6V@45o9GMqdU$4U-#3kFtEyeBE7zk0b z5o%x=fbQ&HmYTGgMd@RKF+V^iQp`FH<13@6Y(uyOLZ~&rDqTYIMX7FXH9vPHRQ!7O zs6*NFnZ@xSv{{|jscD`7T93tj)9Y<_s=&)e#T=w1kLf0h%w#;X5(@so+dv7}-4{(@ zXReXuQQsG=3FW=#J7E)|ZjF|KysBr1{HPjd$yqj!#@y72?xb>Tr(fvPZ8Ou-jAM8_ z-wyEV_jk(mBY;!Ag19EbQ$VOF=YzlUyUzPwG6&r`okVWIZn|Mo5)Z5$5$5xR?+ygQ zmY#wK*d-Z)C75*RZ3bFO6c8HotYp??9O{-k6K-)us%TNFGgU9vLJ(t*MjeiyYR=t*eZ#y2InvE<8DU(PjTM$^DUE@e zZb{JD$JVMxu^`k~P1-O25+<&!tJ=^@%zaS@2>m*%A8lr}`4nJ^kr#oS=~rzTmZ6HP z?S+bqT7()|tHxA!Ue*R63e9_zfcREfET&sXQHz0-kX|K)f+lzeyfV=^TgNfUqF>C` zs85YMR!~xzrpud5&7j7EL$8?ZTEDRMyhCFo>3-}b9Q1ZmjMuf{@1t8T;qN=WhgKz1 z>;h{d_|p4khPa?&5ln`!Ic5-9a3XeD*Mg<+?%rM4xl4FnDyot=GWk{GzXX~d=A{3;2M%k+sc<5#DpT#!sYvXUai9vV* z;aLc(PN4)F9Fin{28rWJYf#^ocnreC~^an!ZwNHB!zb$|{*tUtx51i%_bqF#1(zt65(x zQ)$LKb4c?K1f#75XnuI5LIP?qX~F5a3KQdmiTpwBop0sxE_J~194QCW$Ue=L01)sh z)Jg@e$RJNbWeMDBtdCc%9CbDZw9I~w;*NA;tNr#~W+U*L+@%w=<>)gN9t%>Mx;qAn zC=-_)kx95HC<54CX^zl2y(Kh~(29n-ddO%{#&kDr^;UoRxAE@~Y^8WDn)GXl7s}$; z;Gs(N>ar<=s$l|fhNdo;4dkp0u;(XBwp<i+~gkXn#sLnQvU7mQT9p}EhPQxRnC6zX6@~uqV`ecH|VX5JJ5Zr`|vPECz(tG z&p|)BHp7I>WfwE8mno5vbbZpZSq;nuv`>tAju8?N(}II5p{B_ zh_@+7W$-7FVFS%aZMMZlG-AC}pCgtM=nA51DPMS4vJ(@F^yKkylS$&S?uBfiSUZ%% z&z7?@tIY7MTV^iN+fYQ^nqrojaXmej?3UVrPWRa1dlWZkp4#A!2oc<*``dNzs`G+t zYBubC%%FQ5t{M*9b`y+%uIbW<>SH2m_!Vf_Ns5f zLsL-Quyn4E1Tw*Z07-R?d4Kz#9&1qCCTQ%TCI*_a$jvn&F3UJM`YNU(iS^s7>2!cn zl_$jf$>Pcq>eO>S_o9-KGY&jP4N2K>zkXu07h)*P1ppmSS5zEB7O#9U@eq3=#)ZRb zW|S-GldbrTSY5NG+XOk|s%qgS6nK*({19Bsohjeyn^QwCB**GLvK56K;G+pC4>ceD zCD{X=du((5=8_b8F;)B`k_Redo;dGV+1R@YbpHHsfgZfbDf=lzivZoz?h=Lj4oXo2 zFw;h96vT`o?aCBF$YM;L?{P0q(00W=k4=5&!Ue@?;87RtCb)ES)UZ)YF+suyHPuUT zy7aWn?ecYlM}SmNRDeP80L59gfCHDGV&tB$a)la*8LK52mVDepQE|`p14YTJ8Am5*s3Ks$jduifps8$$A))b2 zz;ixDGnUgBdR6l@OYJ{{=D^Sq3kX`7#G*QnHW#{_kti)ZsAYeUT%QSj8t)NqREg1_ zUn%@(LuiR-Loolyz>$;HgT*)%G>0C9v3@VxgZ(B{#fw;dJ4pCn(Re}RqVnx1I3>AE z97SAM=CUVx4U`R$fhakD*K_k(BmkI^EP-}%q6RZ?w(uf&DV7oA*nTisiF^>CP@%{u zQ=2aMv}&KZ5@cwa{l#|HP?GC@@)r^Of-PW#g}S>IQ0gV2YTjKiS?z6ceMvFZ=m4~`W@tusuV;@I!$i@MG2qs#MSPr>bT za^HP*k+ow(wReVbPGM6wndq@cllRRtEuM8|O2xZ}hi^#swc0*IJ9dJ9?0aq5xuEOV z3{anXS<@23^keJ4p>SmES^nlMRqKcf;8A!de6|PaLskO< z4j5O$Co5FZodK14n7^JUO_2lq#BNpT^WggV!$-vLdp?%ZK(eW=sKqOl_fySJLiuzP zoL!>Xr$Es{eJp5ux;a7ITD_2meqF^ZVwf}rFT>tvr%(#6;oT=q#RZck<|(8Zd!(nNHBhQU)92mYeoj5Xu6aM8Z8q7M@2JTE1q%2BP{M-NG4sly>D zt2EPQuGq)onb+a*W31TV8*?ATs8L_?iN*YGwugn@PtoPdd4hGQL$8l(7vbf)BV%+2 z#dLU{3w+*8l@`AwWnMb#ps2$h;~g7|BewF+jpNy?&+wl?`<-J41fJ!2Oj?`j$?tOZ zl%4iAdGxZK1=pL4x`KVQ!17jiqPY9AUj}B%+)`-dVh1*q7Gy$hWtY)(iK|;efPYuO zyxstlbs!pRybYsEOGM5-wIcu2`>$!#_M2MYp-fGAcU;f2@(wJ^3P*Sfsh{B;6-vbw>0V z8?X)ogBq+-Sgc6gJ$OZNC|dYcM~smKz@`Ut@{JTuC!FPenjFD8EcV-g%af7>CF{$nJz==blmsL4x5Qr`oF`&#ipu&t~Df zebMitxezEA8fyh?r0bheve^zBzv*WkRLNZ*92BA|b0z^&hl`F+U;y<&u)2~Ie*lEV z-df!G)#ngh%KSv2G{x;}QFxBh45&i+G7HP_Ul{94mJGi+lZ8<_(){y2N zBb7%PoI~*?M?4@w$zp3&63wo)6CXnZIgrK)(E6^#WLyi7C=cUnicnWei=#nlv-8d&7 zkI5UBOQ=L|!rF(uiZa8>ui!0m)(a*G;NtUSIQQWu(K`OA6Nt3)ln$pVE{{ij3HlZ? zb5k9;u848l&##jSL5M}5F7*mVP(YUWT&HHCtWLD5`p2S`*(%DGJMyP7upcE%S2QBN zlXNM(t$ULC#vXNWN_%JfzN9rQFAtTrBJ2B^^6K2#B3(cH4MM7>!Jx7Y3SxGZ>$5Xb zORPDg;$fB!56!d|JKlp1Hf+7zWkeNiUEd7EUl!{@k%0Qw8LO*iq+9Dwpqjs7;*8NB z%iAq^_<`m>KA9%;Bp=}kLjVe}#B2e3rHVzGb54#&K|K2drEMAqh?a6kMiZ|GA6b+{M<)sKW%S~n; z6)V5^y1X+ILX#lrESDJZ@W8tFjbHwt8F6@0XqHz!K?n-8Kc1B@l%k5v?YM^3I1=TF zBzu%wwe<>@!FRQdZb2BsI}s&&r}-o&VI92Gj7Acf@!Ge-=&;lTz4(!(OcxGMJ~Zu6 z&y4Z&4thsAts0G_^aJ+rqRgtoMfc&&f>Qw!8v-e?|HHS0d=9#39UldUpP#m-|Jrw= zgLguU*N1|YD!w<*B;s<9sc7EqP01&vCA$FX+{r9Fvog|iRJth!a|#%<9YV)`9JXy> zo^8$|XtQAy=H+d!)gh7jTp4!=3n*E4ov`s`t@V9aP3Kv31Qba{r;kTqJLNWPYR3nf zhZ%YpkJBGPM0KNbt_#`Skfm|05A4y7jQkk*vR=c2m<?5Lj!0V zkARPjM2rZ}lPY8FuD!N`qxCjj&=OnBm>UTkO2~Dm^8Pu3>;T9GYC+a_9!@JS@-KxrOycM~JCj@> zcP?1Mbhw(eac3R&aa<>!s@7U}7P>v(;mC?ZJm)k0Recb2VQ67J{^vMo?`oHGb96@C zP9=d_#)=wj5}nSTc$67XUjK(Y_E@a~><)yng%DIsiZmjgc86M(<3VX(-CGVW zh&sa{oShneZ>$M<=_O-~6bAWq`)w{gpPvktPVE2)P(mnzNuDxtv&cTEZKU9pzb>?| z%c(NvjNY7DaVU1iGk(Ttk2uTSAU+CDcTupG(uTbGe6$AZ{T(Ag-Gu`R-^v2rK0u|; zv_7@6Qj1K0^N`w^fAQrEou#G?Thm*g6Ge0#?gEX z&^0+|HmQL-iQy-(_I^R@C=goHx_U=5cQ8~l`Yl62Xm10o6U(VN*VW5AsKm`n&M?Im z9=Z;_{Nazi9GP9%m4XPmZ2KGSo?(nxBjQy`l35nMtBT#RX zGrD_8Tm2_{9!)Ai*zEaa#Yfc-0g~Ns1f0oGgIh2}NY5aEFYpN=$BBoM$mV@TYbTtz zxSo7~?itU6Ny~~+pA2r3#42q1>=#EDRW(wyySQz(`0EPWPbL7+fV^J$xiAeSMmeCM z#NHEioHzJz(%mjW)5YW~auhEmk6{d6;m-Pj$O1NRofaUFa9oB*uPfI1@G__cB7)yLdlpo={Q>TFq4#;O<%mq`D z;HTjg8+^g26}o_;IoFJc?)2D%aWg3FEqbymp~XdmGq+2k%QEq{vr47mwH&!OK1(Ys5X;d zGy4rAhx2{z#-xTs2tt7+<3n@3m5Fs?NG_k3xEkHlE~bQS#fR8W{+L|Mz6c zw_SupqkI5(h4oG}!@ZPfHX7WRH7z`JiDXPgunQLboD=*T>Fi|ZBU5*e4_QjU)9mFg zGp}J=3h(aA1-)7jFIVE!Enf^tk`g;N`=t{oE9yyESu$NdtO-fu;PTS5;1`Um{ca05g<0(I?p9ukkR zRj;N!2EE3ETyB8gyp#Ar?!-7`TZoTwY*f4(@x=1IW1Q|^ zxdV3gWTk=xwnu6JgNPAO@$ucE2=F!HkA)?@+X+2reUh;G{PBpk_P%H7ngvcIR$ z_L_8tDyd4D5XDmYJ;VI-phD2gHif*$46x#f&lIJ|*}0Q0#5>W94(nLnSFX<+>>ia| zx$|17YUrGuv-V|r2dhGr)$fZI-x>uO7apjW3;{w=?2;S?IaiYd@@XS#p0DZjziiq8 zl|^JCjZCF&L;n_Kg5q5es{p}`HfS#J{DTYj&m?&Ue$@b+cE0D0{ z&CkimzRhPp7&G7(zut~_!BG+uO2(eiWdF`mbGfP<))4UQLTukLu3p8(hgeb{2;gi<0l-^yF6vxu$q_;W%o!HKkwvt6g6)))Gv_5ppY_4-bV3??z>W^x7 zQie5?p zwlfFRkqtf1wQn!WfwWQ(cC!j51@?-lqU%Gcc_P5&Hirs@wN=D2YQS8D~cB zU<+IaIk}91rnDnwhK65-ZD2W9{#pD|!!n@$AXpyWY;rG1#{2XX)<9ZMG`Adzzt!q! zVQtO57tm|hSDFxSujKwSNW*J}loDw5561@H32}R+bZuLPi67P{7>PbWdtKuamGU6# zMkVQ-Waok_6CLLG?UxHi7Ir0NRj1l1V)Mw(BxW=2t>J!FoABk2I?jBRD{wvTeoaInLRz=ZD!U5v9sFV^16qDsm}WkBabKQrE#6PI8geQJiC{kn=PbfS>|YY6d4ES8rx@~e3t3Jg$mVwv zSrPGZ;Z7n)FmtOA-v^tMf_MQpjCnSg&sDR9o(q87J{}ha=;}2I|A3+|Wv){(|MIRt zEr#FG+d~g0J!SWyha3{jm6Glk`_~C@2>h#|9J1-R_l4%Aw7U;Lr^L8UWKh7-&xQDi z^RU>Dn~)yjgH1sBmo>x@f2(7(=Lbn-h{ulO124BJnLl0shx+)>qc(iUmtK}a(GRF% zq<{6Fq<-(D3Iwc|gruKRU(0uZy*#DGWq_|gc#bua{Y$!>0C#q7AnldlZcNONPp%AW z8W)OKOTmESN{eA(^9Xw)?z^nO2o*_S+V@#DAM^h9GGvb#qJm+j)$!_FvRo3o=!2;e z{}!AO^tt@-K1uO(d>m3n)RA(n5^e9*6=%bl7qO&y zZE;bdQn!cV0kHp81E_oq+ z&cK5kW%H%27V67r-q_SVq1FqcXAZQ<6yA`I6YnpXMb(ZI0IU%_AvEw^&TY!^{lPgg7;wqU(oa_hq$@ z?>;pwk{O~WM6>7@Qk^&g75fLMzV-<>V>q_nEfK{iX{U#Px%j&2HrdPvZ^va6c=bZ! zQ1Zf#P{$Gu3cNS5tK>iH6gnzZ){=iV4$YKR6aGK}no0f?-&Pq)3E0lviSG!V>wx6_ zI<Ms_tu*V4a5PPNF|& zelv*grIAiU>mkvtQ^705=EuB0Pf|C9i-zF$$q$*GW}?bZagte4V^hPQ?Bn>fCtLFg0gR407jCMGap z+;wZ;0EL3GfO`5)d7FA)cE>P#bX`*wigM3WYk7rwX_$K;16&p8DEkBYA-bawa+h4w z4=$#Mpewxr$#^;HT^$oX?}4B&?eKXzAI;&_9a4`C&iyMGJ63#P$0LUhf=xy=vf%~h z58yIM9{9^l;N-Qw_vq37K1I|_92%pc>;f#IsER%I7ooOQr-spEt<3o#7y?AD8yqs@m8&L7|<2YnHr6q{Q(1?{^BvxP44sNRVO?qxD?^ z55(3ZI~HqfqX-Q7$U-CL2Icw`EN6s8Kr{6yw)GhV{>btp)xYRo4`>#Y=guprw0Sum z&>N+=1P_hiXC`e=&fB8CxYsDdr{4WY)|y*hmj=O%ShOQiY$2 z@-cr{RYP%Vm4tHLTiPzIs+(uFV{*(~)Hh0}P?H$_{%I+LOu@g zzD{32hy~+0k22Kn|5|JmluXOmg3}EkN@};dN)05%D>EsMEgp~C{e=$Y9K1nWkSrC^ zv5URn7s&e}pe{71(Ie?egsu#AzVdIQ`esVxz@JhJwtB7|WhcshQFq<{jMS9gF3+sE zmJ9{pKsyb%PbLB)%LpeIeRl(i)3?n_2+xE`sp=rz{9)`ZIL$*2nP1*0&`pNZnW5aX zSnl(3`ynzxs{ISI;6aC2mJtN^nE7w`yvNWUOJRS69n>)B2Fc7aqRMxYp#vt>pFnVK zaDJ)O=tuZnhQcP~?BUpnuGf%_o8uVmS*W+L98^Same<-l1p$-8jOC^tlQ%*{m@`i|&Fn4fy1nRk5}E?4)JM;->Y&)K3_?>1g}L^N z(opM@1T+zRXOFbjJa;e}WSYm>n5r%Oq&c+3IJAaJK=!RHT?}I@SIC2^kmG3CA+rv_ zKrnjMWE;=|`(&jCI>4fUQLEV6Ani8_v7nglHfEH)nNagCmNFY30z(EEewtB>Zdhs} zXt3j~R+YHr#Kd1I#iXe{HxU8tb<_US$&3^#d^{Z#DB*A_SVodg3v}P+^$hylNrnVw zf+7BpAX2A*dl~Tw%kkgM28z&oe|m`!dOS3l;5_3d9V`XW^NV(u%_(4425nSi7?Y zCQvxZh)$%H!&h5#Z0!sb01HIb5bv9Xq&Y0OYfrm;44$Ixf5w;x5YAjH8r4f=t(rLr zQuEt&bwBO^t}_XVyc3`nZ+>?jN@`Ao@;-AK2vV7Tg9h_>3kYJY1husyjGvBLiEEa2 z^FaN0Gz)S`d>#hmI{Ix4FJ4d?dJqgRjD|cu->DUa<2w|b#p0MleXE_Z5Hh>E+s9)w z9n{rS>B>S|8XgyC1d^=#3D;ZrA{MDC>6SwYxGIFZ9XuA$d9fdgDbxNi;Tw8Vk69i{ zV$;zXB{<;>3mPi-TNk3iw0-ZosHUaj%?xn}lp5~? zuo1ExKun$f`Kbgj=>x7xdTF!DHe~eR0gApUK4H=Fg3VVsFM_xvAxIhW1o`Z%*54Y1TE2 z&isISfv?qGT5-NE#}mwd&k4SID#Vjvly{#`J+bnKwlXSB{78E{nImu4?93hR44O)T zkZT42GEItwwuAiMR>2NW*}dfX>P!(zAQn@Shp3Xt(V>H09tt#JNJd*<4C2e*Z6tJ+ zo|+?IxT~ZwU#JJ2|G5(BF=G>KwDUldCO$?p%!2Tj|Fflwt|cy6y;*(c!i>}OC$Tux zlz);|W0fT9F;SERMBQi#PB>C(=sg(&Zm+Utai;gujbj4$xS9TWeN}*O`MkFmQZKzf zdVi0?-f;`%H2q#b@wY?^Kti}`@p-@sYfOTA51S#X7aa8 zU1yA7wsz&9g=fc`s=ejn1+dSYWVc8|xs540PbCNwiU+&zB`j3MZ1B2GI zd{~KNFH7!X#U<-#)FPnE`6blDVI0$*bAQqR=&SJ)6i>$#4qC0ba&*;81k!Z)=>}E& z{+;zvgK1j^#X50D2MJk9eb08SzWv*Rhav$Y>UL#}>kSLGks2F6lP5Nx|IFsiUJ>L= zCP%5v6M$Er^$D{td{O%;88~fC`>E`FBVGoIt5{=)psaGe=sTILk9(fZf%%H}u8<8E zC`5TsPvQe5vBG~nuxtiZlS@;+aw_rP@QQf1v`1gsEim9}wThx9r*9-vc2*}LppDJZ zWTrmE2f<`Or(j={ycrO!duo<p_-?$YT3jz{^F5px08GU6Pur4$UlHdYj{N(ZCzn>P z)i{fQQ|>Bs6}kqF6}^6WsRb9`3&cW3fl?Vgr*>9Qmbu1z%U|%?JVairS^bi0$M?_B=($-mZLcnqV6Peu&cI@`M-0ozW8iO@u@^z@_po1s>(KHYIu#RhGv)>9!1 zPcT`8(Z~gFqL|&a|^y11Spy@f!*^=e4kgI_!g~t znqd?#2z8kVJZMA?bPiw+(p31D6&h^j5FG(g=ehjV8h-3>xrTHu53VZtwlI^NU@zWc ztdsp~jE-l(eW4N0E(wLa+8G2TOCtN2yLeV9!TWu(5FGx5d8Ep^UfIB^f0)$n7(hSm zGLWM7<*(~DfdLq}m;`P_-}Od1Cy%Gpj70E=EaGnz(fFAFJc?a1fu!}MfKnLN=uIW@ zC_fkpjBRY=jAc6xAvTsVQ+=ErzS-JhC+IR1oSU zNg2h9up3QDyi@Bd?rlzU$|CP2kfZu(;nJl~TU!mWR!RbvkquciId8@omG5 z`tDEuH!hj&oYxMf$Y?}%MHzcSCdfUetrYK62hbJv?5pP$XX??K;X{0|6*{zRLPwDo zsVcECS@ML+(8Cz;o{MNgMF+zexJK`2HgmGzGmcGS1hxRVri~^btv5Njhe)Jp$NMTa z4@yoeE_GUOh3d2oPceVnQ8;%Kht*}iDA%ygT=8BubyGC*P9%l`seD3T4&2b{n49Am zz|CldGuPSMXQ09Ac@9zDjt)_R&`aP};2@9~7$vD(4nr-jUHCwCUlbChQGoh&E?)v{QtgD8;IOPz1 zf-ld%d`;6^yhW;&5l8Coyr6uW13R=g3G^_he>`83EwjI{B-eo1OXcMJB-fijS#4Yz z3B!3bW~8+Aw@R-_5QwI6*8$pM2VUPmjgmH~EvTt7ufO&4gYnP7$0j?P+M{k!xh|gd zjy+{H#u=iYg($zIQA`a$P*-|9m~|xsUGWv46-|^O87)f(bac76Kx0?Z`bEA_*n2eM z{UNYiCXoZ3d4@H15-#xchZ?l^bwdNH3YKHT9TpqUk8D6%oFwb>*ppKjrZgK>DV!L5y!&&Rj4Iu0aIn!5l<47 z+?=g#RKwI|icJn$C^b?@o7oO16ujQkee7{C&Kmv6iG6H! zJU6o4s;?L-QvwF?fTBY(gMY3cdI8=*{pRKLAPS;C?qcNJJvXM)9#t|%{(*G%LzSpt zb}eUQaxL?_Pd=>7qX-3@xm{Q5524=iUh1mZL7P={&HfNHF@7@c?+=-utg5OsJOraW zn4~ghLeXT!bvJ_TECAP`w(prumYjjrk902@b!qLm$N{QTp;?mlcgrbR1HN?gY(SoJ4)^~_D9=WtR3;seS8 z91BoFolnWNa&+Svjj9eJN?k7gCN&t9M9>ef?q;DXjl_ohMFHSjCc#Za;^9&sTPc#C zMmeS3)5+J&_j%ZMjc29PyJ2EN!SOq>j^*1>GA_76m^yd<*nsGZKob-&_=KICpYyth z<{j`Hk`0rwY1I!1^3p|RBE_A*J}$%;CF#?0D|jYpEp zJ;+Wf7#L3mCH@&A2iOW)c(1yeyJR2THkY{0eRgx#c}BK zaJgO0WLd8Ixg&Uwut#Sf;3hZqOK#Lx(rbky?I{+*MwgF zsppD^iycwJ^;3_>apihg1@e^PBdm{FUiBw^#2TpBH57L4HTj|LPc+{DcvC^f^F?j^ z0q|c;m)ls1M!#JK>ZfS9Ekd1nsy;>hV@29ehlldZ@hJ87a%xsDxzu~6v3arkByyfI zO&D+_wPe4)t5XlC@yDs)$-&>v+eRt-5LI76yx!*yK7DMgo~TS`%WVxeRmBeanl}EnG+NRcG4BV#nYY?8^H; z{YpJiK!StR$jx&~A|~4^uOE=^;VKNxrn*zEAv%pt8H240uzdrR%z+cUnztpg=v;J^ z?4vin`;u4ljZa%N^^d8ty3zc5=|hO4wh$B&CxEz<7M1B3-R z6epS1fS~*R@5w=wv~)UnnLeM&y0RyV@e?D_`?o~KC}#y$tFZ_pJpTtt)m5j^*Si=y zNgtJ5oGy(%=QFh6XW3Q%k*pwC_4e(nP%?gi&^A&=?w9o{A?kZ>8tJ)13))Rerr9IV za;r74N%&REBmg;u>yG}I++bN{Yq^H`E^uZQz}X5TO)L`iE=$z9LV+Fhe}D!GSBfVr zmgOXO^Hg#x4!x4Q2EJ9o4B{K*t@38d%)aZ1j3^Fy0@%zfEDV^%HKIcP4IY3R8^W%w zWhqr7jlnW~e&*qJ^G`R8mq6P1{8phSGtIc6go#v6&y6dEk-^=pS@abSy+TkiDYP}a zHiny=JN7N-x^F>OVpnlgoMHx{>}Z!{-a=v`P*^)f!Es5k(l}*+L;S#p9z(Cz>gJCbSEH`h6SUD_sFH1Ep0S1x& zoOaEi#8xEf&|Kn>rhG%rIwDrZ5x3sqI2rMXJPKAkowjp z+t6`sID8vfR-YQtj1F=chM0oHx(nqT9j^?X&=t9d@t)r{0>%0Pu4xpF==z z+Q(Ngh&4+o9JG!VM}Pc)@rr_P-$cNf!th4axw+6wl3IQI9H>g{J(xwrq<}JG-F6)w zN?QHa<6q(23bcF3N@%&7?fW_<6Ki2!q2uSG+mj{Qx@(6wGcpO+W2wTR??%Yi+m;)T z!-`0Ka2%PrDmd>|iv5nNeZ%pi%nNnSgUt+nh#0(wTRZj6>o zru#e=XG^05{fW$xugnNLrb{luV-$ZdDtMAw;MbQQ9QR1x`oI-xGQ>h;We`SAGGoI( z5jQS91prpN zokagZpVJnA5ZiQF@JP1Q6&nP8Zn^0AQ5cL4NO6094_=my1iInP&uAZ4t6ojYQzuk{ zV%;=&w69fBpL~4@9xA%##7?>=>NocAGSj5n-YGsn+S%JJ1j&@4O7Qoo2%$%^?lBYn zv)m-Lwjj+=TwN3%z;sc0M2|G#00cT7WI}Z?ppzK8#L#a6xug{O?=$V%DOYH7ytRWl zjH&PmYle@bX_4dLSo)Nz{!XwzC2n?q`7G~JvU3{t{{iRbYPvFR%|rnC2y0l> z<`-Zvc7Q^4&HV}FkIMfS1n~T(09=yySxrw(t?oK?E^JX-m;wA^#5FYNUf} zCNGnPoSWW}(Cd1*cyR7A%KLl?hN)7EhVH*#o0P=RHv)bI?Wm9bGunv6jmui~O?6|r zzZ~tg9@(Ri^sox+ElqAUyo!onee7Oq3bNiO?TSaA2~E0niK}(Md%Dm!%oYml@Yu4> z^t(Q9?L_itlX8GY-)M2M0uksZ2cZU@ad%n0nWOTYmoa&JIYTn)9)$gk(QvS7inR4)9z#4SlW8l4`cMVPW4OjU z8LHAgH)#SsXTqJ>?j4t47w96XmELLFKNiihta>?G>UA#8nZnPXQhgp$GFjE+u%u5C z-fh^0Rn5UrPw$j<7zg5cga$*F(3^smsHtUkhb36XD)z19Jd(YzkJZSB*02OED9SzC zIXjM6+-`}q-itUrSGp%R(T z&r|qaVYB(X`?r6#06~HbHl$aT#A=^u2W5vRQR!=^@PKQa!3e#^&H${cN|_u1&bPKp zi6zE=el@=3qGgvWLhZ& zHAauZ5KWqA`AhW!W*ssp(b!h)cOX-xR>Jjy-N~9_Gl|RNHy|DSae)HFy((Aj*}t{s z@?U?sKd1LA0E4OGD^AkuKI`E9b2!(KQfoy4>7y)Dtid>RSY@k* z*W&M53nLmP8-;3F7Nh{^@lM02tlPkC4-IgZ>h6;}Q$7NprMNAiuy$c%!=K3HIW@}t z@p*g#BqG&N=9gnXVc2cE;dp&e!YU{-D4qn+kav(<;=IF~KIpTDVJK}rVl66R)D#sP zBm#zC(+GxHYJkmgD#vG!kEW{md9(S{GMkDvBsht`_-|} zq2Gp7uxbP~KyHY@b$_82@fCjb%;9~`uJY6=u0Ij#>ELr?>t9!?6*oMv51n&z*AY*A6Y>@pev7=jR5Qr+EdEjO+SbX-3rL*rb2`fBFSfsM*-q~GTcB#LgntFS2D~5j7 zA)Y8Zk6`&S={d9pgAsxpGc&Db;-YU`dK8DcL0+9u)cvcM?3By7Ut;j~Mq_ z(=-p6;9+QV0Z|H=PqnPqJLjs*tTFZ3Ew4?;jXjqJQyd2r9bnG1j6jgHO!Zape?~yQ zyl&GFxfX>x(h~RlIK}FooJiH)mQ?Si{T_kDIqOpv)XY8V4pbHqIann8G(Pb6%(}G< z+KXQq08cGV*6oCH+jR<6we@8uOOS8z35g!HkBTzqO)MN$t3O5z;Ry%wUJ27jg8EnpBRU14J$`HG3vps|YN-HuZr0F-wQftD69`toLPU;PkQJ3K>Qt=A`onjLJsQ-!q}(Eckask#FXT{rrxJfyo!ID@kfZs*@g|>m zG5i;#3d|y_K`*~g2C{|F!c{4=5{7~C==F`^FRKV1TJ%aOi`j`ZAQ zv)$&1R{N->^e@r!xj!3}qgSxeos!FuN?4;@pX@2FMle>gIeVad$hCH62l<+yHR;r& zyA^9|O;>B)vFqF=;^|&2>vCGdQOKHVv$!c&2*Y7qB2$Z0cgp*hq zuzhX|UpMf=LmtHMddbVURPLy2oemp_KSmNJz8@w6Z}CxHN%$`Me%qfqnJyv^TXw%R ztKw3;fzkaiI02=02YO)%!f>{ItfO1hi9fP_TS|1N=z#6hcS@@I{q*s)b(=~K8|lh+ zHWB9u0&AqD_F3MoC4&Nf^uf1hGt>h#!Ka^*|L1;L9Q6JHr?P`YAwh$d>7b)ua=14)+>d4;Ev~00afWasdUbo4qH;c9q9$`uXTcHnOlu?H1 z!Dx!QMw%TAUy+9Rc?VFf=Pr_Eey`DlqnXa41LOaGK{EpcB*a8u5h`)<8N|;#Np3?4 zrL~ZVj;LVNgj1&|YV&$^JYaYoL?@DX-=qsk5xckaJkub_ z21widI1wV}(D(C+L+6u_x=1xd(NQ7Q(e;!vykXdZ-8p9n7PCr`Bw8s;1RM+2!;IYm zaGqsBgWVJWeNVmnMgV~HtDc-2*=^Tf&ask=9Acd()G0o*o+fofNl4*WaNi7Z+dn#^ z+1eQI4P(FlT7Q#$6@JUibIQ2Dj44DX);>%YfUcr&Cmqh^B0tMg3dnG_WU^pxc7zeN z#pbJ;ag3#u5x~SWD1FS3rpT}V=tbx_fki3q+(ZNjFxbYX3M)+fl&(!{;y`B|Vv-m~ za;wsrxhBi1XpY!Oj&qv3xSup}kYeP!vf%jK*;YUcD&UaIL>$c->Df7p(tkmK#53r? zFfhtjyNAIWGC$#~MbH0IU(hEjtg5lGG(+MMWesd;)Ob7v-J&`0Q^K<^Y>eRnPf+#Z zO`N#FNTKC4VdrqKZ7xF3S`;;??2_;(8$mV}Gq=Q&>|5K%z>BRh0J;S|QBaH2o}fR9 zzY|~dW~t%h0B);JXMBPki7Y#Cw+B1wQp$iQmzA{#1Qb+^2O8gVdETvIA=hB(EYjKR zO-#+d@8Irz_TZR*HY-@<-}z+=euGl;Ikz;AJv{9*%Dh+V0mCr@+jm^R^?Yx`Ru1i-78)7`rUz=Fu0n zC#-_5|4y~m+eKd{%cqaE`MRFm=lmQh8#A&}&NRnnQ!QYijNiiN)FL(eB-C zf*OEbR*-PDZ1@)~ICd)YWbXcM_oJo8Q!)hk(w!e25RQT1y^r>HPVh!5tWa)D4r``S z^!K#Kvw2iaioKaCtbzSB^Z)X|c`?{|a&I8Xlq&R8(6e9hg&swje|L*!;D#HgZP)9d zG2l%m!6)<#73qP_p|Kb4{zCf}syptA5lTPy53M$G#?T3QMW^=w?*K-^^d(Uy-mfWG z51VPd@xZU66zSbE?2_Y-awz9cW&;fFEi=)8--vK0NADmhOrFYULJb27?XW@iyGM4< zj`=*shPe&7_-mgYL_~3C=L18qFmDN*nj|RG2!bs0^u~P;lnId!`3wCzsm~;>=MMds z{e(*s?1catilKu*m3#j@bph=l8;)1KF2bv`>jBsjyCqXl))eS;jMHscGp}f70pya- z_QuHy;Ibqi$7#PwfV}{oOww8W_`zb~(u1VeaSxYmXJUWNkP(HI%5HI%v12L=P^-Gs z39FIPegiduL`XkSvAG-pskXsjVjX8s)sa6aYte#`BjJjHpbJc$+5Ve3HXO&Gn98|S znW5@=O^1|SOD5r7-}tL%xHsFYhu~Myh75XQpP>W88phbq3dw~tOS-$?TIa|2g|{g@ ztV=@ydKTVt4tS;7(Hj+}W=9$}iEYyD>vpxS3ny}wH5uO9ipYmsYJ#}rtM~EBK}VJ6 z{*}27DSqtuR%z*GIjIhqA~8*GfED-mN(v!9c~h_xoRYa+n%gy?cNc zSih~b`?{KJxtlM#kc0poU!!&_AUWs~6pw%bd!S&P$OsWhj|qk2;L}KSK4M{^OTU3A zVkWMy0)Vz%-0Kz{`)V{)DefadG7a(fxyhyJNXfvWU03Vm>M&>yO3(j_KH}>t`qU?8 zCzNHTtu`WgPKR@IZUIb#xILA>m`L=d_Oq)smxhe}#{fVY{^(#5-Xb9)zEj`96_Cd-kx5#er3BfLM=?rDxQ{#z=*P4XMU_EIH|6Q#fU%ef%ZM3p-Fkk7|u4 zT8xwog4eKHT`HMA>uBKJnn~f0tz2Pze{C=2!w#!W^1QQIj2I5!i2|7n2qwH6PbEwBGF**n&>FBYEK-^~v_)KN}7 zH<={ug84y~amwDZ7j+Ui@+dPt=vVo+^JOAg)nuHC&+yl~st+!6$1pF;M#w-6;WZ80 zZ0=_W;kjhbCo%Z(EErDs7Jhv``UIEg1F!4B)KkV91i-!CgX>w+Wd>?Yt08Ci(Cfd0 z&lBFWq{ehJEOXHKhAR`YUaPx&~sg)Lw+JjUXC;b{Q{cC2^V; zj146{kDC0Tn{S#VK>i#2n03QJ;WAe)LW`NI@CA}$NwBjP)=KvM=Cpx?F6q*Z{?C~D{&8{iwyJ+VBCBp;YDyQqD!UgoE6~^}V(!yT zH@iE#MJ{=}aLgTJTD?$Bi_ zO}d;DFAP5mKrG5_+nVF=)G@u&nUL+=1lfDp(c#g2mxTr784u-Bu7A$?>1O6rEbxTR@Vyn)MMLxvCl*p1RBl%*cvL!q9Fe@4?%= z{q4_PnV))#RW?ZBixxM$a1|RGHTo2pXDDmkzrchXD9U!q+o|HnoM^wC?WS)%TiHe5 zCFjk=AZjRVJNE{eYeis$1WrW>D#S3y5;MT4-D&tx=ApFj_s}}klMw}j)}rL zZuW<8YQOi#4f;N)dUnsusf`g!#xaG~=X8!mUEm%;Dm&mDm9lgLf$*+QQagdK3zmM= z{+!t}yVbr=^koetgM2}4=@p(tz4;3ee=wY1QUIVO)MWYsdxd;*)v1DSBKT3Ez5SXk z+d!p3pbHgjm25zJpfdXkA2l2$`e$}_FUYIACHk+lWEB5Q4L`u&NL2o}bAJl%FzWDWA@<={4@ZP>(7UHJsyH@*>c*D-F8L4`n;b*s zEbP6?smfqUCFt}+Z7d(2@T_mP_Qs4UZy-^wQ^l%NFgf!iOSFerlwl*%ao$<;`i-RB z@)PHrSSgHP9_@>~Qu_gU7k*8Va}ve5!|R44G4=aMY&~0%F45ScK=@cVMg@IhdMPXA zB6u9D@B;%)bmeFi;W$u;zlrh`<^wzenDi ze*iQq+x2DPGt8fp>aQ^_QvCV3bARrKetxa9H_>nXmK>2ilIh@QiyF4b~ z9$pBc}mb9tz_yPIRZC5eV$p zlHQ@0tWvrk!SRFz?zr1J%m6hzfrwIQ@+K&uvxl|P7`Ig;{bayf8Xn3pj71F~~1(7o5JmY4#9_YBeM|K!GcUvQJ>K0BJ^-qBb+wZTNhvyH~y0JsmIaCwN$ADk(U_ z6K4i!Snx}X@q$%f?5e}TTUEPb=ChhqAEQLA1+Nob zyryA?M@{y5_Gq}f?vn-U0<85&AV{o#uj5O6me`loZFE#%fy6DB;paDO1({GG#jytK zUd*-q8QQFhq0N8rf`GQ!mqtgT5G87ZirbNkQ+-?29gZ>wJ^M^|{=rS~SI9H4y6_UG zWG16u55zvr%%&a@&Qn~-i3vyklQLzTfP?B?OYZ!f$RR*A>&{{*#_iH%V;iDCI;zM4 z1z6ww?qf}VM>-qO;KA%9)Ka+Ej6BtCe=~6qmd`gT`U_$;-UX4}bgt6cej!xcHl|@U z*69Uf3T_9ObUzF5=IVw)Fh$CuJFEK$PAw?mpL|My9t78`Gx zC^&9HdqaKeI3RlJ;_+1MO?>C`hU@?f9LiqRO`F?lHe(&ts9!I*$h3=1ia{<$0R09x z9wp{l^^5NMD@WH9dp$@JJBB+oK+1bw^wQ3{{c`7Sn4x&c=XX z`u3$t&|3C|0c_V)OjGE-O%6`bmIDoP9g{VfhR)!&((~b6llyr{+*Q*wqVa$w44mP8 zbMvgX1(a4G=q;%*V1o~l-O>m*s8VIc}9KWX54s_Nbr;wtur`R~XTt_2GJmVXar$r-OLTEeARu{-mL%vdB$jwv@uNP8@(+{If=rkTJbZER0yx#A+m2i5T z@%mpGld{#lmo>7EnUHFw=!A#ijemt%2p7mORtJ@(aM-bBhEvJ$c^rqkzag>=jp6Cn zZ6eaV?sg(ReZMdf%Xw4`P4`3r-aWV-S&2&{#cfIJYWM#3ZYhi&b{7tYdA1>lj{c9Qn&h;! z$8-vj{I8>+EcwH=Pb$34N32;m_<^}|!po;f^d9hPfzHMm7?Jvsp$~C~S6eL;e`MV< zxq>cVxB}+@Q4bQZ8r8|W^GMqYfoCwUzl6aTmXT$%@7yN@vg^8l)q^-8W_T;@JlmUy<4`_0P<3Jb&ycSXCn|9M+G+$Fo4f_(7 zLp3wJt_PyUu7f(gPN%Y0UOJLdJu+ozD@7kI*GCO zZcE-PhsPBogubR6I2*V=Tx>%kyo;Yf0m4>C?>^JKgPh)4NL(xyV!u)bKaii`c#v8K z0<6P^LS@_K8u8WPlMF&ldru(D%%fa=2*yWK8$GCq)YPY?u{S`MvT>$Xm zc%l!00$^P~Mo$^MVwwnR=H>4Tx6zR64OZXL(5?qX>hk+q&kuk(~K2%)puq6t>=9|#Q8!^CfG#U{Yigt zT}N{G>Twlo3@{NgXbzy|0YTKGFdCo_!ILpl^1fg}nLs#T036GINjzh@tpoR_?oGoT z;42t8XG&R%p@y;FcjyNf>T^)Zye1@fDZ-a-8K~hwflKrQ+@?M{Sl~z0xcWfgdXdbE z^ugQeBNlRad|--&y67qSin4fAkU-x@Bg`6&{a8?Xf2Q8^v@+#EZmgH}YQ@-m5v#!o zo0Qc(C}a`^SHSc98h_KR&HmU%dS5EK%+Qf;l7}{tnP=(jhML!aW5oVU0XIVLw$aJv zWkK>b!3*_k>gIOB%Q|=udB5EWB%!#*@wzqX6DKbH|gr7y#y zZpW!yDRLv}@C7Wr!yMw6aXo#o%-3|`) z3oOI}vl)kXEfJ9jr!&|HJ}#ALE^3_CzZ;F8-UTMUg+{#$Pms;(sqtg&6|7;pJ zBmu20;gmX0a29EQvC%^;=MGiP83=K@=y=!?fovgBJ+Xz=((1;vS5{9j4hG=E*RfrQ zi^VQ^(4Rpg7amUKr1k&y?1H;ENH_m9dB=Iw9?+Q10R)!K#szC0o9Soku0zH8DMP6| z7!h#u(k8LiSqNb8Tmj=ovVtrnve3yeZdSbz#pqoS!HT-pG73*s)zX> z)aef!mylAz{ZEa5Zn~621yoy5Y}`X)}WnKV|4q%3(*xU3S{geSEsTxp&pBU zL$ZN{3&{g<5tlehoQQk~dz%MvPo^@=YWa4u0*HlIB|fT=v)sqieqV8bk~ju(C)(rv zdC!5{s_=%iFZhBw&qI^$bz=FcA&lEa-k^7Mm-pY($_8a{v}wcCxzRB+@B64#tA>ZOGb$Kxdjj>Lyt0 zv2I{y(qS%Etb58adLV48#7S2L92TP#deZ>LEiTFOtd4sThx<33F!hTNtGy$m0y)^G zURI4kP-c2iP5s*e)Qxun`1)0{l7Bb;H*f@7NkS?4Q!nViRP(ROwoQH}ronO&K2LYN zGu^bh%NC5<$rBE%$%>)2u?Hy?w3bJ9%hOO3@q9%lRAgnZc+u&HEfTsvk1{Ale3ERl zm{*3^vv&b)uH*#KVX^8_=LV*98i*B|Jm4_6($Yge3Mb84wC=zwkltAZR!a>72vu-v z6SA=e0Qr>@ttS)FmF&Q|B@airem#A%!P9t;PxWTt8MF@_%ur1NmOWvD-T;aBy^$a{ zEaX9xK)kR*Q=o14Vy>#N2Z>WuJ~Jl_0EVdwwSY(0FK0~#RvL>QctBML6miY*UM-AV zVqlW&xY#Q!)L{rWhKG?= zMo?f8uE+6J(t$-cgsk1wpkt18C_3-4fQhjr&xJM#h4Fx$n~d0@R!J{6{Mu-pwi|Sv zY^c`t+~1r&`0&%79?7p1nFm%T#`1=Hso;K3S8tAN^nvlt!~Ti5nJ&o+KvC<~UVL-$ zL>_#u(>8;b$gV3`^gn?2f(Hej;NOluNa6-wl;}S8^%I@i6O+c8_@&I&t19M!kDQ9z zrSQXqJk+y4&IY&DB{<5baS$vzS(f2oDTT%k&&uoWG)Dqx`I`5Clk)L(hvl@Y$K)mp z_d8a^%X{o}$F;z`52yd%%H$^;-Y2t-vN0g)T+L%9;+I;V1m1T>Z<3>>dXeel{zaIf zMsgTkC;yBgq1FMhmYG6dw&qTGdM@Fbp<_7KC$NHQ3HGs9aO!CSldKm`df8CtG-p2C z>^16{m;Z4a{zmgHH|(j2Wr!1sSiN?f^H*>Q#2{R$1BmRxeCh@|@GZ_z zIYVdr$!0vRqdJ<6o_ztPFsV_&Wn2L&7H?mncI774|BWTop$8rqJ^GY6hq(uoYyrEQ z96N2Y!z^$JJ9ygR?)s#2hatCcp94b9kk!9Mz`ppjC+8tH$%7oHD& zWDvRV9IN%Wmb*J8TtnV=rZ~54i!7LuN!AAiFb{5IAr33iy30rXSL_JV;f5! z*STAyC`t$hl=cc#z<12szhWc{$n^Wyvos;y`!q(QMllT~@d6QNz6ho1eucBeB=BN* zy#4P2CxID)ReS6!>+Dmk$CUt!Jgt}3-P}2xO<&(3Q{|PBUEse5dP(q@5Zrs}vIBG4 zi)v_mMaOu~)V08@fyZ;RToi**gwYW(nmz2nw%m`zUBhtl%Ty51k@XaI$zab$r5iYf zX-3=NIS!2QHKSzW(+!aj_iyS7@31_Q-^SvOh$I-FsnL>i;i?Q`fVrXMD&-cKSrSS$ zlC9-9$+#-=0a#uB@a|z#=h0ohn3|#qAj!#X3P&i+rmfuFcBD=AHEj4loAM6$2P;33N(7UYx98Wl$Tiew`@PzxjVa}Jc$_vpV4B`BohaUY7oCYD+DLWl( zd{h~_Ao*k3MRD^yk%hiwA=u5WFRNFOvMPR~@eKcXqkOT7#hL(~Wye^ySk~2De!kE79PaZT@xHx2 zbbM9m#waCuQ$XUnvqIPEg+;kx5+$w<(H4-s!!|oOlP>5_|q&OvkMuAiN`vmm)(! z?l#IG{HA6ti?jD?XET2_nXWmsph5*zA~0tw=R(Je&GFP9JRbsE9(#6b-0gr8h0myC zi6~k96VOa%=rdSn2M_!E+x1)$G8*d>7~Wvmz_tOWnhK%d zK)9Ny0uM|UCuUG~WE{Negr1DB{vRn|?VF2%u3kp9?oI6ojad|yJF}YJW)*}&Ilk8G>vmtjX6!&&w-oCZ)t6Xq z$O~N_t|?PAjB~=YeiaRA1GG^F1li7qq=4=npz_Z6_9S@36YQRE>D(my`roWN`n}j& z9>+tb0{nRa0vQjfRiI%5-1pN;3AoV#d-Sy6{uuk(m5l5*+*wP= zWPVLxF>AP$A;9ax-Q>E@r+95TcV>^_s_b2}Lt>x$cHKhZ{mk(P3S&d*jqhz^(?uo= z_z_-+;bq+M`8&6PU^^g|^Gj0l*MkpAnNgVSyF88#jo0T9!0#X3oo~?c4vi>w>>9L^%TergoRXp;)Gd;tBhE z``yMpq(}0zcj^!(5wd1Vb{5r>!z%x8_34D1x7?Kt8_OO#4W<*C4AxH2%s&3Mn%a&s zVpHYs_7J9BZ2Qx>-g!3`9FnVqxAp^&7L!no6qySA1)k2zUZUl7T#Hhh+|TI644*l> zG2d;dhBP0@%n0r5b37_e&BXpXROL=P$5NPV#?1M3c&w*F78vbpHHeZ+ zTO&FADarYR{B_i@Y41ZV~troT&*r3$t#~ zl8csGndWhd05wp-fk8yCBR7{{Z?qlfHFtY+7%=Od<^;z^;+pLgcVnRsT2GWq9P!3u zkg6I=W1C@BQ(A0Lx0n}J)`i;dg}?C`0x*sn;iEyylACgoQ)OZb%6oyVCse#zq-)xT zC3H3wcE&u<3y~(LKXY-^=@D|j^WtUNn;LvBxZ53Zngm{LP8hiXD7vYp$AhU$uSvi?n8CTEwYr+~KZSsy6v)$?mwQT>i zzR&Iw+cG##1%$S<3yxn)zDw=sB=6v3PLK*L^EV}CKFL@G6|@py!8>~Cue&k-95>{E z$uk0p!+wpH!t+*`I1o8{=G#m1|XWz94!4Wo8b&y+~9W z6WOP$epae!HOf&zodFzLVkY`i@9U2(bQ=LOJFD44jaPUOnaP5XtjIfKa6Jh3Ob9{& zV(YSC2~#CC7JLBV;0NS&a+VPU<5|9N>$H`=Xz~at|9uARZ9Hr6hv(Ar>ePfr>#{Xg zqg2gyI=-lGV9?`Jr}MKzKYwUTcY40k;|&?jAuQWM~sG8cTqU&Q9GbH;&hwgsJR$|CskP zck3;qid5WmrjKF+G_?ags0bfUkv2mz3{lMo__OARKJC%@0JRuxpz(361%e-<{fu^< zw)FE8KYV{EcKsgO0Oc=hRWomfj@bX9E~XyG6Z4pIe_zuV4&+uYkETR*5qgOrZn0VrYj0unKV_DPLcNNQ{zlg&pVJ_vAOF(ETvT3Qpanq zN)4$-U05L~t?^Ne%Kx*+KTDYX8k?FAZGi_D_P|el=il-fTdDig9=(GldT)V#C!yfD8<#msvAyhRnEK&@_W&8g|cH>M4sHpAXu#HxMroumo7&Vqi^>`@sG)J3C7o zltrSO)oHwP#1dwmL*2LebNLb{B^*}*WZ=UZ^%hD=(wo>Se5nP1m$j-LaN_Q9V##bd zS<6E=4({XymH_0?Ia0aB@P-j?sz z5z!KAJIrzhip-SMh>@r5;E=cIPB~7H0(DZ+#k&aAt%@H$LK^=4xd^z?E*XBr>aN6H zCu<82fF*6vFwiHn?&>kRiDtca=fD!Hs;njO2f9R`Y7i!D$;<$K}hnDlKF>J1gbd_Q|^Q_T`%t`$5kfW7Bj?9rJ4zguHHGMrTkr zZn?ETDSnS7&|Oc^;^f4}!({8@F^SiUc!z@Q;VAT?C+aaV%8O3k=^{Cq6}(pZMJp50 zV3hpI#t=yDj2={WfwJg#1`q*r%vqZSzK_%}p?;L7WKrCDnDO>b6VacM{G&QsBY0zxM!{@jRlK(4PK4<)Ph+tSasg2~C#=Z%I+$6i&OEXD zf}^lw@J`ujLnMjVrE7e@;DUjq(VWF>P>6+Z+j8ruLAr5f+it-fN%@@6QMJR( zZ)>sLtokQ_;T_B%OMwMN^pcXT4tsM1Zd)30*NWy?Ml*NSMq)lt6`Ldb(CjxY1THt+z`Eu*A0Vcf zn|QX@FhMRa)cL7EU9m(xLS7P^nkYrc2Rn#)S<2gym#%;8CGr5m^&@7wItO!mYe(x! zun6~F4Z@c6!Jvuu!n3fcR5s){Z_^)X!Rp5cd&ZhzZ>W6(3sTx*WoVGDICqF0tzQsyxQbP~aUje4yIfwcyM8Pu zv)=;M#Mpe^MdZZZMmeKx4vrJaSka$>|JF;s@Bia8rrK%86sW`fCj*q(=R1=r6ZVp-#|f?~+n%?J^cT?vNR5m7OLT*u8U zMoDiBRt&V=?(TSy4qiE;Zk{ijikz>0uox8NY!cxsQ4M1RR?4^cY{aT6{q&-RxM|N# zbJcFzG1*)sh!v>~l<<-6z)1l@S)wv1f*T+Op~7tCj4s}bOtw`RoZCizb?&k4`RWk) zm{wAN6Hlm~N3T(iq|1^WoA$}^f>-rRbSXAr1Sjkp1T|4Pvx}&amDb1+9I33TCT{I< z(gtv@ecfyTN%r|H2pVE`uKBrqXlmz|(k3==)$R<=ht3(md7e-?y~G{&S|x1bl0RiU zkJ9#3xgqL2V;3@!;RI|;PO+@jXG!J!vzgHa<0bt;X*1K>adyjhpJ{JEk^}y^`ReRU zRdIz^M*@HC_bPSQnABuo%I+Ld+toHcOKGXUdiM8_LfU?nTv43pSv1*pUKZk^`$|hH zxt6{d|J488Jest%wz!*svtVxd1%jl4#R?u(wC&wT?0Z24QX{U|u0em>LYy>?%Vozv z8PwI(iLy;rRxujC0*Pn?=}!-{qlmM27m&j?RLX`q9~$b2^v+ZGRXeQug}tgEd(?Nz zUpu*6(6%g>i&fY0`Q8Y>OB{tYjBjfTbVJ^#N3-WtaJ+Zncm+tJPtXv5kP++59=&Nx zaQp~{-jv3EKh=afWGyDH%2{>)1($}~)vf%#`8m&YNoqzibO<-ciA@F{PJD(uw2BdI z--0+E%JahlOGX&To@jH=L%G;Y*#3reSACQ?)sDwY;4~|@HrGo6qMYcluzQ;JGGG%M zm4$FB7Ima~w_=JAV0oS-?qtMkm`+4Ho28T*a^ns)Dq7WPol-t8{o$7fTK=XOz+SSt zF=~Fd47bv7_$VWaES*R#hJy#0b!RfZZme*`ynsz5N^HHwWM0Z6lkS?O@JCo6NwQ`Y zN{;UCqu4ho04jkQaK~Jq(2ntBB)NI#js<@(`{Tolkxjrs9oj^&ep}EcR%Q-Wi0mSJ z^yFX-Fk?PwR%kKVxL4krkkD$;NNwv{QMB@C4wT`+iOpj#Avs;h7BVf1Xu|uGsi3i6 zkK>x4|1rY%&8-M1zlME(ERN&iD?-~>8q4%PmK;&(;+$e{TyiQblDOFL+D~M&SiX_8 zM*#2rCT;O%uBHUrO8s8{D`pR&E#T?5=A)%_JX`#*tS)-6-QA;RgjCdeq|~HLl?9QR#?p` z2es-ClH*hZGzX$M;)cQD)u2DOj5X@(MQtJRq4M_zp4L32?^63Ze8@#I`Y)?umjt&v zgEA2@cV>U>xzKj1-+oYV5Ops5G2}{Y;GZc`kKteJcptffM9C`sp>uszG!woCJk!4C zHSkPJThMbfmwJx`Ul#~zQzowqSG*QTjVJRXN}v47iZbpMExWas)q38_4n5=s+1P-V zB-zk>Ah!uJvXFr2N1-Q>MgzI-Nk0l0YsGejS@3HT*Al$+qdYMws|PyppD~K{ErI|~ z%?b3jht*8m))3=I_J&nI6CtpiB+=DsX8>|77HXpYjW!ljgWKYe@r)|-v|L|V*TQhQ z7vQNU&IJ=lQtMA=2X$&EYnw9D6u&LL!GZT%g|1LQoMI`cV)=T9gOo!5T-&w5ZRi^zQ^5?1?YUu zEOBemQhKa!+|b7gQovLbGEq&E3RdauUVIya+bhg5AV!3o%&B1g^B9J0(Vf?>X_`Jx zCBISAqy^v9{-1Ui#|9mKq|!nvBrY}3Goj{ou5Fbu3^7sInBoi zVS6+K>r}qWH$LUf89CiscEEF!j0m1M5k8J~&IqX{6A1?Ts;8st%LSCsJ%{a&Z2gi> z^4icPvy(LLFaz=sn9`@?0VNDju9UufP*jRe*e(X^^V4Z6KJZUu%9Y#@DFJsOBteOe zlB@LSf>)v72J=oKvqOZxf@!Z8M*)+7BC9_6jKZMB_pYFq$dr9tb}q_^SRH1Ny$R~v zOjn4XyG0ZY9lWyGVK9KEfj~wU<%*(|L=IA6f$GUd3xVq>OM-~8z4@&9nk9tupT*7`zY=U| z&=jhSg@W;O{`IZ^b_OncptkzeEJL&}uNuQ6jf^yeriYqzIHmFy(6$nw?H=-?fKFS$ zn_3E-zspTe6Oysm|2-G9(RTS(yee#2h;79j4A`J%fHL9rc{JB`6zcs+4a}GF<_R%j z{idfOb(xOLJMMo~00xJ5V(hnQzqC}TZ3KKK^?DY5U!?H2i0r%em$Ad+gnW?K!j{8 zZJPSH9C^frrTnXFjq8DaSI%1?u6w20iUUB5&NFQ>HGKTAqa&yX0<5qRtJIwFVOSbL zgtGt{liH#?K)sv2Jw3XwSwb=USxH0OwTO^4VNhX8nzhw2{2XCJoFv4rr8B1_t6TYHqX?qzmu4)BCZ6 znipD+ckg$4 zsfGhTg>=~(5RkmC6(wZBdG$wlN4YGrY>LCDn^;5N>RiU#R6MM0eekpk0M=NNCW&RS zsr1Mrj1^P)?2^t6W;!GdHOt0Y;^U1~3@HTRnetKLJ)5Ig0faGktamW1_e$dZL3>3U zN-9_|ZMt~jB(d;cgu*UxSXR{Y&Kr?B>HUl4Toz;ibfOy9UAOvtDr`cFM2pVj#UbrC zKinVb{(SzT?0rODy{6S-4CYj_XDG~~;Xg!cN~qVs$(Ip+Jdq2eqGKPrw=4OGoAVai zD)^4^UV`f?&MIVmh-4NI&hVZ1Y*@{&O@cs}xgQqrln*9HR%o~@Ep|PKEG)p=6#X!a zC$zr+)X4>*N5TKT6uDqx!W+v3z!_n8x+vNiAFm=eL}YKwVr-a^j-3YHqhG*XNtpe zDXRM-T7NHmu>T8MjX}wpR?rOC(M1W?faQfrl23(Sn{^vDqg~}WrB`u{{+719_gJ*3;}iGj zOy1;Xd!h^96frbC^s z!E_iUdMqZo9?8&dvu;#GtMYy3YJjAkKQj*XWN-&|Wlbsok)aP6;+bZ?E7r(@nsaa4 ziECSthNzdu6+DalVM;H~=o={BdZ{KSr3{1?Gw~Yr;C=&?*6w=-NNuWdSyeD;m?i(P zj{D&E!blyvbY*FPx4petk>872kelgc9}LY-{nLJ12s!spYqYnRaX z-EL@ZJp`RJDmd(^9F%}k>Q859>`>9K+u9CksV+dzdI;DrNqWaYtVZ5_pNE^~l+v5` z2hyFU*mU4@%OS>yD-ksCgrde6%+la- zpAzC}HEkfpB34@7x4mnRLy0>ozjp=$YtU;yH&iz6qEl_r%ndK*J3oIYvpzmUK8kW;R#a0HQ2ZuyX;|HF<@9 zFupnGUhCTz_3k=D322!&qSq76o?v32BbR?~aL6qeEhzHTrKR#5L-wYbwt|K0e_W}7 zktB+bt4O?aKkRdt63rMyV#CCg20G9P@Yyb_p3Kvbbt!|Jw;Tbd2^NS=?065nw0Hb) z{j(}(lHjN~B6Me>Weag0EE1h!Z%G7QnvF&SZTIm0?bR))v~*br&y`)m6XBU^*EAYmx>0UnSMMMI|d3~)7gGOJ(#9}nS8fut^z zQz79ZB9;LjgF@tKn&1-3hR~;aW1$iOcZLRdt<$E9O9_r*BcE~iW_thCC`i%8Y*l6! zo%r^jI()INg=>aqg+BPyxgbX%)maE-B4@D=jMpr5R~c;OyVYtMCfD|x^#uflNF;7Rc5RaAjf)2PG6vD3bF#qwl6KK=eJ4`sS!QpK+Lh=f-Bv*KuQ z^Az35Pf4o`bDBp2HYYW|00Z>k2}pW(_MZL-%qgx=4g4&08l|o)(Q(Df&9U`4p~eM4 z=JX&}im2~qm9^9J>@iqICrHj5%lMtx#*f>d;nDAHT2z7Z4~#=jm2&}#EFu0($gpHa zA&%X}-04AqRQP`%ZOQcZ%oJV4bwV`0!q?a9_2-(tnWVpQPh=)}h*p_R7oQ~i|96ek3Gtltam0da9#~?+>+g|!fiIrNq_g;i%TzAKJV6tXSwT6mFbw%H6(fapktf9#oRV$gmvi`K^aBI%Uy@I!A98=?BQR?S)6U-=bcEIpEUV1rW5Oi)zCAi& z<0yy6wS1xA`QH!!hR_fWaO`6~00=xxj9-!_`dv0Ns_yRv{!D=f8cB>^m{bTH$w~vt z1l9gUSX}yTI#i8=%>!^?#a!=(49hk^;G56gvjpYk zlzm>KATZl!EA|#ucgjrD0*3I}SJ+rB58ZtTRzq&(B66>~yu5Rf7cnVC!C8IF;QL>Y z)>+5Iur(`5pd*qQe^Amx)!;K@)jgJ}eLFU;m;zx-l}TDHBLa<2zQ zdI9vBOGGUgtOhCVJZRS8vAChUNW^&jmZ}2sAlBu2cSA#I{G2=w+u7FsfWMTDVbhQq zreTQ-qxgHc)O1Me5smkgPK9cT#8H&udeppj$bTOs>>&Wl_osMYbGJPIz^h}PGvkX1 z5%7ZW3eKi)dw(vZV`-Hh1Qdq22&)4F)xOy$S&KH4vx7)PPg0yS%JHiQZFzW{zGLgB zuxhzVxqqeonnGx4v+)Wz86$J-yf^Q#*ygiSP&e_F3&WTp%u@gTJ=_e{sVfALMg`X- z+J=uyB#De1u&7m|;6^u-0|@O5(ku4T?Zmx}-OY$trQX_2%W0*&@gr%(+BpMC*GBXr zdRVZxojGGqCVDyA{{ew5y+53I1uc$Xpnvg>FrHfrd0O2y2(#$_Y6>P4mU}@D(F1(P z>I<9xOvHe*Qx*10CbWJcmTtZIdQDBCoF18Bra`pTIU*t40xSe+?8Aorof7Y>8t9ep zXS(^0TF}Y}MDu4S(@$?f-cEipc-9_G7;|&yevm9wMY2Mnq3rNCB?nmeD(lxZVQ$!n zc^5_&X1&GU)w_RfWi9w>Wnq8apkI+V#y_UshOy-&gv^>4bnnda9_rY}=RXgzXl>so znd1xvCY=*OSr^FaS)X1be|>e&>?*Z2CXhO1DzYlpGl;c1qvedu(QPD{|^mu{|gGf1V{WwmjrzcZNNbdP|P=(aBPv? zj2MLk$f9`3d9e(Knc!dp_*THR9bE%izZ=`dfhmm+@?HzK@cH%J6lWBMhHXQv&6lq5TaU1}*=f`th<6uLn z6tP0LrG_!3FOb@H#AN90T!u}XyZJ|}gG95f#P-pW>=t4?w8gv>J@C9Ge9tbQu07Qd zDR-w4T{1N6-#J1TWCLjNLh(sktsoMFyVMmTD9d1s=}S$^zpbQyi6^$E%?|QR{>^tH z30K|Z@h^CB8govfJ_FsCzK^@s=hb&($X0`N%#_PP0h%%^DuPzpVefYa=B01{cVkGK zEhJb>osq!Q{5HNddr}dPM&%*)qI)kjj5KRUyc%ISgUphcFK)Ee(sVDmGj)ACvVSx_ z$vvh)fYTrRw!fizDLuumMZ|2U#>>6~51pmbFz+Tka-kt2LFf5eR2}lC?SAotu2JHg zLweW8WFi^1>HuarJSBIzUoZ4KZB4jq6r>{mafHgX2$fC>z&d{4ctYTu^cphIu8dW9S5c*|1w9dD??*liOLuYg88WxnzcB&NIE*!@%boF zpqgSYb8LK-2#&4@xa>2amKuU)34p!>&-f?IU!0tDKb9D5!2cmh)H!wWjmVTRHCVZX zNK={t_N>czptMa(1u8`NAiR1bm}_i!?idqit^j)_NHxLu(r+OJ;L>-1dYS2gd)F)Z zLg}K*^MrvlV->p8>4%c=PR<3pW1kOw?j!OL%CdEm{{tX*CtulO#p4U(+GHHTFBf_A zgP+(7CVsRiQ_B6;i!919gx%6SANZ|CPVc(6)yGgw7)_{i5z`J3nlu#jCKM^k>he?K}YXI+|Z{-X?2=@36 zKSp%|3YqrWU+Qdhc6MNWM2MDah(YrEOY6S6ndtp~$QSkIskBixQ0+P-1F61hZFA@z z&2(6qTcMpIqrJU(UJv{V4F&iM0%wbY2VxnU zFlny7%dnd+7_418sS{PY2L;Tyi z#L31ngz4DBNm;yo+`)FH*N~x{{9Hx7A)}(vwECPVl@P^Fgd_?&?|)V;RtHTCTN)Kt&V^9|H7GuH zCt~xyd@;5b#+X2dznb>ak4UHC9O@>-}Y&tdTNS>(Kej<3zcN;pPVVR8X9{tF_; zMdLRLVMO`MI`Hy<#2j*LTPo)H@=n2ZR;AtyThSKbj$OyHN34BBFp5F5GQ5hUrAeEU zwUSVI&rJSg6=GkeGl^B# z{MmSKwp^-Z`|emF))(u;v5nQMPq*sVtZ(BsjuGBGnjNG>w0-NJ{7k=Z+Vg_H&LdwU z6JQa@m25Gys^KEQYwthQ0k8!F=-|bYE=0(iMSC?$jIFzYALt*CH{>ZX*=mt#XJrGo zHm&&k29wu^O$`$N65`glA`7xS-?jQrF3AF|GDs`HLXdNPjhH+uku~F7hCz0&2Dd^Z z2NXZPR(8}S^4>GEdT>XO>8qC~F~;nd2m3rxDLQ3D_j$f#zIsVdU-!FAzYd(V60(M! zQ?24^5~oa_K-M>gx;i9hp+5tI3oo|u!N6{XubLy54@ z&O}!ecITx$MPmJV;=VHb1;r~?*DsY$apmg8fhqE>O3vNk05D-w3ajAObP~}H#FOQT zfMu)!DB~1Wx)=iIBE$QfSPf_!=>{__gz7lhZ_G)w6$f;NM`T<03Mm9!;a9WVnRsgR zJ8>1m2q8R$tPUhcr3(B8)2FGh#u?{vQCo3BMb01ZQMiQBSLHAIem#WwY3~>4iu+SP zkeZ8(m+z?JXEEWiT3ml)9gOeED@8XY#9wk~fW4N0p|N?gUD!W9M8Hp=?MonF(v)3{ zaW7c(0tiPe4*=i6inf1lx5>GGbHg?ZSP?I4&UE!=fZSonc5~Fx#fn|TG3nL?@Jk zi@0Xv|ALP$$voF2;7EOn#sQ1`Fmvh_sSL+Ww)Kdv52ZtxZO&1cu6KTeZ`;#?+r9W4mV z^96h)8_jtFaN}kuTS`vxcUXs5DdT&vF3F?}iWzQmHqH9)yE&mK1P@rPK2q__T)z_ZFG4@nN zP>k_#3S2_B_JTYl#~-$Tmpnxeo4%9&eN0Tr1LGN225&(N=xgzjd8Hxv@Ada1(_DB0 zjYsCLkMaKb{P!35o}bb#T1r=bNQg2g3rBRwaFd!_&8#JlKOs7Dq63jFhE(2N9fzXU z1kBRo?)q{?>ks$Bt|6S@w8_Y%oPqv#mXV=c4db=Qnu}7*_~?ZoxxJ8?L8PsB+IL%GpVr774lU))LMjBut zy{Nk@nl>I6)aOCHkcL@BppkwOA0leZ2b>P4JTP0bbQLL&pb3k+%~Yu|Km!U8mWbJy z!W|P&xco~dJG*=0EMUpnq(jA`p@H7qt61@qix(Ukgz*uut#7?EqRP9Zp@q;0y{l)2YSEj@{ znw|=qqYpkghX08*{#C*AMB;y8>(z*DKnb}uHF^kvtP)OhLPZx66I379YR&u`QfZTq zxhfU$%x2;4K%F<6?=>UlUJJpMQC(HAU{QQQ&TGCs@#1^-Rnew>z$U8B4g>_`H}d)6 z83Gd_8zFsfdI-@jJa+f!@S_ByQb^F7eMa^Sc*wycrq|JqJeh9}>QY|yMx>f3E@I)S z2X5Pfvp4jqZ0nI$AS-@IBcr5Wl^uZ=0s8guoi1)x@6zCKX~`pEDOnx;fadZW&D2pZ5SiR9=hh0lOnSe4pj%iU%MF+ zCGL*pjw#6Cs0arCs0a^&uhv@;gqrse@h694=$ujiI#Z=&bq{X?HI-g1yUg2o5>Jv9 z#;=3Z-4DbmwV7fHBm5(QLvq&hXnuczq_kfEY6mHE)c{Y^UT=`IGRMz!r--5k*Sj*j z7nv!_%{>75Ya@&W$-^AmkK@5IvvkpWNC6R-Ua)RH(pCN-k!(MoU2#$S&&mvfUB>8po|Ec2Y>90ziv6M2va_pA zABBL8fRCDquvl?5Tk%$0E?pTRuPmyA;(G}t;bjWn=cRIga3kb*IKx%A_}7}>Z5S?O z8QZl{?hoJTg=)jq03Q^p!*cqJ<<~9aR+&9q;-{}^dAM(OQMYVeYlC=969_wI$tlO!KYz$eu910cz zwoKrS(&G1u5^7zu2v75AO}dNeKSjrQqXsg&2M*6O`GR>FOXQgbKR$e6cHE|0C8?%{ zUSu2ZhaI)NU}&pAK0F122PWj?bCa3L#;0tsvtP(771=4;jb(za!%2Y$YJE*whQ4Du zb6`taxH$*`(FAMFou8=6MfsL2L-S&manimD@*hl4{c2A#7#aL_%PSaTh9x(ljLFUJ ziW{H=y#Y~s+dapz_X=tgek80q027J9EP>RK<7Eg6S|47(I-EBh4>CnJ(EiDkm*Eb} zWAe*yuJ^YZ(MZg@x1%)$F{p7)jsB<1Gcq4nz1Y=0^r!*zv-zv@IPbN9hvD23IF0o@ zp~Xi}>@>v*84)iCra6eqP@6C6_iSx9l#j1%!gBL}IJ2s5jOTG=Pwd*_c$4R;d(uIL zCY6i>xasyQ+T7i&SZPLOFVXJ)OpQakczPFd>27Vx;`zy6QJ;%+Zpr8(BmCe{{cXI& zUqbH6Dre=n005+IKQl)mhTu4ygncH6clNF~c&t6|Nx0oZ0EQFW(;VWFK2L9Pz9h*n zGp2BBB(O)3i1gf!9F3ncoc=O&#abLCi)YtL`wEvgfQC=Q3h8@2-a+NfrW_?6ID^{ zb|~lin27vJ56_Lw<|Wk1`Qb&L_L&thwlaFbiAdLL*YI8iPkJXzs^uWDhd z@$6MX^7c#erzLmrXk+Ws#xjM#4B&(W zy5WoJ6X0B6F93!Y!wr5rZsR+=Aol1q)Tq;;Y&Iv+#`(4b+Tmt-Fk80dcw8p^FTEoT(2`q%@+ zeK+b_jPT%_VQmXciPp2zv#_l?!{0<~BIk6RA;;yn4-ZQ~etX==w!Q>b4vL~V+J?;{ z!ft1Xa2mUZhamlgw9j}+lEwrQ3S29}u>$&!?I^x2<)eM7@}=Gy+iIAS4Q)*UM%Z>DERyXz!S zs(O8naUrqRU%mONw3G|Y!(mXdxk+*=`A8VW(KOc~y68u3xZDotCvR3A|3{S*5k@eJ z4|-k23l^;anelc&Il8ad+iC*iQ;FtrVW^xNq5=|0IK&R;=ql_Q@2 zB#c)ylrw%A1 z^YU;Xg7Kj2tHqgcv?FnlUWX6_7^uy4)%K6ghe-F>xff4@9^Wc@H->KI1s_ z!~(vV%=07&z^ic-0v8$pHQmf00lg_Y(31x!J}f^uK5+u+Mz6r!BBZqx(z!EO=Df;h zeoHUFNBL)uBCBbp<4mZXwfb%`i{2U5-?jDpJs0-p()sP=Hv}OXYmwV+SV8a!CoDR6 z`;3L7c2`skVlz0JTJH3i@gtxErJfOnv7r#nI$pT{A#z*4EomUe()+)DkH&pd;DM&X zMxRbcGmBTeb!=UVKJ$Eee63B+?!a@D1~Hb*Xm3o38{IpJ?u;XqVWMgC4bpX7|EqBm za+q+%J9&7s`6Ceiaz=Ydi18g)bLPBBo`Mdt79LlO-#@Ea(?ZUulkJY$Oej-glBv`j#>J;Pe4p=EzD=^`Y zuF`rXT0LUJqE_@hh(x?VmOjXO-5{=lu-TeqC80%JD_A$C;LpsCV`p_eLCm>fkJ*nXh`a60? z;EYi+`Dr*R{(wEG=f(MAJonO+?9lGMKdBZcXa1pE5k*uwU*vb9BD@qwyweYIyF=QD zV$Eb4g_K%DV!S({!J03ADIEM{wm=xMT?QLp4uD_elFO^Cx2X3B^8`!KPwK+EQC261 zh$=D+r6rDolQ%PB1>CJvGrs^(S z6#&akef6$9qioaX{96b);_(oqd^9vnE#{q1yGpeV{FJ&4ql9kbo+%LrdRATvMoK(e zWkyxN2TH`$UjpJ38#2Q$-TM|A&v^%UwUBU@EOL?ML6&4eyU-NAW={8bxh)Xhh7jbK zsDrdM9===|%j!Y6V)c%Yzs6X*cNx8n)ulNp*?ZC5nB^qPj<>_z8X+AS6y=NHKcAir zNT%`tcusIgtP*c-gFhw85ZHqp8SDNTNBs=1Y%FxFJ8L)ovzbmWPGErN*e5~EEqr7h zltEt@7t%wgba-(bABTfUkWS&pcSIetkZFX1@;~gKNK-JXrJ!5Q_w+e*S^Bn`W`kJN z;jfo*m9TXL_4a594w|})Es{s1qTfGO6F{$s^*)f1T zQ91OVyMPK7yf~z?jl)MdZYGQ90ocG3zv!4U`q?F+cs!ZD@n?5`k>fu#sslQSMOvP# z5I`Ow6k-t_GWzAB2!W028E`MLysfeTpR0>#p)?O0iecmiw#3!wXusn!rpdCB1-TA2>Y?nPU9yS4m@wtos#FL^V-RrXc zc^<>tf6SFe#Z|9cr}V4H1whUH%7}}VY{vz6+Ff<-LYWLwuWOV8(b-b6Ggk|d<|+-b zNF5Z-6iT(rO(iq++>+t8#;;w=&xdqmizcF?#XJAz# z_aG})A~fIt@G!(Re1g~a%x1NmPBOk*6!JPel{cvh%FD0*N@CfbV4o^g#IEl-lWzTf z9%49G2Tsx^l5y>60rX1B%7i)LimwGZtT*n(3AfMkrQ*V2k8hp7G1DmlN3}U^P@$tY z!fxZln#+Q5vyxpXFo;K}N7~SzYGGkmZV0`5Ge1__>b%Rbwnd#@0G6 zeI0$l1q>JP9i=^ie%Z46yX;Q(7m^O2p(Ybz z`)y*RfjF`#hNoV^eK}YL+|y#a;Q1*xK3*SDR;HO>vo|`3Fe(-TM``_)!bbi9M1U>J zAFO`g4I)ARYz7F0<1J~ca$k}X!~U;F=-7gq1=$A(_Q;>cWmb6Cvw}!o9@~WJw z_BiclkU1407u4LG6@X5EK)(r*i`vJu&0~ms6BVJps}ionk1^tT1dQGt2=#BN_P+TI zGwM1vQq$S%>BWqyr|wPXo0pc?p&-gLm$qWiKjDjL5y~#jYH2wv;niA8d0ooCOhDi_ z{0SYYuWmRVsQswTv(#)yKQe7t{6L>cIV}coc({+q2e&TLR6KV$-&*xu5Bwt8HmCh{ zBJ{*^B4YWUc;Em><$9#pzHZV47R(6}0+UJ!&^Ra$MYD9M+_ANJY~%PqqdSq!6_rK! z38T>tQ&7`FNBHQz;;`#b&i?AyB6CG_vWs+Q4j>FwI&pSK&hbe!@JhqZ@2jF81R37R zc@j`q8pTbbVbtMVX}?wQ6ukU(ejlwnU z>6A$P548rqvzwXh2G-Ykj@*hy!jM7K#1duYk{-#N7H6bxVN>gH?}rTGL$bkk zqS`nqHq*kHm%QDuva1Wz!jG;MCcFZAFKaa2DvUptG?dTrSdba` zJyq})U*nQ0K^TQ`fsn42l$)}NR#4-x>VTm@q75u^=286*G(?o%C$vPu9Pv&!o z6QL7V#Mh`Y{H1Z>R@O}20MrXu3ZtspmtR4RqbwJgf}&ZG8XO=?yP9vLp`&*{W3bU- zv>`Kug583J!=V#QGviQevI7trd^M1(oWW5wBs+k*8Ie_ANCd-Y%2^^lOxrRC9P7q) z;H_`AYHWjgfLd)jG`iXkjR2{yV|h1AdQq>&0y90jxt?I9uuTztaU?>==DV0Cr3I&b z2V(48XhTfny=A(=)4Jsfpc*u7GO0Q|hW0}L{z{UA>oD6lrFcA+R+l1_NxZ!ze zDZF`TQP=_=x9$UARBY;*E9HJ)Na6-845&pzHImNpy|qAGD(H0s)5SL^ZWSYi(pi&( z{miglb+=DfK7+pA{$%3lCAbFx)^NL7o{3JL9tyO)Di?i2T1JAkN%2dW|JDxRn-*eu$?Tbexz@y<85Zl<=Pt;;=v|w zAuLc_+Olx>-c}*_q1%^w!8-AmK@f50X0TS%W4JZRjUyF^-aUq+A&v6YPZeIJtBRBK z6O>`RqOYk6GysVtawSg^q_-}NbX2si{1;YvQlrsU1k`rm?0<~Ur)0iOCh!{l`@&Jk09IcFd816T~FHYG^vpJ z;_0)&B#A$hm;J1#Ko>`3F3Rs9iRAAme*C_=`Zi9G z0L=pnI~WTIccHNfPO<+z5od1F9A&2n4SmD`N^;rx1uAhR_1G?m2$?GrB_{5uY^TIy zv{_$^T8!h;*w9f1t`9`_rw+4~rJTL1@D(iY10=GW{b?x^DcZ3FMVOyG?;ati6g(PU zZuLfiR|7q|Anr1-^y_BD6FUr%*kB!e3%K*v%$&Bs9bk~~j_zX5F0xG?U?xbJ-7eXr zD`E(~qu~ntKZSr_%G!`yf9WtFwawEeb}w8uv}`1KGoDWImhSTD-68Adnn{iuTu)JX ztkYqm`;}U_&}8J4#(54&Jl+PEoTZ6FQ?TeePCX(ltaXs4V~g(4(VfyjaH7y z#2S8el=;>8S_|bm@8Emr-1WqXp`CPA4pBXP#me;AElo z4QSIv#lu+NYw}$nEN}|*ScaD{px{4$*~Q?Lw7C01w3wsB&i%72>A@vE<2LvOvq;H&X;Eq!>dY6%F4bT?kl!4;xZ{ z+X4a05#vXYEh_Vo!V*z}ihpOBQixOp=KdLC5h9oV+VD`JN55S{ah5X3Sghc|98&QA z`FFp)ng@dCx{SI3(B!?$bWr=zy}H*E$Yj&WceiOJv!R+vZ&`~aX<x>=-zRI&j@8t3%UYD_oWrS7N#1|psSax@1BEd#3KYqH!1fv4q< zIWd1mVJy}(3Ye%RrtE&yJ+5zs@o%&X#&26jAQ1>OsMIwpa9ScBb3>C?Bb06bS7J`J ztl|jNC$SO?h?~PH{)g<#Eu#+hyCJj}jcIe!*0MFyjwWW(Nebdxz7C>kn?roU#W3bm z|9Bp-tL2x<=OPefX9w@h4r`zcSa8*C=(ox2zmS$NbPQOjVj?!-A#t>jg1Abpy0%Z3 z(#H_Jb{Du&WyTxWJ}Y38s(s9&4iP8~6M>6`SUhYYprK*g)~(emWQnZ$j749Ryyk}! z6ODFkKd@B$JIS~}Br+xmr7d>Orq0R0@`<%u#bI3if8d3Nd+sVU-+?6#h7DU7t|$GS znfp97ZDMJ1Ch6a;_2tB*vRBMuG&KplctE^2KDeIWhi^Fa_O2lOtEc~`itGj**fetIjZ`)Nl>C3rm-1yA}n} zCfnO>nvcdNBSBYq+6e&(wGN z8UPB1uc&D(lWe2N{!ttT6v=f+t%X##*9-qobY1c^B)IOi5Xq;a!zH{=$Ecp^pdS#% zj-=xdLNd8r8Okd*F(M3*n5C^pCXDm1FFdf8-9q|FxuChzo8-XT^O`hyZC$9%N1s^a zj9{Prpx+w8Cgu<}{LRLvPrWM)a7>drRj}ftU=o|v9lKc4ak(Z@D(F()a7o1VdZ=_j zP;Jfo%vP$kvJK5cj#xv>{5u0&G>uZt&p z<45phvU%0I?xF%ME?I0=sK2JrJx?B_MI`X3DxV3&?XTme5{SB*%xDv&RT=TLj;~?E z=oXrmsFzlRoj?dX)4>TNPgl-{_@jC9+q>~ylyFJXQfV9A3}Fu*-$JgXH-yi;W!dJ9 z_ITL7bdDuoeP*RVH3c)b3z#6#MH?j4B#6s88hB*mtB9r3wg*~jN(8qAei@ML*ZPYU zf`}?tk|kEfoE@=k$y#B?b~e5eiiEdLQ~tfvHw0*vPse#5as%kAAt(NDPUAnbt=+K@ z%RpC@Ydf}AQS7J{B`v>^jNJMOKIWW8z`e$PAg5mxy5Ld*I@C%*oo{=dyg^&E5}j{m zyD)eRIPB)-(K-|1!u!>_ku0}e8es1;%rmlnfepXxpy-+=v2Mho13ok}U96&>=a3IJ zq}b6AEoKWqAcC42RaddLye$6r`|3YBZ*~$@lPoREH$(gh%h6V|-GN)U2RW(12Fx8z z+K8MkwzF7y#u4-ioL%QchG|J3?Pfo3kczYqwpcjDSOCwr2|Jf8?3^JIu(l|Tri{LG zV!Ef6gxMY+uQ+JuK}=K#HEuk?vBUz5ZI|2LS3Zl)KX1lMKf#Nn>Ww8_x-IoyS+{ZJ zocJS`(mdN0)0mD=cTNYDc}O>+31xvW<~|NigBs#$xS#_7Ydh-_3pjUPQ>UmM+@%QD z1+p06Rb%MVj6L{^eKE2={K>gac(s`{oPi9)Oamb%z``$N0)Y9@uW;v@T5{BQ>PVu8 z!93m!t-GfD%9`F!$jZKEJ*dheD|8Z%21aTm1-CBR`9HwkO9zVTlJ2l@wrAo$WI`$+ zH$Nh7TCAZGi3HrnB3TDDf)SX5wAUR?>zWr;cAv)UgWDJQF7WA#l$D5Dq5}MPQ$Si-Z|F)3Z7@%*)1c~eP$uN0obqm zq8EQ+;Oyf(lN6j#4xSZodS&dAC|!XY?Vu}tK)$vDj2-2T z^YXkHP>?i-hFaR?Wjj(W>-ttC>OVe~PfT-&kDM`7T%jgdYyoqK--&P{Isgp8?o z`R@qpX$v*{4_d2Zs=ZQH!fysqs2kTc4&`hShR`49?fbk|1TPJK)s!=@$APN%u-uXm9tA}M0n*sodi`IG zXyXtQP!#<7RHpxYHeaoO=d-~6(9V&eH>4{~932-O$Gy=&-KIzOsPkCscF^(dF4va6 z9om>W4P9#uGg1(4}Y9K@&Y%tl9?z>VlI$PCNYLD)KYT;x;-pLHH)Py+B`OBNGpG=p_M^8R$A z#Nh`yn`$JVswgXvW-!0JE!v@x)2&^_iDQTq#4-F{6!=MlFf2ALFO*VS$S6) z^@6a)^6OaH))qxsmVISU1q#MfB>+`hwSpd%{V)-sKXqx!drnCRA5s%q8Dhj0Hpd@q zygWEDOZ;2T?Qzg6S$CQuzxC6bocsRA;?bnY)?q7V?f^4D%)jG6E{r2F5V42gZ&g_n z^92g9HyvQ>Ql@j&5jfW$GxN zx2;>W{~S=^XJMaVq^?6FF@$NidM)eP<)tHJ?5Zx3Jfbe4JrMN&Uo7cKb^^WHl&l4v zsDR{t;PM;8DXzYcyK}(2XxNNEt9`1MX!(=O>v96S`BZXNv^Rs}*?2*wgGvc6)?r7S z>b0GqU`5}!TOzgh@J6!JSDo-)5G1eT+jQVm3VrDSvM6{T<%yRs-G)%9D;7@f*J0jI zbWvl00LoC^7ZrW;k`XkHa9?t4{naKFH694z*GvnO@Q-Mi5Tf-gTEI#2lpWi}tX&1q zDTW6z5HkU8nJ|ZOTy+ogbE*$YUkBYlFkkR2PXuJ5f3QUR8OPLN?=hQNYSk%pHvXSO zTqip7n6L3vn=Jz1Rdl^=CPs@?CM?l`!gSC@(xrQjmGBkOE_1_{5$c8oFO4PJ9L2H5 z6S7>iR6zIX3G5l}qYPtP#Fo9YHv!mdo%4nS-p<*{ZZ+o6TC_$!DS!Zdk{J8V0+I1? z6rPabOM6%k(5j?9Zm62!?dFb1_aF|0pccJY7`<6U_m|#A;3*Oq5{JhCC%DA`UlMc| zuqzJvlM_|wd>+QNFbrGFRNu`|Z?`@#gg-_5BBC^3{vml;x$pq`SCa>QRe6!mfQrZD zpK{5gbVMG11hMeiO1Xr?S|QegxrW^@_q;RQq5AMbL_&CR=qcG)-Hyu^hqP!KzDEQ} z^IN=da>_n;*Qno)IkPAGq3@NgR31tHNn{u z12}1Y?Jv#Bxofvwf|Q~GmDyF^e@#lZfLJ2?)gmN;)6dm_kDlRQlcS@f#{)mkHmh@P z08NXUw?cN*Jz)Eg*<2s^AnBqp=Oh)oC45q|5`_x9m1NF3nOQN-4UhWawnC@4FZe{^ z4^&rKP`&p@<`^9bj3SN=C!Mmp`8YoA@YR)TQo0}P*TxL>Pg~h;8H(h24aZ!P6J5OA zS0cbQU*C_kTv^=^ZIZi>ggw#)39-ft5~#_e^Rhiv;ePZNE}=@@2qK+;ER9<1%yyE~ zL-RHTyskZTtJzj%ITZuze5F2L#qoc1QOIrIt2I|;F;l1Cl9eP!#bhXAeJR@nLgEgoozFOH zB-Ke_cy^w{{qhhA4wuFIjjGr!zi%gy$B6b)X(5X$_gOK17G*>j@o*Ir>KU}Xq4ra< zh7g}QlGdQqlYrq=Unx*rEMrafMhDy556wT)SEL{W;`&=+e=y3CbCXR5 zc_)f%uWcCGsfI-nAMM7>9?JX4kIG*$a{wPKr0)^aQWOX7N#Re$ z<%D_GD0UU)0%qoJKbv5QKET}U+?7AjulBA~K-N78Ol*zvk&lJN5&1QH!4@obm{iTY z9E#tuA;RmCoRnjzshsoAkezXp|4QkDQy<=LyIyAP{0u@vn=*FZ>T7z6Nmfj?*nzb2 zDCbqm3)6ZZKi(Qm+Bl~q+|qM$qtD3>}nT^Pj^Mjb~^Apr_py$=5STwOG0~9az-`V6()y{srfN3vnZw|dvnP} zBSL4ec+$68tH~erWeGbq=($RWf%(`h0>BQ>!-Sv@ zz%9O7G=9iuVN0EZ^@*H#R+eHr;=X^baAG_qDQJ81PgrC%@cvT7KqI}wypU;Q4eb6|UH_PLTn6%Pe&<1!%QoTyw{KcOy`qXqylg~40P=YYXMixF7^s(mYZ zrNr%C?s57iUt*;+!>b{q2v_Fp-Qtv)iP(|k(X{)R(gzR9w{M4Oi$XaV5c)67uuTTK z3vC3WOWjbCVW$Q|PM-R6)@DARWg(9>G{pBile1p^5P-y2wEt;&nYt3pu zSgH3kvA35)r%6JW$Gw|$~X{&qv~0+K(WIp03!Xtm`|kiO1TqWI2*#oY8H}sAhLlyTJAJeTM8i%mB2Si zklyo{{A)pucOHW_X;$n0!k3@pKYis5I2Me6>Dp!JWAJoiOspj~!WpCUA;-4S*4<~; zR>b`tfidwzv~WMoyFBoBmgAUgJp&cELyEkKreLEPl9nji`vxv#fS8fPKRsL1Q{0qw z&bbSg7V#ErN~M6wq)TtM8;d$DDorQ}&s&hpZ(Qm@89zTltrM&&|G6Ys$7IY)<;Qv$Cxb|@=J0qiwdFp4HnOJR#pTM=plvy3kMXtk&)58-7>S&~Cz7{S-H zrTa-qbiN32+lTXPU1EDDC$BsuLRHck;uBDEm#RH=NgrYG%hlPZ#bq){k*9mGRfd>6 zfMCI@R@7v6j6&m)JZrI-;Y*~+b)F3W$ZDzLVP1-SuG$I+`3@}ozoiIVXOCLQl)H`H z3MegmCq`-7t%FoOYeF5%$sO-ltqQB+7AG~(2Jxae_1fiN51C7q=0ubFP(dGQVQJ$p z|M57n?q>R7G0OoYOsRHlaj9;cBm86la!AUH^FUK6#%XB3u6om;e}SZ-F4;O)|9v{I z68JVJeQP%ph?hC?ozrY{pp3ZpQJy(f{Hr9W#kMyMeHd`)06-hxuL6* zIrCLVE z$DITPyQ$hc)Z2j)RuCL&$#%6R9g{n8X41v}z2Kf=A z2%3%tb4PxoASJG0;}0*0B}?*t%5rpM-_k)(`f$YqW?&aY46(ab$nv4=8WSVRN|k#K z&nBnNGKhj*WnM&QY}_m9#ewH=+u&@Nh;BGMW%_x>FK?$V<1-|0ZHc4c_Yoxj5#|8l z{F9~^g+Q@Q8HQL4@4QSPX5DiVzBxA0ylOIVgFW>i2KM8$-}d62nbD4nokuZD74Nr` zSAN>C!Y9xzZDuymNU26(`l%cPqhhHq1;B1Y(79~2KL|nAS1(v<*4U+11^=j$k zY!<2%^ag_~FzF(?sot0ZM z@1ay1TJSuXQ}=s3S%FMIaINsG0ltgQ7pl}D*Y}A;AH^25fTbE*uHL^ zBrKNcZ-EHhsGt>zvN=K=>E}v@z%~n%(-QQAd0coKgV^_ypU``X?y6?d*qk4#)?xp6 zRUGiMZami*F4`R!CLK#Y(Z_3U_I9z?fr>)CoLzViBy_YNtq*f;R@tB%JZDn zJ8-*S@0@;%PX?yTgG6M_V4Z~q4Ayu)a9%rqX<)Cki!GLTP&e&WO9?C6w?2o&GM(CI zAu6Kt3KP76!3xa+G3b6-@PN1}x)HGm{6dOF>t|KHioJtz;ou!elzB+i${E$ zNQXPEr{H7fon4rZQ2t)ln1Vf$yv|Zv2A-{0ucu!aubevB;7DUQr#n^FN*ZsbSm|I zN)^M*JK(s}i)cs#E9vE%RWPKV9X;K1;Ogfq0;VCm+BKg&j14H<0qSuQr|yFcL$kmL zot+h2u8eLDym9m5ckNKL^X*cAGelME0qx|0n`(FG;w@J6j%T*|Xp+*qcw8|DQyxnu zw@E}!*1)}jqO}xs3d!RBGwSi^DqA?BYPJwxLxf6xLW~jl`##YBT_MwXo_3(XkM2blAf44!gpc zs@aPN>TcqlzC7xdz_p8hf;^6;khIKk;q!5<{&tpJO8!m$JRK0=NP@}o!dXKEV~brx z##?>%kzgIL09uj<&l)f-6#o~u7uF6W1gAiaEhHfxO~67UjtWE_Ho1}qBQP$L*&k!M z4Ha2c4S2QhJB49gPN4m!>X)XUzv}%I7AM)@fMr+cU56pXdNb zegYktT=8ees0peq1G5Q#+NN=+`cufkjp4vJHNg)aPKjODm+JNaUcOT5@6)iaNNgOW zs>ge&6m!1g#9pVS(L2jd7&t%vv#}G?^Hv-<&)I8cR35y%cDo51?>!z^6Ks0BQtDzBMd)qeEd?7V+$7~H#>vyE zr~y5uWw8gpOY2&Rb1kJsxz>986`z0_pbWD5B>Ahe8J7s+hxVB6@`l*vpm^g@F$3LT z@H`C|_37vjl^V!iTwW{?30v3RF^I_(*;r~Cj>RyvfFh@J)49t(A4aut`M6JO7vS(Q z`*x73gH6y$X*}Q?$PN7YF+*(5pn;!Gx*`g3M*8*`uOt7Or8i?|&4Z|_+WQOqWMDe2 z0|8adTjKa2uM(aBbz2yYYNB-K--G zU$B#|$B8A7PTn7+y{u*gh*&_^5rsVVLOp~hLfax_Qa6ABK=Eo!n7O+&@jGNAuT+im zu52CcBd-~dhJhJ3SiPhTq8i-s%4}}txw`oPe!TLTbtWQuYKD6Oli0@H#H%2>AkNw2 z1>`g@gsXM+d!a9{YTA06VH6(gtFT))aZr3nN^yk7`W==?f9mb{?}i&OeHTjVg+%P3 zn4!-}Mer05G%+PA2}%xUDa>AN#nev5GgBK}ZZv<_=|@lw zFRm=lHWz>&_~~z`#nzxz2lEqkKqCkMBiGg^-U1ajhU9%3tS3~WF0V&8sIurx;#1pT zT3(=CwY%>0VE)eRMzEvySW{9^Kw|i#h% z(Yloufz+aX$_%FlMN7Ny)i_X3a}l7NVG{;nSYq;?v_m}B-3T<-E^}F73=@h$Ra(WB z46)~d^@T6unlJ;Ju0d35?P2ywwYnSlD50)YboC0hZ)LMEpfx?<69Tk7w89}+C6+=q zVD2)R=&=U&HLn{GUp2V}NQ^k(CTICFehL^D2WS~jnw1mJCS4IE5pez#{le6#dYYRc zhy0v;0~+=7Uq(edcUY-kpwsss5pdSUmcG;Jfilsx!2(f5|CiECwmRn{a}PFyVR^*6 zAD!j^q$5v&mv@;k4B_vy+@doMNc_&3RAJqs*Unnz=hD*-*)TARVAHut*z3fFwy;s{ z2Wr)M&166xzej1Ay^LZJevpogaI#0nXC557S+)irx&m$RO5Ci7PeGcq5mfTJOL$1z zOgdw5a~1qA&0`S9z6yWMa$iXClDRS zO*p{^K~&Ecmv-z}Tzh#Ix_bL4>*xh%b?q2!Kv}gygH7{(7G~I=@sr{BQ2Nx$W3ZKRV|f4188Q-ldLvTHtP?S zLavgnWWISOX7D%W)ViVphzq$;ULp8?Adao~$&0^53Yhrj$uf-c^UsjnW2x!h-8OgO_mn?p}&1^3KoJ4WqsHo|y|Nz__u`OJ)$c-E#j5 z(ZpVSG%K7_zIqA}xoK8;IZg&VU`7A1g)4=)p@bNW9bw$Ee55e+b191(o zfWZm3Op&=~6FA89XeLxgiWtP`y}y9_B&06H6L34EZc#eu9}B<)i6+6}Xu#vvPZbZg z)>;fzK(}!9Fts_yQhn*C^Y@}cwGOkxFCP|?9Uao~o%?^BfFEW7@4_qOiut803bj9B;rz>7FOkYNWewP@W5v$6m_0Qgd*XQ z@A3~~J~CR~e8S*zA9K7Pj{@&;7*WE73I>Y3fdrxH=C6UOOYszG6z9<|gyYW?WOD+9 zw-f2uJ?oSRdsdiDs5sHG=hPRhFRCb-!NOLX}Q@|I1CjYEh(ZusCvy&?!F$SfJTU3crOR^-wW8KE7;{bW? zJ0?n4wh<*@&+qXOWcOhP8?@~KyW*b{1w02XlI5)|e}Uul_4wih6*v?OU)_<99o7t` zFb1?u=jF#f>!R^wonYI0`4 zHh0Z~(Xs|%;l&%uP(})jH-Iz3th-a*U0Xb7OHaC=OAfHSINesK-cIh_Pg3Yt@q0f@ zpGI!?o~p`HFsdk-)4{$DE(cJ!ll_MmrPb``CXe#!D$Y~QbFU!@*0?a%~ z>m89PF3l4M%Q$$IL*%k?0U5HQbRcY#CR=E4wFXoZRN6F#|Zj$0GE(PAEXTr z)g7ihk0DUzb?9fk0} z#QH*Ol$8;?P3aDU=GRRFE~ZDAM#4S${M(j8b6J68F_7n)PFLgkNy_d3>0w*A%4_VJW;|?3QMM%gR)ZA3Wr!PQ5EH6IjrOz}S~O}R{wX_DziuCLyCXbVtnwxMR7oXn|e?NtWlkE_$wX%kBO>&x)Vd;39t-l%mw>Cx@#Tc<*WeIB-nV8( zRNhgZt_G7hgofa?YE%&SF%$4P#-2h_qiH_A=gM7%HWYsM>9lYAXyia3D&F*L4T|cj zYCgB7x}!bUpQ4-s7ibB@f<&07Y1Am6gWR<_$>v}gpNCi?X;wcKqDvOGt`Wuiicg_{ zqW;>XmHyO2!(+g}8!o$fdMy-#&(d;SKI~FUtnW6^%>r3SQ?NCEe2^Wi{-r(;gh0*k z4Elt6SX930alBRRM*sYHk+vf$#W<|__vVG>0p~CypI7l<>=f@+v{fYaH5W`;wqNMG z#)JaOpfAhO8YnJ_QINUmVHIG8`{0I4TN@qelbpPf9}gLZ0gy^%{wblnN>o=$QT-6O8Y6@E667_MNnbQG+CbrjHImkW_>RL@7b6dFbHkfIMQecKgKN z)I?hT|G4JZ0JJHgJ4oj-&lj}+la$PD^_ir}c0t*$rx$Fmr!`q9LE~vEr;a#Lp4%I25aeMEfY?jL<2S?M0g3 zxAl{}$Y_A>qjko23Vvqsoi{j7PaFe(C#4xOp+VW3Rl2>39)2>&`c6H_ibov3P9!j8 zEDPP!pbzj)opZrCki?CRu;6=TrwHI>T>nXa-2t&fJV}L^5_yBD{l35^UpMqFX=;`U z(t;%NpEwG&=`>W3H71h*f62X&5?jsHWI4~wa$s~|{-~CR#XOw_QEjv5I z`vrO(e?q4A$dyQG@-9^lp^iscKrMUPpLnvrT`WZuHCc&Htwg()ZAs33fjB()h~1Gg zc4$W4sUS=5@x8nC52EZC<#|;>yD|RRJPs}CR*;Y!9_s9MwqJdjc`ui~j*wmuu2K2z zr=lH_(%W)Ek`{u|XxvI2>z5RPbw;<0jeCtD?qa4`xusjBb*Ds$ZG=+1_9K<{vwj00gOE~V$qTs~=T+p- z`uOi;?63^A24X&sEB&OP@10*)S2nl$7J-6oC`OSPCp15{b8*wp-nyy6;4Zdc1hI7%^k17Hls9taKrzBh_YCKa5~b){vUqHHV$jhM0WN z!ZqWbl~iMK34i+LRIQ}C7<9$xTU#YSAi^D*XGZ=Da=8SD=3_FdgZFe9WHzhx_91yD zyQ4HBH{t+=jcdfz3m=ibtC;e~UD% zc59j0hK*9@j*Wu7V{j<}pi_E8+S9{93krp3s^uK3h$vz||EtyWe>-y_$TXIHgTGct znSSV04`MoTx!ou13_+N0a+F*IER1wa&SJCnR2jDOR`K+~n}bW}iN3?8 zf_bjIE6a^%0*4J@NI)cxq2HD_OGfg9DoQBM4%Y9BqUGhPmdcqbv%gXIu!*nz+)vkd zJB_}{e<&UY)Ri3(SZ~5{kr)NxEDCV<$k{*kn1dT?_|M21D0AfdwzTqtSPW;gM*lDs zDK!%8=2;rADg1S2IJ&=^v(fbIiohtBe!mOu+Rmy8ctdZdmRp?N}O2|?%00~ax^-iGngha z_~}Xett+sYH&~UjIDIqa7Hs;88gN`9S_Cxc=QXKZYti$vgT7Ms()m2A&(*lit`J{V z!J`b|nk(z|hcxmjV$og0*=~&CD68w}1K6PZs;3?N`+Zb_HD##uO5*lIW4Xheu)$>? zCFAz%EurQU1B3C!Gp&?S3%h--$#LV9!TyT*3T|3?>0FI$zkQRrPg>=Y4o(*j%K7Iy z5beOj(``2~q?*?lcmohce<_vhXU}ql6jUcaCiKhw_4W4-aM59<%K@XgkzIg~ zLN#qhzUS~Z(whG+FMUZ?u!&rX7dal%2Q2o}D%BqYw6-y6KK@?LHI_NmK^Eru3-0tKIjoJ>oD5VGNLFJH~LJJ0&M^#)S)kloJUhq@K=?656iPmVE;vaVZb)B@pSX+$LrN~Jh89PV zVQ*x3#upwZ-T8LAUSgTN6-8Q)E-bahozi<|T;C6#DLmKUiIqxZL<{6y=#kRAwTW^F zpW3VU@{*N+5m%o#T)x=`AXbDqkGvXG!_KhM=@=jbua1==Oc`TlM4#q>siPIsNXZ?}NaVbn2?!-L)3^C*- zl;SdO%BUkaLOj8}b1>N66Tg#AL7|%$C~lh96b9*p+uky8SHq<156 zqU$jRqz>s&VA;+6Cc=TX>`0hzUAN_ zT*98~gmT%AkDgV%R>-)k&=MeeO|Y09vgDDeqMe4e0T%E(>xsfWy4v zvmOTIR#?BQWvAIah~PhhKsolH#1l=TzVtEkab$&DSbmpULzAbblSOow>YFez3YpGO z7G16Cxb{JEru}NJe~!n97}b9zc2$3+ z3L(+%2o%BLYb&AYE)t&}NU<(gE*wj^TrttdF=T8D*etoC;sNAzAl zIsa*VzakYC1&2o_k$B>kRfuJO7RbeKC%eQMG?^vu2z&0`?vgOw$K9NMC3dctxgFZU z-571>*;^xx98Fuy5qVJr9JDs(-`BD82hTpfa`VeGroVaYvgY9O_WJf7WWBD0qny@0 z_v=960UcbnCB5LI8!)bvrTU5E77OW^l2(gH^|@uy4%oMUi&{|yhuoc)_%CNV>1$&- ztD~HC{W@T!@Bk(prw)6CTH-%_>>K~d&C`(G-fcbp?C7qgnc2&c$mJuHl3$&5q$D_P z>K<=_NtVryJpu(kP(w}LKE&?finJ&oJT0)Cr`ynkC9=0SB3&k>S8`HgjAZ{_NN0Z= z_SafCO9<>g$&seAlShK_PN55~T;*>A1vOba(--gS(mCX0akrj2Edc3#NUEks%sXUU z_hooZm)AV%(`CP{@wsCH7Yd>ruB1h^vq9+Jar|r1EB1LO6hPc!?CkOR{*|<(rtd5p zyHrqLQP&{k+S{eqBrc9227qWEg85MZeTG?dkT4-Bzt`^O*aQgl%hYlo!W-~I9D!L- zama@ipd5Aq57p}=wPg)FEHD_FP+6RYc_}~*?!5qIXn`r1H@|1V&hijLx?KH-A4~(VB|BNMouGq=!D({jpJqWK!(D_ita-#oG=HCDyoc zP={I$|3aYk=fg2v5hra*a}i119u~;gF=Gu^q3Qs+Krgl+7WljdCrH zVhF*4n5;%xYX(=Hz>Sex(VW}e>8xM6D>sV?m_;mMFW42IY{9kPG=yCrAr2VhRr??$ zp8G$RJmVs#HX9G_b9KV)sBqgVrhJgH3|!9qH530~6Kbn8_Z1%Yr}4sE>42xc3gD%M zv%=C>)YmnpNKL-K`09Td30#W3G;cVY{+M=kz-i^&8#Tjnr$ds`Qk)r~z-ez@>S}{# z_PJPRvZV)e*h+mm|C-ISQZP4&*|a#T?w=WVlxO%*8KD7T9a>YvmA97F_+@T-Kmxx8 zOL%oy4OJmNkvY&K$Og^EraUdiqh3(Jy4SUEHG2JzBGil3%z0Ka9M@zlcz>zT+eQE) zHta#2So_pBUS?9;TL6e}U7Iv@0U##zBor8;Bc9l^E`HUkGmO=bk&ZrrB5$;a>$RSE za=dQW7UUxYy%TX!kbd*Rj#e}r%V2CL8M4o%AOHtXh&c3fPYJTI&Xt#R#I|s3`dD&0D_{1yaC5<)ogt4_){( z!M6zgqK0{yE^KF$ZH1A zScTKJg;*8bw54zO71lPugOZ-(CdMStTP9x6gcR$i@S~5sxdXO=R+k#{&y}8~Pfjg1 zo?}ZI+!9sH=(WadPqETP{?p=_n|93vp0EGPcuq$H6vKo8wXBvoC0tyWAe~ZDm@9s@FQY54C zq+W_0yXXfR*;(H~|-nH zXy-|8hWL=1dREO4z>$(N0@cAxrj6qIrOXYFN}v$AW)|OiLf8j64nN)Bxa+Uh9XKi| zG|vMgPTxJFcvK$6g~6ItVBlsyqX5(38x;r}JQWnLM)&Sq{JDCv?e-7<8|+4auhZ)` z8p@go7cJGmR5lJH!9*I9l40^YUrArNpd81=>*=oSAWjJ*jYKe~@j~=t<~39HX1E-b z^7|e6PWA!$t@-(eT=A)qPi44& zG_s;1iX<@UC307-Lr-+94p{wg1~5?r?-iUqrpoOdL|fvQg(jLY8Vbeja>hrLq+Fg6 z@^x+FQ+f!iYVm{hmw_-@$+w>YbKTKO|B7p4F2LkN1VCXPpq zXtjUTA=rGJ8i~YXP)z&#J5pIeG#jE=1~y9Kb? zNs7o?b%fMaCgTY+U3dgdothk%L7HonJG;zJjdtHLn5MW?3ipMphjern2E!J|_Cbn^ zGY*3E7o)#(dmR^M@?*_1rFX>c2n{?le*qEFC8{oiqyY>73bF?+P$mN=?7Z;BPx^YSF8@%pr* z1w4LRlxN{7jQn2?78Dr-B*Yq49s$_8{@r$F_PvGvGCJS+;gE}=WzEjVKHu3AC4Ko; z3;xEXn%5eQw`iH(81F(exC80cxGnGLwIYJH{}rgus}l$oKDmE|33u)@bk*`1{s|Lr zQfpbSriqdERDvihuBT)J@jBZU{{t1_OrJ&hz&U_iGtG+K;~}fhcd4B;oThw#e5L#o z=^1<|CjMW4bcn=}BSh-?)yl@eLh3kprR`FQwkbq>=xsA1XNm0t00mPGoUSu*Rv0bb zU3T0Q%fVsbEWijD2*=l?`$$kTAHqIC|Cku`)k>$`J8@R~G{7)7ISQgxK`3ONi?`I&vQ*4T z7rvr9V*Z_OouHo#O1OdBv1QJx$r-L{_Zj8Dcurt)Qq4PfqOUjSk3DJC0+jQV?o9v8NNdMgjL)u&&;Y(FOc% zp!A_3tk>M&1~7VSI^)-w&m+~#@}3T&SEPTSex+AN?-$(J;Qq1-VIN(>#M6L%MV3^|N`4xNPf~j|_ z@yQuV9V)JZh<6WEGEJ3X5c;uYgZ&<_bGemzn@4RHjKb$`fz`c_l~+P0f4uO2CN(1L zBmgmfAHUmJZ?2FI(6?$PSug*_oRH4#Q^6@=Sl;h`<|Xq-P5)Dj{u7J|zgZr=7q|(Y zWk;2_8(}$pc8okzfpiKl0%X6W?HeKjFF zFCOIc1TsDiecs%7X5t*HRH+U%89$$}8Y#1Fl;W3lZMTGaG%eB_{9`^;50Lpat|t0T zt{HvaUVOEm+R8WX1cwQI6CY6ml2FUgV@-3_BN*LKU(_wy51IMqD_mfq?qnVz-?Nq zr5meVGSv~zLjNDiDMRbiiY96{^`8gDqvZLCYrOfCEHCL;n6DYy0l#4GnGrs|^SmXt zs#j54=Eh>*5fx3D0U9KT#wl6~>?BwU;i|}UJr<-)^jGwhwK*3_a6$!FjGAz;gaj6f z3{X~y4ae|K8-rKpPQqZz4?57;Vy}#wuJLocB=dpm?t}iKzirmJ3&N{pfCbkv zo(X+Z;9da~Dqcc|O8!XLHQ^Bcrc5A()+ceo>k9rS=G`7AHvh_m&Kesp>)>U&Od6GO zQJ&EBp1E`NBezf@Dqqxaw&mU*S7<#2_62rOCn3I|MHFsaR={=7$~!| zbj<^_Z2p!?<_}=jNCgTr2^vk{`I6K4b-P}a2;uK#Gju6|5bB@enK}INT;@@w>2mzKwL&zuyYQfpN~<{P+Fn0IHUhtItEZK{5AcHo z2y|$Cil}5r>A4R*N$#{eiIU`TWvgE)pLL@5zH!@u5d`af-4CL3IG>eraPB4QJzhpI zn{D}?r1aH3dr_60ZiP<`^BTFfUsy-z&h+CqpZy$H>Q95gc1j{=%cFiS@uS*y*wV~s z#sb*alNeu#ivysos+%5t3I>Ca{79;CpA9$@WOU1T)4&co_^G!Plh0xUVVTAZn2gQ{ z<$*oJ%6IaLbyr;n&N?sQSBKq~inilR0uhefD{+pUR#@x&!xZNgw2QlbNvWvrU2U!6 zaYY++t}*Kqu&}sVM%KD6mvw(}pT(4>MOV5us@~;%8@EY;<_+@6j`5qA0AYy_hZl@S z8c08}Gvw4$K1`4+!U2K1!>)-HTK*jm(x^;1orWTiDO9vPRAW()N)N&{u^aVoL5K+|t}$>w`Vk^V=RzX9F1Gv%J1Z%{$4E2~6kf#grj2ez9z#qu-oMqG7i>@r8`e;jQ zNi584R=R1)XdH#xkWj5Md=PodWsSvI=a1I{Ixf*-+mOt{ zR0rfGezNj!Q|e-FUSS!gTKh3&FSNR3oVbfE>B`MOM3uJ+hQ(F_GduR);vS!6FAmX` ziuIjPtU%&$av~TXSLw{F4A1qbc)$Sg2iMf3Q*9^YR4+pN$20V4R#eL4LlQx&Y5sO@ zd72ds{>X-$Iu~#TN-qGJ5X8nO+JJEE;QHiX&4atHMH3=?9uB$_-L`fJJUT8#L<7`^Lc zIC@WLTQe(LT+4$(K;v^bZtxHfprK|aRtWVx_z%Pmaga7Z9d2clO2;vptMVxX#~-_x zb$jtEH-1vtS%MgfGtQJ*Y`!=(XB2xp^N6X-F81R zo8fvLP!$`5rkj6bf5%3sUAuK=5~dktUVR_x&y=y}86n)T0YtL(^pp}|Ys}AKA4F;H zw&i4FU8f))*@hpu-tSY?$7?tW+5+^hW(a3sSgx>Z46o6C3@@t5LZ z%zs-LJqZ}L;LL`}0oju7@L|Y<$40?lFnzo9CR5@fBXc_KF^DRTq3sx#yjwMeRo0@M zD+CU6kW_6g)?&Q)Y1`wpYVw#~@^qWIl}q=brHBUfB%1zac6r*P^Cbb&p7~ro0d2+>aVI#VG(F-)I&p1X``wNXFc2NbO2Ev{+k5L~~ zHvkHZvJP_Ho{SU<7$Bt^E0&(X>K~7$z87t85!0demJIg%cF!47mk>c2nO^p9Ium)C zkTANWqg$jw*_X+N+fXNg>npS9UeziFjY)xIu?5^>Mya;Z{H!rs)1ncX{#X)VbxU6c zWLL#jB*@D#;4DN?O^Q*OI$_zk9u{uJjy z*BWc{`Nk?P$M8*7MTqT{-eLzjdI;(>oEaY=eSOv#yU5%0|R ze(;-t%}_EBOPfgA!R0^Yp!T&0gXP&MBo8_t31M`@PtQ=oZk>wY3Q1R*#5B*`P~OVo8_M7$e)=tKFe{Iu*&4o)a4@8Q1pq) zz=he`o&0;o0P}Mrtft8WsX=G-@WZ^Tchg2|Ss`#x(+>A02cl<2-U)1zt!Fa){UV0W z%2k+;ED7Iwg9URUIWTri5fzNcHr+m1J#6>`CeiOa7nK*XMntxC-$X_C&gnX68SDKv znR7&wUzlO@M$Al)}fNSDpy&O1$P*6Mpr-~_v#i)~5pFZB#pSaRu zOu%4cY*Tg%FaD~6E%XXUst0S6;pm&Vpd*Ev+=Ps2%0p@xr}`2O{{Zru1J8GK`k!ms z3dX=c;Otaq^J0iwI=paOHgG3mrLNUUNtG}~R#kIDnk~M*6DlSp|18Al$`P@Y`k1Lt z?*fMv#6w{Ixo}ZPXoh)Xv0`S)RHmL8aSnWvqR*kns7_qFgcSAZ(BehSMZR3ScJ3bG z6J4z&f-4IIUm(sp^T#v(v2x}*oRXj2Be^Go*NTC*0Lk`;d8{a5;6-OAX5PTEhAjfJ z_=X}Ws}ZR#UKi)cyRdFvP6|v(8TEd9m?e0~Ib2fJEr*Y)u;LaLJdlS!K$r9teI13r zB7%*L0rBYE1sF0tRe^G{F-7wfeU^(ne0A{0 zXY7*92mA2)I47!RZLZ4@6Cfx8k@1x1GK+W)~sfTo2uAkSU+E93pN3J#A5=*EWZ1d=UkT za$a(MUu8|vkTaTbPfmFDJwCtDO55$r$GKlc#lP)sUu?2VsyBzyj)J!l(@gVzXu9$V zd#u1h{O$nSYObwP!^}xWvb_m@-z7a9W0{T%DJoMHxJ(+ASRhgBLq;@18khNVDVsFb+V@=li)^6}gWPQzwC@{e?2!qfd9g+$cwaA<1 zYmpj;{NQceGpru!R?;9L0ol*-V#ajbvGNDW`ho8!5IHT^Y9qht_`OmV&ZoMO+4`(F z-K<84l}hco4bW$3BI`yU8EA`VQ{bk%pbZ|ebPa1xSC4!KHXl=*c5CTTeV45MjDjoW$Vchpyb=$M zI`Z>?l9NZy9fnRM*kQN(kg^y_u|hd?`5>9{DvI7m*&drKc@sztoRg_GNT*7c@kd^- zVu)&E4Rxk?rt8ml`Argb}l_t?<=e8fm*stm|$M}30+0iy@Pi5j?QJ$ zv85!JNhRSpx1{ch>U-tsQg!KS+|k(3^tUc@u1&$j^;>jnJ4&Wel7DF+IrZ^SB@iHP zzOLY@gGUm@{b%m-fI*PGd6MH!U9`@JCw*CJ5`y#NIsOsQe z;sRDd>C$X)<5`Tv9qmEpv}Q1VG7o zoU*5DM9cUGC#QB`^R67ed{pEmGDsf?7>tk#cbg<7?37$MQ;_<-7&Hpyg8Qr!w3MS- zDT^F!TeHkKL9E!M+z|2CuwHs0lF`jf^pO4CtCII>d9h7igSz2syt`PIKKI-}5x)?Q z37&^GM!`tCx7@EArS+C7pq1Km>%1sao>~CBV)U&v9_<+^1`;z&*E{&t(CN;KGxnng z>OhN_c|dbnc%uGw5M!|30X=u2n}M&kJP2XND{U)C znZlmsl4QEtWNjQlWj-|&OapXRETE0N3n{Y{>_u>)0|(p`tyfoTnJ=^;mYu8BpkHh2 z2)I}$5B~~u-=-T*J|(FV?GW8#10cu*ROnJF;Ls?)wt8N4iZj0G@jED_IUb}oVxu4Eu4SRyOz*9Fe@et z1<7UM9pL(w?bq(_1U`goWtKXE8#o1Xf@k}|VTh9;eS!*5Ta5aY_8ys%bVY-Qb}f$S zB9454UE&c@SAYM?h(N7t{ObJ? zq_>qppgeyNy+6IH4k=p}G+ZP70M>5G#lFLjx*OUF6k^ONHr$%wxCZ0r9*GA?1h$9a z#7Lar`*>n|4^qUi*YJccymm#djfR!Ob4+jXdY;6=YbwIfwtYzr6q7es0G`Rch?>H9 zmGqvL^VUdqiC|SQ{Or=O7_l|RXF?9b+6BA6w>9?q38Daekk-VpDphu@nPAjSk6E9s zBaoJmV5i4+$O0ikI&Upf zlz>1w`w^=RKj`d-Kj_f=A9bbYS}77cx)#=ZoCWS#ZvDH-_J?M-K`>#kiJ1CmvB6Hx zCDm3g<^$0-GWXpBZe+H3bu~|ik9rUsO~=Xw%4o2RBO?g~ zoYu)}@Wd`n=w{i9$n(?i7Sri4ygDy=`w^;ou;R-{&gGC8CU+bmkSv6I76i;2$cgDe zW0im;v_DpbfyLY1$DU)CQwv0V95KwwsHG zPx6^9*w@H|r|^?zp7SZugCS&vmJwGneU;pKa@6B0(>><4yN%$GloMKA=hQtX-pMbN zel}6d7_flpy57NV?b6N%i-;%&s#cv?)O-6XGg=SXLJ-V2X?>%*y)T(o(2R-J193~^fbCSguf~Ugc!#EG!eH=b8|D~o5gi?(--qN8Q+ZfTx7`$?&#*q zcvnYjm+yA8B*YqeI4*n*f3whh`Td-;NNEjcBl}o){$MxV@3#)}Gm&&lcd@LCD18Qd zbem#QfvF83FF8r>x2TjaB{JdWt^G&8 zqu~kZ`c3__B0oN1wNX}&2;gY6F!gUYg^)4eRAwsq`=6;_v@tC#x691Iv)7y{e(W<{ znZ#iU*`O2DqLs{)<7njiMLGe$<0?}EZLf?i)%c7aZIlZbtc_9hL^O#{q};47;3$t- z-qlX*4^T0ov#Q03(z!wxKG~9Bn1#%glsA2Fd0*P)E1+H5u(1NeuGK3#cC_<5r{Qlx zjN9G!gEF|M3=hc1B>8#)L(Q2-OhXE6=R9COQ4dU z1m15lgKvg}#r}Q&q=qh}P)nPQPQnx!m=S%?Top5lp^$u};58PX2HA7jt&rf&NN=)% zkune|;bXuCzL>o}2VKG~#h*)1G-l6|7!sY-xFeCRzcuksECOCUnXBC@_Tl9UPfW@~ zb?>oYoQ^|nQVUw7udNpn#U1pc;gO$A!3S)l=qB?LBgvwb7+tE^GuJLAoUa`xrJYB` zSpGFM19nHg{VG-$O}$%=gM)IPoGLJJ7YHrQ{}PO(EE?;2Oz}3C>mbrsogKd01vJ}Z{$3m@G<9@foz1yXpFb^_!)KWkQPnY)U&N)mc4 zY0TB^{3jZH2IZq?V__k5GO<5y_@ySmwUP`pixWh%JP25M5D~}+ywCT)of8a6|F7p? z6=5N$$_Rx`RTVoCfhI<46{@EF?cNxA>7^;rzcOAIvAj+QYE^@&v=u>H9HODjf60d~ zHJfJ^Uy%4~XCJSk2a#K5C1--2w z^3HuMJ2LEP28T2WMYmFhTVxjmFEU3aKyDbO(s)xmN|?aEA2C2vl`2mHlf=hk`GGLD zt@TqQJc}9LR9CK{-44!_#uNDG^+3K{0SYkl%F@p}3sId78FM9fDF!-gNAE z)-D}tXXdW2y@H>ICe&{~R(V4FNm~q#0Nq($hN+nBlahR-^hvp>!fBbQ;_K>P`b=sH z)%E)6$DRd_A|rYg6i~x)6y3j0#xU?aF=AJUHpa;7NFZ?11yc{-|G2*wGkh>O@fFxC z{Hpz>CZ;wY4R%?*UNt5IhM8obLdbB|_D*SLL6=+iKv*#G>m$OfzZ`80n(wtZannc{ zcvLobE6@y9vV)<*ua4>idOAvI#_K~*rYpk6nBcHux>T>Yzn)<^ z+#IK5Ub0?N;<$X$mSE#NT=nya&OO8Bu8fIesb=g`r+$JFZaUT8`QFR%y@xCR_$6ob4=-*Cbw=BNV-D zC%?;)6KXmYB+iwOqjAB5msae;LlWg18Q^u}8h)$~z80NR#=Py+uS#yktvZ^_EPiLW zn20T=FVF+9jzyO3%N-mUJFR2(@K8FTIWgBeJCNDP=dNp$g=TFE4m^_1iyR!;i`uV3 zS{+m1%ai{zA^ldpYj{{qOyEG-k>UPP+Mm&25*ibZ0HDJrOsv6P(N_jIscFadU-=OF zP-Z?A_phElbz!~kojr8yfLU~xQ=cx&^WYoJgnwp2rqZOT7N;(wq3zHK2k8`Cs17Cb zELo8tW4U;+%XKZ@!nY!Wsdr~?PCW1g2_!?>uA0C!^uB6?C?4Eu5wj9JW%Hrm%z80w z;8NNJ_DCwpJV`kY)WXkkkdT2c%Mct5GV(CClwmRx;){BcCKr<=~6@a)kcT zHJmqH3lrQ+tao0h4;h@I2htWGalSj4K8qdkW2WlZoyFXAx3}Z9co0NwE zY?n5lsMiZ;Quhz)XesJWbcDLZ=pQQZ zlzwFWXrpbDAYh_;Lrxon3-2jv?l^my2U1GVyu*;NHssO};6KGi{^EAisjK}7ri898 zMf=jdevmZykTlcy5DXprN#z@#v?S#}PtCR!Oe+v0?WA4=+d7eH^!DSZ!H7zcK~dis zn?)j|W^z=ap(`ANHZCwMC1dfm#eHNJLJM1FZ`^4pV12+pUD-vH^1HsDrUHT4b%vgZ za!h(Km$F+fX;kNrfy?hgq_an*85uGHIYMV7Ad|IvEfBIk2@&Qh4qMj9?P2dbKS(W# z`*(_tTRDATwj_s$LeI4T@WZj~k89_|bKYqTD{avjnkG1h{ia(tpxDw%RW(CO4rTob zsP8jOF7!ZgdO;;NHM>)#>Qv9WRW?u>ejNxZ7M!8Y_vLV%IejH6ao|aUf_9Qsg7xlF zXcEj*GE>m!TgFVg&YFx_6LgMggiVt(Dr?Y1^IJ%)*5lsKPvF%sM=8oUP;Qd#-i9q5 zwDF_({M*5EM5Uu-Sxw_^In-qv{zD&SB-;P4;X`fvYKnHmIYwR=ps#qKDmQsCop&Ty zPwKE;gt!aZ{$qi+s+fn$Ql*pD^Ae+;8uKiEY`u_w|FHl?ac6l~q)HT{SGa>OW8o3?MrIY3Le+q}<+dtxflz0y3E6G!Mw_#BQ_^{dNNFJgn@0(d z7Jpgvj32kJ)>Zgdt>&Ls;DIk-#U<9)0yjfiNcB+3sa#KGUw%0jctcqlUdIbUvyS4bx31kNJGBvKPFW>kqNTb!~PT# zCU@qyjg%@)1CLLT)Zvw(0avWStM#)u2SFgd9AJ|3vAQ|R1iQ`|)ycZ1X``_^4mwi8 zWxEFb4sCAq{n3W_U4`s8W-Fz_hmJ~>Pev#JLC+oMm)8!^=tr20YH-q1si^SGWj|#e zDR7ckD*=OJj1RX82%ryxH20zxAeZQb_Z_G%i>Zg{ENjN~#KjO(2VymjHgX}{UpCkh zaTn!AZm5?uH@q*$NW{3SpknHId8K89!#DU3v@q_ntTFbKWHY;`kDa9^bIg^^5WhVL zVB;$wu)&@bg^DzuOz1D;Tot!I(zf)dr!^0H-|RQI3#ApBS?+n)D#$H|STny&;#SmX z)lm3X+ZX093r>8dS`lnO)%IW@rO!Eq5xPizE1x5Xro(A`Uau%m(!M#K3-{$XSOAijBs(3zKX1%yDfSa}!o$Xz~rJ zb`nH?QwCZsBRidx3IoZ&o=K^sya?jghazD0CzkI5m=@{KI zN%H+wZBMKs`eSjbeb#m^_Gg<{jncfC(N%DGKH|HC*l%A>k|}41s&ev|+RGrmFTv@` z;Z@?$lmGZBG;uNqL#9K`nXZtNROC;z*aaKFN4GVq?HyPqVvDfekZwFb;Sz1T{CMoX z%;$&q!Ti=z$C4Zn9uRCzuqJ@s{kXN;SVt;5Z1#x!M&pdW0NvJ1sZ+`g@wg}ggZX>Z9AwsRj7dD9RZF=q?*WR zV|-Ar8xzE8v#HdNeEISJLlz)@_g)!0aL*s-&(&3tdv(aeB32;CB+rN3rhwrM4rLHR zeJ{2Yag}8zYZ;9|tIA>H6N6M|FRmq7GMMPZUM1wPte?K6M?HaElb0GB00Dv>i|R5^ z#?!ssypCF{BzPapLAUgt4@J!%f1nV3{0dMiFJXX<8)YlMbIY*X9*+e$4PGt}6l5x+73M=gzv^d!V6}f@2H=b~WIci` zm!nl1(dHhOW@Ceu>(kC9{sk~`bd#wm68L+E^RUS-C=QKEK;{DVPaAB%{k| zBz_DFh^j%j^^NRwoxQ&RJDXS#oxpuOl{&1r$07w_Z`-bBh@PenmJAKKlVy%mPebsg zU)TyV&ul}kbqoo-PrQ)a#CTf!Vo05(K8#gp2#7HIpWmAQlW{+;&hsE16MFr#2!LKx z!KDvpT@jLfEZIHL$tK`xsQmNjX8DS}VGk~mqpDXQ^NDOaj2Ri@GjAf?lsz@u*bh$> zQg%iJ%_x9qAIi?WWhp!y!z3t_)~Yf)4p3kGj}UN?!^wv-!zSl1efIPwh8+?g15je( zx{YDKt&6B2ag9iRQ~h&YN3R$d@ye^7b#c~^nuN?EA>L4GTuBVq`2p}Go(-L#ni2Zu zLpAC&J0S31`hbq#%C`iFp$XjEc?-I48BZvli&yyQ>USZW3Nc$3LP3wq{kq zDZO&pWfYA@E%lu(r$vQ>jO=mSm(MIa`imhTesk;2esO^DigO!53~vrx9O%+-fkS^! z!!@1xyY)>Y4-2=|*q+~9k75%ZkfK~ixm^Mo>}=^YoWbP(4_Tg$Hj+XWfrXYBtB@l zlvMfa=jZC;z(w%%jKac@N@)l9W+*X^*M&L?PB%o?nGox7Cxp>`HJ zwDAr|Hy0NHrSOb!G%pS-NGHRlPpa&Py9B*`eSf&XNF-__zcop_Tqb(YLhIE#5&RyhD(70dZ+;S{8^| z)qblX&pK`0&)xOBU+sYK5D}HxM{{^F6oWc*^`M;Y8uh-m?=qOmh4ie)upBK*PBFJ* zqm&yE{&65+5=RrMQs`$?mbS+AB|^y6r@cHy9R_Y~H0b3YFbaBIn3??467zfN1fsfF zPYN^poBp1=IrK0ib!_>jeP0dPr-#Kw%e>#1e-GFiQ>*-&(+KV`bV}d3EBtG_YJC-5 z&VN)kTE@BoYM91}-m`GiBw2U0SR$9-YJ4Df87M`S-;BIK{3b8`+ID!S24GOR|F}ed z{D%Ac7sOl4FTo&uT_Gu2z#Z^)LJ(gv@wm^dA`>jQro03kHh1#QFyA=kyWzRtI}r{@AI0NZ0~nQ4aMVbBO7n0x?rdIefKb>590M|XfRmSIZ> z8`Pc82GX)J&e?Aj~rzB^!y-?054bj*LaILR0E zf0R249G!mKaLfn;r4Nat{H({i8Kn!ZvT~DAzxE=+QhaK z$;WH@$HcuH;@T!f!yEmU#4%Uy6qPY5Sc;Rz($>NXEX5A3m01;LbuSMl?6FK8knUAPkcxMq*Wr2V28 zfubCaP$hSYbUnC%dNE658+|9_2&9cADOs2*{7GJbFV>emN9YnvD-A(4Odnr=xm}v1 zvnV$Y6~GW$fUY~)E6EA&PlKB6Zln{!xc2GD^{I4xYmJv}or~$})2Eue}w}Xsgf7YbWv;yOOKZ@|NG~q4eaf_uCe>?#C-0L)9)jAf4 z-H=3rRHV~BfL!3GYh1a5*5~+xVNPM9QR=KBIE^TUb_e5Kr#JKnjg)*7H6`Kfz8%-v z5S2YD=bN3P_ilLh+57F{MX>?1Y(#3I3A!W^CsZfB5_3W6jCtD{n5s8yKFk(#+*z!* zsAhz~t4T!|icsi39}ZILOrCh&#eTr)*8H(4v)LmO)v{rmbt@SR!~mG+=>dBCBk5UL zk9mO2@}Q0-tNU@WoD}LQhIVNlON>Kc znP6pKX@b&Ur+p3Xw)ei)(eMqX3}A35sH!h1mYhEk{)(PwL#^M!n9C|1DX;8uK4pJ89qmPDkP4gF@av$eL-1fl79T|JX%tkk;>CD{lG#O-7QsWr;uEu*vy;pH`aj{x(7 zvvx9l(qz!!Fi(j0b&RxtPy64B6PBCRydgay_@k~7JmSXzr}5c{w0h`Q*!|n2K%$+E zma1eaGfghQk9LCjU#&3iH;ue+el%chP6JV(n^0e^6MRL`wC(Ie+;Bu~prwK#cgpQd z=<`xhhL+Th2VRRrSZY=dxEwHRhZI{pHW)TC4Ujn29ZiXJ-yawMCPrK$K;UrEU)ki# z1(0bwM>2kb`KoacYRgt!E+zO>B-^zR&A~siccCFgIb19Szab{@EyT|o7x4C@8)SJG zEenryhxDG?GkT6TEcR`L-VJR=%C|x|P^b{w8kcuumIobMP;F%kD(hZ5IT^II4q*6s z;CiW2YQL?ExqY&6_8+UPM6iz{p5h{8Ew)#Y3t6J5__#o(C=blgt!q3hBU7{z`cqAR`>h09^p~Zi7jgx=n3?OEQe4673gK42#~1-h@v= zt^-Ngz$Zd}7z?CZv5(Q`dmn~h(oi(bq!xId|BP9e#bHV`RQ|3$=(%ih@I*}gbmNB* z0%}=wDyPGrq!{^PPb9~2O(_Lx#2k%nM+E@g-T5FDF`n|?iy39AMa6DwC`@!PY_e6B zJ;>8~^qbd{VluBPiLK-@ppUHqrDs@~rL<6t8+5;mg_%7vF_V{fl=~7c;`;Vd3ef0- z=ph`KIua`s`NvQc6bpbgKk%8rA8$TWz{ACV^Y0~qq7493^p?^-z>8`GC9QKZQ6`G2 zD{oelDdobV*+q~@b~Tye9z4{NQ%25hJ4bS>U2`YwnWEdeb2m6Hr_5P$FX>Yd8Uaof z0HdLRdpEK5N{z!FtzbRDK72H~>`=F0`$gt9Nu{SwxK**dMTk zg+~I1ei~yKA?1<};&}}j`U+vl{DwOkb7-M`BZ(aFm)qUF;${+Oa%&xU+Mb2@Lyt_h z3m%Ztq%|(eUf+Z5I8f|t4-N8cGn=45C;lTa;F2agHB( zTL1)POYFn<>JR=k9Et8Sp~B+}6D-xsB2WUSkSRF&FyILq_Z&j67fHLOof_+=-u%9$ z6p}#?FVZXdAswih1qNxMlxi8-_bJO37fI!zk(7d8tu|GHqDI9EfWb)On_dB)a`PSH z+3HkMjy%MUPU{6m(vBIpLc7snb<=ZG3 z4qm%(&oKW^#-Pc652|isy7t8tNX!nx_$h&|sXh|oV3Jph>hulP*#gxdsH|-7^pL8; zzn`YOVVIIH7u%8M$ zeGv5c@1`)@fH$n|=(6*ZXv06ZK!CuDu}J8aU=1E{^Fb0>21)tiFL!STF4>(`Rn2F( z5Pkj&e}wQdK!k4?#{f`x_$5TO9@X&L8TJsAi$g@(mF*3(hzr3U%37s$tR!MmJQD26 z2GJW98yv(-PhW!R^{6yvY5^dD*9Du;mMR;Kf{RpjSp{E4NXSD5VS{c1z}jsJ?P?0R5a zN!k-p4!>{UYI5Yt57w7zKTp)mEgdD(Wa7^u3k%|Ph5mJ*L^mv;hA*0G5m5>Ys*N8^XH4u{%=PCmZNGP{XB)nB`t4y`KoK2KI#I2# z&=00*Envn&hLl4yh0n>ZuBg-qKKFJjw+y}ZAX+7)FL`J1Ynh(3w=wzKX;~bymT07qTf|*Vy;u~mPgy4Y` zsBufO%G54waH`haZj5;c&@QjVmwC^E3G@LYyM$*(jq=jpRa$V?k$ez=%=F%9Q0d-D zwq?dh@PuIcC%mmQy_u2Oow#t}e#2_I4?|0ov(6jGSJ4J(IbpN{&cvv)V*x39vzD&{ zTVQsp#CBI!qcw4lu2OZzokxSwbX_{m1l31zj8?C~@|waTz7e}xC>>$ok-HPMbhST@ zS>P@af9fm4=e1Xa%JYNF7G8C+JcEcYl{$ua~B9#oyJ z`9r*1FE33nHArib&NHOy2oJSI|s}|T(^S~gcWvxp2zyO(R^;tIWV|ekN zH~jfeh?%e~)n#!`Ho58|nlzlSHEd}he;5=*y{*Nz)-m|t9yLsNbOuL9u1;!?gL-X} zn9kJMO|=}L7{60e*oP`oK9?&b@Op|3*oAhnG6_Exy-h7VI86g$|Ii1NuyKI-Ew%yW|FNH zk$AvCSRc>B#+FE&H09(2$9#ao?}|QGc|^mVB9uU80ydVpzqvHzc&ciW z+({8i$j0O~41(LG``lq6ob4~;J?1$a5C|*x!F8O`SRcpDJ7=XlSSip0?voVr#5IWa ztIi-OXZ{Y%LBVj#E5iYkRAyZ}<3G`_6Xk5m-aZ(Hww2Y1c{la=xqCGd0>?4iu2v23 z+h!{9h2223xjgED6?_YA1TyfB4U3d=yw%Br_RYMA4axltH}W($c9M42tOYP;tRDPUmpdQSx*KKuJHG^BZ<7F7$ssim?$F5jMQlDu zMf9cAV-+gcim7E|X*JYNm};Fi+ilA(5G$cens`YGkLO)`bp9epLnY2L!3*P z6pMe|F}xEfI1{HGXb3LR)6tnvbH=02E0)bIfjGCW^u zq}++PpY5}^T{kHBgASq+K#sKVlT12$Z2Qh*Od~lLn%xQFrG(j7GQ<3JJ4h%{e>GhW z6)E5GK^6wZ789ZDCEYJJvFFH85L9n@%Vs+$5GXBdxT&f*qv1Wj6mms$yzpj0CzE-+ zu%XIbdq4=;(KlTvq=-+W-2Q}kkx4avw(`k6FiKwzmLE?BOdT)M{qbV~*H$i$>(ec^ z%#>Z0rGYao4$zSG`d-Ji}m$ojdiW}eyBt|14FRV6rZd>+8Fo^5&CeK?pa8PIv zQb=_yv-$#rewoPJR#nBqUlEMJfeUU@=wO;i8|h4xAtagDR@q|kGMw0CSkzGRCl zLUV}+gx}7v>-!n-vB0T5u}?!lE%atGYP;7X$@H+h^D9UeXszG8qIIax&TX3hGGex% z8o>NBu~u8vy0p^^zX)n?9@%ey_{20??G97s`yxzcs^|9UIg|o?|5J-;=b?YKWA^GXyCx|T9XP}z>#Dn%in0A zE+i6TVz)aBo{X-J$AIkL_K9X|j46aM@;E~nqVW#^?(AP161Tjksr~NxVNixJ1Nc`I zcOJ!TJ65-ow2{{relI9JDC%YO|2mYsdaOuW(yWa2P#NBX1}3ZWr$! z^na?x9bd>UL7>gLrGo=iyndQxvgY0l1YA8YY8;>+|RBO^o5172g~b`sOf*3iaeuyf6|(9H*!? zunT}OjO#t!QqGpcZ?9RBU@*PHJ!Pv$hOEMkQ0x+;Bg0Jre+oRKGDwBc@#Fki8H5go z8zB`T>*l}^o$u-=?TeIsMv84bm;zNHmN9wz=s88)4TOB*JRrHJ=y?;b6BtC&bpp_} zeMHo}N?*7ap6oes^SBMAx9_y}eoaYJ*S89oXePYzxF2&vPgGQSkfKKoX3g2T5B?vz# zagTrevQOt8Ap6%>@qvc(_2%L))Qj?OEzio|S-#^4Wtb2hZCk>9C~OdPCp+w-^| zZ?{hwYUb$`-E>+W@|XXI-DB(#ZY#1N!{#~nbYWX*NrIfy@HKgLVrTWAb@yU+cqoK*6yeaH{Fe!b$Yx1#`E58?Ey~;>%LN%6q(CL21SL#?H5^Rp;*< z^tYc@=y)p`JslNJm#B3hh>4ea#nrF6vsolWA9aX2VGASA^WQNt#X)4O3-K@ir>|=;@5^@f5df~+bQ`X^4pB}P{0@(V4-%Z zmVnj1Mq0|2F@>9(@B*2H;?Ec4LV3EKpVTTfy;!`rgU2Fspu1I)m)5-ENN}F*31?kl z2OOy1YAX(Fhq z6MMc`Ms6yeK)WO_X;e%y?A=d}3efwcgw5K>7Lp4CF!pbZUFgbHskIQ1$Jdgc0h7Tg zeD1#!3BzsvJ_FRM&b7$>=5J~rJE&7DDND%9UNjrG9lp$pq?T28cZ(pZ`p;C z(p*ag;m+Ne~ole;2+B z9MMI|%oCG@$f6<(8%r=B(}HqJj7xEVpEuon++gakJT*k-=SND|`C0(aFkjl7+afuY zC?qQz%rMmwNX3JJi0CmJd2M0$Br!xRM?^d;Km_Z*F)6;@f zy!c8EOhduP^k-BF{TYk+*s@(J6z(}~?O#XR82v80SzS_ihr%d+wy>whV3i;Ht#St! z$_0Dgik@sTa(X%VH-!B60NbCVE;%`P0Fu4cR!u#^%CSi4*J|&}Dhy}HhJ^LJXrSb?la=De9_xkH6ts{ zEc4G}_#{xJM`T;l^q5X3pF)a?kj1K#Fs=2#dXf34gnP5Rt5%yEgNmlu_8;gb!Wm+& z9XMmX7IZMbNm6Nr`-s*=Ic-fNs&$&JT@vQQgZ4|QyVvSH#((V$syXSMNo@0*lQ=tM zJ>TjQY(St@5{fE9ls%N&HF=hgqa|c^$OoM8@YedyrB#ws3MPE!hXRp$bIqRDa=5O6|?f<5D9lvGxWWXI(09} zW|7j;`6zswfh5)vsOR5Q7BmZfUHA|T|6*`6Z$vGi5n1Iyjo$}6We~LRrE1v}BgNE6 z%*kbid=9=X@%72Ch3vZNpl;$HG+{*iQq17@o+jR)IY5NC26R6919cn0s;yKaONLSlu&O&F)3cDB z{;tzYlMq%Wx&1(lFv>PWufVA@uLO01cUJUKu~QAU=F-1(`tTImv^x=)XS zE;G}H@AT$N{^}|SPcirw%q|RBtU-0@m%nu-@+^p}3Na!ABG?M1M_-INgLYbT#X~cn z)|^Bvk2MKD2E16p-sK_fqo;~1KqIyN>gZTQ0Wp_HZ!YaUK!|ixsaSQK0FpSNT@T{t zGI@{qFv17#zL-&;rt#sgav9uS<|^O%A#U|)OrSX>;3~8|@VvA+V;Yw<>@~&)irK84 zeiP%Tf!3hIN9*mOXL5iv`J!artKOtZl_37=K>mcgqTLL@ySnjY!qXsNblL%Wc)6&h zNdf5`^3rA9$-A3NyRbpB$fz`kCB&*g>ITSs>9~?iSGuiAD|O+-3G0i8`U`bdj3&*; z6(IBAjQgJRY-dfsCn<%rp&U9!F0P7Nf-2sE;(J0`+-Pw1a;UV{|0^ig0V`^7a_f)C z`A6*4U6@+VSicBhZ||5twIB>!{%*(62-b32z~>X7`7eCppJ0*81{6_Z&-IKjMU)%cr6BM+cd8W?hoUx~4PO!;ZNCzo7a# z{qlM2M49fy6}6JWQMc!A#XK7Te1%-ZarA|0pCMEazRRB^p=Hl5zd$41^v5n&Z>-9a zJ;og4O64F=3&x*26_!8Q}O~=CH z*%RxF-r}*jK~c7C;7+^SCpcN~KPab65k>zq(7x^7GUU-H0u(bF^sag;rX#>00)b%? zZ}TQLO)I~a>$xfLEAk)l>9ah)iBKSa#mIS&<1`;XCTWLDg9=0Go^l1f$pU1}~wr-e)t3s08VTU8SoxL`Urd#C~Ye7~wf8T6q zV`0T!VaO=7CdzpcARm65!F~@oxR)U#_2tK+V{xJbh+I!dlGu};=8j>ayuiSR8dkrb zEG0L}wsfp~nBZAcBO5yMebqb>i;lO23aN< z#YN)(nPL>8RtTFZ*yUT?!`R`r+DYb9uI(K}>>0#8;ItZS^fZM)7;s5!!iu zVOr21z82=$deTj0Cf__9F^1CR*(#VBKJov?*0Pwt=)%h237}(XJ7+XqmMboFpA-hc zTXUVGCy0T@!*F;(n15zy!?s%oN%w6ay?&+w2k0Bz!cwT}e3`R4O?yrB<;HZJo^eAf z?^!UObREK4*fUcd-8EuOKm&8=%Oj@mkTyVVAv!n|wEMLGa?pqckvMk$)pt zKqR5>s6s;eUUmlm!7C+9h7mz-4*mPQZ=)hq)I!Hf6IUjYxvddV<}1CTah-r((Ix?F z)$1KGxz6pxjjLeTr-mkymUnxgnaX#AcO^e{~!SmC9Cc;kJrSq z337lDM`4V3EJnO&yv`1-2)L+~G2N(n2J{=2m5%9~X{HchxgCc-TNY{hCtQ>6*GR@} zCcmS{%;~MTTKWFW)Akfg4ZIA$k$k|_8(f%YBrlR-1sZNO$Xs8+YL%rP2-eq}p;$tXv`&gZs{Z8U&)Vx^+zYP5tTi!qf zBe%G<5Ycix6NR_!+(WesQkN2)XI}txQm`Iu`}v9tE{D=qwIBpseRm|VDj`2ozJxmupmdz=*c*p6Jqf=C=pQl7WqI|NBNgcH zmC7Qi26dKQ>x(oFU2LIXV1qsg(M z${qtRNMUmOpbJnXgz*=0PYO)Q3@wm`-#AR| zRXLE4E$048hGfp!9Z`C#pi@z;V)=`=xk3nwITa*o3){W3h6f>>V%Usa3ZLOM4TJ04 zU{~W<%`GrTGM@yd5s5c2=4rd>P}eBy?j&y5Rd1!nOqNr|<-tiYRv*=psRWf{VX8~~ zC%Pj=6F)iR>1lTl3s9dvfKd~3bSZ4GJ9Ld_%BxrQeTJ6voFwA|6E)9;0%4vu0E8^_ z+Ruabu7b*LYEZ|ac*{qZDzJsSVDPLe68s8arnB5Gy;qVr{*8^k1!#Q=BKLrgE`g?! zx1SY%v4RE!?)wdT5>YV;{H~tu!TPo7(#BJuRJHz9-zu0k0fkQM!42eCp=8USgxD;I zC7^{&IkI7Amkx@4{vmg1`$ex@XRsCfV=-fp)tNGB+s;;oc&npvpp1MRp0tG5!(ND8~`egdqsxmJU?kIW9CPl_5Y9 z5?+%TegV(TndOXtr8}@yA3M5<)M|3yGYtc39xNdC{k($kIFC0R>43EAADle8( zJ)jnRixQRU?9N2Fmq$m%{C-7)Z<<7T$M@qg!Qme#a|%O<$+~YrI5DC+9zm}U5G?18O zMPLmM5y*DHkCg{Yex5e{yugFT5ydPaZotZUBL}~xpen1?-{P!X$SY{*PW2|($4>L) zEXJ1bG{N5viU{>iQBk$VfSjT(1a0XeG!GC=+I1OKxj7cDJuD|zs$0C*4Y%CapV?&O zh(m;^(O21j*YU5!ij@eT$3y~xRw8=Ut^&$wlJZ&95xoS5MMLs%eI265 z9r_Cnf>$`lxNN(~h-tDQ&mhksCbHP4UYoPdDHpnEm`T(+&OJH8{^RPQ4o6?GX{?#)OCy! z+1^eG?$w&q5acZ2mX&aVy2`tYGZAlQlEax`4+5X9_Q4qDch}NlJfCTImuuUP)aaBf zAY&N!a%kd+ZNZKwm-3+zKkt&PQ^ZUkr==RlGUmD0f^r^7R4hS1gn>fy+sdj4%r6FM zbzddv>rg4&_(&1(SM82%KY^HOKopN{?~5=ZMy`()1%NnGBw+@n*ZSL>G!zL4XPd%< zapG%Mgkr_@WPE6;s%)y50b}%0K8|Y~pop{ZK^II}v)N*BvN{q`$n+I4+iJAP2BrK7 z`pxf6HV!NCBjgP9DEHqenTFh$_0@A(vG5z#=QwvAp8N4gO$bM=V^rUfAMn=-rmao1 zeuQMqx_ka=O=hTmtUz$_=hhs$wym-lislk2-XRoi*SIRg2cHs#iK+g15rmPk{VHmD zvvJ#x!Mr_P2uv+{s?}<;r7x+eBi^)>k%y5eXWQ($bVBn~je^*ypE;lcxL7kZp%j#o z4k-;{L0!ugJEXaAOL(Q{fbDI&U+={lo59L8k(bdZJJajSr7l*SF14u31BSiyCaA@Q zp47X<5cVh7HQ(m_9IqKf?|x{zJE`-c4`-18T2a+LUcQ>ln1L{n_##3yxI`|?je^8e znP93X)>6K;l*BHYRlCDMa5Qe*L*m#_*>f90MQfcbG4Yyv%bOMXR;Dp|+iD<4+H+?` z&}?x(Gqs54MxqZ2gcHv$KA$9B!JJ?yV{L(?gtzR)xpwweWq4bd6TYqN6r^9`(KHZw zR$`e&{So<|9C8MG=!l*rK%6Q?D2I^4UuRyT1C-?LDLpqDFk(WTLGV)U;k-&L_yykh zN-}7cKve==Ytz`7K6wx2cR&pn2j0>fDHUqW_+dP*XRs-u>YqggfS2pJiV30~Dlh4d z-yvD;NJ|w`E-%7m9fI8}7jGqBPVT`rQ~xQ-;s|VQ(hQMmerI@m!e<6MESsp5JKgZ6 z@;wGq(Bpo|ocb*T%bq9IG)#LB7RR4lly6YNkk-eNUm}$pdx0*nXS^vD z(7;`*EIf@z$fMY=b;ow8=@Hyr=BE~d%AvNWFR70;++9&uDak_1oM955U9* zB~j1fX)3(;FGRm~2|Ey1%S<=>klk*$Od4@u*O>bK}}f@cbQiLT^K4Bm#p_S;QW zWt_klF5AZhwf^tmv7E`79Zcp zXBUY5?l-gvKBz+)zbX{L5~kjyo4C?Ta_eND#m*?U!Nf=L&y=Orb{{zg%McoNrusnKIDp`d@NIovYKoVnEXUG@Tj+P80q(lmq2673u1|7CL} zmcfU4WJ$;xR7B@__&1VvyRQbNaF_deQdNkTdrN>UVkiiBUfERiaZd%4Uq2~Cz+vwL zk3hQIh*xI8yvEAZJj(ZMi_5>p?<79?+|2Mz?tX;vKa~zXIqh7LY{9<5--DzbD4@$f zG*8W+D~9isII`XzO&&f^^)t%#`}y(@6Kg3_2y~nrlMLk91RvN_L{L`;em!Vl=u2#<}&Z5Jb<4|=>)F5c~ zNpQ`w+Su_^PR7zDaJ{q*HxCw=^RbMgvJt zi+S!}8Ns9d{M1=RcOd@@7JN+1x5r;#=^aRREkUPyVIWsL_k zr_Xb(<4CW#k-bbr+Qk?$|HVnoAvj^-&c)P6ivH+jZF!q-n%07v^WFlidm);!Q8_d_k|NLRsKy?xhgd6~WBXFB{9^RduRn#9l8q+Ryvyau@z({HXH7UrzOzzR(L zL8V)G`&_^Z;q6XLa3g)Xm_cIaL!LC-q+{}Sa~NpX7qE-z6?c+ID_XOCDX_H!+Ybi_ zjbETA7B7dHiijWo85EagEn&_44h9cjyq#g7&ek&H|w!#>0XxU<~V7f@&g(o3n*e-;K$uL}`0HBZ^ zy9bmJ-N}etKJ4Bj`uP}OK88%3m~ zs9^#FY=xGvHz`WWe%mx;7TG+>K(-aDlVM_EByTpkJP(lSK@D-Dm=LnTgz%5jsgAG( zk+t?Wp#4xmD67MmUZ%vvHo|Ukgfelp(xGQ2HjsC`+72E+$OlVsJ?Dclhi8P@8Z|jG zb;=c4;>zNx+v&ca9o1-aLR&cVS9xue6_$UOngncuW@BeZ)q_53tJx{=AzGCdUKDw2ZgMrqFz}40%7n-;6v?}Y%Z4WRy9eM*WNy)54QcSYV-oT| z1_d=y%Vwj!i3+4c(C{ad6lM@BOX{}6RHm9hTHAlv%enP(|p*H_}e35sXI-Pr@d zpM~L9UXLW#+YC;jo~2le_6XCJQB0*T2_$A&OehU>LOCx_&8M*E%zSS{30%pw%}Q5= z^=%E&19rtku{^|k6^4{?Jg`T~|55to@p1!Bm#2fLV>yd5D8`MONLBDFY8f~{X5f8k zB9zmXc1@WYs-4K?^D5q|8_b1`vH0( z%+R_f<%eRE%8iYoS&uT^{3Ju5#}^Am&=Z8OBKw1}!pO>SfLhP!Q$4w*wT6JNGHAJ~ zZ*e9QnnB9G)=KVc47YtLdwi2V9r69$3nooi!VHJ> zS72=L$R(aIMEv`h@;)egcKPOzBH*n%<+bs_(}P8CZiBG4 zW}%NN)5%R0_Vi=0y|HshD^nN?wyz=>BN!&lF^;oIit6@t(|Vf0t}Tbof51WfoB&5O zMhh=2OZG6=SZ4YW*FIB(I&oQxHXX~1;6C%%SV4u{6`4L!o)*+q%Kd&AiSx6hIEU`) zFvs{Z;z&Qf5Qt+ONnlIL7Qg(8QvKY4aOQ7>*-M$CyQWZ4((zZqYa|cW+Oq3d58vtx zH0gE}a=eNlwlgYWdMUR;6A-icU;c0+d7X93C3^d~)_n{%skmMy8hz-H@4*?(7mcX) zv|uP5ez$dqyO*+_!W~Zz>e_m|DcA?A#W&I9m)9ix4`Zh?7{B|*Qm}v!2;j}1@egLy zwfhCQ+w-`{Wdwml-X1F|;|Q_rmX8-JSC#z!(`A1DbBoK|GDA|fkSEILbM>TG!Ht5K zTp%-Q!#v{ORiFEn!qN9;S=OvY#g6&^)*!Dhng5JED=c5f(H_DkGS;cEFxbVOp1Cc< zmDTW;`L`Iqv(YIP%}@m{21bH7-5BCFP<-KJ-g(Mw$~8dn6&Uyyu8=dE7Ht`yJmzr_ zIUWZ*d6A%bcSC&#cKLl9D(8L(MpSL+WP@~>rTFnZ`KlCl8wlg_PEgO0ag^Re9Oj;X z>!~EdyhI?6Tum0z_{$`;rY_Z^>Gd-_^5)W4EUyZ~d=gS)u#gR#R(fFfHcnt|b-INS zmtnl5w5?9w|H^Tds4VvIuF|)|oJs#HQ16yBz+nQtmZVQS zGCVv>7JEi;5jF`i!)@=OJ&P(sM@hmLQG{cdZKzFvBR@PjVI0TJM+KOI74sCT^o8MU zj~2dEqeLvsx9TGW;{*e6@H6F-d*fHG9i97v=jj z_veO`(Z~ymF656U>YvRA-Ba%R20iN@?`|AD0KOL5^Kh%TPPpnoCQ(;*V!}=8w&>q2#|z?dZa^t< zGW@Z}W=dQQz=#XTmk~LR+w!VDs?H}0VO5z5*!gG73hB)Ui0$jSKfL@y+{6ss2iFs$px$L#4E1<6jSv4NT>bZpIm;JKkwPnH!upQH@l7! zs_xi|@f`>0_;=a?${;d~n}|tYFs_JDS_Ec4sjAf?;@7GxIoCGg;_huxb)gbb7yM~C zH~^w}WoYjIXGGF#DvPwt8bu&dg;Qd+Zf$U$47t@JSz-RpAHxhKCpkn-%V3=(=m`{- zuVyaz_cDjt%B#(h!X8`XpO3e>xk#LA0o)%wa<$;KlMHw7h8u>NzA)LY-|j`A<@!ol z=2g+~d4a&W57eeA#~>&Xo^vp(I4)?PeqfGp90U$rADx7cRxb}u!*IqF9cww~;}y^# zGr2LkcoG^z9F+d)>0^i8GUqkG+R z`ZG0$b(lqlgnhFn?gWm)>i)+oqV|W#VNnB=|4m%;(NY%g z<1Ig&&8XsB#7B?{pmsg*i>T9SB>0q5YP7pSV z+sKhFX93z7>a~jMoUR47Acgmu&IKo4X(3%)Y7Cn%Nljdcdgehf z8lI+jD#v|4m}M}8(~EX8HmPXT{y8{oA>l$k_3{TNW>E}$VaY=;nMb`iv9It;rn0p; z>t(71_Rz=dc2kZwoHB+A^=CI|SNF29l}oDa4p(8rk>DUheswZ!dHAje+sqJz+aFWsJVRCie%y) zGhhTX32JVxy1yu$L8@i+xM|6r7-KMkX4~orN(#{ATI6x1PF6G zm;hP4;i9YLdKA<`il*`OMZrGHyl`k*;w5$6SbEZ#+m4*=e1ruC zmj8Ll0#R%YPPJI@^KmM=_7f~4yrRQKS`8~a>e@bXe`I3f`MlEHNO9Ve) zugTimcU20f*T}+LD1({>w9`X)kZg1}gEoz>&#=Ud{W^*cFF#)TnZ^ql0#s&_*f_VCX^Di1UacX74Pc{KA@r zDnL+CFYDVAoSTQV9&*>YT35B<7#t0byzGyDX;d`61{sA&)UiercV`>?2fqvqs;B4xCR@9GUigRz#@XT#V*6_k^P#E+D6Iq8PYnSQR{<8Q z!XG>zDCbJ%a(-lqD0YCZy<9e7-#TT%P=AqB7uXdL9Z_Ib{AH9W>yY|SuXfqSNs)jmmC>1<|~^siRcp zbBv$!a(GM@!MV%@fT7TG^4tw54+#i(8V0&Th_fSX1NBKjR_)h+7-{~v<(?c62Y!(l zC;%99N-OgoMSzM-sw_+9n1n9(j|VoX3wz$c3D&kb2PTI+1lFNVL) z-Ft{)tYYhKY;9_?jKr1o@Tiewt-)FbKg}>f+NLDY@+tP^x$BuGW)ccEJ;{L)t#t23%v_;RXS=@>zx){1n)Nha? z{5djuTRFV5k{l`a=hlET))fbbut7&B|GAFPTnULd+3ZCI8i90b1m-Y<9K^au+-Kin zm>w+2vL}9Jz3K-{NDRDX|+&4|ca9LS~7+xtZ4qhd+)!DoGQ<&&0!eCva^ z`K^ijYS?z5OulslCgS;!wmBG@X)`-dFqY^Y=a~Tus%7&L#KzTv+(&crH+ZPyq;wTA zw%vYhS>mL+!KMFT_%!??ml}Fw%K(^!1sZ20O{4$@A9dhH{~1G0$2?zRa*rcPxo2w&o+_@&4F;u z8VGi8GW-i#nZP@x)~jcdGN3d1oF2k>PgXd9@iRmo_UsqieD>AIH+zC^ZOEcp-p+7y zK@{j@XzO-IX{dmn+ABZ)%QLGh5lrAOw)@9q(APxf%Sl|G=h;W{H`-K6o;Ngp2zj=i zqJpg==CW^Q8kOWXkmV5!i0iA}hv*DYth7%8f4S%`#S!q=Qzm-*D}yYFE94GJ9{PSP zQG7~m@n2)YzoXVJ1{<*l{?B#sI#rdfg}>`+J!H}Hgmy;Y?=|uq1qz5mgses5dj-Jo z|Nn%A7-sy=V|0Orkn!aZk)b* z1Yj=DZu0H9(%?Sk}8Aj-!cI5&15EDyqQYMClm*Afa#C`cS zMpWftgn3zi8mM7!K-BF>V2vH3?U{qwF>5>{slR{{2=k#8{tLByF>H&_E<6z%>FBW3 zWG=r7>X9Lzm6R8r4tYxE1Z*V7iWhUw>RSHylbLMQ=CQfN-M zTY51Jxjj1Od>-0`4AM}khVM^*&Iy9F`Gg!>S_I#Ao;9-6$szI4VF*}w3}RJ_@!UMZ z%RgZcD1r*-^R_|#Nd(GnDRVyYIjDMn+{<$1TWgO?xCbx;>Xw|!=&%KqO&)?7khXh2 zY$DgZtbeP7%Xw!hKdFDUw8QLm4wVFpc#-hO@MCrTt6d z_3F>=tX#xE5a$mO%11j*b^a{-;&-nHvOa<)lv6l|iQ}@gr&UD|u(1*rwvD3FiBl<= z0V17@Y~`hd_MOEu)ZF3dpO#Dn6(`MO)}+t$^M$YJ5nLkXiNL z*STFRDJ$?F-Cx+9P+X&BuV&$Z+6rDbN|%EQs_MP2b2-OB@B~XgH62FMxdwG!%WN6O z1*gO!vx1a_N~_g|yI^;}u*@!&t3$^cTBld~(*yzYq80&5N&~t!Dr*?d(hG=ZxtPjf z*jkVyM<5sx1pmn}G{)+Ftvzozt{O@kpd93Xtsq&2478Huw0VtX)u+2vY_~F)q7%KE z20;ag`eM4eOkan=U%ao##XS#imcq1yaBpISCJ7ltuAkOZJ%6t9c?ZeJbi@HaTX|7$ z0>o}ut(xXb>z#Sa;FNROW1&37p!Uok>47|~Dpz}j{e^^A0kBlmXCUG2lvee6RrWbo zYcASd`|{gorttjmY9n)p$zgYfchQN-y`qU)uMTfA%_!>dPCezOxR46G zkQLGFA7Cnics;%lcPALXy6OW$3AbSe9N63wUQl8Itw*w4*>yVw2*OJd+%B6eWGjTY zT_pDW605-_qVl8|=TYN!cDdczGDUZc;w=q)7D|NmHn{dYPy(?TqLjlK-rz}!`2R?{ z=#0AM6Ig536>oF%{LeToi^&6sRd>ctJBJPqDUx$=kf-7c$Co2y@$iE`3}2G`6cOc7 z|HMTU)|>zBQOp~z7JaFkBXlVrukvuH$pD>{48X!~Ay6*15MjSN(6Vgb#&|AHQ3ZaSQHG+gyJLV#7uUbsV-<-;v7v zALkCVDD=%=#$IUZ&=0V*53#;cBnr1OF~Hc)q{GtuBN z7c%8{x=-yQNcSWX)JjuqREo!?=s^IfIx8-MGdSPFIEy+6chm90qS)D9x3>GiCI9u+ zIjrhmKl=OWlU{vqx4-&Vuf;WX8_G5UO^G(NWpVEsC;e@2C63a}@VO!AK0jd1rY^@;^yN-q|N8I)H55=3dXRT4FLaSatu;27 zW3@nQsTBDf4>Iv4v~L!SXkP>ZL!q{n)cemt0#*+8vIx>u#yBApux}3tnCuby^mK_^ z_ZxKZbN`$abKvG4G&~o?4Mn4&Wnq^cGNSU9>pTIkeJQ;@g%z1Fq=e<=!^}qOlrx|7 z&&8L28ZrGGOEqV6b~2zR~F#wf0eImvzcF;-5DM2ja5@FM`&Cc(bA^$$gF z@?+{$`k~2K8I@@BF8b0xMa5J7Pt>(Gc-6tZeO5`}K;)VsND|JUi)7N9x`xwt#D{@y zkej;X?FGqtq5-EJ_JFUiNl-KGbT3-G_C8hP=Zl9SX#PZVZwu9noSs3PG6@%|{Bjt0 z;5vha2TMSAUIDFXn+B(6+KDPT6WhjHRHLO$v&%9zK3kxOaL!?mJFq)0Z;c#FLV0|U z-0&kh5yJjAoxm{ip*`@Hy@$D%``4$eE?a(j(;DDb5{Gy^)Sp~P`*kr3gLrfnUWO8r zdQol}$))nay6P~^y-bp?$!egRLyYv0&*)yf3*nlst_!j`>NGAQZz$J9g=h?(E}I7i zTH@u>$dYOf-SXN`-Sy0=+b)ic2{rcZKMNa$2Z@3jio_Kg)qlSay3S2eDt6H@i2z$d zWh=0tm4N#H6p_sLPjmBgajzTO<-*k@8;GQz`p$BW`WrdZC=n_3LKOSohgH}(?c=jb z0KQA7jXqf$sJT!_pT=$4qjl594zt!e@ONd~R^^;F!y?d&?tMj%;kblDFKDB`M#Xr} z&GzVPuNRGO?v;75NenzuT>P6c6HZ^r6H`?TxZkz&?EfNT`u6Le2ocUL$nIDbDYHJ3 zM|Vwz5pi5o&3~;Q(JNO^PM!Lz65P8g`WQSIS0ry(G4b*ueUX@BHHH$*%&y1d&88HQ z2&G!P$EHZ!E%C0GRE`XuH&oQjT&ifOz`$UNAu}~{FuOgu?uDtOi@YzQMxYrL!8y%X zpC?=sk7AQY^OHEvt%ty`4PpqqA2%^s+|ggKaO&#_T8VFVka75Ei21P+DbCEY=y5<2 zlqXO53WmoC?!>0B`LzvHd?W;8ah0x+Ji=N=S4Tucj<8r^Ra>GT(RY9w2FofhY(y4M zgNk$;mB|+EM+;tLHbqLDg-Q-u>?iA5H!k7lVBC28(09*YJi#tR&%4WN+a3#2c#9}%sg6dELlmD? z?p#1G2b?on+-)51U@6mP@>7USdn4uMx%Ab~1~vD#~0zI_TK+j-PN; zFZb3&OtxXqBMWZn;UHJA{#<``Pl#HmDFed`9N-~UAnwy>HMH1t^K7MbTJgJqUP|K) z_Cf~g`W);i0UGo&Yvq-w-~d2$27E_svfuz9ezWKkp@e%(lMo^eDG2cwoX(e=GAo8D zJ?sz2x0s12m3xBx0`*=RMRJ8@`6nL6Uyofr330uOrZJ9W#Vh`r@(X%*^TNpqU#+XxKaV+P zFb`EaOZ!g3!&P^?j|5~wBE|W-oY>T?VDhq&6x4he%$4_&@2P4l63a0w%%m;X9Wo>R zK9sE1c=FeI@QV8rP$T2-M;HdMKye*I2eH>L>Qu zIzl?SehA(!Yl&e+q{lB*QF>017PA5DNaJ7V#*GxQ9NsbQuq zafgM)b<4LTEQnU5P&^HHMdz2}9TV{#B82#~)ariaoCp%M|0ABsmTY&2iY^D}H9`{& z_)I?r>IXo0@o}pic6!d5pxcegCB>XsumSRI_9Xjh)0}Fs$**BdSAlevex$@U0iD!B zV%1Lq)Fq>Tf&J9vUTeH_mt<7Q0y=6%i8-7nBgn6gEVdi!t2>B$QSv0%Rq93;p-hES zKE-u$(@U14oVP&j1fSS9uT=%aG^(W4=hbvF-h9v5>#iFJS z#u3ZIZq-bmRES8S`z8Ht?N-HxX%)VC6H>kst?NN?wwcG<_t4m9mHYh1flVToFCdK3 zSCR(!pjrkZqAW5sw?QWD0y|uQMOXQ?p3~LNzt$AM+(qba=_`6+#XntgF1Eu8q(pN# zeliU1nQ8xTr^_TcCSK9C_rETSM=?drnOz*C9OHSf2GJuq>Fif88GZFebf`7BLh9yI zeKNufOm25Lj`R4QZ>2zvbhy%4aWOoiEW#?L4>(niut!mW;uavi;NuF}+g!r>)hF6g zt-RN(~5)>F635skidB$n%yfe?+z3ihoEuKY?~hfGnm6)~ve&HkB7yx-zmaqkbC z?8}fMdK)3M=}BVpA}kESf52iMNou(~rw5e!+K@qi;Vn+B4Fj7$uazE>Q{TXAKf!XE z{cjxcT2M(&5At;OFG=G^yMM%(oxx#4J6jj1`OjEA*swb%MWt&c8fwJAJ{DQ*!xAP> z*ZIkG;XE><^5^N}h?vx<{CM5A(mK|LU_{OvVg2-H6R=ysV4Ocs_WrbxJ-`$bcOqOQ zTq{z`(_y_(R?t*o2o_5yp@u3%O~aJ?!t#u5jUH`_)$uut1R(>8Q-vrlFBQnZCpUHN!e*J6XK|@Yxq->VBg|Ca;zpSd;eW9}CBobGo zKlR!#*8ZCb$;knD!izD#>fY7S^sNp|I(GO{Vq=qQO{m~pJ=uyEtvu=?I?wHHLmU=W z@4^P>=nS@LqJV?7=UKXDSV(c32YIKw9M8=@XBN2+tac>dn9u+wWDP&d|9w zjk`U~QnNm zMhgD8USq=r>tmgP+g~Zu4EQe9z)2rH!&=~TSMa`nYZn6U*S}`R;z1v`u;T!_0s-8> znse;mW6k)p1ztX^(F$0Eo(qHh>_L*aA_zUV(LTA>K2@T@H^qHxA3@6#%#@GC{&KC< zhhepN)g!03JG@35vx{>kR9mNZL)Cp}m0fB4oCHHcUAiU?gBcJDN+8`FwMU9iER<+; z!6fygCK2k|)F!!Eg1ZZsqM_M#Y7+WzwxAP%G3ukY8Ax!{3!=~kXxJ_FzpS`t%2bvh z`~u~%I@bKb=>SJSxWDv%U7A5oy}>kCPx{}wr%8Bd`P{!-r*D5k>qh@zlrWc{_D9U6 z$g^1jRT0xdj5r3Ig{v>Q54Cr^B&McQX}Ch22XLPMv}%}(UrQiY+z)BC2jAf*i2V`E z6i9Cdk0h+d)cy5nk@y(5L$G`ud>3lHZ&(T!khY>v_XMRez`MO-nc8_>LPbEVk!g}5 zpGz7Bpc7^y;5z!xMSD^gASLJ_hq~@}kegCiwn>4urtTYpZev(=enqRjntm(O98=vK zul(oI9X~TGmTgJoaaE+q`@;M7ON4mq>XPuUMJ1&MfSXEisR2{w>3?B4o%L>40Dc-Q zD0pbM$11A$m~2%#V;4Rq#4#vSDYbGCvY}ci)Vf1p_KBpYQYAb@UZ=NV_Xn*~Ub>-h z==U0yAD`aG4suVNnnOmOx+236V2n-vC?bQO*`Z80E6(gLW5;HE&8tr5GnrU88*(Bs zsq!3$?0O*JdnAl*j%3pFjOO-5ijuBGKITF6Sau@gry4+eK&+Ou1^;_8xcs8II5~BW z@(RP)A9j}nT`gC}*L0T43Wt@Hzw)3Yz?btzzbGMldyS@%l#jwHWdrOtH#z4hD2WG0 zza}0PF2m1$c!+Ag8$64=ecE8{>uaNu2m0zhFQ>>D3u8?z4Ti)FPX6t$*b3ySQmqu) z`I>%25KbZk2K>Y=hVr(=CKS!&sVnX_hne#7EM%m4s|j(Z>10G|%`u zL*IqwSe*R$5XJ4R!%^_Dx&6{L)H(Fj>|dDU6hCD0#x(Sg=14?)$-Ku^go=&sv#^f7 z207CK4Z@1^v%)Am#4dHJ4`XL0kI5og^}B2YS3skWcDJ+FdQ7F=AN*dw!9HUid^tzi zWc%HYxqk^bWb_5Bl!3){VlceM!GHKbmd{mw6Z){s2J`i{mvxJ6l zNB{-opahMUFp|xGD+^#6mQLbJs2#w-bYy+x#h$0+HdIuie4O=3QbZ&GY!=%w-__hs zX@_=Qh>AjxEGO}Sw9jwLW~T>R$#n(78lUXO6v`$c8wATO!$~$#uQWY?T2%`nC_nzzriZh3G|>0@Nm<*K^{u7 z+o!WlphJHHE@UREp1`|pz_N5d3rZO2!LQI3|z95)yzBC;7$F7Ox1MRwb&`EZ8O%Hk=faJMf zeelswsr%%<2|?)wW+rU=5N6I0L~y&(psHbEyA0#+U254FxlX}iT}U|sM$Ws)EvAt3 zznue+#aT=`FCq0B3DX|U`hzXRM`akqUt@wBjeL$nIocIMrLgYWX0uJNeKzTKWRN-jS%oyjK^KPSkft3p-kdRP1nXR%c3C$-0B7@c(Y%a1} z)SHu6S4vF%>(<+Zk>EB7%ooi@=52_hLgGiHka>h!zxMf10kI_SCoU@X!4lF(&@~-B zL4`r!@E`*uPbdFv*oOT=0KQKK(69 z$Y6@z2u_nL5v9N3gD9UGz=OYv;|(a>umc6WvadV?eF+$6MWv{fZzdzKY<6eU4l0JNf74m58dI-!~by3VltM2!S)nb#<2WuW;a(6+Q=N@ZsmjQ*4Lc?hq z&TD4_kLzx0(O2HbI)hBPy2OtR6?t^#w#a0heVFlCUPAPessUz5;naGw&}|j}udQmX z8{c38;a2r>GU;mZQKs;K#hX;-Owx)h9aHgOCG4<#9=35Rt4L5)p)S_3;3QoDh&}(| z39AlyHpQs?2d2X~tO9+GORN#Y(S^q_Oh?`SYuzk4o>9f!B^)cgwg5+Cz4;T=9D}+F z?rOQzDBYC9<@E)-EhW7MVv*5t%mjrP@&46ag2Q5P)c8W>T#YrADAEO$zK6!gwXxZh zNLlFhN9GTjg-_ifMewq)1N!S@5bbr`Zv-xf^f!rXUb3oIN0AV}FIzDH_bTN(Po z?Fn9wQ~q-6!3stJEpgLkMZmQ{b)cMK-y09}M+_@An%2odU1q?~gWj2FZbXY(!=`5k z20dO=4rkVKD8Aym6)>t5!TNBx)-G?Tn}U4w?=;BDD%#u21IOW^y0cYRB{BW~BWPAr zKraIObfoywAbql@4iEvb$I#!R7Ornc49jOTRtFle$2fd*JfpCrtViF9lio_`_RIp} zlZrF7eZm3F)T9o)xc!g-saG#O1~w}9q}Z6GY|E~JxwW%af6n7EbA^*jXLRjq%xy2X zF2w7~d^W=qyhahg@`Z=SrRHYnL(Sht%9M3%cOlNG?jezNaXJ?+G)na zY?&)u4p|Fkcd?EKz@i{N=u# zqTiXBFH2gAk-F39RVaKa&g867QspiWsnN8cH2G!dQ9SK?GQ*5-UOhP(1_MMKkFaRR zelXyxNmgzJ2PkUMgC%q~uO~qm1l7gs#3I+5LX& z&z#W4r}E@C=0b4)Gze%4HzVtnFQOyL<_Zn^Ew05Oj?A(i1CdhI6i$U{;JePco@^CT zvX0hw+K$hZj6y>wNn%?? z=0Y5G4#(6?yOpmZqR*PpKE7^-yTynW{j>(}dxr-TYKbNpt` zVZ-VVwc72SAg^mgJll^sD2R}(N>qlPW5rZUo@Oq?f5p=JF7KYv^bq1($-Etey?^8f z$CwaZiVz*?hPaJORE%71M0SAQhaj0-E+-kd^g!8z9K$whAPqxNUn`H&XQ9EG!9#P; zhm$rinyW973gmM_9;Mu{?tQvZ3{xz1a1QA%1{11~EpE9IPy%e}p`jo#%~b>VD7N4q zswU$Gq9OHA>qLX(@yB9wvA8fkuK|sKy?yIg_7;sKExgi5e8}9r z=ifJSNw@^)0aIV7in{sD_Hq|ibFY;`Vqo677!b;ownhm1Y0v9J>fo}dh_6$;=N!in z8*lcr_zZdLTX*iWr#)-u{A`&Hh;o7r%A_FKHu=**soGa!lLB9YiODn|5P9!SN?hOL z3|qShJVx(mLM|6j10-K9q+4qhuCtRd%VH_i|JripG=?#FmJQ1N$18GTywd4H334KyZy}WoP`sB9@>nb!auV z7ZRCmp4c+}T7DT@`~RW8dRZTikS^=jkfuDIDvM!;g`*2`RTfzh!w7<1OEb%bw}5mU zyLcMh{Sb`o)ZzWwf68<`-ij+ zIzjegIG&>!tKz|+`vq42o3jt~5ah8)Ori`b>YN$(wuu^;K-y;ZBE<7!LO}%Pais~F zY3!KH)h7^B+^@eeXJilwTuw%1ZI5k){89dUZ+BDr6XEt4g@(Hm{xtx-=9J{&Cxjbp?7KP;o7lC?%K-M3Y34Puk3J}lSOlkdd%+`t4&yq)}F0_zL} zF<v+`Bmu}kbYuceY-I|JK=X`$1_EP`6s|lv zNeEf&kT4ZH7x0OPyvGR(GDx5b!t$dF%Uw37|cX@H9%Qf{&@OH#o<4OK#o?4#Z^1p9GIaD zyjQA6>#4`E%MmbXMrc0;?pxcz|7C>t4`Xczy|o_!%pkM9g>(8(O;3U>5jzsA=>K}- zi7$|&(I@i}W<+7RQ3;cY&bOLH%_@z$J(JS>TkRQKRPMh|#uTR^<(5LcL)*~EaFkp- zhHqR;n~94*9$ZAs?nBt;yV>%*6(AYIMY(57#MnC(ir^CHIy7je2%&CIS&9R8I?d1m zhb0`Eh;MhAluHx;()B=zRqQHl=owv=dmFP0eBwkS(Y%(Jnf{h2;drq3Zt&Vl66h^< zZw6jj{2m))5E0ABF)InPBChA!nVit`N*^29`(b1^TL$j=ic?%DdaVM7go4o^l8s`( zQ3nVjcoE=nr9?Ogzo*WvY%RB14?g8mRqSCP=#v(H_(+~EWrDlA~ zO8>9w_QshX55eJEO9su?r9^2})=GkV0lklL{LcHv9Z>0gt?*}AWDw6gbUBAC?Vx6p zbEUumW6Q$5m(~ugL+_`(QgG@oTyJ2pqqn`?CKb#nDut`G9}sNh_K3{JsWF#YF>kS{ zwKQdO{+ci?qMEZW=5QGfD}xz4=K`owK4Wjh94n6ydl*PVlX6?5aor5}VCACDr^d5} zn}69jazP&48)|S829<;!yadm-extPv(U4f4Ncq-j*j zlTX7U-Y?w3|Hu0h7Y2u&Be;;=auVo?Ix_g&pF1Kr+2qL^{m^CmWx_ncMN7b;2~B-j zr-sV2ZsCW{!c{e!o&v_3z$l|&(xaP;q9_)&dJGMsMm<+qkNUzkZb5#Hx;^T{w7>?leBweo54z%gBP&*nUbYQGV??twU~wNVc%bxkD8K1(Mn>~6V2vDqEnu`RAx47nFCTY zZQ(;#0S(pt@4nszJ8F_b*EUhMQrnMGId!}u-cTH0@3~2E)mcudP&lv52D5*r>x`hqOIwC^$7gS*8bjfHMg>4QW2+0p>kRM z;Qgd7sw^t5$So{$7U#=C^rJHfZ2pj#qox`eipgcCmO~pewlA(C3sBhn>{|V>PPnqR z>=9{eGUGO{y=)wsps7)FAMNK|9`f}iTu)ohVKrB8S62R2^hN<5>t3sG!j}Tg0!@nx zECVT3S|g?&nDwTkR}{F+Tl2tPtA#EUh+O}Z95fS#vu%vSV^+JC>lG3A1m-B^9$>u!AeXF*^dZfS?q{P z)T04s$fvTqXEH24W(Jw4e9+6AKlz1}t#|REVLs!;i$60{w;?oE@1-rp8;lKfLco7T zPCrxj?x#;N;L#tx2ndeFey3OeGYOk0@=Rg-+;srMmW6+f+w#gz$9;!@6X5yaICks!TX>%H}-NcpXojK}A zbS%^>h<^MGs|6`phEvV75Ib!)1wH8~pj4RNX}pBAjx!v7gh30{bZCN8856PFrv!tH z=M#uVgCEr8Hyj43C$WeL?-agONUVS(w3G%5){~ltN*?T^TQIm8rab_jTcE&KmW(Sz zK1_)?Y~%#@nnzg2NIE6}g@*@_rgExs&67x@ekFTV+v(OiiFf+5wTDJGWr zSqO+)2-WY@v*B8`iizQ@szT&FgJ7>CsOsi_UI@oaEdRHZxze~jz#d680#z=Ggl}57 z1U>*F`#N*?SU}HDZ*ayYhwhaItpbL8gq{Yk2Bphk$L5h|el{H<&U)g5>}KB4Nq9%V z1QiseHpZfgrMusX)v|l^x|~)wFMCruKi_9pp6l{b&eJMafqCXAmp;WbA0gyQ{Sdlx zTvR)U7^V{o1aTs0Y!@H-eR`Rz{no}fq;j}Abf*OuBXSpGqg{x7*Bmgh<0}s=a@{9i zSc3EcammKQ%w{abN95oeL8C+AF``cf|6lpbY$@5pdy2a)oTVELbH3VN%5A{g`bz#R z8Ncyl6laLw6W8;bYL?5H4kX&9(lz2j$6Z?PgF034JF0)-2VJ)akb9UBVnW1#cnB6q zSgYEhc3fGKPMAP6ZC^5V6O#!ZfC1z|b%>>D7R zkz7N?#m|gZ1?tEGWj{qNf&7e^p0|9*^|u)D;v#msJy3U`*d6q8IUx6E!$`imc8)_X zEc5c2K{u7hW0glaC8IC3>f4EVjG>Ss7hVvWN_(IT;uU15tWYZB8`-?@m(azdk~h{z zLY;hPTsSI7tBcc$x+iw44!}suLykfzaiT9G?N+6|3;`oCfDht>8DLDQqiClO1(ZV3 z9}x~Eu`Sth zC&6u7-w=dMGPEeQ(5!aC61Dt^^=04@YP6!zQ`!2$k1y%7hi0)^Syeb>g7)6C+dNhFBHoz<$R$)pc|xLvg*`6H49R z)6*M!9XRnWz9@YGUB8%({`0_gowjNY0H6m?B#73|)PVqiC z1q;X6iubpf5Qst)atZq68p>GZL>9QgUMj*-LK~n>&jY}7SW)<%4Uf_k^E)Tl4=BQ# zLr!&OuUQ58vSmY=ykTs`7oo17-)~=grV(qn<5opGI3Z1gyHX}nY+A)%VO=5&Vph*c zo5_LH!>oWxOnwtRNSznnUw}&8vIB2p{cm@NR;-lUlz&WQoGW$fZw?PkQRMQ9D6EM8 zbSEO>bhh(Bg7ZJ$yoVQt2eGH*3dysL*-swzzqoNS_wm-5#ZLP%!rA5nC1W65!(A5B zZx|AT&Z*73(r~H3;k9bd8D_vwZZ9&gu#29AX=A$lyUk2!5jywHL;^>%07mB9h<&akzM;sf*3e%wGAfyDiFm9`C5V!sXD{^(2x@#lTvQ?e?MQc#) zZIk!O+-ImJ5k>c7aoTCrCiR7eqmtMuV;cwA+@pAdhd19`(C-8e(CwYLqaK1gSMi*G zzK=%sJT{^Dj$2j%dS@EWF+z*Uh)T-!F4sm@$CA4&GqbP)Vi+g0Y_%MYym-6?eYDSY9L63W zxbO9v{{DyFm)nZ_DzB!FpyS@Wy3PkZ%cM-VG&NvuADEAQsQCwe+9e_*=y36o+QkSE z`!)3iPZdtK6B>ux0IK%g_FevSlj^Awra#jvh>b4($zMGsU0oMB)<}5-IUwzc4hCxg zWDj)-*Hw}t1k(O>+TaNPLH)G-9PC#GS8p@X1(Ya#y&ph$TScJNI;K^8Si1JZta;Q_wRI4c|RJPgACtlR(5dgvoIEuH^&+!41HM+_E2$7ckKAg;AtY*$gzv~t@ zk=uF0A4D6Y5LN7q@;~q*OcNe()pU~avdS=Il2LB;+NhbH&E=J*V--RC#`ego8M+OX z)hFpCeDk`uavWAAGCfPoJwc?E(GJ2(_B>pVx&YIrKaQYI@Y7DO$SoJjQ80xQt;Lb2 zg@N`<&W35oj8$j!*FgdjeAbWm|tc)>7ENOB}S*nf*0` zLnBF*+sDUaz>;V4D}2t3511p|p6Qj6Cc!7w2~{(_M$`(jULKfZAj$*c_AlrB1uSd2fiHHc)FL7H1Cps#jJ~ z@CbWzf^482>)DFjYnLt@1QBDs9XI=>++!ekoP&N z8K_~VK!!v?3z-5OQGBGbGlP*gDeilfh@m^U(Wg|&n8}Q?$v%osd(;ZuQt7Wl#m#le z&AOgCqktZ8catcubYgHqsbx#H(h0heFT3kb3@Uie2R@*lLdkMZ-aiX)+Jb=c`0I>} zl(zE%ut>QAi3{U;DP&GvZze%q2BIrK`Z?W&Bo&><%I=BQ{Z;&wCd`G>sGXHQSIovn zXxY?4aj!^QnU%hErF|*p;H(!9Eq6m-BTk1=-uiKv?$4Tvk4kmydmNL4J2cH$RQ{Fw zx*X!@G<4Uc^pk=YJp4Sk!3P9LT-|H}6LYufDb86tMbLG^h#eMsHbSrxgPUXtNam#g z@S5Xn7qD^bj8bC_T#wf4p{Q$Qt9LloZegOqmPsEfIW;dnVQ&qZIv*!3ztNvh;)@eg z2qUFeJ1@YbVCYvWMF&tlBRYM}||hUdP$gB=}9&y&F6S-8wqRh8hK%f`D+pA^1_S;rdz@A=WOW&g%;5`X#l)orrY z?3-6T30eUftgP`D>9aohWH$ED31(^sOy6~yVij$xe895qK`-O`Bd?K{L z3DxCesjN#%>R$^809x5!Z%p7)0Hx_wORG|b@B$%w?Ss~FB}M69GebNgByaDBBo75O z^PlrI=F0^!ohVscS-EpKb#pj(DmT+#9KF21aU~FMobb~^2#J6x&sp7}UhASc6Sm}k ziqND{ZxV)V%d4Mzw3?yD0juVf0rw3`OCb^F3Ii6QrT}_|Tef&d_HAE$s0n^+N+gL=b zEsd503Ba>fzb!x2;_ICfEriLbQR}U$a$oPkazLq=BSHUFdp>kHiGffYd^(8weKYFD zw9C`mfI4<36(*^3#?aS5jN40BQ3M{m${JMURLbyZQ&y>1yS%S_T$x+aFG+P;H#;R= zDfIH*vt}sY&C~y9+A@%>1`L_K*=-Y5@Ox2b;V#IJ0qYCjEp123XfMeK4J~X!S7%jc z*o;HT`fiAu*bCUf3z$b1h%6;twHxRBrMkk3A zWx%_KQY0veb zWoxrRhc%9&ttga9UYNT+mXZ0zy z!1{Mj%1nLAsQ|&oto9Ta_H^oz%S}r<9Jra|729vB6$`}b2Fl_V@LX6aTW6i>qY)SV zlVJwbl|aMflYV)%Lv(jXsp5g})fA+AHoBhj@H~WmKqG~i?&r%SSexaKQ7vZU3E71g z%U`XxVAWW%>b4GO(p>wsGUSJuzivpvbC#EP6jHp)l$v=W)flvY7llbSm{g41A$yuE z`eEXFGQl;drLg_VXoou^Ot%oE0)byB+#BL_zjjb895kqo zSS)iVNP~aisH)tKKcwC6InR?~Zi-q%7-z-n4x-QwELG7aQk^ZC`fR_AgUzM zR~hr=F@ce_^@I7o{QQX(v^_=sGNBVQZma|MRS71)?8U)4%Oo@hHmmIImh6L}+N}|mTy$Vj!RmX*Bob5}n0Hp8irYxlqn;8iYfGWIkpy8m)v93x z$w!;WOPl@89MVcUCwRIU{8;Vx3A{pTaR4|IH8{yXN>Ll*g(i3Q#|wK#uV;H3WeSqP zq&InkRhm_gJ3Z&<@{QlXqB&)%Uwg-(0&NC6*vC)58v z6L>3%{c8sqJ5UN{SF@@-iMt68wbQjeJzL8mU=tMotV%<*-I78*6sU&LQ{JfU7hBWh*&6B;dSIOZZpAaA-(iZ zcrueHWLBth=6T45B2x7t_?JJUuUpP>ho&Key_S$suxKL8K+nO?|Fa3!g4Xb-vRkhBUn#SV0uUh7<%TzeE%m2s8V25-y(!Mm+t7JBPSl}ttA|&7 z3F;qdF(hi!PmJ9vb$mSpC8;eGe;&*TQc5t!-K$bbkI?*>o0S{g7p^wTHQN1zXZ9$8 z^LMI$xD8*UGL7^kmOV~Z|B?IPAAZpW0*KNBPm?20>d;F#G%^i6mqMz5x3Iv|p+$=S z44!SglD(QX=Ek8ekn*J{Ld2Bx~m7iVx&D^WrbfijQr zwescucU~bMRJE_0V_z_;cKqpeFMB)*kpJzY54x0?Uf@Av{C#h!u<&72$I`FQhZd@^ zA5a!Z74Q7(0K-Txt85{NGrF-I5P`b8g;2)uUetOEcbNP$*(WiqZMWL#ECnfeDceOq zn`8|VGc9{Sd{(1~q=@Px<9)*KN6Qp%cFnvDHQ^w>vMXh`w|5!h?CLngt!#yG446b2 zr#^+AM&mWC`0$7}&594`A4p&6Bq)zJDlCpnG-p$pfNA5E(?Irhb$2#@houJ8Oj(cD zVT%!@Tv1uCPfnpzO78$N&N@coP>0Dez8lh4y0{x|DlMP^_>9NgGh5asgrq zyLmHrb3R{APkWr2PefIn`9sczHwT|v>*#8$-L%K0*Ymbrrna;LCrweQIKzfOB% zJ@mIQGGmUg&tGi zl^LX4kq&NcMP8^Olb2n2g&zmMgu4g)ao2fVCi7Q_UQD^uI+IXRj2almV&d^w7=d8s258^29?mD79loDL1;@7+EH{q8UK~5?d+ADmsbHH~Bt`tMkf#L9 z%#M7CZ{-6f?x#NfOzF^NB*?K#(;_(%zS)E}OA^0VupkFO`oIuFndTz)D<=xX*&d)W zP|zAJm7%aUM$J>DrSd@9R6n*@ttjA35$>a_SGp0FP;o%#wX@YWwxz3kex9X0y{q=E|kltaas{jPHX|dW6K)sb4#Oo6Gkj93pw3! zc`N`a>TxqpB2xZ$GwN;^212B`N&tBdG-*gNba0$$oJ#Nb*6lBO!#h}UFXUPil#wKl4~8`quC!?f_U_imI8r{K4?R4e%Va20;c3AKcv}L zaIaa>@I>eK{pvBn@i><&Fp2oIia7-hBMG72Ll8XaAgIJa@Y{40W@#)kcc~AAf_z=( z`6yZk4|Ebtk&?BL6_FC;=}j@l+#du{RcpSXy@{_uZJ!gcBSq_xo>8JT&UAtaeMhq; zGx&X{ew{YdBFWnSB1}Fgt>BRlwivmlpl6cnPdZ`(p7U7`apXQV`1tnI%( zVL}pwo_bCLFpWB>c1cQ<7Y<-5`9c#XXNij^wL^msKEMqH(glZ#DtGc(*`Nq~-hrI5kMLX=5^2dyBIOQ|l9x=iI;d+k}6EBBrF*{)^>=#V%Qz%zVaGu|rL~(#|%KbhkC(&aLq*%%+ zc_{vN>g+P&Tp5XuNh@kDBl+Mlm{O3+BUBK@L=bTahnC(b{eimo| zdt0>f!<3c7hq^W5#A=6rFjoFan{I!+!wE_EK`xRj`H4Q$D{>im><2ekk9M99#(Z1~ zTJUNbN(tgXs+ggo*LwfXC+0CF?Ib}~46A|z861ysDBJA&mWhoyuz&5ys~}I36jiP) z7>pqor1X@@@{Rg-R>U*!#9%qf-;$`H&&~`}aT*B3=)_3TTCo&16&zxhbqE!yLgD~N z3F!K3H#EarSBtP@@x_c*a*p|$VZ$i>PHmqn{c}%y4$ljV=sB=w`r8+V(Ef<(3`Ue9 zkVGw^5o$JkVKnc`kDd0%9;bbvR})TIalU7)K=zouQRd1h8IGZcQNOLeF3aFF37n-H z|Kem*D}Q(gCP5VgTd4Z1FldpURfEre4}mOlZcp9oHIL9dG{ zzDq&$B~G?2*68E^>evk47@$_$L%>BEb=ObRPV)u|?&`Z6(BaC>9q3Y5>Z#=p3*1D< zpb#b&%Xs8wa-4zvvHln4v3q)JNFc5XL}j&sIk!OF(+N zbf;Zq^7Ai*RGx=$gz=VbFyvTY@sN zvb{a*ga_Y|R6ECum8iRGO?wc-PpNhB9MJDvAvhxxNKhfD&zkqMLR#>ELpbR>&Stx} zwzDOusebbF9G3$ad9CECk*BhRxP(1DCPwUfDU_FX73Y+e&T8b@gH_V z79_pNWkw}T+?C`J>tHU;ID*>awcy$%*omRR_O5KE;fn~926+(Ny&_VLj+oB0hwD6m z(GOE=g;+J)zbi(DMp)cs({c^%kL&~=bUuV!k@#Q}gyd11VB0c|eSJY5Za8OSmjM&u zveKTiE(O=-CP*o_jzvj)Fz71v9CAs`ZW#^?eD&r-3#e*$c4sT;E`Dc(ZA5#BRC-F1 zRt;c8#CNG}f;BJLmZUC^51gFTVz{BvG3k@R1fWb#f&zG-o8XA_nQoYcy6hxz{fn-# zUU=+-ow#kL*`Qm$=;43zBKJY7qVnCMxRnQwk6N`27)8+>S-KV2wfCmuL{GcRuHX&yx!H0FXM(s2&X6$v z@lMQ=0wGR&3_F@V$a#W2c+|JB&ONP=@WUY5Dx0q))&kipr>&9g3QzvYPBsQIn`^nl zd*GXcAFqj(Wg#t8D21#gs{2x9af-)aMI3Fm^%^(s5gL3~4>BWx9L_Vx=+tmM&%?j; z#HHgJ^|iYfnlHA@e1AYI089a7G#J#LlwsUrNz!|6U+@POF-sN7%o#S%@~l$Z31Bik5<)v@3|I(^dikgscJ7$wVegXl4|E4ALhITn zTB9_#`w8|dFY8xcC$lU}jd2OytMcbK4$X zZO`r+M`&^I?@q6juhI@?@*48b{#O#Q52du&L1e815T^p?kH)dDj_zfRR0or84@SiK zxUz~8h^rE#U+*?rKR&w2C5}csXr$GOil+_cVjyO)@E*)L(;V4rjvv=Pd_OdQ1&93Pa3 zO3Ju8g8G5J@|^h#Y`it8Hi9e@JDA2gOwh=dG}ak&IS#03Bj8$GqqtkJx^0^;zA<*` zmHw&KPaGC+&PV-9s3H{=5&X09WML?Ve#Ze7M0UfdQvxsP!Bk~_2x^sQ^#<_|`d(iX zZ2(YY+3Z0i6a;BuWz8$|9HPRN;j1$8>WFp5n6Xk%G9)>^=F8cpdY0uGPP(&iTcR%= z4CBn2UDEtbnZ{Af&+ko&oajU+C8?3Qf>N9NZFSHPgoUr#{T`w6+jKG?Liobu0=1OB zO|lsnl(U4o^F zE}Gc)#q8vQSHrzf&9a*s-xXoD^26>gp4rPjIeEOXLViqm@bj6Q)|SM@8ZDXWw| z&fK8+5sr=j4!hznS92_^H?sjwlnf~D=n#@N0Tw7^HM}}SiXAIB&O9b$6QwEwxCK5P zLp*Q^$Sy0(qwIZizufyoiD*McW2VZX1ex=9#;rEEab7>KoFr!hs(~V&&b1AjYWFZM zD4~Pz!w>~Qp`OVcrm9N_UyDvpALncob}yc09lAJEaRO~VME#MGRrqa#nmUP@sS1T5 z2~g^;EEI#~!~5L%P(Qf~H#pCP@>N-zS&_vLGFdJ>n+5`aXy$ngox1dTC9#h6l^ds; zlfY7{9h}OGEc{dPcXbRX`>t;`*s*2PwA3&i_t?FDoK9puB^(|rb8Mgn0acZzqkI`P zja!5s8ty0k@aO48dt*bU1mIIHFN(xA5Tw9WVGJ0+QBbt{-A7#-{!^?vRT*XhmG=p~ zs0j@#ivw~W7{+zB9sE+o^S81XB&WiCAGL_$U$(DNuNg1!+_-b| zEoh|#)lds*hJqtbYSH3Ng4%?&A@weybzrsgD*i|vVeW+kIKm8TUpWaK6&PBj;37r_ z3Rlb^hMjq@gh)jiN3eXam|{Y_5hY9s!rRc)5lyN_ho4_?tH5C+<91&kFxn@5z{w^) z#8izO?3JR!Rd%jlGOj&4de6oXboJgk1HgS|VUXpiwJ~Z&Q~2LA0lC)vEa?Rn1^HpW z3H7!$!t~QoKr79=qnt;Nl03TGt0W8qFl?Kz)_vjB^M`h8#)@+PLa$^soh;|P)3y?( zzKTXG_b)`pSUqjmN~@)E_jCLOU&2u>%wb*eCm{EM)zsSUo_9Dzk%#y@gS;!_s@=To%; zLE`vb!Lm!tSZwJd=m;#XC+_SM3ev96x#Wc*<@4c?FbUQO#k=|GRr)S)DeF@94+efd za$Ad^l311UeRL`uX4%8Q=_x+#G#Lpk&o@^n=pVy3yGg^hmfevd2OYTVD%3JAER)}S z$z%apmqq5+imf&&^n5PJisKCHIie`?2s97YV`udu)HHdgHVe^U!~{^ds&a|j{gUit zA7*t^g73POo3k)0l(`RUr*(fJPy(HW^R0c1_h-Q2%u1>x_hYbvbb=9szGIG z!u)YWh$W!WGrX@^54_`IGlL~2I$)rKmj`{1xj17P=FqI(h|rwbn6`pX-cBg2tu`CI z+H>jzbyRd&-0)R>8vWCof6uf8{e}8tm5PMS_MU*$ua~&SXw*kTg+blEf`lr)`K+S5 zGFj1iSJkJ3XE&ORZ-GY)iSv65ZA}WqAv9#T3mD|Kh0;}=-?LI1}gVTHLAy8xjFAcYL*R)Ha2-B zBY=eGZ)3NQ1LoR@bKWPYFq{KjJ)B>WD3nL0)ioM%xJY*Ss{Z_9q7oP_D?fPN0F}HJ z3%mrY__a_KoUopj1_ftwB5QE6XaatQgV`H!+%9eiCO7b|iI}W<0&Hi8dtAfAl2>q7 zkylE0KWuld;ozE{jYN6n>qxz=ho%z9!uJKBn<|Y?_lKglK@s=+(?`A%O!*UBTiNAMejXs(X9_fctU&T_&2=<0n>tSY@TGFmsk!=Qz^70u53< zt77MVP)pAWBA|{1z3I}UekG3xx0^Lak$Z<=yyUIYl{uA57*x%)4aGSTN0$}Mb-$2w zOUmcCfh0k?FZ_hW&J{_+^19!xItR%XQe=zS6GS~4@_Wp*?XTX}J6^&%&e0n=sqaAH zEd{I@C~xnFp%5azIUo5XJQ*qTmT~YN1x=W(gK6lo81PbE9Ii~|Kf-E))2rhMe)jOgkw~S|r7<5Yvqa-MF3cQWzBJU^bpS&^yuXTcdLG}6(%V?E zz>wtcl>|k8GVGQ_a~J0TOReOssRSGQMMg3K;cQZ9P7KVti(mwzvQga5zxJ0IlFi8d z@soP&y?t79xP*XRQJKfXzmy%&jA%;O&Q7acA8CqM#Gnh<@T;lR*o|WVRbIGUu8VOL zVOJ;X@&OwogWV0Yw-@-<<&v39x#3Oqs>M;0mNL@5evFVR{S9rZJINsN0^m^$Tw=8~ zU2N91b1ZqHbzc`v2f_g4GHWdTTZe?f2lh@Zl1s@aVOUVlxCZd2hgJr3}&fS1m9@_but6Hs;zX1E@}XXjXe5h z;F>v~^>8;_D=8s;FQs?ZpiM99A(7$g#5y!Fm+P2HA-T2ITX>iqE>x|2vgq`YHw6RD zeuHc`-ZEOP>*lf)0gAVRY+<|?*fnsY$7;GHG3Qi({2`EO(yeTZ%unUo$go+ z{>;0KYA&+v$i{xknZ`t_bn$haTj;iY53l=c2=nQ5Xtm5r=w92Wk1}*lDpMRAg83M| z>~b)hQY*&pe_jS#RiF(B1_0W^BgFHfp@a zK)m&_K;2#5x;+*h`#JeK4_h9tZY8GpptUz}n-~FBP(gC0#fx)BqDwk%1CZ6TGp~t4 zti;G_zuB7$%}NS9?Zmkilp!-6UcC(%{|S;wJ6m|ugyqg+<`7adjwrNdEjn({V(7Y| z)Zw1Y*Wl^(&7Du_-jA;23>-xbU~WF$g*>!b1~kmAbpMWEy&0&eT1;TCmNKqOxtyg$iw8Y^FktI zfc0o=ny2{?AV0*W>lFFYCWXfuBe#hAWpOebZ&87pc|HVksy54Er-RpKi;8<|EiQ3h zE4U)m_DHlW)cAXT`2P&dUxu?u^b>`w^DvKcvMN7LJR(j$Rk?38@lT>VHa@M%MU)>? zB=l&cA6m@2zsLN-_!FkWc5VK~FG@yVhIQCeLElR{1=~rQXB#&zaXD^a$E_>2)c|K@ zZRhH~F4%k6Uxdx3Uz!%|0Oe<9_X{iYEc`bE%Oa=in5LsXA&c||3A}vRjB6~JV_TlI zhL|nv4{5-c3)^C*%ubF>z{fjrDI5B%EdN*4>a6Ony;045V38D6s3{V08~cz+3;qP} zX|iGO76h&n0ju@x$(b1$-L9ERt3Y||lL;nCo-_V|PAGW2k}et{h<>NU>ND#EbzPeiu}3_;1VaKBl=nQ-t?*m6I6 z{)8o6TksbxQG`zT%QAy@@i-FKR10h|^x-9Y@S8Gp|+o^fU=H)Gk~XZP|Y z#j=M}N@YME!4o`1#k$v)3KJl3p#Le)SP-ldYVCCY`&ZejONnVRsW%Q5M=gQokky%S z{qfWRAOr~$IU@(dnU?mJk`IG5R^X|npH9-U=Y>Qcb6AsgA!dBJ-gczB;S{0t@E$YJ zb-jhZTm)EX9Lg7B<1{yMa;raAHi`4^=PQ6AvnnPDDFL8v#|Gj(ME0t~>@y;^NJZVE zZapYI+RG<|uhyN6qjMlV_=SU70o);Fa{MHHxl2_Fdv*|>^kw-O$dt9JM=8VofHP!`A)zK7-nznFrmEM?qu?o{$q8|Hx#gl_S z7$iW4rs}5niUL(rygC9Fa`6)k;G=l3is+zxFX+MYAg`ovWA(>?Sh=i*8d1xeuEXer zy}$<)67WIzZ&cyWKCrOu4{A|ExNZ{Lgo4=_x4qtkpO(6ETD_j^jU?uTe=&6)tTi2 zNj;3qUtc**{D1tL8FgdDE$ikpXjWznPiKMWr*=yka8eBPuvhS5@~qC*%P z2|J_({;dfkKoZp*r=_q^aGoN{i-m?YTf{){Kns1wcnPt*`!?Fp=Co%;tII;|zS8QV zj#A+JG7;hk5MgKS{~lY-*lZFlQ`@CMnItUr3|)aP>(9m2%Pp)QTa|1 z=+*e2^)6=uFA-;Y#0+|A6e>qgsuPuLi+EdP^A$^;j8@Wk!aqY|$236>9{AMA7;r`6 zQ`yMFMU5RN_*o^$p*HWtyutG1k{z{ZWWkLu&wKGAfl>xhJN_G^pVUo%qW5S=mzN~2 zUS-1VIZ7@Ohbv24U#^PF$~NrT5kYiIKW#ws%OEoS+SJ@axPrK-9vb$#!-&i~G=|ZF zCDH+2e>opg^<&Dn{R*IX(LgwXVt`tq56f+>*1i;gf4jZ1p2hy*I{1Z(#|{R~Pw&F= z^n1VSG58IIvGiHl&Qe`;-7QvgGgj3EgKH6CQltqJ z%pD=1nhQyuyg^V?k)ZV$xl|WO&cq%9BXqC_1MK)}I{0@c?I945-^vRwRfMl23Do1! zei<9?cM&ISCX2`QZ+3&|XdOTwv6dwku)?J(Ns;3~5D|p+kU?pA0k3`awVvCPa!=0d z>JE~;=suXDsGLx}Z-$=$7^kOr10aBV=tUB{;u>ljRn&+%5Mc zYuJnLWy%qKOA+><(%ep)r>=u)28t~GO=b?@P@GltIaA-kAo3Se_8dbK5XMFD`W^%ko2!%vgImM4N0!kW7IILU=ox8msPjBU$mIM z9yy#haq808syHszF@8ZTYViWnzqJhu+b0QTwNpiKb=??LmlEFdH3_pcSnXn~b|P2o zEDOp7ZMIKtA?Ls|?ZefkEtqm2^flV5fu@Wm}Xqo4u=DSbPlORY_eTed}|38~~ zYgUhlr?kTIV6>;ln~u|k0^ZSzD_63GJ?Ju3q|VZkd||J6cnTEJSojExq$L7Na=Pm2 z6&O_LK^U814Pj-FAKJnP(X|Tz1rHSplT<1 z(`#@FIB?z}VZHv2lE)r`p#X_%g%7=?mE*eK+~t^_?lo<`X2?STApx!*e&G*~-1D<>b*(p`c}+QTdu!ALkB2<11vjGd6q`bm8Zq2Tq>zj%Jf3m{#>ni0DTJJMy) zhq#6F$f!(8fyxhdcytv&+yPO*B;I1~)Y8`)JSq_DQX z4w`m!2#@|ejsQlly`hIa4IgkSvojP>C=!MJ!V!m)Zm%8?i^}P-C598g)LQgPtXE4y z2sD9+L&YiEwuM&h<5yJL&lzujeUMH*+^@mbX*KMCQa4f(7Ax zbQ6g$*}y@qbOot66UY42#xt3S9PY^`?pO!dJZX!4i!VH)bc$Sn06xW1+K>lf7kPcJ;al;$Y%quU%3VuiBJX2q?M6UKxQ65?vUBdW(;y581*SxePbxJxb-$= z6>csZNno*b0MIqMp+i}{i#fnTrdAxx@8pX6|$VUK#>D z?CA&8aBkdaCEX4tp<#4Mx->fD)r(I}Mj9qu+f<#y6#+ce_ zr^1}aux44la`-#2jh4J`EuR>_mI8QdPTpwmANbL<=K95XZBlyDyUv60%>ht z(IAEDyQ4#70uOgdh?zSg0)lT<<@(@Pn$cX~aqJxsLgEy*0EK9vQ7gK)s}7Kp_h2h? zZeRU3QI*RaadHW!zjlNWXu^<_y1Ex4oEC$x8&1EclPstkVaCMMov5#lzRaW&6hYHa z6Y>gWXKr8P3vg=irc#QM#Zxw-S$$`HL_fj0N^z>cbSdnw7hKc%Oqy`1U?m>QK7 z0Oki!#$TCe3nB?(S+;XzP`R>R6$MLGD4|s`AGe%|TPv zS>|)M45Z7y6$<5s63eHe4Zch^bhb6Zcg(4nhy~^wnT>8s$h?l;Ah5*nj{DwP=r#z> zG7D;yW&dpTX5m4}Oe8;R4vr`U%`^ODl*(qz{9Uk6G%1H?i^6kZJ0~c*3}SdG+hKC} z;5bkAIz?&7=(MUMnQROAP3^|%b$MubN+0;>lQ;Y)wfDe&oRLx2vp4UA(@)Ge5A-B> zoJ4TR7X@kNNJ-ij(jk%LHsk67(AvpqzduJ&<8a)RAma*I4hd235|IyV;+3&z9Lbo4 zozLu(0P{~`{=u|_vi1%r5qxtdU`NXrB%1uB7QnA629;0k#fYbKxUnZa95QH7Y>`|` zxdV)!6l*!)J6JtC(~tpjeCug*J?5;yvHz!@plM;14*LFD+I`8yNwyu5p!F+QmKrli zerxPo6snCferTGB=U0}jp``wnzk?tNc}yEox=Wcw%VGSaf37z-xMKCe1O{BwxIFzV zemQ&KH8)euICj=vDXl}gz{jzOWWU1jeGM6xMlJxs!ADBt#kN`vD9A@pc;yZff5fgT zyd4jY_{Zf>dDbL95c*}CT+XAbtpRm0!p8lt@syJvmwF8V({OD##bJ7)^pxWyXAR;7 z-}xn*OXHF%4U@dJ?D^ViPiML%iDOq6n4RVMMvw$)YT5R(6XTgkL1Hn%ur)Vg@v13e zsC$>FGJqs^Govh6b2Fh0r{9??mP2egM=_d3A7P2pyH}(y&w4H`_g7b$lu>DoH@yIl zhX5SVVK|fo-z5r0=%`7ksU`w50N@;;+75;(C8c|T?wJK|RJ*(?g@`(WDj@lecw*u| zx36>PkU}yIoHQGI#SnURp3Al*CBK;KYn8|iTw@7sSbot(9|F~<4HtM-{^ zArOq}yfzJSE!<8#+a>Fn`jsiG-{-EiQ(FiWBMk^Bir=ZfK@Wv*p3eifzAq1TaJjRa zXLH}leyhZOe3cqrj?)Im%VRCbe=}Z97Fe*f7y)+r6{pamQ&BRdQgJ$*!#Oy6ldE3P%s45$P;g4b@q$YL=KwPPeyP;|4%jCg?_Kri z^<`4Ae(l^P>}Bi3bL6XbN2@o-p1`GuPsl)LqU}L-LdnU%wvjzz=#=Yz+WfAKnXn`% zfnB+KvSSU(fE2)NAHT%(d+M!-K+}F_LBv>VPC~2dmcsePCo5+NT-1iT(;l&MR|Hyn zHY=wod390<3X6OS|9(G6r9>RBn#IJry}LoOlv{asHX04t|SyEh~f1sdZsr0Srp9$&D*+969>(g^IHPV7#M{F2 zG4&hFG&CKj-&*OnsUl9E=3LPp+rHH&IcK+u7R(<3HthM@(iJtz8ie6OV8Org0=D5z zuE?N2bbxYeGU6DC_$<=3`C%i%<{cDn@0nm|4UeDg@PJk+0a&c)YIbHEFdK}Xh&l{m zL@u4KD$_-jtB8!Q*bp3vQ+?n=5Njyb6|2QfXL9{QinH}tQ+_?!2L<#f7^AAZyRr)f zX)`Z^yKdz&Rl#w}F^K*jb)e)KuO@oZ$k2T6!t??3nhW>cY3uZU89P znOZ$3K#YH9pgsAc^V;@^$gpE?6qjKWKa@S*Z!=yNie5Y8^Aa%{J)dWciH4%u@+Y=l zDD#80?{4o7Ze+Ct^KG#NBx4|D9rH*2LnIfwT0@oIwekt$2`>*>B}q zZM~{wa?`wo9So8@dJR+ZUl5ddyG)1Zs9#VaxJ4k_>@UbXPYPau1hxHaB03ENEWDdw z0_2>=DO4Hl+dsiib#8HWPnEgSA^FFGHRQ$%Xo{9!aJsZ*jbQtm$oX_R{k46#Odmyv zb7R10RdasYOf;~m`SV$koSjGk?@9r6%%tE@x=9|MVPhA=JM|$|LL}ZqX#4=6I$N@a zsn)p4kC&d)y_vt&Z`x0Mq3o!=+o54JT4W9IJU#VSc1 zyC!AmzT>@5_}$5?YVK$307SS*F)hk8`$D{GX}a`Z-$<>9soi4Kh%7Bb@AibyWA0nOw+6&UOJhVJy#Sb$`pM3&IrgmqA1 z=Q@og+ov&QjUHPn4o}Ti-BLKVYAt%Vu&sT=c8}c<=W6Zfcc_|8EXpM<{~^2J5Ho{U z^$C|4+`BWfF8^`|KMWNp*9J+i9}JH8WSKivd-74^ECExIUa7VvXFz=$3%gB8)x*4s zSDD-)xZXyo*e>c}#SG&7I~c$8Npm14vyc)^Fbc(KQIoM&dy2|*&Hl8<(Sp|lNgpaXD5zkfwazk;2g^R?|1=*ypr%q^R z(~%667O#vD;S)~B~#U1A(C#H6vWD4c&4iCahb;mCWL z^Nx)dlDtm<&I?T{dZt#Zc-)O4u14rno0YoJ$1`OZx1ti!Q3~%Ic6#*nQC~pFZAqM< zm67N_`ziRu)cRD&0}2FRO2G^>8Sipvcli?}Gy9?X7`xy&v=lSDuU23Yu!L6ahya%; zpooqJKYuzu@n_t0EOi_exTK+}8MFtXe)W7k_xt5Sn(Vx{yft%aV&8A0RzEx*b_ zlcrUO@W@nSVY15Zbh(jIn@V|mxc9xi{@bS@1fSd}XIMI58|-mR!gsjGi(|miQK|LL zg*MQJey7>6$q=oK<2bJR;VrZp6x&a*55eX&*cX zm1Da^pnc;$eOwi13aC+PoI46#))G*Ig^z;Wr}kmww2DfjM<|U zt)Ia-wDLNqbRRz7`aV2w>q?uwiZuh3#majF0V+*{#0`^K=wpIcWY}k?eajcUlxQsx z^U;jf1#XPPoykM#2?EisY%u$%m|1R#Sv>^-{s&JIdG>O(8;Iki^a%V8FW}#jkUBS? zlHeaFfeIA8RYc2)FlzK>P2DyL%kbiP`eRbBDR2unh@<;t1Js5%$he7`Dc;gVa4?~1 z^dAbYLLHLiqJ7poae-&Jwk4W0^n$Jh$=TaEywe6mqCu7}f zpUARMWU)PgH=#$SB&VJ#QFCK_?HG?8Vci#u9YZ`^e$Dc*&N!z$}ECwl(bj^C%R(Ym-;sd^?7u1Oir^sf^} zq%>NknoZQ}Y*`3}3PF{5caWee@?Nld{!tbuzSa7vLH$~H=I+H}Okr_Y4iSON2?V#H zQ;RRy+V>~b@|xhVW)Xv0#<40(q#5EmpO9SK$;W1~7$=q8ruLWHHt!KS(TT@?x7pY?|?i#0ky9p^oPh;3y-%QWf+ak>d=I z!Qm~{^aitYDi-YVwxVi^2~z1-6H4K1LS-AHvZwgqc2DCBDO1j6%qFDOtAA0C&N8vh z$ZRpTEk(Uze%#g!aLn$n)wk|gWm)GTbj8;eOY0O3$a1vP($lap?#%~CSUl6AgulA} z8>A78?kb~L@Bfx=oM(7GQ8g(@faiD}e^$K?f5#6fnPCZ3K`@2=I?z_vl)l4vBD9Pp zD}3NW4SV>~I}BK*H&G-OJH6`@;hFAF9yJfkCzeS;gWlC&U%Vj;r>E*ZV^Y5Tb{^r< z`fVs*H-{C{^f&#N=*IA(GgiqnhGlIIR>S%rPr4E0WPlT)0%NHZ(g*-+tT8i`BxGQO z)#*U^`vey_2>uRRC53gpn6c{2f9y%eHhFzl1?%_KyEEFk2n{~*J&_nmeh#1{7amdr zJDl1>@MP14@Du{dmoG*+|MsMw-9;w|W>X;GKuXLY>*XptsGxaVyPgo93xL!O9+t%$ zStAT>=AgEG@-xY;L6}YI>`)9Utv{M%Ba9FlK{d!^ z(Z+e^9DC#+fnDKXoKgG?YPpb`nYb$F zlMtBl^e|5Eq7>6wb2AAdi+qC*pVy}v%9gg^|B32{ohYCL{vMkD|0f7wW9x9|K?@ZC zDd>$>Xb6zt4!xzB)?$cXws|m#&z>G%vTQv5TdiyF6h+5Zs>ew6UI6N*l3WiJV)Ckptn|dP$Kl9RH-)9uXHeG7p8=Ex*9DTN=+zrvZkCR8Bj; zozakRk++W%8`XmI?ePjtv<3>b(4pMPTyAyRkatMBHm2#DBgmtklcE*VI=7S7qakqswJiM^cbBezeLwtGeZG-;PAhJoXy)8#9xzZxkpv(O)>U zE21F0^|IIE{8IT?f1;yuf@O@4igm{Dc+JXM;y69`KzT3M06Of}@4-BiD7ZlxWcaM? zzQd9|0)ta(E)BFr9oe=0Ok^8Hb{#nKMp#Y33Ci$-ZI}M-1%ebbthaYnwz$M)aiW^swk!R7s6Y_w zcl3VlOfK#|D0V*H!0rpv#?S`+nslEc2#S#JXG*Z8kgk;{1)cG8^O^o^zA7NGe-}6; z4AIu_;2=J;TZ(cy%;TK&$Sivhi5C24nP8IM$ST|il8eM9#7Ou{5e`o$Cbv>;sF4(P zQQ|!^?ioqe54gZPCuhX8=(*Q8xg_uihGD008{(~1aF+4R0? z?*Q*@u~*tXdR3vpSjdwqYhAW$X!i^;(IH79O1D(7924#611y@-9551N7AZdW`=1Te z(T%(6Sj+#)*)$Jmi~2+UCb!P1Yg6X7#;pEaX>R=w1l4gY)4@<|v>Qp6 z=<`=eJ-}P1E974&cD)$t`YHye+q`*6P#H^?^w-HZLC~)n%6|1UqNuvFBDoq&9E%(^ z4EnopeBWOcn@b?xzD}%6EoC<#xv)ngUUH}W2^XuBGLT-7CVqnTV4SAb%u44===SOe(d>74C4d`&Fp=vo%BDD1`*vhzX5kOV3-IDks`jAK25v9VR z8WvEmomy=}ok?9bGD-4^15u(BcM!+|#6tiL@Q6{AxM&FIbWayQq=bFvU4;EjC_bq6 zrLAb^4Ca~$ZLxGwL7Gr0vQC)g^0=E*@r8e;sOT-D8Xn~0 zC*Rz$n_L~fYDM9{H;GH8-I`ibwZ3|(Iks@19-Gt|LeyTSKfbx|ezNMw3~CIC6vvke z|1=2O)i&!wE&z=saqvk(k>orT9>a*oCeXW!%_T z@ZAjLCMJzf-kK>A3Yy0!$BMqr*Jot@`Bj=E7NlH%iZ-v=GmRhIjM2wtAIM(6sw2bV zTb)PzLfE^v9w4EcZ)RIJ@-QemumA)ELzt%x0wliL2V_m6>yu`;RL)nOS3?e=ZEvAc z49!-&ng40Qgv31yDZGS@X?_vWo;H!4CoB@7;uqZI<{Ni}Ui>bIB#I;hM>>behIHb2yJcgJb_17ZUgaop%-lq71x0&ZtnB?L4AZ7?icg%$aQ ze_qg)iDteZ{_t@X7Dt&y9R2)_Ivs(ykrD|y(>QYw3BVZZX?z(mrR6V zDtXsimwP@iy+PWPO_k5os<(S1eh0NY0TIdmv`ALvjAfp>f7eHNohY$iGrzE+_!85} zG*#nNG6Q6%Gh)8++;q+!23biG+vf*Ez6yRFaO?mj-5ETGuEejI(-T8Q)L-ER%;;Qz zN%fpx^)bWd(J7A4x8Q+l>4nZ0ENJZ+%xp4NtVE7VJwb=5vrK{6@-vh>3Jy88qV&JJ zi08Ji+I({pz&t?%K`#tI`+*}!(2mNxl~lHho4MW43q`)MxqJ_NEUG4s1?#KPQ?_9| zaE)jqM{=91_bh&Q$2=bUk6W6oLGg|v7Y!FQsf__{kjnhdS(qb{7zQElJa z1NriHoWh=oHK947Nw`D--J^dq4Npf07CDNUw&kO38#7Wsbu%r?Pa}`xsfNf-hpK?_ zuB-CRkJO$U;mLq38VVcJ*{nF5A5~BR%+jViNPjls^*J5L0|yf3psaV4!RV=^_j1@g1vvIO!$%nrHI=k)wgLO|V@rrTi$m!H%|t&B>QYr9PL6z% z>ml^+w_trC)A?!vDz?yMM@?#dE3bywJ^bnLrJ5}1yl?m6&U9WR@MgP2MK6P&!5~v{ zbTJRUJ2N!#dcdCaS>CD~zo9%^Mis+-$$QO5Pz9GC95}E3gq`m7C1`k3D(Gm!d!KVo zGx-WBhP3)7u|^QrP8kCsQ52Sh4R$i1NW)D8#w;W;m$oRMF$iZ8?8Y|4d74IYF(tDn zV@}+w0@}G=Y7R%;5GrX4la{O3AhJ3CRi2B5Mu%A#bZlf zJ9JqqTZVSY@F2bttidTnIXcl|a$=7?rxx&0bS?i`>H*d<$@E&p#Sz10LCe&ULx2gD1&a-Y)JS4C_$a=4!WDua5E0BbQfV7|LXs;>2Ta~t8wjX-<-R^R>e=*D_bS#r` zfdQGgQ4EN{P~Obg2SI7s8LDcpH!=3wmSgQ{kTipKWzJN^mYK&lNrLJ3AHA;g4S7KF z$PxMyY`R&e?-f*^NTivQFFO;VrLx!wI8562^&aKzZysf6H)4L;6sS1g{=|Or`+|7g z5Kf>AfR_PQ8oZNNkz}ckG5m>T)NE&D4(|~S!~8Jm3A&(U6sXL0Db0w$2+X1pDy?J? zE8IxO!3utmE;|Gach1wRM8<$YN0nqP3ra>7SP;woC1T-$;8i?=phUn+uE2?a5c&aI zx(9^pIG50|Ft8oFyX?O}&b(x5`bn1xI$m(Td&}sN7CE|G!q09QgW5~^f*+SKawyx3 z2)(!QFxc&q?d26iP!62Ja@3TmBmkM~RQO54=#&b* zYUSiXl%Lq9(#?{Jr$qs;^6ccJ%Ew!bY**1C?v( zy4f)kI%3hb0@zj-EflvY5!lq+n_e}MsJ}9{n}FpoL1t9Pz0ICI7toY254EISb*yoW z-f90f5X)phNBV1E(0Zls5ROp?UQwWKB=<)DqnYDUN9V2yRyu?^O6nh#onZ#F!j)EL z#=Lz@E|lzW!)&YY!B{WHXUzycMV0Ft*6Tp}7%RYS3-Oce>}d8Y$Q4!oNtq zwIbM*s(DL$BoFe#_|r8+jY>TzIy+VL@e{S2fs9)!``G4O1TkH{gjL4Fvk@Gm>f9n= z!d;vPEyQT7R0hu=oP67jOZ`kjKyhZo`2afmxT)Ry3}J}y#Q6751dbWY-+HobF%k3P z*5+tm_y+@n`X||m1ch#5p*l3`3#Bs5m8Z?D)mz^Hzl{=no11Ug8v)SP{67p9+R<_5 z`yc6{4KwyL{k5xv>#o{i&$n67JWTfurW>EjSqn~~X zXVyYPUF1TA zike@GlO7vj{bnVs6M&2%D=9qm0`|>HVSDoM`edtEAGs;=kIm}a5m4X$mtEL0gvAGV zE;j~!6iobPJ3gwfQG|-HXeA)!{)h^Wn?uvh>r6x( zejx7V9^%r#nvwiswIY^;H4xkYVYWa{Dx+i%u~TvARyOh(rma4VcE(%JT7 z>EqNQ{=g8yF;Xl7#9;?62={-f+d&e}TlbynWZ#+rz3-S6baH~J1v(+@xy;Tz0 zCCBd-HHljm_6gba8TJYZygM5BIOlo!WR9bsU`HH>XG)eC40Y`vI3?<>HI>Bl4)nsO zTE4{Yd1ehY^nWTq8aX#Tmi@5}gJ?OceT zY4drn7n`OVpkPGzvZHJfLjratNO*Ai8pu{=#3`%On$IvXc9(BDr+KOny_|P2*Uu6! zjMMF)=|MVTWzDj^}UsDaEj7+gFV#SOzLj>ZRd>r~)yT zhQ52R<&|g5^+&o&kn);{H^}JPrU;x$xuRFqzvf;#6R;rBIiqDQDs0^OKl#}`#l7nb z@QCfO*!p~k@?U9AM4ONsvT(uO2;w)kquATGf_iU3Wus!ZI|V5O3814Q=$Xdr5N-TDNK@G+V%21h#75~Bn7V!C4({VVdd z5SE9~M9b3|@pSBv4+Q^bw8(kVuaHBNY-l7rE2a0-NGD=w z=M;}l97_&A(=sF=`PQWM`SiZh>s2=CY@do&?_Kd!?V>K|4H{?~yB0&OA(&(>DURzS zL>hHPtJgKd1=gaK)5EpMj!hr`7cvhpqx1Luuk3>$F9e`6ONS{Axx& z0IZs6o>udmtNFSq1DmR&$Rajo>9&@vZ#VtM^-*#Dn_nN9`3^@q;3YyGS=1#LXxy4W z2ke&Xs_@&Kw&eC8e7V zBdWb^i|)mb_8y(1`&#xvdD(T^z|$5yBXgj^A9llGY7>nm6YT!5MsG3|OvNb6MzFug z^lx82d7i#_m&qWG91_t3f_aun5zGcBPH)H))iyVLC&;0A+?iB`Owa(pa)XkW1-!X7LqUbgMn~ z-n?_2arQ$6gXf10AUtRyd`6tmzfsIv;9)c2e?-(^cCLKWgzJ%fkYhrRudP6=yw%kb zA2X3evqqE1SJ+0Hh*}rr$;Gv)?p;9*zCI(jOY~oUf;x{Rsel;{@c$>#Na{gNJ}7TH zW$1A=26#;G_NOV-uY7|*nY+@*r={t|9tf!oL>TO#6u`)_4mx{3VK`nc*l1UR3Zz** zj)5~!FjCS{uHA0yJ1}4{$YM~y$?fPc1 z@}w8!r7^b@lh_n$V=-QA&}y#*ch$Oyne#II4%ODEiq725UtLi2V`foN4O7ARsVBgP zO1b==@{Vh9P=xURB*A!yY8Y!XZ%WUma+e70AYOY4F4Hs-Xho>!;N>i3YghEm3E=~C zrE$0@HC@2CqpIfVhgwT1Cibz0pr%U)+m*`VKnq1xRjWSCot8!NeXe1C?jJW#9=SAEkSn*FY-XBC zlWofH#r$@P7ynq^#wOLvJh$23bx&O6`Hfo-2P{UCPhUmuH#)jyXJvT7GZXakVr!f1 zrBMeLcUE?TImu5oMvns#xFa}wR~D&^%iBjd5G}CPe8$2R4dG*p$)%&hXy0^a-7X_V zfV`|lOT#I!TCVOq#C@w@rk^VK?&U)SbWNRfNOv-xow-gJ%_C<)sv;Q{B_tcNsUMnL ztR1s-ny7MyIsOY`#BWFq00(Gyu8J}eV>A%(5$yIo~{L+tVEJ9eWZ7FHmmrESp5wBNQ zBFexB-uBd)8BQh8Cy58icImKA#blgBF+d`W#ST<71ub@y0z+jx_5%P%4Bay-Uf7$4 z;55%=cB(aAv@XN%2h5YEfJ@CR?Y(h}wl51(8J?y|hn+5_S!t_I7tm9synhD!YFOh7<(n8z<*`UuN61x^^W*sr0S_dTzfj8x%ww%z#DpBL3 zfpIW(4EhW|Awq93MmPK&-a2=_TuS=Wq?9wvhn7mFz0K}_XHbGOm5Kw8Gz*4OIvzB} zzN(cD-5VE&#H_buuzK1hSi%_x^E|lmSUR2G7?&|HkBl0=xNe=i;YoE4f%*p8&{Gto za_=zd~N*H_DkcSdPe!8LZ<5qlKwJ#CS5OvN3^ht#;>p!yBuDJdvqyU8KeS@ z!WJj?uH^x{>lkC%Bp66MI4Eo@9qTg;K97jc8P=P3a5>B-?l8yc?4%3L%cRwk5}8i) zTxlnPzGv3Qla2x?TrzcoQ^5&dEJXk(im=6^RxKhBQj?PEy<@z$be54ez8bDB5&!%m zy}+*Sc4zrFC5cv97}~mGFZ8G;UsBf|_D~Q05<#v$;2V~FvIM6uoXzMc4zltD%F#&3 z9Dnp?_FifYS>j_0P+5J=dpr-amb({jI%xKhZTr)$NsuE;L`qJ;#sWb6SL`7q6&R>L z4*yA@4{j$(ho;{~eSKkS!(lrr|IT2So@p-Luwr%t+GZ(HGy(4G>SO6iOVyKBehJm{ z$(S^%wI&tKikH9sSArL5JCk1H6`U$hte0;-Duo=IV1!YAdt>zgkC4wJL&T!?5vBAt zDtRo(&yXrmkRENK9Z5}Wz$FqAcXkYlx#alY&}MW7Y06iNf5?7;r-?R7 z!yp6-y=eq)Fbx=9F)v{EHvsByxB)RYU$=_}ufQ3Rz{fel@OGSGs&W%y++1zUf(Wu4 zFP8&Lw>=3)5dcX*w!c5omu9rl&(*_}`rcI|Irkb!zFtdoN$e;tF0zvh!4S}w8ltVN46?H%Q+>NMRoC+T||U}&kconMLrJ`g7Q`dRAXgK`_E(|7=pA5 zmd8t_PkZ%!v{n?^c{mcXwYeGH+-GaYJI=wx%JAPc6OqsK0J?Z>(onts*>&=sl#}FJQ}# z1~?QSxe%NAmp~*(NDj4^dyt)nZPnUoH|x6GY*<0038D$YQ4ImzFBn@N-ZvcU5IjnG zzI&wFf>JE5E@ag9;F{?NmgjA7+NRswr6Y5fc7@FTMw6iH&Kow_fC1GVmsg9`&2P*~ zJV9Q<+`f32l^e;&EZziE&sImN;+Ag9YXO|>Vl6YS&?m57vG~D+< zwF=K+nXw0!f8>MBv_g^=E6TYOm%`ryd?{~3$SA5eQAp0OOzmXje;zx9sI^1^ZBc|E zG^ovn*|*+O0V;||GH~vXnKXNxn43civJ%`1!|?ujgSml*7D_b@30xGh zjHWeXgT%nB=b>LSt>zV(;+FoQK69BXNJ|4Q1{FZp1Pp?RIcw%K)H(xnfsoy50{3Cp zNEr88a%aXewZ84l!J;8_!?!hwxL7+uNu>sa;O-j9J`qACADYVa+z!TfcU1+?)Skzk zpY_42+a^c|Rp4`gXyFd=FdZwCZ&Zi68@X8U3&H$!W({3Mk{(XdQZr|45`^ znuIVIeqnBn-t>_>Ef!)4_Y64&QQck&;6amOB$?F6dj$&hrZ(h-K2)Yi2gf5p6V@v) z(eA(&vO>=;HPs*A6aRoZJST`7x)SOS^Xgpwz2bk&02Mk13z#8)AhvJd1oF;!Vm4n- zfqj799uZMEis%KBWa-3AjyFp%ZQg!ijD|7pFD?|{_{T%pEMI`17MfN#LJ=e3wG~FQ z2n{8O$oj5$bUL5$BQj{Qev7DjrF`;#5^<_$Oqc zKvt9=dE29xdfrnb2T_v6nZS=LOBBGq`J~BNK^!lvDK9@gCU8OPy2pwow_ORgVWW+Q_EKxF_RiEF_#)JohYM{;`(ZbH81u;;{h+BQg53;~GpxvkE#MXJ3a% zWq5<~?mEt@iy9_z)W!}cJxbS3=_0ZYyp14}FgdGq`=Vo2iCN`egPA4A?0@__}yq(K$wL=xb!pi=bjvG@LZynh6N%wS*he$3;AK)+H9Hh$CZS7^| z<^$+m)-Rs!;CB~X0$M?!ljFEJ0lHj5T zzDf-&!rFbroL#(k0gv4l&=r7V9D97la$=LBjSo~YLl2?VzZB7$M)0U7|vrjXt3#+MkkX0^OzCXyc7k0twtTA03XzcXm{uC zFg+VcYfjQHQX%qN&7f(-Nf7k;5;U@~hnG10_l~#-Jmt%*<~fcQR4LvanD?7CT{Iwbq+@wh=4LqkF#|2us3G)RT`toSQhNO~0Q>J2OwUMx_ot4(8-T8|% zXLv;sE;HB5ec`?V2voMPLt-f8mzmAF@-yy1X})FMjT3HS5^n)L`>={8>Eezrz` zl~+x!_D|A-2;dRh?AQYu$M)8;nqN@96{w8kvYLu0{R|FUwP9y{7iK z7X;xUzLaLbd{@)~kttM+o5cu_T#dxWUzKxa)Mhs`7GOqv)CU5yJJCx3#*X|;KOcO8 z%7=im9J~<%qZ6<~gc5YfFL+s%lgoOKkmpOd=*3d>trWCymbuC$I}Scv_Og5cd3|ls zyvr&ZY)$&AJ3|~8Qj!)*ZJgR3Rih3 z{r^RohF1(;^YkQCjB(@rAu_>-}YoxK>HR$W+ioSx{2;<5%Nrr@yeDY!|a3k)BV2dpWp)xabV)r*r zD3CQbT1L9*BrOW)-$N4nRjl4g7I%FmQY>+s(NNE(dsxOUH2{BYPk-c{CN$^SGtg3U~`MaCK6R{SoIcc zA?uu|Hh?n4IXabGvwd^4DDTy6<7ne+Ow_wcqYyU|id7nMMS{(g4Dca+1g2}FXOWo1z|ulT|S z67;zSuSIq4OHdo2PTQjLr(LDuXw-2L|)`u%{jNtQAv%+a&U>uHMy2hibc zA%hI`=i<1@B`@D2h|My5y#2YSv9n}-%c>&sm0~qE5mWn~xgp+%WdC31?3&5gbW5Y* zak_@*(vOpYLl+;}(kCRV00#!RsEk|bKJju!X6hzPD8?^dUaU=A4+0>LsPI`rthM~K zdwa6x)pkTukpKoerJap*(Q8sPiem5Kd9K_3RESVbG0CE&SpWIxm*=$&)O?m~gELVS zU8S&=^sae%0{9MB)`}*tR;=m39nN)68rdh;E%G`nL&&F>RA&k-4P}GkSwKa#9ME=~ zSP=<%GT_Zumy+OgC0ZPN(xrh3E#vVEEZuq);e*EceHO3TR8Hb?W2(KdLZu(ouqR;I z*Lzn66g5u<{iY}^?&RzWF<-iq9(VF-55C$}8xIIcv&BW$K*%UU8}D;!Tmvpud;}We zD;6`bc+7?(QwPyX)E!=|W9=WpG)bTJIVjNAec(N!&n#(}#BdD=c0VGw-iA#FP! za3cM${AEm6c9TgSL%4Sii|%LWksN^QmomsIXnioJqpi2rwk|(0{z@lbOFm+{nWn8mD_Af1-wETXBrXvA8MmBYHaT+kxC@PUsW1mcjV zy#9}9A646qB?tTzZh_8=S_8|T?$X$T*D+qIUUZb84SlG1M-47LmTf>D*nt8dsVW z&TcJ}mUO44xEyWVZ!})u)_S?kBi=tm`pFUr!otUk6j!u!w+MrJYQ5kousj1Sw6=?B z;EXv)8NMBK_`e-tm`vseh<03P*|!{Ww?~+B^6K%y7D_d&DD#_J5J(h}CmpH;1t8R?o{_;?^ z5(>R6JRL}!df20FNL@v}d%lGbtyCk*PxVzGOeJmL@oW5L$pDxD^E+h=!(yr{y zhKn21(ge;T3zp|xXZB|N*pqfAApIC&Ij4he*g_37c;Lde9#PXyyz*!7+LcSPcl{dH zY#a>4#fbxiqa^|q2O&{G2B)vrZgza4H-MsP?O9(kgMMUtX^QAt-QP@U>+C9LS?9zD zl8W_C(C{`@>k2gc@3w^-xB&}f8yU4pmLUl06=T}+VMkQ{ zY!z@~w?w$tiF6e4-wgrH4TWPW z=36|05eGwdS?|$nu_mRMnE}hv-DOGKo=Eet-*X{?@xSmShGiuSp8$Dpkq$flqg@$?>wp(Xf<5@2-j4T{*-{w^ zMBj;5k9J*Asis5k7b_AKYi4Vx&Tn%kVHV8>?r}06hb-s!JJ`0@ALe?O0Z+0WrO;k${H0`_dAqE zR5C8{F8-wSAOpaT0`Bzehf*H?{qj5NGa3&lY(Ythv(^QiLeF*D$=7Bt3<;nFwYWMx z=`KsaDBwP9{wdfLQhWqYtPOpoeb@flc<;eRRi(Ve@ zeePi~3b{wssY2gDbv_{qlbq=j008)RaG8=6i_!>l&I{RK%$fY8n)V%a#_Bpy{amsC z?HTl?0)}v|PVwIq%Jo^jK&7z4)oi(?DlE`WYZb9EB2hSdzg?_H7y9QBTQ0-(3o`oF zCqOk*-Ay_#I)-uEPbWg2MKS66mXrFCBw}Qyt42Y})WbqaEDhz~H@B)l)Ytw#T+@)@5G@nW zJkc7IrjSUg5aHhMGG+0^xbfznygA5#Y{_&>OW>d*chR2o5=fQ(_7!#^e$vj;Xe9l8 zQIly`{2;5QXbpc$w?!=`$~6>r_@%6|7gRM+fV5WNPXiCp?ce_0KJMv`K`E0#n5oI+ z>~q_c@mr7(|7s0puvE~b>5Qs4JwhZ5&-6O!(<{X?TO2{b>}tAAp%vR)Xg51-(ECa+#2OePkQ;EHv=kFKnx3u(H(GVJ=>K z$K)lEmP1_a(;OBBgB^8Lo>)&it)&)?2JJ#%+!HLyPqumHD~s3c^3c}3Zgt1aT(dR= zs%PpkO(V5|NknM?&^A}X*Fw4(|0dnenJSx08<<KrQPF|0ID z1pe(p7|T|nu~XXBboe3S3MAy zI!cs@3eQwJ;GX2&40*vl#sMAPROpaE%%##|CDo*UjRon6diO=Lcb=4%UfGUd9`j=+ z3|u+SE$cyM>vZU+j_wyp8i6YR2d=658ynkVy;T67*xrYMv$w@b;stB?>Ldq zYWxOeJ3NM4nL+~7$o?#!qfVw>EE!-q@_fJOlm19dmdYb|2MLwu1gyP;34 zMk?Z9OmjU+Arl2IKkR~1a<*DPdNftv8z~WLEv%^uk{Y_zJ&qVTzGJM{I{gK|Gb&pjKg4JXaP8f%)r-3Xd~^%lEbmF4+0(rmnfH}mo4L9 zYNYqDKfc*>KRZ-?z;i=499)qXGboH}tM8N8kS z_Rz7_Bcw$*O}lF&&YUqxdQ|E4dWy3;ppSne6g;Gq0j;~!k42UVlZ2f3|5mhFLOWMB zGAfmhqHsM4rZquog!QecVl-8W`y(soEpXOY2)ZciQa;fj=j5OH5OI`2)2$ zm^Y_E`g9`D9UebBB2Y0DCo@fy=DxC2#&~aKw5-x~3PqkoHH_wkxIYz|nnR@7uibax zahu3qb&vB%HgpXJasZaY!s<_LR7frw&e-1 zkFKAabbzBiZFFJQe^aER1V?Et9&@EUnlQH(LK||O8nu(Wu zfQ9bZxa!PL0BYYcaxLw`$vxZ`O%jVxOU!TUT^;nTb|xPLs;Q&~z2z6Hrn)$*EL!Pq zjN%}J;E;Q=p?}c+h3GAmc)IDW!p0pO5sXNn7m1= zBG&_eL4{Gt6@0Dzh%5F?a+9R%?!R_*)dRl;;L*cZJffJG0BXC_Pb9#ND#CVFBdg65 zNy|r!E$8_x6Q@~EZ-&?xT4io!Q&jS_o;BT$yh#{SQEyo)RZv{RPcgDsmB8mx{tGE* ziO;R2W66lBcq}~-*-|5$nVN%PI#(JmSlFOI*5J!{w8v}oj7Fzb=q+4I3 zc>Am)6#A-a+&)15>6~4-f@Go;&Qb_CrTRVN7G0(9ZpZFe$GMXR%mkwjgA@>;)a$BB zu@j8l5ux$P5Vk)t2h?U>r5T?M4m~0jM`9-yFntmgH1w9PbtK_UZiAK3#OTT*BsM}r zr>uIgoudfyk()sBoO6;quWq^t21B`1AnIBo^AOzdE^L*b2LrcxIS!>TO>ry*pD?&G z>c5CQw=<-ZB?r*<3ZKWXc8plGhGgree*|^Aov+12eQK-6`LCjLxZut>z>8H&L=Z1A zP;7rbhg6ZLf4pPLXQMl$<-?CNtL{S+h!$;Cu`T-0DN&=&o>&E?w+le57mExMV(4tn z7||I(n&MGbGYYFx+h%w#b(c72^u9gJ&lar00b9oqy;glf7MepNGDf%Zgr!?!OLf}S zEiuENuU^LFu@EPdV7Z!2avyP3_rn&q9WO-W26ijK4P8d7JIpAhF(qy-y8EVma^W8Deq(zT;eF)30| zE+3lnvX4<~poOYgo|9anWFd*jw|!uKFxEAK8Y9vk3!K5uV3Qk@lxXfKR$qykY5_+I z(_0&yho6Op?&nX>3Zg6D595)s-P~Eh1ioVE8W%DhjFu$ft{k8{mu=6rH1(gaNfX$& zzDcCxY2lMSQ$6WUmVt2=#D4s-?P*K zu28)|XyL2vaQu~aWBv$4MjAM%t$oA2gi^21q#B($ID6Bfm=ayf796vD$d8l~@ z^vN-69x`#l;y!-FRHU&1K9qs#s%M0XnLb=Z_NopYUO8cIIFtK-yZdBjW=V zlbFOVP`*{0fIYgR#-RqhJh26${t}F+P+ueZ&!@pwCh>ifiQ^=~kT?+kPV5SoDob$B z){w4rO*M8BzX8S_4`VU-GB8^wIZ`g$>1bc@?5=1zWSJ;y08X{@}SH@$RCHWpa%sN-k+Vv00dO~LEF_G=Qs zi(7bNsrj(W!5SWyL%e1?vGD4!vrUh+xJV|@Od-iYw>Jhq`7{M9ktfzdF2Ym0Z+!S| z+9+B?lLmXjp9;(}ToV5LZPrJO$SzH|45JJ1T)#Cjm2)Oi0UC2+hOEh?poWQ?DCEIo zI4=<<_-Te0-vXHy?Oqlu;D$-pWp^xrVY>LM1*aNA`|bf+TNDHx_25)e(?RNv6B5#; z;QW^u#Vx;;oWd2zeq}&}a685u1b#ByfxPdBU6O=pW!qLbR!zBIOPA(TL(8m%OuMil zOYreoh|L^$8g|E?oG>(gNuCuQ%wM;q4pYA5@}7 zeXW%n^eHuay_&+@VjZPxXzrNQ?Xj8&*Z9g5hv8xlp7T`c$9mf=JOEo|0t9^ZaGgfF zpdN{XobfrJqj{h>IC;yqpFIwTa*IV9F7Scz<^MmN-Gloa^k0Hr}jBA)o zFIj}`;=x4Xy3IH~K2U*>wy+@J|E~K9$YOv-?d^45bl^Uss~H(C9#upPetne#>T~2} zN+Z3~VjMid=&JK$^u?8$Qy!dt6MNWuMqy%aHua??UpjFHT=6DBrJFp-vA55NeYo#( z+)sUdP%Oe*2_^Z@*Sl5jZWjpa@4xi>D(IvCZ+Y3)!j9|)wFGmL+ff7-U>)y8@ljEZ2&>(&FAbQdBs&ESs@n$=fTgLf=pQGkln4!+Sy zd9Yw^lgrqeBzz2Hor5Bd5NdS^l#psuL{F zv1!IPMVue|;NMB#K+%{Q3?Y*5y%Q0-NSd$R6Olrw?ob2|z%8(?s&kt`pmt2tRv}=2 z4v#$0(Jk!v)B%_7&}2~J@<8vPb^CvZURrD<#tX@isMh>b;!5o!kXpF7R?q{4$`*RJ z(-O7x<`#1^TZ(Efzx0zV?K~Y0)FkbOmPk6vu=N_GtmQy{-g^|pb_)vf^5H4Nu1%WH zyx9?`oI)0*GoSf2 zZLy9}l@vdysLFNqIklNkPt^U!1w{RJ1~MtVZQH(2x}ljcT*7&4msXb`uFe<8_OUIRijHe>pKyBEmHuHAQl>X zmw6$D1xTCfQlK{K0V*Yd+|{dCN|XDK52^U_t@VNdll z$&}lgG;TCDqu3XF6~*zsDAaSMiMgxJ{i>pI?ypX25?{uNUNWvASs5lm;~(RA_CchE zLpJ*b-ScG~6ixd3xzwoN+N0}Dde_zZ2GrPz$}u~2yI})zKPlV{n&s3^+I`Xs5-;9e zo)BxsWfLW=XK9`jU-v5uRg>!#axX5A_$YOjQhPQ+lFMF1#iLraTTi9iSGr+DqK+0AWj;G0paZlQFF{Pf>|;^#}_@4FxI2XY~sl+PGRb4)1R zrFX^H%1c|89x-J~f=s_`i~s^k_54&O@aP!ayE7u;dfb*IEVoyvI6?HF{UHc(!C=`& zB{%7Mxu_}{R|l#Ig`A_YuqrW0Q0gyF+nBg!$64SR=GQ|TE~+Qeb;a{Zsu7&3c>{|O z##)N&G*Tw)42TFZrX^ulpovI*(KtT_Y)adqe}@AHHbf!PlF^#{lM47^!*{jumrR)u zPDw*5yM;Yy0EfnNE*%EYtpeaR%f9J^KTRVbEtY&uVa!^z1IO@TlNK9j!ngvMY(Ia|?(J|>db$Qb zz-qcXl++)t&9aCV1C!-<0QKzA0%p4Ia5=|LU4!;=YjPhjjagE!3`1vyb~3~iD@ks} zTF@xsrIl_UZ|{^Mp_5OBS_8q2V1ef!&%UoXjn2+yKZ?SHL@WU(@@x+i(;qOD((_La zOQ=5bGfh>e1y%~1ZcW?(fXUaKi@w*L`y;8%`NL*xwc3n5$F`Vrmx%@Zn?Qt6BI(%A zp5CuxjpTtK2o`XMM-p$7K`pd<)g;jf_YN(7bO|5`Xfs#F_THBNk;t;9G!aI!jJx9| zMS1BQxi>Hj$`W{uEP`RP+i687P69oAbI!vR@gw@Lp|)$~!dfZcBQ2JnBX_}5C^muW z#M~GRcX4ZM~Yz7uhvDqk=gvIWYNd*GaZ`BnZdgJ3>NAmD! z2>hBDOCVY_B?s|aC64`1#uwL%i30n$qp2;GQOM$5VF9mmGNb2Mj!|6>3|2Am zv!$4K4H_38wPDY*is|H1dxb=%(J0XjS}q<5N|24s!M1k^5DCDP%79&^8Qy-!DB^VK ziyM!K3qj2`UgWx(RRmT{=VD4`=R;GirrLbN?@JQqis4DK5zf4M2cjOC6h$o3Hwi_9 zK*eU_G7Ffr!-jbL#MIher7g3=BMWN4Q01<4hzG%fdtIA)t=Ah$=(s~={die~BjfJT zk!J2ec}}IHU&oMqkAp-y6U&7W=wH05;3J0Q7;zA*~gX^Y9Dp8Dq8U~La=sRNd z=SsJQ4~~SV7^@kKgbKAA3-nI|rqYhd1`1>NP(qdg74{YWosVIECBugjz@5(9b|~GV zGUiyrll+(Bg)&z8UJ?{J!P>uZC|UrpANb>Lv*;Fkv3=udLQ34J7rY<#k4-@MU@c!X zjoPGjKOy3?5o$1@+cVw|86=)YSrOygt$Mam8L`g&IQqa!b#Zf)o76KDSl)OV22pvwqX9!=HR&6n<)G6nKn0ch#-JsG>e!w2B!pQotME32VwKCCtw^9OXHX_O&6<|5U?CL zCGgr}urh8;aZ=E7tSeNl=&Nt%m$-DAgNq!}=A%f6NFt*$J>#EajhkwaY=F?I+fH`* z%ICn8ZN*!pph}ey`(NGIP#4miKxzgJ-}6B636|W^9p}dRp@A2rRt6F;SZ@LY?DtIO z7np1wJ`}6Bui@{9Oq$jM)_j{?b|XnDzYhF6(P792NZT)hlvg9Aqb8FA?7Ow~3P>)T zT(o3l{v7vpxr?tZE6)2lLZQ|3ZN)VjUUNFm?*_+X447*B$|zT@%3*c z5M3dcl^vKw89g6!opPCn66Fljehm4#1+tl_5CtSivu7JGt#7OIMXR{vc9RID_$qqc z;?IYaUu~MR!yeT^OV^&*l7v_8S2hkaMDHv7d9KR>mOyhY5bw|gS!VW@+_Xa=>U#Ej zvz{UyS4NnwxvLgmK)4_LK%l+TmX}FW-&Dv4HFQ4BqL%WB07i(hYXEkOH2sqMT}rAj z+EaYMfk~yT2k8AsEO{T2&B#X$uVs26#|jb1H;VLC?MQc`!ms3DjCp-*TM^3e9pk}c zl7^uy9lZ-C8HY?#4J+b2v!aeXBl>&F)9 z9G3+g!9%nAeTa=NfT3TR474@PzKoY8W}G;+%AN_!W4sKIh~>Nv_3tFDMH=Lj`8}9x zXp82-akUL&*@6`6)KkL^&GY@oc@MaANh$lz>&WGURVDy(1Jsc$yNgJudQs;W;>%img76390?1hvnP86e z4JFRLElr}XRyyS|Gd$f2Y|K;kh8K;wCc^@6wVQDmy)`nza{1xeW~4P-9+?FvIO@XU z=S$1z1I!f8&=KKDhO@lEa0Y18OW}Jf&3y=58;ITmWaDuhfHt#>-WRL3t`S>YhptO3 zmq$$b2G!be?>9A;HXgOu!7*)L=kO+FsFu7H55B8gm-To?=#=e16}vC^&`<1(AQzd* zYNeEzZCBrt&Dn6u?Fse>LuK0BJ7;ZI{@SZTVg_qm7P_g+DJ;_BF{{#vD4CtJPQFsG zPBg-$CgzN9GauJIVo&44yWflv!FJG)XeL*&>w+khIT%q6m?#Fj2IyV}bySpTDfrc} z!cuLXks?nQVV3ODJa@3^=1=}D=dO1>*V^F2zE+(euN-T?p($aaEBlfoQJ&qN4=}pt zFLl3f>th|(;j9Zh7aXu$2w`KU+OnubUZ_WQV}e~AOTdf8dFHyL_3C$9NiztBKL$|Y z+dUyP|57l-22JCavfLK-9TdhtoAU{q{30-$ER&$|Z=Dof}9 zTSNDoNMOQ9=^-C7-Ao;p#R0n)$b3>wLaO99yonK>$`0;?-lIA-tf}j7&oX}QKs30~ zWojAlXx7A_cF>ndkgqC(jh$|VBecF< zX%FRf1u{SAS* zzn-Bhy}D=Co}!zl-~ARrer6&%6L0IJDOzq6=3PousS{{XiI4frDt*}jLWDnsp+R*I z**K{cEFkb$Day1W!(*}ZRD#h?Yts)-;YG02(}dNec($jH<129Alnm%9DuVGCD_Mx||&*p*0 zolcf>3iBCouly!=@0_&gl8Hcd6qf-*q?fC5&q8@)=M(z1_m{}kZkyFCB-v7r#nY5y zjp?@}-pYN6p^kzxh#`Nz`bN%QvKMdiTRCtl!loB# z&Eoy!jRM9ey1_n@>09iB58%R0ZQfsQBWn1CSa`?!j+(fZ`CoJsYyhP=n7hHw~_QUeW`Fcqg}(3#U(sO>G}YGnp%oO=Rcqq>Z*j? zAa%;FLDKRVMW%$qia?k#U|77zOeD#2H4#4u-rB_IDekgY;LVa7lj(EtesEid#~$wH zP~W_no6dddrO|H&lrv_7DV$dSq%f9hK*_?kVIUZDLJdaaJf9}f$9;j!Ooo0fs4GSE zpbrOBda<)W>c5EU>}mcB0TwQFR>}gi0MMgd1p$3D7>HUDy_WrQtnl(R79w$NZ{^VCZ8W~Gya0@7L{2i8h$GDanxDRc&>Lai*q-E(`i_|alJjv^YG1!J$PVvf>a1n^Yi#cMfMqCp{ST3WvRlL~@^*j?AaH||(nN$BEhO5g z^yR;xFURqd%{u1LK{RY;rWGUX(Chwy32$WpB+Pz@J5KO|+Wh%zAwA=TYq1#dFLifN z(Ok_yKjfo#g1YbVYI;Oy>V>8*DPXwQ+*mKD+8sXu=e<0Fq!P#899b4QJ_D86ha|Ng zm@;`!!0Rfykmjtsv-~N3O7&dJo%l$;*KxvX4bq2MifVV?qhY8NSz~l@pkb6ZD7@f$ zQskTJe|cD!f*U#vL)?$B>?;jfD2JD#Xy{kyT_FXh=;M|+4!8%SNZf?Z;4=-Y`=d)s zirMd<^WVJA%u3}d<$$cdqoV~V=bj!(0EOa2waQGN1te`SeVgUI-Fcl|GBxz!gJ9jX=L{z?J)bb-!`*%%^hUmSh0U)}4cUkIQUWN6o zzk8b;KW)r5swLuCaYbRo2%_*gMEg#+KV3KXQ=k^gz&idv# zgR|EdYxy45?h=U42jCdFN%sTwk!SXwgj8Zz}%@>6iknF_p<6VF_uMx(N} z;Hu5ENW!n2UX&N%I26Z)Jkyk_)6`njZRz)c`xCsWN;we2 z2P>8&-V4F#KmEA0^0Zmyz}-8PvrDs>_sY88klydj!i|K%!~!HmdiDs7;7|(2#%7#U z=+`H>6{2a|@0!zTpm9KAjslXpb`f4uC?s`)AybhHBrg!o`wJ}=d&S9dc9blAT3bwS zp-+y(sPSXgI!}R`a0Of_*4&)^Jj@Gjo6eEzO}HL+uJ5t}@p@lny$G`HQUy z;%(Slc*{DjVDyF^2iGID_$#i==y_Ng#9T{m_APJK;r8F3X^DNcyqQdsXy5Y zNpdqtc*0>n?n#at1Ujq$r^mG%I-SK)2RNuI(g~{MHAM5Kpo-LvxZ+SpIr0j%+0NW1 zlH9{1(D6sD?-gruIT4!D8Ju<^UWGRWh1K>vtzc?)%?ce44=HJyB;VH>?M{L{m65`5 zc*%aKS?|8N8pX2B_3ha~c8nA|$#7UOsek)M8wLzo-hmRjoEDHZYG`QI)$7)paWRnv zkJXm)^ah4mpLv3MG%sB>{YZsc%PB>Dw|o71X#gYHbGTQdA(nxx);Kg64^kw||2pt( zhCP$g{l&v`Q$Tkt%Me{?V6Vh#C)9{Eg zBLmv^td)yO?*#V8k&}m_SK^-Sq?}P{TX|04(v|4B6TvbQy$c(4^UzcMN#mAB(2^A} zAfc7Uor*z2WrFMFKXri4(?CUQ{hfMnJd$7fue>GVP?lkv?}9i_u75s#(T~hea$`qp z8@cK%kQn9lJ6^)#ec~8`@G<)PO8y9Hc@<;^%Y4A1Bz)e8KoobBn`(xrGP1Q%fo6)p ztg69oJseRmiVf6uye?8n62(Y;=p(#vYZtck9yywLBTkI5T6qk6VTws01(uLyG~ixZ z`>SVaA~rFu5i^D3awHrz@4@W_-7PcQF`)PtmtVf*U(qkZ+ym4%M*k=vd}{WfKBVKg z+OjxO2nT9(Kir9&J=uJ{2%gS9z4Ix{F=3yA4k_q{V!1IKL2(+{ASc=wMMKlydYGL% z$(M|ov6TVYp>?H+%vKhEw1WTzO-PUg<(@XbHYcsXlM9&f)_J4|2)h_8UxdDm-X~!d=id^Ks$$a{O6Fm44e8&&f3q6mnFpT zU{!a>@Z=?PXT83MOsA8%`XKj~7JJyOb<7H@**I#o78lMs`J=}Wli$tVwNr)Ft*0h8 zN##`sS{2$%vj1P)2Kj|E43Z`Gem@SEGryL%o@CzBP7m7-q}2MwWxN#i% zfyDAV63;q|^^I9Z#wJ^uVxG5o0*GfwSIn`kxwJ3z$0i2@&I(0xjw zQM64GQajq?RqFr-hk}q7E1=MGtxhGjBpy9?R>sLkI9Sk<=Es>{>1|+fh0EhPbtH?K zwY~sujxMBcJuZN8E%>h$WELS(j(#>_Yx_SEg^ZgZ_$ ziypaS;E6Ot=o8M?u)yi>`a*D`P?+h}m282P;9V%e>s<=bcvWKOOwNR%=W5VWdt7ok z(uo1g>PHv$np1 zQ_V)~%$A;XWs$>0nWwhJbfW3%s+8X+-DQ@iOoV!$U6Zw0)=SK>=&aUwG;oYVQjHDP zJ>0l`!ka=q6`u0nx+1UphfisX5tyROhKAjwOB?`_{)cd6z--cfcxMT?;+={k1W!FH z@jGy%*I}al?7mT`(tV*jba06nK|%$JmK8k0a?;@?)A0Ftc?R>!N?niwREvJ#jZJnN zbMDNqI3%kpif5ia3P>GE3B(9Hma6>MpN0NsO2A@SN<9sHwJw37ME7z3Q>`V#v585p zN(VD9#@Cb$&M}!WZy3tfQYoJ zu3(zKPo8U~k(*IA`Wmf*`I!U^Lh$*xt`7i`x|$|pf6-Rfk%gKKGR9>a467Xc_g6J_ zK(^$9j<2$C^MUSNfu55~XRD8Xl+r=)&385lT~B38H6_B2phUvevv0Z#vC$nf$3$Q~ z6=OK5c|-1%U$n=J)8b0zZrB#$;qYIF`0(;%O^yfSyi5D?S{Ne7(RntE?wXeT;m*na zpp?LIKPh-bOKnDSt8(|0GjAs^kTh#52NsrdEEaX^hWl|nEL3|_GhaFZ&|vyfG+*Vp z2#{_qi#mj6v3xoq^B{$eCP$;I-&8wN&;9iA(VGSuHod9;GN#i z>Q?ryY51`aKl}J9{3Ij>9o7b(aiE*H>$^CjnJsz7>;&yDR&^QMh{(LAiwbR&m7mUH zAZnI%+$?i3pAwU0gxNxy5cL`yg2L3px{3P9)R3-CXW+6X6SSu*HTkIKqS0z-yB|n_ zhG}N4DJ(qmJd9*uN5P)<#2ESRi;Rlah)2)=r=8z$ht`XToyO)kL>re&=<#P)vaC+7 z>hZr7_uMYjY=IYGh1R!=?YZQmTcqnLT1FLJq%=Y5q=hb6h6&ILe=_}={5MI5^4Zx| zO(CG!7Sy3RMBjv6r(o@T-#dG|uuZ2v5$-s9l7m4%TIU~C6r6kwE<_*eI?8)}s5xir zvwi$j50$B!C~U7|-~SIH5?xaNP|CmPYRYu=KX(2oWEz)kDf&r4ZqOK(HcW?P;Hu98 zaS*ed!`3XLS{5ksnR=)U{5N2KgHYMxOM+KZwR|c!h6dHD0#F#XDi4_WZ#AB0~7NmaUMp3TkB<3)1d#C4oKdKm?={ zggiz~*4MHQc-X{F0msf591V!#^TH-%hks3*8_}hmx$?gb5+_XMAIECX30>`%>h1Y; zG7r9^`yB@bb~PEPX)8ILt@|6r)o&v}0DRayu3b?M>Upt79vX5}bG8)wM#ZbKZw_{) zGBH!avs@G^MYEZtXuYtAGN`tjy{Lx)^fWaX4*0Z~xZIfcfNKk9_A~>xZ1yuf5AGA3p#G7uVdzVCGD1??t(Tg;w&+XUD-(Y{$xB#_RiA9MO zH8`~qcT3NP2#Etq0PnPG+ZNfQa=S1brKV#yFgLrUt-O1`)9 zWmcCbt6D!r3ez~`7(2e!PxUDutQtD4cPTpY6H%^}WYw8-aVn+WP!}FQ?`y$3? zqJ@18!I^mp!7y3fG~%XF<3Lkr?SK~7zjTpmlKfgG`}|u8gR^u>{!g3Gs|e58q{S39 zLhqsVeSGmU2uyz*1&0XC(7S-mF&_Rw;Wa+KNPbLbt}t+L#ac}F6MVih*6Wg50*d)P>Udw;0bm~dt$+eGbyo&hCMd)J+cxD3Atd@JgWwo= zuO?%+JR=ZDDhbEy^A~ifh=^+tNKp1n#|+$C=4|?}n*h_YE1tbjTsUfT;Bkyd%)Xn2 z2hDt(n?b-@4f&O&JeXjoPtBQul^7;UpcCdZ=5b)!B2n+}CIHM}I4EY6+q9OB*{=%B zyfZ9h6~ZXJ&(g-newMyd5RixiGj$_O5f@>hajR_a8{%#oTHfCMT9sQTLep~o;(c_?syO*|Fr+lLt9Z&h0+S`~`t#k03CHP1yD@CW60OLScZ!Z*CW5T zEH$>NZdTDvOHNiyLHI{XCfEBoWYlApu=o3G#rjOPxKdYHpDh6`++3qCI>*Is!VLhu zwD(0m7>fMuDRi~T5|&x6+BNMXI-2(n85-?;zmMD}-F^uf#*-khsSha3c@<7aqRE@< zL4+`w&eVnc%h?3pF&K{}&eACHI+h`lR{(wEasS% z4s_5HGhiZ5>w5(>DqIz@_^_g^5X@#I#)3W;EWz)&HS_F)R{5%lQKxI9Wv5WrEYmwA zR3E=IQez13#XYc;O>%l8(Z@`*7`>e0B>?cnk0wsiF7y`?jdFNxQ>lM6&8J^Ae1opZ zGX2mbs2*maeE;t0gH? zu&rwzuYKytqefgz8v8KN2V()E;@oz+W2Ch$i5k+tw`w5i@Dp<#*3EgNA^EwtIngi-?ofbzueh0u1cZ4ym>FnRL-w!QJ|<*^YPgMOlx$iGX*rnj zWP@3U|H4r`3YD1^M$B#DMRO=%*?(ofYOdU4S6`V)|0DEDq$l|(^R?B+v zX7Z7214a&dBMt4>|-&QKy$RS_3h6sXmf)ZuRgB}DLGx#)S3IHTae1`s=Ug9KUk z9+tdZlK=vz%SNnOO-FIPhEbT*6ZEN{E&_`-KS!8gEDs8DvwqzX)*T%yegW&7QX9RM z9}BH+$aq}CF@O&*!12^eExJ~!BZ}C*+mfD%w_8O&fo!nYwcMp@cJ8LM6jTJ#a1UTqK5DKn(kc?sn?#A zS4^vwMtDbdl6@L8K6*}J)Z-ee_C&-+Q((;`;^hfehXK%XSCEtbW(`7-j*f?v(frE>Bt|mpjMs(JQW-S$B!1XD3qt|sktVc z872!HMq&eUdajY9Y9F+M`*3VPt+Q{eoc96M9o1acN}$)JXL)OS&70!jP@T4Q{I^&S zOF;*E@mqcY+k*igfCI38uv}R-|L+j^>|^2Df6wT#46fi}DF|Xxg`l9I)X$?AqSnD* z;70F!XD5tfN-T&ZICY#6q>ZuygDGNY<#x8->9L zGJWk@b%O$L%j2TNP<>f({dQjt_ljr#H@*=b8ry5)syeDA#NNIKqpP4;OuTg8Bq=va zQvMEKBPSndEQLoX1rZFKQ6OgwQ3LxD>Yn!?;C_K^Q{BU_(-%06YDvX&K1Lw*J)XaJ zJ?F-jN>%d|CzE-00Q_Mb^}@ebRCDxPuj;ar95u*kO#1`j{W2%gj!^xm^u!)d*Y#;q z;h7ZNXEJDSH5j*C?Mx&8bXT^;n=m9W;pO_+2T(0b6rfAs5xHNm!dRy8*RayW#uWcb zzhx=gwv=pR88MfM_9Pl@4$A(h?=@cEBLjPE;}r%p0y1uFwhb-DtCPT-SclkgJ;B6d z(@Bx+nx+CZ9IKTbd29tkaBSb8l$leU?Cj&KwzWa2o#Hp##$24s?x&k^_B1&WL!o&L zUHqVp9wB5zB3cOS^Op3=v?l~yfSIojXt+kKXgC^xxow+(rFhYL&TNalbol8giC#pC z?&*RMOICsop+o=vTF2zPX%vGj)U}xIP;3A^#pD|^N*LYap`@N`dWdC5sbs8 zcpZ-Gk(mdb;@;R6Rx={b;Nub%(;c%7T5ouVshzeii%3JSJrb>-bB*wO)bQADmHM|B z1Wk%Ag*?zKp#yW!6ma?E#hdPz3)3M;O(DMq6aibLh?7S(l`*@=BK;@YMtNNp&Mr9~NOY zGPyJeWJs?Z>bf3VoFQQ-;x0VsZ}x4NOKN)ru)LcytjY-2``{%wD5j(S#r150%U@$EJ!kZc(VZ*HracU@ErDT)=CcWsb*gYr=!DX0Q?*)+_|s6=2WW0fJ)3L+ znU3|%AW7`9{#W?4p4zZ2V%FN>_+n1%W@PEv;jt!Bm(Ygi@r2*xa=}jiK#B`gf}>B@ z1~Il$Nni1^9f?F$VHc?r!n_+|UGCke8-;8sOWtM6onGk0lyR;re_;g14q)`+Rv-xF zTn}saifkbX2|I%C-`cG>`vJL`n?=SzU@Ib}@$Nrh12v;ujPao4k-soO(%jz$DP09O z=AFUHu>uxGc4!iuP>)HybyF~H2>+QO(Z`?og~@sh2-QQ53Ln3HP%fsD5iO&bN|7bqjj+T;nhyG|pql`Z*jsFj6v+Sf!Cwv(_oYs{0w z3NzY_GLLHXv~QQ9)CR^YonHRFh`VUy*kED$h2zo1FwGldgMK{pS;>9L(Q5LR@)}K= zhipOxf=x?|NiX|10^9K9CJN7U#CY&oE zNY-)W-}ig9?_JM%`UBWYgBY!A+~%w*@ZT@d!xdYzI0#btr^OP~agtx3IWOq19rvZT zAnr?CR^Cj8I@}rNh3YpY=mQ@R9siKkqhTAYdzA#zEb}`e3qO@^G0-_tifYP$F0IHd zi>7x!*D!1Xf~`U!2~|QCE5cp6>1Qx}ELTDV>&GiecZwIc~*^Y_I3q5;;kjudSS`W>WJqF zJ8cSeV-D8tE(`$rX@wv3n04lAPFxyZ)owCRO7v4Ka(mmsuD&z4hfMaE{Pws)MmoWO zR2Qbq=8qhvs>f(rKVArxhp5X-1!4-}{8PzKVt%wJO&`SK3-`tJo>ITjRWo=A0A-=C zQ1zpoSLYaz!9pY-@9^s7?l|t-qjZ&xVHmN)vn*4tfkY#pu*aO5>%b|RvQHkphYBby z57=Z1j|QUj8K|j=)etEsns?%%Owy0)KbJ$8*a+1 z;~M3)UAiB9^pcfU_iIJ>xQg(ppM}emAu&GnM15G^#UBZT`u}5Hn_5fqRDT z8N;=g{kM+5fE;2(cmOqoJ^8i@#Juld=>YF5+JfHbz{2j_ibv@jiBSdusDy zfY4uY(HLqgGB)|}x?q!i(x6}#PSgKk7h(%4=-+bg zjIJ#xu7n3qgyVt<(vq&AfIT~^KCaAM&zjvst16)N{pJgJzKuNdqCI3vZ+ICI%{fiUrC~8HRAbXlRlm7dbU+|e z&fexj92@oJ4j&c!H9}6M-)`c+ChhrRg`!8f-X*}%>t_?OrlFJsmhP}~9(D8gODK16 zqN=xm0ZbqUC&d*rujOUC8V@X}Q!K4iMNXOq$O*KXn@|cIbKf6IY4oj>gpK;zb2Y(x z#QYy5rkaLPM9XTNl~{Qj5xN_cbF=*YR9)0rBRMLe;VHff0xF`Ef*+m-Oqz39Qobne zQigfJLip|+Btz$@3F;idwbJ{!j~O~Xc?i?yl`9IpF==DBXH*96=!Ef@mrA__h$CO^ zGbscP)9}RgQgCQtGsHtxn7K-DkG#^>uL*>A3xv0(rIL?c`5ySkHhtlLXLhSAKwc$ zABuB$b9B_SCOpB*4mFn3U(Ro`#L9HkH289%-a$=6Qjy%zi#|8{;q9fgblo+orRb1bRp0Q6hCW#_V zWLYhd1vUP!2?V8@(}6?);^C~9$3%rY9kr(oIUf|2`^qMkie0(IHeCLyJpXbd(wd^o z-wfxA{d?N>d&GVn;Y-p0Cqh>30HUf$v?6P4TpTT`%asbeMjd z@&UaQYAD4A!~tm=NfZP|rMUA|crNN}(c}TFPU3()TW}Db#bKKys;$!Xu1^1~d=$R5 zk#N)w$2DoRobQPDpe908&0xxOrN?7A>nn)ln6QCyCCOv8X zlgdrSjSZmIP8n0Z`4zSU(O*dN4i(M;c_p#5HV(UEcFiW{eVwL6Po0CG=xWB8_|9`Q zBe~!(+}@@Y;<-`r+o5+6U?&Zap3lV3<^E_GFY6D|Any-=d-QnmkPcFfE`GMw8U}Yb z-k{-F{X!ctNsa{o=H240JwT!Zs%r&Xc>V`FQ7*v?i%9pWvFd-I<_gZflIbYyxYK<% z&E+*MO&7CU1VU6pfk`>W&P4itZT%aMs#yShf}jJpaa2u!nr^uKPtfsPXQ{Y3sJNA) zHig7tF(#Ta3=v*Q!j&ZW?L z2rp)6u=i%#Kadqmx{N+w=0}7+!fgnpELy;x{=_ptn~vc)ob#T(0Rz(9!o=(VP$T-< zd@uj|9Zgeu^gjM#`6oI)yaN4me+L$|GK1YT~{;LrxR6#axxbC;G{D%=8d793o@W|HDPJAeY`o?;J~2V5Ygc58w@- zfNa}fUhctF00ZtwAWB0R>9-8v(Z?3C8bKrA{dpm<(#4w9+B9n}hS+G|onM8idpP-v zE)&pZj@2LAt0jb?1%4q~BA;guz@lm*6_f!RKxzj7hz>oWz52dsgpbCI;B8XzTh7=_ zr;7q)WQ@KCO<9dRp@J zyy}?mQF_O$V`ouZGLdKiu+PLLsya$JZ_%zm51Z|PTP*nDrPMI#T=S}>Sn$l>pyDAc>RPoW%owDEDyp1FjNa(=T`w;V6${$P*bwk=00j z{2SY&O4XP`Yql@!3QWD#+fS*zHHG6})L)!r)2ygCQ!Lg(^zN5h&H^W2!_d>ufxdoh z?{zg~ZxE|tolW~J7&@Wxsk_5NeCt>K>^ zPlNl;Ejnqn3Vw$uFiok9g4KAV2Qzep&SFnXx7i?rk0w^g z?9$)qeNEljaRPXCvv>%*(5SD5INpw~Z+149-i!I=@x*n-~Fkf8?N&tWp?a`_n(9VjwJJ${$jmk*tRWWoq&*Wm911Rkh35%op2f&%S|7VSs5;RqXbBZQqfy#FZRx zE3aKk=JB=kho@!Fo0s5S-G51Hmu@sn(!faal5oCbUCPtVnl>@M)v055RUi!Zr(3P8Wf znXO}Mhs)8JWJb%Lc$e%>_HU+uA@Ijb`DM*iX-PWJge1-*rlnlezo9-bbUe-Q=dtf% z2OaA8%<1__^Ny0wpz58hXs1|``?*aGoeoWsuym*?duU_kmnwCxjWn^(T>1`;@n=E+ zm}6qE$cBNj(!L)T0gRNZL{ss;*j0`z!UfFyak^fSR10y%`e}v%Q+eu0_id(;^J|py ziot)Ls-DLL9?b7=#FYdbX~?{g4{Tfa%{ZD7-`a{1+83c98wG61b~rItX*5c`i&k;$ zpO;dJzPdt!oXWo3`wxLa=yp&7J@74Y6=G>e6fS7CkZ*mkeu}-Hi0P_E`E$;!M~(A2 z{`4zP0P%OO;-J9lV%>Iz${#_s(ZSRM8P*d;tVg)#?ojr;9TB02A&FL-jRnW$RK;W-F@gsjQ|*7T^KOrQi5v#*X40wH%mf(-*k*d zg7GT>MpL8ayA8sg^GpNq8wp;zY*p_J?x*{hIGgNV7yLpr#=I|-h0o`Qcl%Z8q2$T+ zcl8DclBkXSD@x*@STv(9d#Vl96$q3ezm5o=(`&>uSE^2|DE-ZBWM%72V`Nnhg6+ks zmEUus4WeaMWCwQpAWWK9U4Ds}63ld&lA{K;r9?wWy$N7dua#ZRY6-K(aM(q_U|A*l zGVkjh5U|&y>cnrf?z(<)a}!-A9pV560$5>ncr7?+O)vfMZHy;0b^(t3+hDFbCn2JzVssVd;;yFl&=~qKZ zgyA4X7+$tF+gB(VBV}|?Qa-i`KQsgjW9eKAVs^vYa?!=3NL0KG%H*yDx`@z08HS$C ztz@zGc~`ncl62Cy2>r=l3GOeed9^}dLwGoXfF?Kjq2wZ=oF(lof~KB;v9Y=ot3T;>=YYz(NU=_-4G~=p`lvuqUE_139BH9TUy_))A|p1L+n@_<%s-}BOv^R&%h zMD*E1_~>eFe7|^$N|yZ2-a3U-o=J!s!&0-9lMycC!>*t^kOO~DUtVF zd3L0N&o!o799|YfZ2LW)Njd^QhAO@>#CjG`qbAHa{Q=EW;nOrOS;WK4R3EnPgyjBW z$Lr2~2!^EXQ~8c?0375#pQLlLvoUyKvb0)7+xJ1M*i*X+H0qdCwbVWFRUtrp%-prB%d9s+)Kfr%XOpb zvphXoc0WSE$%4=r#DtcHphX1M>Zm6Ryf3bz>V(96p#pJeL})o8R()xM^k$!+=)`Qi zMB1+3582qWpSnit6B(JGL(1H2hSg7?>UvXs-Oa|`^WkDm4Tsl2dWEggKVAo89%cRihw{033A+w6=X zfq);jIAb&#APWhD{%I-8BmfiTASVJ@RH=g-&N~t`E1{moKJp=1E2H()Pe1{5La(A1 zV=CF5bfbK3DRo#?0FF&Cz03Y<4PbSy&2AQfxl!#x_ zMT;ok*Mq1W9v0wD7VuLFIcXj}rj`kgdD0yR{)bg@vMU0wu`^p+>tJT{_AObkK9!as>E|WSyuc?Wy z4}^2&1q*^Fzca?Q&vdntqU(RFYuw`^GO+-xUBtd(DI%OT8&i1*E1_N|f`Ha+;m`ss zez#J^`|tNX7P7#J>D`|Sb%exz9}2K;y?*(M1}v1y0dgy_RI1wJX39)`h+~aH+S91P z^H=#Q=4!Oauv&sZ)}u4Mg%;6Pj?XHUq3sr`4RKsknV^MjsL_XW%+}UJA89OdVM->7 z)%+pKVPJ;Sba>e(@q5n={uLBQcPp+all2_ZbXgG}r>+=#Kjp{p>fmpv0p`_TKq)-i z7b3+`y7Q#1AW?W6gVYjSHridWoU@GKTWdOlut;L_HajX23aNhUlm^hCm>!okHKu$x z&-dK3bQPq=V+m&^^hI7vndM<81BabadKPWOC<$$b{(g(v%Fd)RFg$?g@Lq`)WsB4M z7>$Ofk%Ns5a8mrs7A1KlS)Cm5Qf7I1mo7T85VJ_8>OpYlQ;qB*8)9WnL{37;98r*+ zginudm4Q)u`2Z1{SbZ*R8uP%!(@hnH5iUfD_8}4 zR=e6flC>$R15AuuhnKlbPzd;xmSeEzeb+7aJ#fpljp&}|EOhpLhFEzfuEx*O4E&#_ zhKtuduvscDv0yfpWhzX;swOVl#L1S#^VMM2Yt#EQuz)xQ1RSB5bYzJS5is3euj@8* zh6m18=>{3AcO>vGK8(#7X15MZbYuKK<-LO0@av!^W|xmX4FJYh#039Mr{~SeV9AN# zr>7ZHo2FEW_SEtJDtF$Ixp+Q339W9VK>p##VI)9^dLveitWrWCOHL_8<)i@vW*q2n&zh@fh~pT&YH+ECD?dSu!oF z1e<|)c;5NN2ztmqyh;sE{iS$tjw5k1b8Y4$RDj~7?IXk89G5S5L^XNTov(Y*8QSYz zY{UqpTsm0;k5E+74ZbGkwdw=#=+#t>on7>@(1(8*ibv>HrY|;AVpra;&)xFQ_+%&ec3kFJt%q< z^394NZVoK;QbrH^J8aZE54F%8Mpe$kBx1B!E1y7hJ^|!}$@0n6y?2c=*BbAiBC>gY z12l^vBX_$|Dv{qMb$j6j)1_6KPM`n$*d7hd|6#Y2Tq@tXgl7_zn>Vj|s(9b-FRlc| z&gHMtpN7UHNNE@eXm6>|h|-Io@ZR)r2m<`~7s+i8fJE`k%gTdu$BItoKg$?@XU!O{ zIRXN6UZD%X->KoH)gLhhWYq^=NOgl_p6wJ-7-t5ntaBu#1!H0zwdM8Sc%Q58MJl>V-uM z(A(^vf;)a`9ZQqNM=5Pz^s9HNLba@mS+d^IUh}^0xFqUTk!lSfR)Jk5RRly+DY~2# z7&&Wd9_$VI*aX~5c){J?za}B4{BA-}k|AAzt8^uwq;JET*)y|(NL3si+6j01sf~UP z7#$;eJ;?`a$n3V46JvZl;^GeJ>7JycWJ((;=2JdN>2MV3>F6~*Fwl!=d5)5Dc)e}z z`BrM}VRH!13)m@ON!m5kSYMi<+*r$pHi#Z7^wqa%;Cfr-DGclCFVQh)|j%?Awq>C~n{EKj|96;n-%AJ&^eh>j` z8LI6+IC^u2ajKaIAz*uko#co2(TRmyF_v;J`0{G;`Lk2GbtC=5)vnJ5&%{g*q zcT$H%_F^r9&=UZrMZD5M&Bk95s$_&H8XYTG>(F=%{i8RWswOcPrAD*E7sQ_C-ZXM$ zgl+3p`sHIDd3ziCe$RcbjJgN{kOygtLqJX8DpH|gwjz8EuptZPT|M3CZhlV2&V_#n zw&f_99Uw>NZ$u=|Y}fioJC<&QPMmFOy4r+<`h>bp8fwjxO>{Vf;1etuZ4lW;-KEl) zGNcdOqsL&*f+N>*MYfqae*>^@TH3gmJGPRjH#9@wDecw zffot{LlZ;xs}yjx_T0QQI075%t0=*KcGD9&Uc+MZ11^8e`lP7Ra8dB;T&X}x^>wU03$^PcmJJ#m{Ovx%q%f!AY zd<5xEdss?M!Ww@XYf}$7IB3K|JBV#hFpWz%(PA8_3sckO_f(?iyLjQaF96hQ=!c*# zpX#({bQF|E4qi^kLH!}I$WITqt<;~>4)N*HeB;JoE<237J8~7eP;nR7&4hrDxwxhm z)m3R)5V?*|k^KMVAfV}p=Q1y1$^uhNK9}`xG^IRWAK1kuox?l9Dj24h{hmwj5xdRg z$|Y-ld^sF3u_ZlUnQN<`lLw1XNbF$#q=tk{p3V{6KZ9bXCS#*dqs}L+$+>Jcwc(;9 zSDE;HXAT7dh*GNX5q(Gp@Uh9#MT?4t!;2ibEDK z)d&CUM*EUg<_?;klTne7^#q7lbRnSgvn)ojAZ&Hr?uh;&nX+3qu1^zh&4ZWs506DN z?_^Wc|JP?kjZxcjGDGLOyDrA3Xw0#+)kZIf6EG)j@TMMwp3n!8J;cC`iXC~F5#zxv zk~&^1Mm>Sk%}*}xk8#mr>+3Qf;ngZ81YGpCpAt7GU*vZCJ0Xw3D^Pa0o!o5w*;dTH z0`CySXiOqQ_mNf7ZQ<7H+-gA0)iES<%IU@<9s=?U!$}(Q9Gp8VGnw#O%^-|BBg`Bw z!kyg=KY2S%>g_O=a>;>ME;O$Q?1PC+CLhbN|@3{RQm^tBbv)A_ql55K)h@ta= zAJ~+PSke3n?k3ytXn!EV_Kt4r;hkx-Rb{sH)uY>=6D9M~wOh<$U?aGw_~~W|+py28 z=Yg5pSAnB?llqahE#}qMpAo}D{d76(8F-r=Nn_^D7svpR(wR9USCHbwU;VV1ay?P` zP$+g=T{a!n-@`T$k!#)(r-xNfqIEycZ&#HjR5yKQxa;PfnaTjxyU(e~3T8WfXEOx5 zZ`OxW=?8nZn2R^e7O>>q_;G}z_8Fv1Czy29;$ch-hK?&DTh~S!vcjfBH+fr;v{BS( zr)?t^{6E}uhHBJOl3INArBb+`gNI~00%Q7k>#sZ^0~{TV)Gy1Uqd52)0Ee^9VIQ7b z)fa;5$QB**y|6MyocV-W9c=~x5ieaA>DNocs4V7{Wdj{-5SRB~l6rv4xm;l6mYy2*6SH>>e#xpRDY4hec1Lpeq!RF#>lZ~ z4j=n0f-@ifl0Wy0RpE%tl@FZG4dtGBIwu!E!|>y@W|0*1&G#Q!H3aZX`~I|jM~y6! z5e?xkFuc3Y-iX%{#_bkn+6&IwvbW%mL4W)vnka`)X@52Ta7tX_lkJc%XD@qce1ufK z(pj0{Xrt))lL=*`9p9Z<^0@_)V_JxDyuiK63cP>Y7y8ZDa4L|udI88a+a@VCJ7Ust zOh$v4wR`obztM3cY|e~fWu)^-Igr=Y#^>8o!f4l0Iz)3c98~^cIEMBr07s%X+<2u+)Zh$bR&k##ndqK8CI4Wx zcBZA_o!yu!9|d~6KC@X&bu9QZtK8SnsEbHzPEbG+i;nR18LSr&1ckONBo9-`<_;0; zlPS54nh=6S$4{0ERg+EaC5y58mCG_c{T!pGl`1C?NnKcFfb(pKhNJ;@Cg!ah@7g=Z zU?|ok2oJCpJAAXkr`&d)C5t*P#E*<lm#(YBjK{Nd{9CjI;~` zTTb&SOI=QqpAB?Q3qQ!yJhZIy?PIU_4Dz9Q2OrOLhg=QNgHjxx9oR8@I5->&qzV8O zb*kJlwDYpa8wpMbs$QnMvg)dU3@v_FK!mG>%2uhBX2Nc-1tYLogmAck*Xx%|YRl?d zCt31GskVZ;{K$z!+rMp&`BYhDu|5X(ILOOhAwG8Idl_CXZf{ng~bylS*ZxTj+v@XKG{CxbDOjxHQ=a(1`} zE|W0|tj6m59x%i2tXZPOBOc84x1*-(xT4k97FK8Bv)SU6f3OQTPxCRPM#^?2Sp8UK zMhw~@_L_TfZIe~|kU&4U6;5O`1pBY*kd*S&B4XJ|zDH(#T@enyO&b#qMCrvltnm%D zvceVK$V{=uOf_S-^5IT&WUS3hWIBgNdbtpngazMphnE|SNLhVV%VeIW_g>opLKH9_ z3YLb~`h_gL14Dbdsbkj2sAwImmrbdVp$fWq+P*Py^j-|22;zs%d zEB~7mm4eUgh-C6`$E8b?G6v! zdqF7T)K7)N4qq9T=4x{Y4ni=6X^&p*EQ^36lCGGf8O`b^%9(jrPIyERNb71GX|t7x znald9LP+ndfa?$ZP8@l?4&C2f-O450j6=SwdNXzDz{t#l^DbAv=+sKn(r_6KWT2cX5Ek}}=pUnnVsB?#1=j54Nf6_GXHK1S@f$!|{-309~NqSn3x zV-s{d5Ez>?Up9I_f80+T}Nzy4^) zM^rk65iE}jtRQ;XExWF&E-cdB)~f{@W-pS~RN2F7rPNEW=whBk*dzn9vdhQaZA@gT zzGTCBa4;vKf|6=IsFS%QEBh!;D9&W>tBv_UZ{4)PODt)3blO!Y+P}CD1o8yRL=*K0 z&n1Wz)M&}KclXTEc+-A5@kzvv6S5}|xRe#*uXz@S0!lRLgT1&JH>gm9kR}U9n;_vd zh`}E*O{*-!SQE-#P?}CEcZ;hyPRp1TwT|NU^}y_6I4NDMC;;3_OMdj`6z3K8J1!&c zGK%%6Q{2;%$7oICL?_W3dqid$T5Rfd2RJ|+@*QC|_`9C~Xrd{kLO1l!M?RHX_M zc+AKfAk0S(bFUj?(8lBw2SckeflhHN%_Qge`#5;aFn}8GFRQc@K#g=zgITQOPG`f^}p92>RI0Ftg((v7ZYD+q|QEF+# zGP?g*ktc1Ez>%=bHDPoEPSo}3Kr9{|$R=E^jO@@SfgmG=s@ljlGVa22!2cpX-NLi+ zpxp3e{5Ru1D;w`dmn#|@AL&oaR;d<}zHtD?Q0+>;n`EC~-G8~3zV_{BLbP<4-pxdo zI56Fqod9-}?V&sGcU3qzsYENMfj@5-iScbhG%piEngBWdyo&XK>2xsz$kDB=$ot8yZFZ#+ChXM?_| zVWs|}*l>>GxE12$D-Ls6FVg25=O>XP5e|AXcwaHh4KmFXL_i7TknNTKHTQFSwtJ>+ z&6R&T2Bp${^!!yjwTzj18wm659gl-Q?ZAQ}X)DhMFuvAQUa=kE63@jea+zt z$kGlIMk{NA8>*^)xXbUMPQ<=yivJ6sSrIUW?kP)WVR9s&BJ;*xsGkOa7FaY6wM)TiLn$sB5Ww5u~K&CVZNIN#UsjyPN$n`aSi@*1{U2WD%v93@qg z@LaOXM8MONR8XP(!Z?X}(%s9%>qZlFa3g=rlwl;fz zoA3hXG8v`C2IpsZwmsyU1ISD9v-lJ5Cm@}IlKHLtG%D4PR*5h34cvDY=B;_(PDXm~ zo;cDzW0Zy_YF54g8Ta^2qmRu)ft*QiFPO>2E98wIw^l~!g^f2<(MaN_qe z$+>8pMRd;rF7lIbvvxg58>V~ZGilx!y)o%^|;I$KO2Lvb!3=!%i!BiPxp{PXZ1tF)e=CQHjpNf?1%)ocwEuG0i1ft}It-Y5=F#qU%`P8(Eh2KrILeFZMm? zF3gYrtWSlSm68{MUjbdlnD}a~=tl8iF6N45$iM!c{J6&^CD@D((q0rbNI~CeM>d_I zp=N#X{9XRk3FSlbTR=YBa6m4Pdam8C@N#*Y8IbH#V`w z^E&bXML@d0_8cqBr~9l&(FJfjto8QF;2y^sbBXgKujbVIV=2?u0$WnHNAZ~w3R^#9 zF-ltV9IjG=`lwsnoDR{ZudyDlH=zg$|M02tDtO8Hl*KQbuKu+0yR+UTw&{y?7VPcZ zWh(0a@<@T+qgqAD7l5HY50(E=7Q8g1c6qCCCH3Z2t=HcA;5o!SAJHGlTm4%_pto>) zL}N_F^Mqwf$6Z5Y-LMPbN6jGzM1Nq-mvwI;E@aA0R}-onqqOwenT_TlpzZL5Ks#ae_0`XkZwE?QClIH4u(( ze1ydT&YCcToQna5GRdm`kD7{)^crLgp$PDP-3@_1z1QixtJHpT87PGYx-pLNJqK?z zOv~W6Fi0G0n7(?h|+d%j5US@alv9Beai_{ z#N%q#URb^i+#f~)g>bpDW>e5A+vxf-MOWkQ9E_N09dG$D3Ue^Fxf74wv_t)$8Vq1T zZZ(hx*eM{8BKZhHl~_Yuf~$q2S0fRLer)ZVjULfnMf!3n(&B;Y*l_UAx&A|tCf}?C zh)hSJgKquoffF^$=ZaoY{1o?2;!IVdhdS>foxY(u**!D($pW5J__O6MejcTeJ5V_> zR}pBnNTp6(YlKix@i+@NKJ0V->oQRQ1Q1cr!N7r?L2Aq}?>Ee4%AP7wXQYyCQ|Z5D zNn52qFErK1k#$(|F`n6msjcXUIk~r#|!N=4X!3t|-QlyZUO$Ja!hNyYG zHJp{>S|o3IDHGE?ym5%KJdCiz_ReRQ<$w@2_R2AtM#Hxhj|8l*zU#mWt2LKPhDl+i zwzDL_YpMjqnKd%NZgGgNYgPZddSk_FSFObrM5uW33uO-h7pFjPls(n~QS>+CX{GN$ z_Nk&V+aw*&oq?&(N17qE=;Xg|-z!e(z4FB)j1%x2@A~So>U|%UK;ymp_F)`Oc;OTY zs)7Teqy{X8(9^C#N?{(Z#h#<3bA+0{hza4pZjv%Qh8zLVhPGHL3^>UuPear;QF_ed zVt_TQ$CUC-@@7#xSK2YYQ5x3(@jO#8JYP(pNt%)~@WFQm!;)f}ocHYP3Y^4+2f3Pi zA7Y&;4iX0RJmUTt6J~%(4%*w(>!&QLx1Ui_1zRYf@O;=mLSx;;*}iSyWGEjw8hGNG ziCzpUWQQ&?1Y24gT1Uw+X=j6x91l+1NaOHVd&lb5(fiMK*R*zOE(Xf-h%Hp6I73H& zn;f7fPh@F=XA9zaX%F%JpC>_Z7DxyO1|XJ+E=k9G1Rpa5aU-f($;gr}`&!+$UdG3} zY0eDm$2H=LE=c!yIUuP^5)-!8)Cd`UsY{7|j4+v^N;~~mLjVLHt?{=Cu&E3%xk$>K zn5?x%Xn9@xd5OFwcuDLg4A{*Uv~m))8$H{z0!i@sGE(3R$mEZ&PRP49w!`77e`@G{ml%( z-E2-n&idRH9tJt3e-O|)ZAcnC6YXL4FnbGc;>mP=jcoEbQRK^#kZ{>R%-<(ZxQCO?5#GFpV^Eoo$pk52@yDDS=*_v zzy1aH&fXInMjn?UN@lWZi;GeH3;&PBX7Uf#9PT)lmth%amGpa?Ns_B~ zg66vodc_#pXITY<0yxEiFxgh08gw{nGftxygsX^_5R2VZ#QhX7$@sAg6~R@d_OVxM z_e!*}2S=UDa~(r&7WZwo1qW1Xiy!!dKqixA!r&a=IT4k8MJr5tev+^ji?>;cyS2nP9hW`@>b5zXbr%@@0~{uM33qP z54=vBT~c7m{Lm$HcWF~XK{1`#*+by(e0QCXQh~IEUFNIN>r!UaNset`(I0Jmp50o{ z+Lw+ox4c;j9AA>8_w|K5+I)Y@3}|kKuR9Qm2(Y4st&5zRE7+r_jqF7Kte_I~8BGbm zT z%5^4VK1pue=lD^F-H+!M35Dq$AvCHgv zlqMf<$rngLRJQk^II2Pow1Eq~t5>}S?ZQH+hZZajUA4Df6#v{`y~HsZ=;XQsZhcMDa;NoJGx(Ezjc_5o=&PEw-GWCA*u#%GCo8$RDYJFO zQ0z1_sepuXvpb-g(1kmDWK6J@Lm+}`ZGn6VGy^g1jn7ifbUn6vAK@?vCPj6E7HM|UMDvX0>S*MDJ5SGo7U?c2H!-@y!DNlxb zFfosB4y)LtX%HEA>e-Axo(9R}HdH?nep&gIk1a7r+94=48l zK7QVpxkfqmn;+r)_h@QIVuUB%4oaNYNT^fwHQR;xj*G4v1u}P}q6enjK$n!%5*i44 zVbz9Ijk5ONSE2$849DudiinVcVy%2}wEzRMMpm}X{lm@9*}f|-AgUPbVZQR&SOsyEoq7~FHH z=Tb5PbK!kjRkY$@N7lfR^O#)HO@P75)1_e<`0 z@GoSnhY;7I#^)J4DWbK%tI1&nUBBO5_>Ej2unSVZO8En^$y z2OG5;h}+ytY?L|0cOew~#@^pK`-pnr^D_t8U+%&g-eue|1@NPF_rk%?LL<$tJ#7Sk95UV`A>(D-;z(HO6F5v1^3QX8c9Y3{&h0|#o!~Yuf_IHLht}-} z9hJMW@+Po~IeKt1An3+{M?X5BcG{+QfT98BYo}9hyelU=YLIu)YDVOZ)CyN7+j6?> z%*8{tNK$-kDYlRcJC;qphelBHno3yjj73;Vbu=vL8;(i_I$<*Lyz-Is?2{138rOUp z>GZ0l^)do}{SIM%wl(oIwL<~< zBq={Cdz?qwCoJO>Bf0z}eZ*}$Ngqj*Mem_&!I+j==R+p#60$FcdVpsoDq|~nL`xv+ zYET&^(nd#`!ax5^PohfAQi>-o(>3Z`g>C8@ad|h4k1Ym^jGr7O-6!+o2E=29J8 z&wLBwlM2ODk*?VgsW_CJaYp*~E3oaJ9B8=!tXI8?H7{o+4py%@qTK4hfo-1$#9iNXc!3wM*w8m8^51Hfm+jKm)mWn< z&J!`(9+Ge{Ha134*K-~B{ps;1r;zTLpxt&)|2S*l%<4w_TV{oT{$0|c@aVwP zGE3?;Goz)Rn1a`)j2>>g@YGIRZp282B`iaFYXh51Au`9iJ5pc9*T!gr2dtBbG~G_A zb#d_j{7r5J|F-W&IZmB%$V)RQcZ2FXaf|ni*dbfVes-1Zo=L9;!t-vGE&QNzWr-n? z^-l(a#@@K=H7r&|#Y=<&FEVABzcomGC_x=fdzi`;w5=5WnQOkA>>@r}Uo&5CMwArr z?jPy(>wlOyalH%8BZG|WQWK`!(c>a36sDG^-$4V!qZ>v4l4!xns{r6uMa#nBZzSUG zf#Fc4J#guj3L^+yErKOC++|***Jf_M ztiIk`5p5-)06_Zrh-oWBhaqygMhpKkfKLnOd)r@hI=D&=xLl(bkYJp02@0_DtkFU) zl_I1s6BT#@3kaioHsL+A0|7JuP}*6?Y`&Jn&sH3c$Q#@!sPFw(4Wslq6EOu8HFl=G zx@Mo-7*)k>G~507O-IgOQXUqzY`3BU2a0*3gVv0KI~8nc7%^c3@f`OtoF3?`Dq|$F z#N#cPjG!UdC@_%1B5j2Vh0TmNv+RojV!x*~!N+zvfmlv_BTfYtNSQd)X0_^;=Z{~! zS1z%ASbDT!MWrQJtF9Y4H6Fn&>Q*NJG?xMK8?uh@7tDn8sgInK_D;l2{wSoq9pGf& z!q4U~zmPf_&k%7Tn3#eF=BaWp{gDnE!}D|3tZaj9m|D2rDtZ7AyS5UmjY` zIVxU|)GeE|c5&KQq>C>`&HQ^vCOk!kqIe71Rb9PFxpvNgDy| z#)xJEc(mwI?)KK!71!*#t9YUVo>)E>eho`Bu5AX?K2ACxI(V0(-k_OgtBoaDyqFv$ zq|MT|p43zH%8d6A_870Ih+%?Ab0%2Yz1TogE{r(x-etng7TdGaCX;iOIBqP4zTyxj zgaOPSlLz)}N+T5gNK`L05mM4dCUA~~sqiYnl?XLYzv5vP&1 zx+E&=b?btdlBBf`aQL)#ww+86NMKy{U)E=co=c#Cff!(I#bXi+ca_5?!f^fVZyeEA zv2*ToD@?o9bR-R0iGk`~^%ALTtl4biaZYgFP*c$?>6_1G{TeqSqMMao zCtL`E_H1QB&!EvCoB=*1wRGyn^7_07v;IF}cj!TL*`#$-U05-7~3Jq3jl zwGtht5e3rzf?`ka3%oXR)2+Be>_IpN#(@mdp~^?%o*WC!$wfYyt{ee?hjcdA)qg?- zSZR_Y1Q~!dVK4A$xhU{-_3m;oWjW#`aq~J2X%}n%;veV0^GG(g6?okS<_povWD#W4CaaotebdDrh?B@?>h%|9bepz=}D^cmrdZHu(SZXbRs{K(8vE9{ANHe%4%W zSp(tkf7Dq1(nEu_D~&8dbB0!2=#xUt5ukg|WQd?L5>E!iv#q1FUrT;{wqtbDYbqNu zEI#-p-OZnqnczctSqr(&r-1H-1LJUaXe)<3DhLqKM>)m2fs7Ar9f^5K&v*2GQGd!E z6C17M@g%{g!A$BU%#63ZN**kG-UQ$J#4mq+=FU22b_vf54KQQClc`?DTbtDd$tU%M za|fvXxh&5eBQJ#ozSv0iUo6P$DWN%mwiL~TIsyo9bU2Sdx03@w!G{RY2kX;`lVLmu z;GhVBp-8$NFJpv>Fj#h71Fm+f3=$r#Z>kYcp{i54!Ky*#Hz=pu7m?vAN=@sI0(%32 z@>54HQ&|Q{M{E^&mYV#ytkSii%o-r#2HrbibxcM?Q-Hf&JVW;%>)j2Pw8A~T9N&Q4u6UtrEZvICE4nqkwCNYLeA zU^4HJBf-sZF9yHJzte4RL5`KaHd~cR(#2`Lw1B zb-=csk$FZ+wZ9(jw_IHa?&@LHTZ^FM6sV8eVF=d?aNEj1(&1DKHe|(E!H;m$w}w0F zqsIDm$xmPjap_CGv`HLm0yak}E%jH7JH?OBm9h3u);2|bNxV4e3WxgHdKy7hSyeP{ zJ3byUvX3G(?2R@DvVHXm*TOMWx;wbTK@ck={p2aLt(6-}R3srJXG}F2HkI}yN2)%r zCBbnDzR#uJ4=9?oRP?xh)*#}Y+t{Gc$)UXaqb?PuxgQ|1Ldgr-l?d8MU23-5kTTLY zTeLB)n#G$tk!-0}mrQPjy!X6zF`E7aW!g2i$7ga9!xFTb*aI{&58BOsAikH+7!($9 zZ&w9|*o+IGOqa@2`@I3f`@28?r6&kC#F;=tf>fv$3{d>Rz_7R%F9FM$)=iPGS~?RQ zEvw-(~$IG+TXW3QZ|cW58{ zykA`Jw#!7mTB;9v>p7=Hu%o`@m#@5v0pf)m8E&(74@aC{SVQy^LxirQ9-=^7!J1V zBGrEl0cPRWhV5Tlb&NbiE=0w@)R=SE-e+spTmo6I5uw8-$Mq0eStk zbQ}Hwe&B)P=i?~5st{-Q-Shj9`K^(rgf4KVU8KK+9Ek!Rri8m+>*_e;36M?!&$-!E z<-^(F)*u%wv3@jWJZGh)Ink-B7jH(-?P8e6TfJHLWJN4YcRigl5CDtAE~smW#8d9A zLD)uBHLTu`9^6q>zMIBjWo*%q*g=NG0GM zM!cXd80v;L++3D+Apko4Q_@%P)eBz5u5wX_#%IV9qJH)5K1Na(MNn1D_81;Jt@x9F&C|+b*W~38pHvXQ2<{Tnldnsec~!&=rh~wS%iahv zB)#xuk=u-D8dTN|+9TKtcwl^D;y9+%? zufL{9U)_?R(oMzJz_d}WUQ@e~?(<_&4 z!tWK2UQw*lHz=-4g0Yi3*qp5eO$70Y{E79`tQ0hfH#S?55$KLl7-LZ##BQhp_Z*|M zEsa`5Sjzr@Z^EkH1vz2za z{;K&fNpv)gzbH1PISZ);-fE9|Cb)CyR&6#~Pgv zQEJFWeQ{^Q1)uDO)pwMGin)5e=TrfH!=?9wpjQab8PE(4p4iUXg4OuI|0{1UQhJB=% zg=Pxr%{lN&KOhks-75T4{@xWKQa=luG1I9)|5?0jwSzs&cc`d*fT$p+ zCadqRB1{1$`LHUO_?yOQha|bqQF$AZs`vxogT>rC7g#k5Bs$@#!i1+sP#U`HU?g|s z)|-n&IPc6vy5kqX69fq`@%}h;+Nd#d6hd=39g!H7Dmi4F6iMIwFAPo7#K1O;cdIR zj^QQ&%9rRM4Py;j34$2>I*hFt2eZ^j@fH1#9=s>ih6~g1>H|_I{6HietXKzDR0EpWr_~w!DfANg*!5sFtaZF5Qhju)1IPBX;e!E_mur$G zP5f?!+`*4~?=U^#_#!5hcY^NcX83U*&N+ng63SNd#o?__ds!=m)Bi@f6H4*pgYt#~ z(NRcSaeQrn%&27o1i!XIStW&d@|A$vDO+b^U&B45_gx}Qk$6>rD$HQX^JJ0)!LZFC zU-6LpJgaKuEi!}`o7m)U!>m1wC$F21qnQ(PqdO?r8l3-0)hh z@*_(6Hke!mK4&Va&Hilp@7f0;$Uh%$njS^Ps^DQq=BKR~v0#M} z+|jCW4)AQiZSk={B9;lB6eNw=%;oqrKbPI=Clh}uYkyg?(R7EnJk=P^G}df}R2pl> zuC2NfcpZiU*Is7^#nMQboP4M)Pr+e#HfSmuQt-*y^>vw3SOy-Kd)yS)1&g|5-{IT5 z>VxnWPhogkEP;Ny59_tF5+hA$drMHkTiOX8$z(77g!!dVJz{@z2F4BfwBt554N$h3 za;_kLRbiflo=0v|*GrGrtj<}qz{-KfRyJwn61BAgI)T_wBvk*AXd})0VpxM4j5CJ@ zfmX6tlo8VZeQr;}l)vDhIXYBSS=y%ptidYVMzDuCx8y%1X2L>7p=gZ5fw*Jc)Cf+% z$n>8TN*x{e^G@->CyNAjAy6U6Ca+>ASzNZ($IqMkhk1f_n>0)A#H4e(fi^hFxi@`A z;D7Bx;3FJujE4xympEe1850oHe3m_BW>e1S*ku&BHzym}-3Pb*X!L=q%J!e0#~xp4 zO)Ed}v7`y?@a7cr^b#rF*6)+*1?H%vZtXc8G)n9UBw5SL=`n{4ts!OsgP4y`(Kac< z0vIZ764fqo%jeB8q^>=iJakTrrV4S3K>HDr_C*CJV#&78!*J~CaMXJl_n$AGht0Jn&rNSm#>}i zn+h_+!sRH>aNm?cO1z<9HuUtF>#a`Un}ZO+WxOwvsL*M{#Cvx42IO7%8g834w=Wic zp%9~HfTOaVXu+f(FSxY+z7QiHBa)ooxx}Mqy>iwOh|5xhUo`Tbb2Hm}UEd4Ua2nw$ zu;z%#Ojsi248wE)1BkULOTAU>mdKI}?vrWb?w5VOwI<3P$v?LxQ*MGZ-a{NOKrmvz z3hyws)gL?sYdTFw?*O!4B^CD{Krx)0Nk2JH7}-K|Z_e@^`UP!m;V!m>2^Wl-BG5Me z4ddWt>W%-ntyBJ8SIC~L`z1;T+JHzYyR6u9D7J3!=sAagoo`Qk*IRYU${nHNp}nw+ z;a~A*iSOVAhwq%=;PM%Sxs`U|a+*2ITgS$69rVemwj(!2MyZC^-(rZN65D&hAQ8JF z=hUZOtou3-5y9Bd;0ulFK2?!@X#%fAqGURlO{r@l8>$;*05tU&OLL@d8t2bLrjDc# z1byto*X)r}U)YLz=udJEQ1mRatrxXJR&grGGH5=fAP@alIw_mi?H|<@T>s_dftp~ zkPoK+6f#EM(9!?Z;JIknQ#d(-YCemG*0RsKi1SXo4L6X}SF;hSw%|lZUi*bqHdIx! z$G3j;aP%R@94zBiC@>G?RPzKMoDJON*x6iXN0bZ329-nJ>%_JV0rp0?x-Z(tu_WC# z&aix0q^1i8?v;Tv?M_aCCK2VW?g+=Th{;4y5r?=lTNUAFwHSFTA(R72{)qJlS+n68 zLd4^o-z%M|Xx~IR-+@vTLeNL(|&=R2%&Y3F_9%y;`4bn`BdpuS?ejr>l? zNiH&a$Ogk8{)!yv=>{ns^vWSy(!|6~t1xUzdpIL$DEGUGiPA;m_X<(Hh&SCDyrq&s zgjbiN47_tGY98aoQJ*Z}C<8^K&iel+WWO!@n_M6s;~q#ETEz~t;#0RZG&0kbt1WtT z9O?lTtG}Aj$q23@Q;Dl8LTr>;cXn&k8>MTHuz#AlrBLWP5=Yij!lSpN_-WuZ1%1p5 z{=Ueh?2tNpRMH?z!j`gEj#$ld(KigL{nuYqooU%;~ZMtBY= zMay@oC-Wi2yI7!cIFXLk>;Es;I0WTyO1Lu%QqM*z1E2i+>Qan*=HCEi{`!NgHRcn4 zrW1^D8jpvLJy8c?%shXx4i)j%NwlK0g9Psp$ay}_=Fy7yW>eD#8F0zWG=UBA=MXRM z*5xz7t{|mf(eU;^Mf|6tOjlEAVkXZYFV&THx!lYjQXzUGC3pLk7?p4F>sxT)2lxZf z7wq{WRjn1`7TNsS>?wT_f=iB6yi=nj^SiWOWW4BvEE(xV;-b7epvPK{bTswHRtzJAv*Vp1RW$!b0P~7*0<{n2;=%gc#p?LP2sRYx)Ki!EyjI{S_h|+uyL`OcdrjyQM*LmS}A_A&5zQ$Ge4G0)?#VN<3 z6haN+)|WwXY2^h079-t-JCv+$y7m7#N_C z-%SIjGMLn0PZnDjXNMY9v<8&@imWAO`N;!bzPk$QYwyo8fQwf`sycDO+9tBSs*!l0 zYf$rY*QJrdn4U49mmn@s_)C5SazpbObJW7Af8tNX`gr?i}L3O?SnYQ*naPoRH-+!Cukp$QQH^V6o?2qB;)`| zsC|_+T7b}};@Oov^#HD=##Gb9cT*M~^D^A+OjW~(Z|+HtzS2WujQQUHwaN2^hJCPh z85@QQ=dxrPfZeixd+3uzK1qfz6#{^GL)S;OPy zD7LiXPgmn@ZWvcs1J&C*!xV7n0CZO=aRjiIp$Q;hV&KyRQjx~z)05Irw^_1T542q@ zt>i}4s6Oi_CK3GX>O$29R5c{Se9J9d%ZVUuaM|njV2p%wm#rsxr9+s%XzXR&b_?M; z*{LD62%gU-ng1w}7;o^Qm5?o>lv7>Tz-!cw&;Y|aUl%g~MU&+^(Yg_-6W0;k{-M6k zi5vRjK_DB7WE|jWQ>X)mg4sLJ>=A=ZdS@OyX&M;dTQw_ermR<&@Oz7!E@uJ5i9)aAoRoZ)-i} zhq}oLj`YUHG%YPlAE2&E^;>=cGc>&}4&4~xWiz~p9CN1~&QI6QFq6%qE;m)3b0zLh zJd0+brdlty`vmaT`$`$pHi^nkHb?#MLiT4AG$QHLX=C>P(KOj8VosnzQ&`etx`#3U z3a<&gZO&2{_sT|x$di;mqD__W^S+!o{5zTcL^cm$K_0je9a-K3zdRPi`T`XdS3>Pm@lH$|{l2LV}~TRF5RKV%&P&B@*|3BhN_r`s!1dtU|IGkf#<4x6$x z$VVp6AeUlcMh?RXnpCLFHtEY2MD}M*6YTKOc^}TCA3abaHvNI!pW77bp#ITX<*u$E z(@1$+G0>fgl|1(bJ461v0ii`pl~`waMb`K#mtCKiV}d5>^78634qXpw)az4}_>Sb? z7>E0!J8A$cW}R?8IMOJWZ{+8B0?%6~6_?qxW3%C?!#ZO32;jA=5I7Sb?Lr_VAI62x zAV?X=0l8K9u^)kLW;0?Lt6a=z!pfm~1j^6n&s+Ne=7zgHX->QF-q<^t*~Bv73Tt92 zBxFoi{2gZ`L*90qE`HPT0(Yo|OBFtRGh?YBbQz2aIPehTO4a4;^>iA7!~H&X6CKV3 zGo`OaOI%2Ph?+tNa39^ra5;%~99wTHasU=1c$wN>;m)Vu*U%{xNPTdsUr;`PCLoNS zIzPljM+_Pz>txmWyX}z1IQBxL!8nq;94SMO`hbkaEK-ZP4Sp=Q-3IN3p_ye`FbsTt z3TbgA*&0z2Snbs%s2~;7##nu{Qrz}lc zlX<`wH))L8Os)j8d=cuEYY?AFf;Gzgl?%Fu1^Td8$P6qNm+DQ*^c@v9em!BK=O-j; zWtt@!#U6N8w9^Z3Vlv$|qn#i$Qhms4y$myaNl?iBr?Liv;D7M?QvTJ`b3>p?*QJ}% z#6IQi(B~wMG;WMOd=?mDFrHeJNGJHMfpe}!&QpLX4>T6N1M(fC-tfzgLBPNju2{K} zg|cPpA%q}pf3uCP_zq>=-48x8I)#t&Ug}=2*vYeQK_d0Q|51_REFg3UR?Mx+tB&{e zGVb4P9DGBfLlkkg6!NY~#F@8-gJTkaL|_(^(19}WFaQr*)>Aqlmg2opNzr@g-u_YW%A}9(gV&Hna)(U+qZoCN8GqyiB73V z)wXvTw2bS*8-e4kG0C%*%uN1x^Vk;Cm~Bd6*d1ya1}FGDMZ@PBGrCHID(H}IV3uEW zb#e@&Cyvy-gnG8aoPrp&-(ak_2ol+z4H~~Bpn@e-mYc+r>nY>0au$p!=JSr{d%sKe zqj%TVKENfiStc`k)z~4U2P=-AyP>q^6wac#fC@Ud(&`*p^kx_x_>yhr@1_tw1~n`$ zPr>b|V7P1M-2fdFe{oCWpx!n8YE7@FG}yRNEfX6BkvnjWqtb) z70>CNlyLSN{EK6MjVb22%&j|gor02W_({r5_Y2|kZ?vZ2tXGls*v@X;J&#XVd_ZGL@SJmCuJ>&&N?^%f< z%@%b)H&u{H4RyuVm>HhU8}CWRKyd#`fyX4(lvTa^caX&wQ*sv<%r26)^4DL$WjqsGA|$%_ zI40^t+NPAbE2xg!gFq>YH#s!L8jfo@=S?&byz^ZK?c4@N?ldghR)A=33n0of@7XL? zO`v_1S}ve?d-m*)EoK&`6bgYl_XLk7j@-tVhR9+?meT>`~-)84F+ah7+O4&mkT zUA7a|wu*MlyG;gyPe=0|u35okv9pwGvVVc60C+%jSH|5x^GqkrSi+!tki%FB#9k2XWnI^8%i$gHBMH0J_?A%7)?vK+f89}>BT5hCLx0} zK)vOrC}^XX-gyW@s>rZDb;rAcVoY3U z0MkX4WD3=T%^H8LpD9x_)Aw_Kzi8U!r?q*fGQ3%t6|v_qlXUxQbwEOyTJz%#rIP7c zIO%HQ_sH($a`xf&jh-%~8gzq*uJ#+S*my4B{VgC((U>`Xt_fh!(TyJx_Aw(N9D=i(OHRb>j+=!09MG`ACQ=2x8k90MfAQ=Fzed)ErsGhmSw|_45z?ZvsZKd z)F2Jv_F)8{IcwY2)+P;>h%-|sBbtC!idT$xjvOUxh$LmF5qRS#6p7$csHiuH z>-CN?6pP%#k0o26o(yUX7Ut!L{AX;e|DNt<^geBC@mkY`4U$m^86C5qiWO6_P+IFQ zkJ){>n(U01NR&Q8NM+y7#cHdAqaU&wK^G*0-n-DsCfS9V`q#A7^;2mpZ2SaCd%C}b zsA2qi$NLq_&;QzvldsgR?|9`nVera!70CpeEmt!2Pd49Sq4?NEs4)5w&3mWQoS{$! zP|}2HN8!j**jl)izz~N(jI_>l_&)2>o>%krNJC`@$Nk~NP=wJZ*t?3ES~@9pPLPrCSg zAS?is!o4Tsa>do>q0Ijx6=+U&X-VF$hCxFtx=yW2@8Q_D7)oKtAGr$ZJ@x$V{#>>f zVtez8jv||UCr1|81Ft5XHoLQk|C9~rL2`*>CHpaWh}gvK<5THo&KY% zb>UAxeC$B48WE^UUxMW8@hzkM(NeND*>GU-VJc7BSq=^_!@^0qGJMuGgQFs&w*R+q-{u4o&;o|VK&u+m{sON3{Ice2h23nsC7j)Z7CB86Qq+# zNZ_iFi++;%Ql6h7u88*b?*|~?&{In}95~x-S;Gl=oc93G?-9Zh8uNEK>sRA% zEQUz{vY?N6-ac^K3|Cr;-qU5I=BRbh^Yn{p+VFC51a0rZjCt{1N{TfTdGLT-89Sb_ zQN!h5f%2_rkDp&g%5PJVtnkStkZ#GRJ`;g(_n^LcW_+{`DXOAMuozTsqhg^#0Qt5S z!C@l38PQ#`5_8YANFu zAd6mt-3LaAywRnDmA_xa=Q*|*)KW#G?2 z8v`K-@%)#fUAfA&L2V4I#(rxApUQ1JR@P3@bEKKdWy|Q30n_mv!9lEcOe+O7K3VmK`a7>#yucE-Zb4%0Px#D+Ivg zmG6o`8OlX7-ctO4nb1ajJj!jQjB>=9?*`a7yp_U{Kk~L{FkE>4btGh$|-7E`Hh=PCY)}iJ6z1dBgEo9TYXkb4i+JLbLmlFvv$+M};IY zgzrW%vngvOZkF1TI&1s|S3LjGn_x*?IFrPJ%_5CAfU+(bCTv|nB(yU#$yg-^mFuS z=N0h(dha1Cf-FK!U9N*CFF)5n)BWXMhVna9Ce8x|INM3lSANn@iyr1ym6 z{mQ-3s_i6yRE9aKP-rp~UM!F7Lb)kYV5z!4z@Z2^G1ER=ll!E3^dhtR$fTuP9#r@Vki#3U_na2!tvyFI}?_6e)NNl+oeT+fb+DVsv1=gR}=^-=b{ycQ0 zI7R&mb}6}e5qcPhCa*%Q_P30N^2FjeZ09y#aO(E@9C_B{)0h&>ctW4`CsPxgkg{&$nV+O!gs2Qb&e(K)*#p(@c=hK$iIbSSRv|6trt^giFQzaF9{d% zvzszsIa{=dym160M-j0Uiw3oit8a&cKRjnvZ&whWwuX z>il(`^)r(dUZt}knw}%|2=9qRmi50=Q{cVoRGc~!V zbDr;vZ!nge;x71vZo19*Wc5mT=BIjxP3K?|~0d{WHT4cU>1sQAaaP*u&BKLamxBh@0PECg3P zLIdbpSk_ibWno>bz)@BI13u)ATgo`eYN9@lquxd;78JC33hl)APKQq2?`nC@!Mp#j zd2-dCbtIiyA?U@Ytzek}3z7z=!qX(oo*`1+F73WGvLyaFLFy-1YxQ9y88|V`RpP*V z9tPI!ZRffrS*(z3jJ+@{rcxVorm4ODXW@T|vu4<+HTMrJdi2C&)}_<7!0L4~iDlr& z=yM*ij$r7lYC2Mm81OFas`IE>CdI8v-o=XBlqhy9(6&RZc_U`WVt>K*(-UvfVU;Vs z1^`fT7-l|!U1Y+IFkFa$hp884E~!C#TsodMRC!%#<$To$$B(431FP+yP zdvRg#OE><)zF`n9&u{>stDKxBYB6x^sfiYajC$QD7YIx?4POpxST0cY^x_R_NB`k} zH~rCQuctunh|sVlX+b+R@mb&HTPz28d{*)a`B*fD_Ip?8{{uTF7CaWH#LZO}^gyOT zWrIm{jMo&UX8SrQs>*l-I}&ab-HD@QDiSB!J83ea=k%AVf#GL1ZvC+pPs|9N6BR_Z zg{vO$aD-|o)y?95+T8byobDj=#RxP|OaO(b!+xP7{n?VdJiPD0TA*A^x2cD>8no94 z5q`4Rf6ZZkC0yuQ>$(l9*J0#JG44D;!Oxs8x+)zan;hGbG*DsWaQ1H~o954wLO}e~>lE-|T`;YZkm~DE;`t~YB_$gMm!#dv z#hL-Yl3%F`n`0VIw_Ppm5w&2cD4+F#t`RB@onXArbVcw@ylbq#nArTxbo7}u6ywK3 z#xY_A&f+mbBG#f6RaPq`y8uB>*4`$W1$?Ke09Mm<^p!$e(OC=w^A;`bexX)3+rsSioyCyXaQ>58-JIC3D&ql`R>7qd$^ z*gO+fLi!`p$oov?9dq@tm{qaikKonpj?7GEATnXVy|G4oPK6oDKKF~;%xYMlx&so-orM!BcTIl_6g#lt>25_~N?+3TTo3@;nDQ~tHKzqh9cqF?s30CN&4@!o z%h6*d8+*5Ak7*(`exay*G82bf_7f_%7mD%o2HU0+Ofy=2ezHWliA33^l}(`Eb8t*y zls}SMzQkP4ZE0gV;*I9(`+lXW2RBi(z>{prF$ZVfkNClPituavxDutEz#cnQ)Pvsk=I9u# zgb%W>)nxc5dLEknGexaScWuTV2YiOpjR30LEprZIwi|@ zTCu!)@B&WvEc(Zf=VKu*B6^g9$u5K6uy2)y&0rIR05#`b+hQc+fy?IJYHSuedK}0< zGJ`0NDP0wmadM42_maY2Rff2~@T~t~#tvuo!+#G+{BA*T-b(Eb0BHOtEs;WH?*#At zXrqUdyfKtmAj;9o2S6>nr`UcVMIPWW$W*R0LbCP%mr6en#V@k`t0vn%i;nZOb0aHj zxliTd9+gEcwqGUbF|pK+sHB0#8E|V=5Xn9b=AF%&qtEhsqw*p(BVN~;NuXD!HXOSg zk_tv8&&s<7G~mnYmg`r9# z=y`H*HhMs{BtzI6TP@&Oh?z*VQ=VBzPk9YRx5VBC)g$7!Z??9nW_a%AWN0O0iQy^_ z*r&{vT-4H=_EKJ(`>!X8-ZKtRT?kwa<|^jN^Pc!L@V+iW(L{>etM!`=@kUjGIDx!i z@OTNwa;n{AXZTPbB||6;U=~1^tgkyE8Wf>V1K9X>0bqB{{^vKyvUxECRGft5TNA#JYfcKt7{P1+rjCRB6J3dWm0l3{+P4&3Zbok8?BVOiz8o}QsVR&H zp|WI1-1D6E4i~>rcS#B+JZzCh#i^uoh_t|dbtH6HE*q3J|2yNH%aH&8TC$E2NQO4^ zVl005$p3mD`7M#|B3ma*<1AN*O~0w@1*ej4IwxJ!CMi3%j`$q=KI~*PJO3bwrb-`> z0{hB=%~1e(%OV1-RxaxmKEAdK& zQ4Q}RvQ`}l%fG&4 zAPuDz2cb~T9kIdU(ZIRj9F=_Np~0>WQTn8qrZZdF8@=(zU*Z82C2zg7}fe2E6e0d;oKK^zkL+AOE3-qZKYv{8f=V)?CX8+D2 z)@3|MU4C9(`AQIX-WIla<-4PPd)Gq7xF)fB=Z~Q48$?;Qqsu4&H7#E-=ihA#g?O?< za(kv)RIs>ohi-o5UHm7BA!)W`_?~>9HIxv)tFe-qdRh1~v@9qKj5nJE2R1)Op-98m z9A6=uLshiHeb`NwZ_zrN@k|#_qBUOaZlzSQmyXQ;T;=$*i+VKP0SNR7smbhvbX`s5 zftYUw^_Jq1G;vd(=f-~-CW(gd0neVSoyr9nGnYBcc-gfRAMH8Z(6w}-=#5A=T`LKbjx#7Mj8!p?0eS4d!d}m<~)ps5BTV5MDs9+SGN2IlFiVdn@0kE-P#R=kFlC~ z&-Z-;y$z;Njkk#=*r(#?E5Jmrv_9_%M4mSBgk=Ap^g>s1kya&ve{J@b@^+}Mb=c6q zn#5FhFIY`h0#I!M+9R9%=!^j3ZU(29=Q1JnNccH)w>=3gug^sy@T4?|Q{;%9*R6Z5 zfHKrT#WK1E&9Y=Wy9iKfk!V9X`5ISN#n_a*m!)39y|iF5!jC#haD_wS#I><7(UWu8 zlnUa2WO}Qv?=)AmrD#6pzX}qNuHP=2z%vG*2m>zFYl`Cg4YY)aC>eIW5zt*~SitUF z#xIlaIT9AL8lb#$LlF{G*a$~J3FLh z9OP@jHqcZY{UIxP)Q;d=bd?Yg=tN-tMr2q`6jeJ*du0W25trkw+KW4bc#G37+>MEB zapfG%Y|V``ws%jKq$o2$dnO+8mYawFs(>K;SFYGgWp;z07i7Z`x~AM=WjW|xZ?yYi zN&CMIRBF9g{;%E>k*C8-zj>fUJ5~vv@JP-ckJmlkN44<{qgf~i&c{`Ay3Z_F;~(D( zj4b*sC1mgEG;qF~tDbz4uf7mqVQVngs&kxkPv;BWSbWBjtr=0|6G$y4NkW(e*s@F# zaox8w0f!!U$pHYxpg?x%E5BI6AC`od6_CagAFkjuO2f>~`zhYvm!@h_F+?onqEm$O z*hgaz?Fp%3b5;inY=Pp`Nc;MhVd(O+xA75 z#AMeZ5MUt+JS~n5eRx7k2%rll?__m6ZS(@y;FXZi7*R~E9?m;Q=FMs|;vG)~%0}Rr ziS!~ks=IWsFSd0N0Rimjxr@auu-?qC;44V#itn1d&P&yF_=CN2^4r>d0~&-9qzT;0 z-O$FnUdu`z8Sc5yXal&y@0kJQZS$Mg!itpqMe7jxZ+<_O?ps0R|3(=xiu{J zxUrbSZP#!q)N5j{ki`eP{h$aF5F0T#HBs+Mn<&(-)JJ=mp0#Db7j%yjOy6$`=;K8^eSHc z-p-qBr%MplueucvZ@qK+jXYsd_K5Ce*H7<}w4ZNLHGGESe3FZY(~^t#;S(2gJlq#$ zZiPZE0Q>uz->jQe!VX-p)Fizec)y2y7Xf`KfSsX2(Y|(iIL?R{oXz|p^_8hXTDmuT zCAPsy^(G$)vD~O#h`31XMTgm{XNMO$#l;yf1jhvSeU7PLBO5cnEjLlA{y)2VPT0dV zhOzA;+`4GZKvjnAVcdLxi?!i3`}6O_{}TuRMFwfJo;1Tx61;a&!cPu)zG3-QiSN6i zCDZtBg&xeBoPXshel%f=m@RT~shXEh{d_Yp#5?EdG7-2^d@=5`PYsB(K}wQ`x_xE% zVKp+UKDroCW*x+AaL=oV@`PhEVFw+|f+ zPV+H@>KD;bnH_VNUbqcBx7`ukj}kV*6AhS4$|!vT7|!6z@+4p=&2O}N3t@;}Mj(^N zd~vFR#vZdI?N9rC^XTI3&x;_ApG*pZWKh+o@fCGIdanl~JybxMxS-ceCj`(z?zXo2 zm7lc{l1eSZ&kaKsC7?f0;9-(U9!jG{;EPG;j!Bm}pMJGZ?vJhNDraQoPSo0@1x$Zk zorYLi{C0~+^h{ljMm8zl=`>xHdT`Rs>7L?R za+U^`dV_S36y=Jpa_}u@1n?B`5yb6D9crSZKfsaZmR@hd0dF0xNj6Pc@R11LQNoE4 zSDk46{T;ud5%^<|sKCO0tQ5K3y_8Ge#2E(N6U%ts2E}InTiz?k;p&s)6EW|Gx>1Az zb(wQ27!~G?hx#)IAMXLFg8oq(0QkMwRx2sLb)~TaF!&ib+H`V?6p@x}jLu7S{oB9l z_D80R?^Iwzy$*z87(h!o6<8NFjnYh``|dNrsk|-(reg4hrC93fP*t)&v*2!ufZYbslNQJAKwWZz1qr0JOk56bW_SzGlno3P3;Xn7x{ zv6+qqQr!Y~k2^Fay^j9;6u+N2Fc$S7RB{8`*~QXKUu9UK!o6Dpus9^XHlJ@sMj&U| z6LO5!&WvM}G80T%UkrUlZknUyZU~~_0sV!3+5cM%?uaXT050sijEFU?b90+h3RdX@ z?h(->h7m?TSCyu>v@pnP0?Huv4*acERm8GKy)2xAw)p`Kf)=gk+m&l*U3A~)xOzMb zizXqh`I~jTYO#WOLc(=n-;$#c!Hy&hXzp>M+j|YUB&$nbW^4`ym%H-+^g?jpnf69@ zd0JSGXw@w`+dwtWkn7bv$E5Gg0meq_w53u1XK@sA2bUOdAv`%9! z50ItObDEMcZ2qpEPXBOs;i7D?X$3T<${@?K7I z)e_w?tMKiv^=ckky$yblGp7Q8f3hO+02z{z>a(>#txxPsd+y4g<=XgE-9MvF+Hg5u zr8L@EsH3^%ZL57jrs}&d<%zU_W$vc%(V8!kgZ7b_zYE&3!8>6)^lRcq^rpEx#gl*Q zBV+`zw?&{=6rvJ#eU07%}dB1?XEA%(~NIbTiB+$FVeV034#^EF`l)|%)r>^to z&R>$v%HE7vX4z=B^rz*awOwC7ke?elf-i=09tmthD&T?bM{SadYJ#K33EAp{-$?8@ z{C0iuY48ed)_}5nVXvxq-j*A_f&Q5gEdwq{^v?6FJqtUR9ev}`C|^_V-1N4ACIHKG z8sV@x@3a7X@n0y7ZYAv)fREe_*9>dARmAR2lL$mC;^^67x7TIx)D=a};_GsqNc%0BLM4o!%58|~^@yjD6_EEo!sxTVqbmX;&EJ5MTtPY@#mJSCm z{A@pJ?{XOvg22+OX6eQjW6RU`9+gK;9f)$2UgZQQNUpcK;}?>5ph;9gRtoiAcsnRX z^P<$y`f*x1WJtchf*@;Oos!SFmqio*X*>H8T}(CPN6AU(M+UhY^%FqtN<8-#{|YBompHPi3EMDSEzZHKUt5x-8#zK zMixzq?)y!3r$I(eUEjGS-2W`f}gCM$n+<|v%ZKL;8O?wt55siJ}$kwj$p zQ-&%_*7gyTnkBm**r<@6T%0KF#SIr9KDH{oYFy_puD(otw z{=a5eJqUS#ck)g)1x9p7_z%2wUV14o)Vi~O3uH_DWG#XX5~cOXOzT8fBd{Jf%CntS zc$@Jx-g6E?ccsfV_9}a9%0=>5n1#RmPgM(umoGp(<(R1+pc2ByEknLpXoogn{)JMZ zXWx%#<8Wg`gI3~TC>w9JUWdv`Kz0530Mi}(Vc7)lM;zhu*XR6fOQ%W(Jd5&gB^>~nA`U}>Yp@Rw!)2RopGkJVZV2MDs6@^y?V+2KTC{2OgD43~lQZ(VNU=ygm0N zcUdKmVQ-qI?e5Lr`+Zuk^N7#U7yI65)OPwlr;k1jV@InEa#?pK0>CatuF*VQmak;{Bb)F`78hKCHPWK)mdVTOj^9}7L=xc6rHY6Q ztpjx03d&pr%1pZ8K%{^6gb{uFojFMI+Oxq>;nrLXX-?fKuCN3^tP25e;{}<#V5{yo z{I^ux7B1ohLHoT)t$*XZ`J{&}ILALp65G1OcgL_v@c+FQSKihcChy_u2L@y?*@ZP> zS}kI^8%3n@1&1~t;dD%jFN8V)|IoDD@odEseTzdLuHH3ENbsn-)^W<=8?{w+&M_6i zsSoOqhtjewAAoaIiPw=0e>PMGA4a_2V?RN&h`RtHj>P5YT&4l*F{q89eM_Un+du9g zdw4^-mR8&wLj_X>qh@$p1Tig{zl4##Ww+OZ?Lmm_WAf1tUeH|;kx|9)kK+M)sMix9 zs8}*<6k?m?&ye~J(zA|x@o|{(YhLB=6TkV+&?&dT;J9*eeFPf`s9?3UH=w#Q(d^1h zBmxJ)0=WL%-n9n5Dt@7z_MtdKVPkOd^{h}=uqUsS71^8*E?Rpqz>-SbZc z?wdu{JP<-|F1@=Swi0!D=@AKkW2GnZ-BoxD^%@>5P)cU|&kc0HD)vcouD4J(tUUZn z#aJpB^APa(*)D#Hd-L=QnIM#vi$70sy!|O;dJbs`17JfO1AK|uaY0(b63Vn;C$ z`bgYyZu|oJ4kg{ukLUOjOgwK_I3Q1jekOPb+ zttrk3+s+kG)9NXP+?U1^)*~54q6iwb6Z|DcE%f~by{V*}T7)V=4sQR+5>cq2IoD6F z5I`Lw<~gfrpyiTtd)Izs2-JGH5vc&8#=4yLD4ad(w2gm{;+~yeCYHcMFFUm0{;1FL zarfn9aZa2v8OCEY3wXya5hP`_1Q_!m81`YMTp;Kw#?YU5vqtL{eD029&cdjq9jk*M z#s?C;u7S}hVUaEe)FAADfgC31?1eegklEfC%?A_id&wCn;jxcFe6vjsBa2CWds!Xl z$K$b1{fzR09z7cQ-y8D&Hts8nR_%303Ezm$x0H+gK(F~F@V>3^Q<%d{qYos;ksO*n zfj`y%sE4JzJ8r?KtCBt8B(>TInNyLC$@?LDjNf;v@_Ig-ZDtFDmV_WSS%Vl(I-uDN z{idDwj)Qi~hlL;_2enQO3_V;}M%_93)&bj`J%Q!d9uQ+JuSY;jDeGEvivF7(^#d*n zkttEmZP%+CFu=69rD%4r^I*P(TeXbkn@C7T)J>w``9AX_#tyWtDZ>_=HLDJC^NPV8 zMI8~Ux?$c$0M|77$(0UTd{2H%l(Xl>we<&>!&v95%ua#~%?be$#T(4^00=-S`;jhM zr5L{~(RwMyp-DY4m@&p5GB`51(Vh~!kAeME8^j)=`69d>NqLjT9l4QydYn3bFCpVZdQ{KF``eE`gtTg;( zmU(B;qYoG3_j_x!AdAIFMY@>A9TY!QnpHVAp=j+_L5ZgBAGlkV0=^of{}nJ$Yr{6jPyTRJuo`z^nM6jD zm~qkH)?BIVXE^()V~cz46Ysr)9`wH-vfPZ3$kMDOY>Zq^`oGBI)Hnw%6Np&;jn@-u zb`jXetvExw{e&RolD*DlW}v=J%FZ!iR1n9L9Qk-0*j#$Q48q?`NgzIUA1xqa9yu|z z^q#4Ka>|f>&1GmgN0>E#2!{+=7lFiaX1q{@}t=+637G-?$Y%UZ^opab;n61HC(~vG44`Y8D|^ zL-bUV`hX?5ObG)^Z-)MBJbU_#JIM0^LFmfc4=8MR^8}eR(cbf6^$J<<}}u= zplf*@D63^7-kk*K;=8`L#T7Nbq>*1+3MJKc|NRi==afpwfM@;=Ux4&Jh47qsa1wY6 z(~EP%4<-irV!CVVEty=X|UWC{k)S6tW46G zzsmk%R&V3-6G5B+&>mGNpGM&~;^9a2ZL|qYs7Eg`yDO&y-?jJ#-WXZibVWKlq1%d5 zdsyVO29JMV6vnh9CA3c&3V}l%xFkn$fRg0&ZLqc^RwG>RtfHmr;R%E03epwUA0Q}- zi;IYgw23rWMBj;ujhQ$VOVG`t_AAJ8k}95ok^4?cXm{DRs*~4?F#q^r$RlD1bDWD> zPz?ZaO%E=bb_Nn-nkGWmk1LB47cxPFnXk#h4KWUdNxs`)`;@2NNt&VYj_!(;%q zd=TL8cP3?@SBa!?OxN`3AKl2aI{i&S_+ zhl%Fq?3{)AR*O}q*SSi7d{IOG_NtE5;oF(gFaD2mNTnfAoVkydg|WL=onij7am^`` z+n20mED!teE+r;MZKg7KUa?uL{eu|@qfTgyx^iCFu{(FPt+yIULH*EM>yI68UUjNVcC~>Za z8Mi8Hy1gc!iu1re$;xlP;*VXu`!lwDNqFK=!_f!|Az2E_>%(j;syGUT*?rY1u#~$z z?7}Hx6{mV$|IF%_89(iqQ%^5?3k=aAcN_Zdd_gz(W~X7pk&Q?~)}~I+nO>Dy%KLWl zOt!GJ^ol?fj6TJti6h}fazYgd_{a3?-Zo93t!XGE zcm#@J46gTM?2<;YM80oa@Yz7ZueDvuDO{|Y)ApDMK>2))Awy&yG&SCPmli_0VY<6P zU)FKDfi7AGJYu)mbWV-FCmZGZN41$0aMRMvL`C~1he(t-D*6kn9b+isj%AD@v{D6{ z+!Tmy8C^U)n>ewgLor+Kn$)>OnrnTy#v`1lx+|p;?c^Hd_Xb#9)}9o`LknshEu@mL+7H@`DPB8Ntf)EjPQit zEYy!Zd~Rn8U-9@VQM}N3BOWwHj|fSrqMz5XBJWc&_BZ;g2%nRT=Wbgf;8BqlAYx#%mP&V^kI`NU=BsT=uMvjjY+ zsd>;dLDbm7l)I+J80~4EKY-kh3|VFxJV@L0Jm`tiTRhh1oB$#ugV6i5Gy&cagahq5 zJoqcbt(7e7I}0zNTw}5c)fJfM4798r~G| zFz*!?bTvDtVaKquw!P zk{UETpZiSq8*nSg!37bWQ!8rKkq1D)O2(*?R|pIa!L&11H4V{0=KuNp;`Y&T&Wx4;C?a{ z{+oHzs1F=eOTg_*$nClx4EZW;b z^LK08j_IcCNU&oy8X(_Uc_nNUSE2Z zL7q96D4R2pq@Fn4SBAV$)7+pPXlew|0{z!N%7&uy1u{&lrXe<@1>yz6&mN6%%_w;q zNPvn@5=s~zWmZZ3oE0F<0Y!4(QNW$kT;S(gafW{ zTpArbI`&Q)zhK%PMgnQgA%}EKpT*av0nnJnRdcxQ=r|?_#)anpGj&MA8AO_s4$~DJ zO|}!em!F4S?s*nM z+uDAfDyL|_dmP4BK`cN?m(HY=xiPA%>ApkEYb&yo@?`$nPaDl;OjD|o78PzLBex!x zA8TCsFCWF4s z2C;7RoG~guY|8|}Yq99zSJTEL36rA#Lc!aw|6MC~NM+2Hq}Y#Ujl{&TL4mz3jqiQO zMS((_YUxpo2dS^gc=8+Yt%|;d<2v_u<+G6qx?AD3n+}E?4xhurw$gfU(hFDpBGn$2 zdWw=z7?Y3b{|3F4xM=m*<=QMdwWWp#JZkP!;(j65MDQ;o3U8Qt2*EXFx+72={nk7f z?D!{DtU{HU3oFs2j7{f59MWt z;L;cdv(rv*g46glGpaylj2e&_EagsmgW~EF+cw_^?uc7nveHlV`C>%V{#2nu!%rg3iv#}OmIK1XU zH}e8B9$GKwMuQA`_gg6YWQ8nEBu^T4)tot;V6wxrwV6a6RV=~Q&mwrd ziJNr2wLU}O`v=NJ16lKGzv35>H-9t!uFZg3o%jb$<4Vd}qlJMVVpM#izzJtB#7MIq zhOIXCpg}-7K66BhgY;sIHb^N20blA{$-^!J?KC24wpBW_KE*CddS##8c@dhOtq6)` zQc;lc5MMAsBd{^x@gC(T5V`HyVEoP=&|}-ONV$kxVx;bwFQa&*8QL6}WAG*Xr64z;$82@A%kFDUH| zlnD>JhfZg;wtJ;~M1@~mwu@!0GoN}Tx;}@nXuEah3CGE;;82!W0k?VOgpHX)TAlCD zQ)g`j<_vn|PsziQrNm?r$%5I$`GA50sD#6cH8k7$w+>_<$tafk4(7)^0K!m$)ZAU+ zMmok(^>$ByjG(XRg&R|P>L#Z7w@ht01uo8q=619-%GJvoa{(NLa&ShghMrG}++5T9isf#>D zHa|IBo48Hz$L^ofJd>RA>CcQw&vGq?T!;ktoFvx|(k|rEdp@P^j4ulRu3lgp{%liI zA4us_+Z!M)KZ@3s8dzu|q#E_TF)foSl0ic^5A<+H@xRduVg+iaK-F}l{Ws_~D9yko z#Wt9=KF;*KVIk-SAf}ORtV z4W!u{*B^ulQG@eOa6UoYIQ)v2y#F76UsvA99hy9|76d0%Un=gRcMv#3LeT7J1TZbp z1fk2lMCq$%WEb>#lV zn1(FFPAH530TTRMm``%L!OtvMBUK2kmHB%*ce$sw%EjmBf$JxAi^x)pcs3sM zAR8&o>gHnnM5mnu`Noj(OJ}f{SO+ zxN0HK$56~ZQ;100DcK#Hg~ifIc&euxJ6$Iv-O_3(i?GgSD#0<2zZJ6}B--c(^-n>i z`C`jQc`+rh*^K^zG_)j&IweW_)K~WxroVl*zljBDFwGo7^EraYj+eMWa_Hi3Bmx$7 zSBJ7F+1j?@0+BSv``aGAXkQ;Ze$k^4kw!#DL(v9QK;mp7fT=x7gv`l0%^{6P<<}H+H*9aazMX z;6m{%6Jn_ldxxON<=*x|;Bo9piFx<`84XLmWA4qn2DsGaB!z89c@-!3E(3QQXX88j z!-w8HPL;(glZM(32;jI^SNncFQwp@Tf~|b+%8=}$=e6vCdd56>S#YN(c#j~K1Mx93 z)$3wA=mk0S+W`~v<+$6q;Lph{|A1<@q4lIm7)B|pPDiEIrxcL()RJfm+Y zVX7dD)+$Q0W53m9Gt&A_N~aobc@VX#oVPB$?% z2GO1cIdV#WM_(0nUEY*4CY%Jg83T)Aj;+_}+Ab7RYKmBZQ7qa=sjin_s_B#7(%@XE zM0d2TSiqtsCt_@oU%`C&=#ZN=sj^21hjAjXZKCipvNhP2mG_gPd-V5y!={ROeniuW zEJE*Xw?Oe+mSEZ(+T0iH%X-K6k~Tzp}p|~5^scZ8tEAIr!bZ`5ACnW|bjyN5G%1cWFE7ryzD!hoIrqK+W2HYH~VC{%h!(q3KC zQe=NN(r#Bb?6e>3c*W;RXCt^gPd{%#s8&(6{+-?PGV>>l;5WQ-zExH<74k-xWN!E8r}yuXCv?**YqfT`+%#q{9pc-kZxyFjOI51JqMC7B$% zwg}{Z5_{{QVN`18Vhk2fN?q>56K;1UD_N>z2HIkb(MUw-$yg+?LRV$Pv*=8SZN4Ci zmzFkf>acD-bJ$We7yVIP-#IXRKI8?A4_#c8E*?H#`nuj=i$wo9;2+e6YL9jJV5;xJ zO4A(~k#;7yGtK6Cmj#K5Qh;lVB;SF(&PuArxx8{#y;B$(5#H5pi{YSWLacP)_{hBn z`6L6K&NzKHI*;vzD2Ue7Kmz4*RuRSyfJTzHgfi#9rE5i#>q7(e_=bhD7JkjsumyX|)Uf8@9;(f3* zj|@TP*kqbiXh^=G9yosy8`-G%1wkmDi!&UVIwVW!p?SG~#JJLrJU)9WF+zddlU!f9 zTxAM}i5j!3`haXtkw%s1VuinIIGrn1B4IhDhFUN*Cw=dl(tOwBNf3lT1|5Z|Q1JR)Mc!$GF9WLGK9vyyD{BU18+gNyi~QyCvFUGv z9S5IY-GCA#lP&Q!NhzK~9Y@|_ri-*~dbN~d6 zJWl7rwA&NZN6|obE`>j)a?RY&Oz8Bn#9=Srv&<5xUkw5S1)O_Pm*@W|4ANCDevn(> zT}kc9ZIAXA8ACL~%Y(rIYD!5KD)X+v_H`bj5SKnR+mhpDB`91=@HdxNk#7L=8nNBI zzLvpJNR>&V#ZwPw4QTM{d4;xk4xbze4Q3SIgg*nl!0%{XgPXE~8M-R;CHVp+uB`3m zOsL@g^g65fPEAmvt@0);g@0I7BNs0}`y&1kT_9o>QNxywH!_v1-CMwCXXPr>iKBqtssRTlnOcOa|>#gLW#NmDt17hvP12&uobLpD#c!6Z|nUw{ok!VMwRlbSM^+Dn+wdSw9tR482WxS$VSZui)k94qM#PE`~$uUQl?+z0V6B6N?=UeK;%D8jABQ@w4b_S2s%_rV0W2^Y7t1njO0l1}OSCvXxt|yI;!R@+|5( zJE-co&oXRLZ6%GH+FKTMQ)QwBZx)eC6EKls!LLt?C{}lk)m0*E{As3fTVIl=FY^e9 z8FWt&+EjeFI4c6Yt(z&yC8?!UgTQ6iWSw^l49SjZ=F>AqPEmIF1?s-Mz|S=)MNN1( zVpD=I{>r34jwzf3Z;oUaiY$stiA=KV`W$yj#t z#FkGPn$o#<)g1L67sZ=8OFlnPK|bMkB!(Rysx)bX!@8wi1WkcDoft?aU^$R6$Fbtf zkLYwzv-1QBV+8I>Rhrjs9!S^IA2~yU`eikYx$qfH<3Jk86jK0*j5)WqL~_YZjiyVp z;f_;sE-XySQPH>=LCSajqK~^`LpcO{9GY{}yvYt`3XxhmjJt4HvKKdTZ-E3=;Ff*T zr_y%i2Bcx{>HChA)WpedN-v+gUcrJ1(~`Bhg`PAR)_F%e;W;zStm4Ph?D|5>y-u`l zd1rof)MuVF3RIm_vYmCg=;Ac=3j=gq0>}jSY>;0g{mI~`?$UtV!Ns1_G#3~y*A(SI z2!k0hg_CAO=TV`ijm& zdWC9)Sl^Ug3|HF&5D0Sl-)K#)IuA_mc|{yFb8tN#R;;8c!R;J{z5wXlT|7Z(SvAU% zGUjvL!duD8*tKpJw#XCLt`B*+&DRa-p%70E+&&jSmo&n;1oT>IR;}-LgVPxmE6njX zHk|zQ79t!+k5$VZCx=`8+A+xP2Cf6uFpq+_2?YYh@hhai*>oh}0==#H~tKD>QhXj&j%+|y-1L`TNeCUzvSOdO#GA$lvZGDyUwd|4&$+ypIM1EswUo(e0 z9f0Khi#|dWhpX*Pu+kTBglaOOKDJtUQ;!&Qz4lJ;R+5A8K?Gou0Idr`U z)Yl-27<(Zks-_=}hzc7J}VqgxGJ zA3tZFAssx26guC?Jy-B;x~}6kXm3{YY?6Fee{?=96P5%80LAahA^<-?z`sYNs>Li) zn0G9%7#35^G{@V$oLcO9X^}x;+JltE6|x(BYj5^-lvH9RLoD&?kg5ap`M{I1znmuokF;--s+daPY%P&db8ntg)*qs>RAN`)h8aKF% zjFdRGyiZon|GZS?YtfG5`j9caV7_a?Dy zH8%@`A`*Rk6teg${BmHzY<3DNBOV;mp@=sgFzC9N14c%}Rl-b{WoyLp(l7E1x z@3{Y{k8_)cyy!Ykq$O9HAXmLYOD~aDOjPUnpH!nC!vU)(l{u17c%tkJmqjSc z+9!1~5vo?I2&tK*;5o>Oy$;a@Tl`+A!+*P|ariy~FUpSF;95~V&ym`Hy2>{*p}!#L zi0Q0GNr@%1z(^x(JUvyleDu@^+k=uW>-J_p`pbn`uvn;`i_BavO)hThyV{at*mC22 zTk2E}FBLml@snaez@jm6Q`)H(C~I{wKb?N%B6(fzhr+_N)yD&(<1PQ=mfkb3*)G;+ z7WwqN(V@I45h$G*v&Gw{Rp;3cJQNq@Xqb`v+r4@&ALhIb(yJ6j8xp?mI^XFynzt}` zl^hc@MEeK&G{d*M*&MBM2R4ejXDyc3!kU)5zdjswW60dDA!|UshEb+7t3K$G`8Yh&5;9@{1MAn z!2`e@Lj2pKU?_Lw6BwgrKGlm1kqfHEPA#}h4l{4-WMXGvjqHepif+`GVW48DWZ-u> zd}heKtX$9~j@L7T*wg7rKZC%N#HC-~x4}GQ{p(3EA|P)P;6~PAIZ{w{QhY^ngTC|} zndz~k@=TJ^4!R%bdFW9D&ngZ{3(M4E_JTsY;53=eQhW($$2#x+FsD=t-?}MprM#hNrw#{hzA3>QRxs!RX6&Fce;g? zlC1H(5fOusI&<_^;wg)%445bh9}KXQKqkl^n>*_RTpQFvB-Jf1Cjc2-e5VB32_%*! z7swlDafY8I^qChhKUtmWy33@D!@jgcW!lF*a%OzdmXmJ!c5h!#f4SM^W%M*yb{Fc$ z-9{Wrg}YBkI@QxzMEerOZ;^IPv3X4PT5hbkY^V0JMIzYT)50j;FOp&Yh8Df|z}MKY z+KrtYy6L$G2vXL|zR7KhlruK=2xAFQw{FaFV*F;Ld;&;vt$^s*e2<;_XU8QAGM8anLM$`GY0OM}gGhkKlWr5v zcW_tjUE?w%)vz#AA|?TD4)KeU6NX;$W{|lm{5Q*DVFBg*{=cRWf*KJ}(@MWN59O3M;4=l|Ge#-QQ#Qo}Hj{U(>{NRx!F1_z||Pz zL&EOu9C1uxh4uO;-Z^L`i|cgCyAjrz@joLak570ryzzX;uf;%z*R1v0RqMd4Wf!@3 zf$2R!C5A)E>gvymJIB71z!2IjjsF6kQByPz@POnt|M$7Un~SMATTN|rBaYqeFo07N zMiKZ31Zxv6_0}vZKijj6qjo2hSW!Xc4*Oa{*3!bo71TEd64CuFnfNV?s2c6HtZ_!k z(N(d|s*FTX_Z%zc%+E)~Q5}?>lqWvoOoK35 zt&*7aO>MTxX5Q3m)FqkYc0tR*@%;hqAYh(<5{aQ80oLwfdJ0{-~sv_o(CADe=7+F*oJ1B5uZ6rPaUG znrP7`az%9bFZS6S5Be!_0(A|;K<3*SM9M$P^P(L%Sw^ygifGMeW&8x2VCeoAM^IE$(E)AZ#oixXKc98fkY!5#L{X61gXP>i(W>lgpW z<+~?V0l=C83q^buT6u($LT4;$<1?S81dA_>)-|xsrWAdFxQuDfCgde~@k`UD_5e=g zPHa}?Vl(B)nHl!LAe3G_pk-*!O#7~$P<-CG&UVcX?nli#yso$S zl?9MwH=(vsxeBVEN@MJgFGx%(fG&G0mAjFsjZVqLK#?}AkkP6gbhbIEo&b+oP1zqb zomEGJzJjj8xi7N$kqKP9>H%B3`Q2FH-;@tFQVUaoySMl)+l)ruIG0h2$wFU(k<^>} zWN-~(1CQ{Yu8Z;KXaB=9dsDqL+)jkCQ1>46s_wO~davmlNQp>SuF z_KnVGdJd;vXKn<2gpV>@QfEef9*8ECx5aC3X#N7s8#fE?l-- z5FAGt`BcIe25_fW1m<@q9p_&F*o3&;)JeqelU$>ve{Mz`)eCIv!kW2{3V(}?rl0>! zMh3>6G97Vum@A!~SM&|L8{bklXKfvibO!(gtc;B zuO!*F+NTxABW{I~qCv7a?FsveZ0v6?BP^M6WX}<26)y&}y?C6z#;S|LD{ZD?&N*1Y z{VHIm-A!s>8Nnh1H`jR?o{=v+mFPyMVc87s>&!t2L`hD)6qCkNk=w+_gJuoeiCqa+ zRDiOL<<;;M?B?D~d+AI@*?RUkdJopjye$gi?c?{k(-C@V^7bi_y8C7NUqAKpOZk@%+&!t_fAVo8 zS@m7nb-Zr5WL`x&iHO%x*?x@kc`8T1es2dMJSph&#ug|gyqP4`)v`HWJub~ySD?fJ zJFOfa>Uz9X@MGCZmdp})sn~hidy5AGNqpu`v?`DtvQ8O%52;HSjq8;OB){uB>@OTXKCm%=Cf@@lY#A z8SUbMR?DL!(}2xnzvGjo<2d=X4p7m)Lx-H)Puk00|2v$nT!k3GU>D~L^tLsxf$7zR z^P1j}oBetssAWV&EQ|I=ts$}Ij7(h&MoDOzZj;H!gg{8{YUx!-J^}#{z2#z8hI~gZ zJKN7LWb%M*9pVj4nU1Nl+Q(RWGfY+F6OSU9PH4Mu2KjiF_Y>V^h^m29!SIBLf|RQR z+Hoq3Wm9rjlbWz-6RX8hPK)(L>MtA(pIu_AxteCZ!|T7OZ3mfH?}Y$pUd#eDgH^*WPIM z50YLf3l){Yb=Z{mCu6gQPLebAPAvtmbb&pUPP;3N!s@kK^8^bt*@&G$G(`XpFy_KC zmE|pWnQ~cqU3XHuVanzd*R9f|c`({jV2tIDM}qZ7N}Aq1<1<${gU_^Zk-P2_5tfEk){ zJ(e#fo{$twD zaFF8Q?Ly%T9HX&Ah|ftZc#M+H+p?x)9Q7}zb%0BHmXt2N8hpQ3f@q0SeFLzq`%{U3W1k5k-l(LDuA-{ zj~Qv{ftv%SK`M4kLpRE4u9X?URfGjN->hUNm50ZaL_+szzRkYbUn2E|4@)Ypondp2 zanXLv;=BSi{(6lJzX@t|*@Z*#pbjCK--K*hM#xV}oo@0EGOoP4-^Reb3jIr`?rfaf zee=D{w2~37eBZph*u7bH@r=rF%iB?CCI7X7hRQHV-;1LA69k?ab|AoqdKioY<-2MM z#!seV69U02rCqY6K0f=MJW_eV`UA|dS5yMN6gs1*-X^l9kVP@!BVlbz?}G5sZXjYw zo1RhV&flQ+M*|B_zOUWlR}Cu6w}Ei;KX@8L)~9@K17;1(wa=-HA1LuHZ`FWU#fsd{Mwy3#`b8*t;JA?&6d^%{-iEaf|u<~HzZw-|*oi-V1u`JizDqo>QU-~@?Lm4(C!IJ6U;^Z*~@ z?vt9iZL6NTds?DJpP|lLHZNS8S%E$<<8M}D4LH~E9HW46WjxHrO$MLF`!+a^v_xIk3*D$RfrWOHxb$x$npds#!7C9tjv=};@2w{EiD1x;aIwG( z+LD)UGhH8yXanA&Rec>M&X1b3fd%d|32b{fLlgEh>(!<*1B&AzE&xck_*9T3Eniah zucgiI#AvAVi36`V*e=;Nx83~BKw?zMdOBMEuLt~O2tx9*;)wXJrUDd?7xDuKq?70X)9b>M%& zh6Ph8GhZcd98@vLFLD@-G~>mHL7?jUCP_GW!&!RApO3`tc$7)I#eKmb-=mQK)@vQFcU zKT0-*eI-Q5+M%U8O5ST3_mi0%GZy>bD9qcMOM|_f-yJDTq@obS{--55cf zSJ9Zk`C#s@i4l39DB@tDw-G|)J1pd6ld#>VU}>`#+#d4fhQIheMl63;uo{Di7c;dx zKLV0Lc+^CTpOu0nUpY&$oo!ATT<;qcoH9npOlgsnW`ze7$m9YTBB2h5|B;16`mUa+ z1JuiE;MOMRcH?8?nrz7-&mHD>_MVWk1eNf5)(vm;`ksI4pu;M-ke^u5t`4P&M`uc( zm7Zt3W7@d#`6iUPVQrx(Z*c$^FQ){O+Gn|H3EovN`37ivcWP;LZOkC){KQ5=WmSw? zO--|u$|CH$t?OM<-tH?TeX?8at#c2bfFZcfydaA;bY0-@uq*o$U#F2RP-vmPKGy6r z(HY+zIu4Fe_>tsdv^T)H6U{&dLf>j4nm+C+Pl^Pbet%6%TFT`f94v&&sms~;2;}?~ z^3ikhhbtIb3BIGOTEq$u4!T~Iv$L#Pylz&A1f}E) z@B}UyrZRSrEev~~*wO3_z|YXOxHs9%Cy8%{r4HHZpyIrLqvyzVG8XdH043rUo+RNC zOnq_kHT%KAvBgWgiNE1tpq%P!Q_Ko?$CgGF@uC-Bor_ero>DKrN&uoc`F;VhFT!xa zEw!85r`^Oo(>@bf(H!H|!iA+nj05knS(H^T<+aH48<}Dr7Bk$dCu&Fr3#mveKme2S z%~Czki5r=oy$Kr;32sYzAHc#Vm33)LHGjhH;Yq)6Q_=c!{}sSk0yID4>j0t!>QtT} z*x<;oIZlTBJo;JT>OoA>L$-3&$ArGqp!pKyZ_C3&zaF!UF}w8N=f^Myjw#TGiHHZ$ zug-g}K7g1yBg<(cGtAnt5Ie`RhE*>&szC)bZD-xMC1m-mxi~3=Oyrf!MT+y9r{2TD z@}kgylpX~xWajFHZ5ujp*mbzR{Ug|MLwW}x;(ngUVPeP4Ne4Dcy}{ZGZNt zzELSHQWz>Ys!tT48WVO0$7yP$x*1RSmclz7@=?4%866QrDA+0;TxvfA#^#a{495sH zAj#mlH_(ILF9_lf8nyi3ClrssT`^MhzRddk&&Um_4(~In=^roj97|<79GH41ce8IL*&E(1~_V0VG%O7ep8eYRK250;;Lx z?U;e99X}c$ClCT8ek|3YSeH{Q+2=1i#bv0^SqEqUI4D8Y)}@gt%#BWL3pAe^a2~{g zgTz3EOZxv0&M&>LF^fj_9Agvi3<4?&dd0!CX}iw`yip;nriDgtRcYC5yZ<*?U{2&+ z@?Je;J~6PB005#R`3ci$Xl&8(9EDmMbX%vWB06kk9#29fd^(9XgisZhZ?<0mwMoj2 zz?3LRanS(nwC2dDYzQ-rd~GO^o5%nf@c#11&X0pBUx0*~=Z6jZ?3g`M-bW502aRXj z&N&?Xc1NUbPK?00b8?_i6%60xZ{X`%xh2BFY4jp8_rQFVf!JNbfO;*(OM~djmL1RQ z2;g$;@!6+%k4VzqNJ7J!-0&D-2f#m+xxc^p>i*bN za~-J@ltL7>+4_}Wo=GO@WcVBB>EMSM!m+zAan{*lWhh%p46FgIX<7}{C<|w&h+UCY zknp)$;w9ayIRWZzHNOuve@GD_y&TsP*q{l=pY@bP>%6QZGGVs*tEOh}7$Q}u)cKHd z^#q^BH^(iJTQHfN(hl>{^n>_N)D^^X9OuQTg>AaKWVUA|T&W$D5}y0RNfGN>aan;Y zuakbUMQAFa8t?>po+rKc7w`~uR(idFliPnSpO-FLMKWMCqKz4OpfGo0o}d}&OsfG6F5q~tx5Ao(s%EUIvrx(sflFnx zmbUiHHMV@Ai4n$K9M=Kn+M}VWm^}egB9E26Lu3=OV?39zEqXT{CK~tV0SWgim4ig> z+}{`epUUJ0rQ-HN8-mAn+aKINH%mb2l3;=eyE{AOkNUxjQbJyAH&e1&tEOH2+_otF zs?c>}geZ#F=Z=@yno$wL`54GPj)1CmrS>Ss)uabUTEq7k29tFsfH7L~@|ayp|Z75wdGlqz2JjBO}me!M7Y z?nFe(GpIOy3+);hQ6pRq^IyN>B77`mJqGGLlBLV7amzWyDzPGmv(D1O=bmbPPqQ6Q zRX$g6PsM-0?(PylYYOufr|kj%N2o^N$K=+Km}n0FcxvMN${~ z|KbNCdnjw{S%gUl>qsWywJ5<(Ng6d3$CjLPV${+1pdID-2DtavWR$8Vp{obj zY3x3{0)&_Q3UMH>*H(=2&yD)^z8~H1aXR~-JuAPyc8+FS2QpB`|4vWRN)1pJ(a=V+ zMkD$PoX??zAKYcW_S~_&DIY&Gbyzn3!<}fEdRwnY1se6auB#W885C8rR{axLly!b7?ZiYL!RVfL@<4jLapKD2 zK3Z5&bBF1hE6SmQ&da+cURn-(w-k{Fd|01t9}fFOOnD7 z4bW-ti;~#EE_YFh?)+5+m=Fl5&GrS23v&IT)-s@DruK zcx8JA)jwV`@;~Laryon7s^c=~S{p4xCz%qOKB!&SLVuwOmlJ{|%RnyZL(w=kM#_9# z1SRV^r4NthmdrVqhbr%*-!Y(ukb-fFLDocIT#=W%f8 z*HxXbZjmNd3DJz%(xLR!f38{89Ry5gR&Thy(mX3h%fkci*%%4p!blD3Zlx7ZE*5Lv zy@9j(vQpCO%?UIX(?G^R0)L3?;MmaLiIeSoP-yJFGmN5*)c=I}^|#jurisj}(S70$ zk1^MT zhDEQ#%l!&;mtqr1`x7@z_9)z)lRKG3{C?X0S8*a-glgIWz%DN#-}KDjeh|{{N=t@@xJKo-zyjYQF7UuF zOzsO|FyElRuhruj8NIe0ZGd(;d^mlrM?6^pTxeE#@{ueJsRF&#+ZzG)8+A&+gU^P_0U^FaN56rXb$phnIqAz4k2D9HkFccfhu!J#D zh0W{lF03G$SJR8TE0sZ#kJ%Nz4H~hxU=E&yjlA<@@JB7yza}*@MC*0Q5om}EUfXoU zn<|abY*eFVdnbk4s%FW*YGMS*;)8{B2F`Zt6&jMfK49X&0uqWzYcu&@zr(T^7 zzvald_2$z12v;SqU8E32oj8CC`3cu%z9nCGaB(9aUe{6hSt8)!DtWI z0y|0)P{7Y|tQkW$m^pMH1byQJUWCS6#+Pb@%rJ*@dARE!7>0>j?UUfPq=AZ@Ac;a= z=8lT$83QdnyT}fcT^4ol-r*B%1>bmFpR;gz`Gq zx^)gv0!$^f>pKY;{ScyO)|Ec_IwXr9B7%E50EGDc-rY9KFUx?KP7A=p#S4?v(4%iu z_+Z_#mLuo#lA}R`DyX3(amlih^$Dw1p>_1UheE=bSUvUcFe-p~LbJ|eX7)<7djZuqcuQ_Hw9?@S?@#wZ~A zq8MAGLK+oU43+z@4uA0n=eArh^FD8z-&MAeJE1I{Qz(cpxCL_v0p7j_p#=9+^IDZq&mdj%fl^M$qz zGBhtV8T3%*;c@~n5CFYK_~eC(CZ3Ce%tmT5FhLpNR&s7bsXZ4ai?;}ANd__84T*;K zVTHaj#Y!Pzpe+wI-~^A&Ko>F|(EfWus~jk~lu`Y>h@J5G<2o9Vx~(8xqyIVPX+Yn} zR3{FDBiaePBU4`BU~8>#VKlFhAywJl_Bc&!w;q7yf7&1J#d4}Aq$77MZiuaD+XuPY zZxXJ;P-F~Bc7`A+AV1+S@V+|kou-puBVUbrW90|KrV+%?kWRxVZl~r?BN@_jA^=<& z$>5>`T2*`IOFLspxOr=Kt&Y10C+el@#ikJtWX^NQlod?gd(b%Ggbi;GPkKj*WEl~o zZ7*uKoj28?gkm+@vk>M)J`O>trekgJSO}I6V!Hj$KW#%x1KYPI_zK*t>teOQ<-j-b zX90Ms*~xngo?{VDOSVYEA#aWqe!=`ndwba*Z)AchS!I6J_&th>gX(sLP$*q%@0|Xr zzqyLuA6+`gA+|VOjPT?!RQd>lU;g3%O~+R`8A90gLqKk2h0)x>=$dEZgUJPj(EJt6 zLBU(T!~N%Dn|=3l z#dz_#2;M(PZKab8cghkB&~i_!7gO8RfX&&v%yAv>XS&zNy)v|;sy%V8h1Uh3^%k>> z21i{C*SOX4&5R^M%9NNMNlA96b2guo)JDohDiod>Z$en-lE)08OH~{zO?%zx=0NNBRg?V7mNy&=`QJYA z$%H)c#ILO(;mrab#!ut&A!P!8XX19CN*SY@MWKYjXy9jgfb7#uH~=M4KPIU^$fx;n zEWFk<<}pQ}c{o~*;(mZInV5A|v=Rx*(ep#k-*LEt6lFB9l)cDAq#4Pz(81Si{XX(fqI8kdo!G$o$3km`C-MOD$cS(3?HIP1IwYzhW6co_W$A{|20O zqGAK2j!kKm8V?C81KKlhw|fUP(c4nX>In1lq0V`CWP-B6ISkdr2kC-u?+02RHm zo(rd`wMtTSP@UZr(wDKq?k{qeD03@V($tl)I+QWVT(KS~CB#e66Fv3-RtDX4TYlNF zDTmUn*HoaN=zaAlt@E_TUrKntP3(9}NnEDj} z_ITpr%W*V8H<|Jn&YWX}soM^Y*flAOhI7yh7*#ch}#FbtIznGX~PWG!g@i z5WE#6NT5GxT|m$49^HlYqd-i05=622HtH(9jWI2zsnnx+dE2XNp z!De@y+JTw|B$fRUXC3~QuSh%QaB)b!uw&fIyc;-N52$L9K*{um1YhusSr}ZlsRL6xa|ENC7U=(;S-)HAxA*AWGps zW_o+mw4X>_553nRec~=qmdu`)1koOk^W=S7i_A4*CLXPaKUlUx7U%OK;BNsMsXf|R z+yDH)ij85^ye0U)Sq=4*TWCye4e3n8DkF4EPz@Id;iAqa1I@|M?CG$YE#uIm-iWEI z^J7VZs0W3JyV>;E)Ql8L4-UB9mt*}L78Y|^$55yaj&&(=w_v(&&74@0ynXx6)jb?Y zCNlhv8Vp&Crz}+-l01g+leMbsw%2zwi*&Q@TO8B<$w^S6>X{cyu9mewpDzg3i4jOJ z>ScdulHaCxTHh@Kx%qLb*%GsB&x$|R5&!bsZ!=LqkHHhA-g-b5(?12^Ktr6HQ30jUxCdBvfIY=1f0I*^2Z& zhTciVt0|V(>z>|4?F;v1GONhogiwX&g#6@&g>YEBPuYF5(DjQYS(zYT%$JH&9p&z4 z7?y!Ccx2v_wHoSay)=w$tHDEd;j1wP;zvfmFGSpLo6hwqXwz{?K@L&a?KMh>2yp{& zUCZ8phNi_%l}j;dSDyx69>+BKUGz5S)Xc>Uah1W53rv22g&2TGj0(gy}k5rZp@H{Wx0 z^e7hv_e2mHO^>pp4JT&}(#HJY=^3Gw+-NqN?wBEx`nU9T+R|4U8f=>7jK@iPVkg~$ z6Uc7S!N@m!Shf~&!~{GXZ9UrU*95%C5R}gTF*^649dE1@c?lEjg=wSupay=suh(Z> zryW^_#r9u+p5;kYv%NO&|LC?ri~lb#D86PhSLm8lB%<%-F61jHC>+WaJ?zA<$+;;)Lb;v&14s)1*1xR~29{ZxmC zd0&GCmFFQdrMfjz$e$xoV4$8X)#X36ufui^PO#YAXr9}7MSzRHA6oa>v?oTvT6dR< zX6w4#8P@C#EnU*6A>k7{Du}0_VYOlRo)!YrFNY+PEP>>Z?Av~`4Z$UCr%=JQxC^x5 zIWO3;zwd8Oq9oj-1G;`QlWb80;$(OCGuFKb&1X(I&idc2(uSs^N3Q%wbP!n)hfG=@ zIW}kgC`U{t_n!0?2*yty97soaz2_Sx$U z&>FPIDhCJ1uN*ql4THyqX`t|+A+dSnjo4xGjxs2MkZG#X^PjBMf06F$a_~WiZMkG+ z{)b>GXWQf;F9!)+d=L*S#s{_4$M#EH-*bCSk($t=s5ixiQe)bko=ok#ZuQ^p`!zlc zr+=O9;*#>qjjT<^_qv;Fl;k^?X*1>!Me*+lr*G1xxYhCWK-rhm&sNMh+X&NwIDw|c^lsgWTJn;VcdYt?uYirB9x^%jjU5nK!&Ay?&yZ%$mOP;gqvzs zSySFAiO)hL2mhm7QNBJX@IHPoLJn8T;bf3?ebBWL2xN7qFqZ&a*RS0!OA}K0&f}`cNHPKpJR&HhP1`i2gAx>Lb1=aG|z#PT>`U{ z_TYN%>g?m9i4I$k>3;FUf@!a?>#0Y(oH9&GNT zTNn4Tw#3_2S*XP2N~uAml6u$S?$yH) zR`14{k>V~1Pvo_zhOq97PcwaaVYbaW5_t$Q<-aCs8_VT2u^pDr&IzQjJ!Y&H;76}Z-Csf z#bv!-9&bUB_Z)NZZoI$cx)tPjw1g92WduW}F=kb2M3cvrM#f+5(mBL-)Yg*|tC*ds z!nrZ$GqDkY#@a76df5h9Z7TSxdwWapLA#jPqa<0k=#RBw2GsRd>VLy0#SsbKV&@GV zD(%lbkTEm%%ODAT6=qFxRXen66RK#O^U%o$^NIzpn&Hm|k!|4Wu4)l5wa1|Ol*7rC zLCvex4PG@EZf}U(%OY$2NhH!w?`V@$q!2&6#)ORRm=Zg=UltRvu&G1zC2X!(4*#s$rUdFno~#PK@#@~%+SWDSCB9%=#v<*u5dm0R?KR^!te*iuAZei z6??S{bRD zsnRJ+pM3umy1_n3> zO;mrD$ve&cs(>a;$-#+@kdmVO6-kk<03vob2gIE2E@%VMv;mO*2I7GRp{8Gcu~iaC z>*13!GtEowfCOVVXeJ8`750<*9IXr3KHYoWHXwyzI_Mk`x$g;Yhe^Qr^&{5^a>VJuWypi2)n4X!rNJfPnN69dRit+IWl&YBQG&-Ebu1~A0B=hp zTQzey+D{m>jLuU$fH{%=x+?oZn%$LnF;QKwiFeqdA%=Ltj#UmxWvJBW&yE!w^0zaK z2C#ajk3#zV&T)j=_Y2+G?19?X* zCQsh=#xzK&f6daATel{cnOh8omH{B!fe`seL5big>{kP+KGZb={7B%L!~VQYKMlbj zcw0%<21+x(v%R4NPv9SJH1MJZ$wN)tM&lrtrFo+o>}L8`3y%|m9C#LT?MYFGc00Z< z4S=%Z5;qpvJhaa3W}Arhb+P|_L^huyw>&gw?2avx+#RmkB$&3^D~^>y3LSO*9cF?|SGe8@@8x4&ha+u!HHrrT%pTL8NGSMR%UHM_$jU zaz%Wf2h}0ODFnM6Ndr{``%l$viN5jm)07(-1HX7@;{`srEdl^8(FHLN&H3^NcYfF< zPwkB6CL1lczlofmva-@mz|#S7ma z+6ZGUUL@#|Sv-rq{2eESUy*M%fJxlrzE=7wvO_eb6XyrUkkd;#-<=qd(LWp0n z@mc&eg%3+>s=1zQkaXJEvbMT5%KuB!I!!x((j`3$I3$cIL)u6jS!vWO--sx#EpW@8 z$a!PbF^2#&Cqm`8y3X$fVN4vtSyc#}Di)0nCl!m33S)n`U`SVEP1vnls}Nvr>^MA{ zh1kZxoL8j$;>X2!F{RU1p?e(XyT7ODqAUcxCZ`Btb+n?FyaTgsYEb76K?~Aqfs!wS z0~Ie^8Kq49>bEPLQ@oWk0fFBBo==$uh6dCMtGE1lJY5oD={X6h4E(K9RP>pl1&FO; z^TebZd8wS1JsB4L8H=N82`~AHnUwE;$s0F2U%be=d2J)eWDaJBA|nlYTqzLooDGTt&IvGxX*8MyMmN@Sb6eMF(}LD7me zqyRkI`$(#z&kwm4_wm^Szb4jE9k=Eivc+QVsHJ@25{cW6F6a(^k@rgr&mCJdq7Uaq zW!d4@wbU}Hd7}Qjkmm56@HNwP5Sd&S1tlxNr-OclGr$ch_vYokMEgU5z*m+zdh8;S z7Kk@cm~ei^lFv8VS-baf+y0*i_=>i2)kBXP96FK3;M*ShZXW$ql`$ICxrqn{Sz^5v(8_v7HLxa}2eQc>WoMxsag%)VP5Z!RU; zYBaLtj+#ZuUa)&ClG)^LRbsr#f^Ws$@bG3bgnz!)pBVq*E)j3Ay_mlRr{)hrx<6ci z4`aUsL_==g74UoN;pac}@&lvaxm$N|=P#UN8)8g9xf&0By$2V#HH&~P&1M?g1NKtX zrLVf!-~p&jf!_~j7Bu8PF6xl*Kpp>)3|Kn(`TU;FXucg`SQr4z%Ai|=k6abeO7e|> zn%MrwJZldpdCFWW9>cO|om)nmE}JT3T%KvRtmeaG#8Zhx3Ix{>u9La0|2fu8|0^rV zg`02YUK{$GS%MJ8G*T8C@?iJ-6skXO5T&4Z?Nj;v#LNY*&~=DCd0RMu11rAiE7{lW zovW10bxC6ZY7)CaZLm*0M}>P_ZgYHFQkl4j2S=>R`rbOLLP2 z@$w*Id*41nNdQzptH1m@1efBL+~BoKaSRz2xFjh+r=rM|MPNV0oc@=8obJSdyW~>- z9^cLB_`|v{SQ89n?BE*~2IC?i(YS|`C>hTr``6F|*A%3SsC4UgTimR&0!3iTc<%v{ z(gWI9RM+qe<*R%k`&x|&LdKI573>VvtbZG2k8r8X@eFXBDo|4$kJpTa;t22To3so( zi_YUlcE)RxDY(SV$tR(^BU2yt)&Ul$)V;JSb`g9;@PW<#hYsmD`Sp^&S9g!ED^Mus={@UHIBQmKAg^$vYh+`-F zozw~sF$eS-Ykog!UQ!!B#$uy-!$KFFj!EFIJDyy74_3jTlzBZgk|*C0*h%*21lNihKW#XRX*g(EhYt*+rh2PYQGB|Hy}5FYicndDbV#>!!007_-6|5O$^a(|P#X zA+7#La`0pSxTXP{`hdb{-YjR4&1^?ex^|&Mjoz-9Q=3u<26nE&+FAt;g*_$Sn?%S* zN(3!AFOE>G>3@so(FS6QW^W~F7%<=9&OyQp4Uz2YD9J;W*gB%G8~-|!k!~H!Fn@pr zZELSQ{GI78jWa?4wSuHe`(qZWXqOE5N(z5WJ$WzjtEU{gXbVLE&bn+3377bRnFM$N z#n%Zhnot7Wpm`;o`KY;geKs?{1N-3v;K)2>3ttdn0uZ+G*4 zt9${&R)bn+j~k_JDDAS+xIuBj(E>;X4=!}=?~V_BcJUh4O(vm-nPkxB~`0T%O<_iji;y zx2R%3YzT@!d(V$L_Q{ofa_muA>M*^947T`9fo+evjVsjFuFOw#^jAU7NtusZ(Zqj2vZjh(wPgOQe7-epIYQ-)np zfSV5bFA_@2chni26LD1}Wmy{UY0Y`GB`lAeJlT*M*fn@CCHp(fgx)I)-W+3$RjoRF z|4S4AAM7W&oay~}Rfq+Y6TL9pW+ z!b=(K_{rBc!MLTPcoMH&Ng#g;AyVCdC|iv;HmlkFp8xgVFO@Mp+wf^&Mb6(;*eQ*7 z)m9En1e2!XJO!q7mtqrimvhvOFf!tYg*rn*m#*%3C*rO4;9McfK$E}9&Sn{7jHOpK zEJFRBHST`S0L23_t&n9`buP(5r&&%=iLb{plgz63=avvAgRVrc`7X6`tQ=PAnP_Y8T} z2?K!x)O*UDr`-K`zJhRpSg^K27l~$`-HjE4OD=@yVcTdzrs{wVK=65EGs1NnJLdIf z5W*3^m@kmgT!^c$By)?>oV4tOjDy-cYBkM7q*-IJ3iCkT1H5U#$llJ3;en=P&P0zp zs~9&f(o#mPzT^EFOC8z19D9hbg)2(3DB~=P_{MJ^s?wUBib;LCI%+0WCpk`+jf4rz zUu|>W^?>{H!K*QSuwFC@j-$2ossklMC67YZAC;|Pj0h{e7QU*3#lL_&JMI+t zt^N8h1>6x+$EV&qrb~}>%QLqoI-^u(vnDqzeAjf@-sl8!idx2#`4$iGZh>?wTADe& zN-nk>1tSnjP*~42%oN(EFf1vMeHBi$dMdVn-?wDySQ}89JNI*_6*{kh)D)oOk!~Q# z7Dr61(#2HG;uw5Zo)=5QUiE?p)6~id1k7V{`yi5YlITp99u#<9h1~S?)~BU9Vp})C zrSVEpNONC!gp=6B>SPz&GUwMwL6Qib+_xNsh_wtTq^c#LF8&nz?AsQj3BCU5SLh&8 z@@)RCB@o@L5=vG;NVtQ7__M&K>0?%F4!7AR!bc@xj zQF}0UKAC8`S=l=|adf8*qm?CwNDU-cr$s8`mclQt)Laj*r~p#mdb}7G9|7Tu{(mzC zp^O8L(UD24gD99ZCer(MTKXACQo7lv8m1g~T_M)8x>~+)t~m1L0)!rXG%xkvO9xtT zQXw-~~fUlt*0ski4uYh^i-qLT-t; z;BjE)NFU^A|NQcJ*9{%$GQyeJz3unC*H=f7b~?1iejOy8$ROR+rbXYlJqR&1!s2ex z$u2i(NgEb1u-I(e%TkaT{6-K{V5au=QVURD(K%9_opj7xW>|QPd6PXYA>c=86xI6g~%( z)kX}NcgiijV`}q6&nxdvi#bgNNraEZ5nqM(X<~tZAfpIcKVCRMJWRSf4g2h|sT%Ih zJ2KzB;F&%*2=l??9Mi{J>lx@XL15LNVHX!}9llfF6vZ859`;a}jIdvEpVroQpGP+5 z;O(#AEFG|cl55jjnhE;>d$fK0%snE$J2=BiNR&qxI#V^6U{$OXCUC)n0BR}^C#o}h!c?Koh_ZoIW$7m*#(np zm$%vIui$>=mi1@voz{-6s~G88b2BuHh&_9mOK&PEvy!HqBt5Y2&x@k6DoKE^aVBCu zNA?rib3Y~v^Ur?z!If|rz(GTr6qEP%9!yr8`RV{7ewLmsBnwxH9n9p*0SNBMarmHB z19QZFJD2KyDrODDeq0?2{jc&))EKS#<+~kUbA={zDTwE7+T2oe_LoV3an_CMb#l?GdE z^MbOnEw#sH&&yjR!_1;%Z_AI)YmOWu(ZrDTpGn|z0?5hG5$eGX=Xsf;2?Z$LI|;6uXIKP~#86J!%K3i37kIY|uz@H_dXY=Wo!3H(P&w z4&!>_7++MNF4fTf?-9~9Mk+9rlMQ|A_mjt=2YNML$afzmm+N+>p4wxZ-e2C2eKFRX zJ~G6HE!g+waByFq_!Ze;KQ1=_#TzfRQ+d7EQZ-IU{Z9{Vxn6lc}Bh5{j^j=CGDE zCH)CS+J@1B5d+!MwMt6GZ_h0G{v}>7b8D;>edZrl-S|){x5-dqo8ADAo$obROxp8Y z<|^zqW9%!v-QBX#(7L5PoF}U5|?`%XzGuDVULQT8`64#_D0^o0ahnm<) zD02Vn=L}2LfZ-LGaxbl5mV%K7h5=Xh2F%28+V|@<7)2CX{*1afa>aMKo&02i>dEc{ z6+KXWm;d9@cclDw!Z%zJ#@Ru8-mB~ud@$NigPT!pBZwU0i3GE}OG%2l ze8RrmDGwSR=Ad5|;!#ft@kn(V0V6${SFp7LpC0W5y}sLgVfKUN;fPL1bQ|%4A21b) z)XvZ{xn;kKWkid`SWqC((m#?T23U0U$uDOHN_FmMLj#;V$1Fcm@7HFSE{S$+LuU6z zz@fO{EUq_EX7B=<$!Vt>5wNZD2_q=ELzujoR2`qr@seRM$Pb$(cDLgTYs&y|cEIH< zC&Cc9=JzJSp_!g3Oo7v#ezRGWLCr^Bb)0I0GnP^5xdy{unM{1vH-d+Y*xXNu&JKR> z;9q^ZCfDH=hZ+M6r_WII#EBs7^@@6PuvVNq3s`Dm8$D(m36KyTBYkf|?Cfz&GZ{vQb{bq(K}gtxN!a(7UNZ(ij)U`QVM25hjOA zK8G?I>S9Z$*+6<-F;)LII_!{48WQ>Ak{wQ? zsg?gZ3)jyez8Y-hJ!z>sm`;~t?C%)w+nrKdNwy^gmHUNbtJFfjbE2hOj`FelEpfbb zM6lWJZMz2tr1_``9pk5<4MxXM5}`^SXpv6f8`oS3+&xY+|!3Qb)jmZFtb;9NnLOq z$g@MnaHm@XS>=0@#Jd`4g%#&rzOE8A1a$ab+EY?;|HVjC{GiR~4!>(v+qO>ilxp zsTh}g-z*MbA{E4<=}yC%f1x)$_BTWrmlIH zXo0!n{?@_?m!!ay`nGBAl^~x91F5|6%}m|8#9i{V|EQyx@87---ZGf-nr%$+F@hrF z_=h1`=TrC&qaSw8iLkHvn|2{FNK0fxWUwkxx4-OV{!R1d+vsM&FzffC_bFtav|t9e z-%X?t*FUw}9sIxTb$+}A&V*ER`r%)Bm@MGXXc4UritSoBhSn}{R1snr2{WO>LQbFzXu~B6qf6UdK^& zGf3gZRR8dKWR~1V!?*H$uAH4wskA;Y-;)=`2X97P_wJG(q3!wW@N1)0oq#+nyCM7T zK-L7*qZRK3GWNO9QGot`{gF=nFYA6~WUieN?)lw5%NJZUZKyc_U-+KQDMy@%nZZ>r zJ9$r)^Rh24l z-OR%VLa#1XtLJ@$sPHc(n)PqkSp(v<1HGl-E%cxt8{rg7XOv_5UpQml$=+SF_F=%= z9GKS?EQM873Wue-N=qWbh6+lDuBnT9z?JLRGqFyKf*x5zUF+&JoJp+_I^&2>%w}~o zu3g`o9wjW@OP5r~zhCs_8@MjRvh$`i%#H=^=nb;%%8J?~$a7h^AOsusV7UucwWl@D z43XYhg9zCdPHC?rO>cpHn$I+3$HL{waz5P)dXNgFs%v~4jsqAMkf3-q->9dF($WB?l!-??-YAtpD(Ba=>EQz{UD7q(3{8Z_beP?OjtRGk6eF zGoq5vAi2rCqvoY9c$0eg8LhY|W9FuKHXm-0D4nYI3B5S@XTF?U?YchhOluPZ?f#aK zBrfji_syzKqCrgCn=|ox`)_kD6JL{*B8{bwrcbptOvwdVg(5e>sr(DGOv+B{gdsc5 z1p-G8@W2gfHSpJN)LL>N6j4PYpxu^8KC}z$mE|RV?10mY5_46b! zO-jg7tmo1~*@Lwrx7Xlxky#O7iq^$#PccYn86e8s3tE#-82fabu7n7;Q{#_dXhQN6 zsR3+k#}MZqcjIc(HjDc2hAJVCnl&GppUNoOe8aDXik^mfnt{hAgwYnri(o`s+BW~+ z>c^>_Buqa~U*NkG5oZ0*s`%Gw`)%g!k)jFVFE*1<<#NG7nCvdd1noz1J|%VA<{@*|M`|WF+e*KovsEOqVB` z08A7ix_PEv>_hLtJJ&TSiX&_>GQc<)5zylBJ}Q?`&9Rmkadr&*oVEyZ#@jB$L@1~@ zg!%Cr%+2>~R#k+M=P+_c6|6Z`|G zL}cjM>_oN^mTM3>06j5r$Hxd^k`>oeDR#betrANNE}2J6S?`CN0XXT*ILuRWF;fys z0c@uuu0MXFh=xeAk6e?7tKx-)kPw8m#vO;28$`9v?bHB47T#j?uwnqAA8e2j;!SZP zfZ~!nQ75^F-m!|BT4tr1qCo;iVB4l!a^by&M;fa+UKIo$UC7<+k{Nj zUZDukZ)IxwVFxyoDHUz!w__#R(VND3tJDh+$P8XDw@T|miBmMbitPPGu9P1h? zzds2nu$#LqFntU4Q*$nbnT`xh{L_^`KHJZ+2JmeEzn%Y?-cjo9l^#VF%z5QhLEF#4 zjAGq5cd9MH*v7m!J0}<22NG&v+w5_ft^)B!-cY-%Yj`hz8Q!p`lk=zE?sx~BS$_)kH2Rw3 z*r2eaS7K=J60SaIK#)0SU=a7a<@EB-R@V=Xf}vx5aV$Ww{dkfnf|r{_=1X=Zg{fMA%pjq|> zn3vUN*LVs9Gf5~zKlZQzWG~CqD=MIyI_9^=q(d+!Xr#9xFThZ3SRCrmfT@=gns4iT zaRVO*wRLTc=mUAl5GV8v23C@6m?SQC_IU(>v3k@YkwrHo9m8T{fPTu@MGlRTGPS%sM*R(YF5?sY&4^;e-mIENMQ z;4HNniP?4w?H{3uJl0IB6IOhj5s(06+`?YEI1e(1WzRl|}Idr8mR4@4Md316B9B7S9ene-Jn zFdk4R05LDSBlytF1^juPKzR*(!;MpX!b(A^z+a zfEI76gSO}b%H18*R#owgKqvFj=> z>9Le8IIEO;h?HVW6_Y3=7<2c1ybb#fft=wqsytGJt+;Ep0r`Y3y@@v;SO@BCN6Xf= zC`3Xp{v7;K{BZN&>6Vg5e{JwGV-P3IyT(bm{^mRC zkgfyHlpBIK_u02+0Hhm26c#itXpuxa+FHr-*~*Jt$X7?NcUOb-$|Hh1k=KZbQ7!%M zY{@^?Mfl>q4ws-lGESdGUDT!i8EKPbbTc;v5affc4P@Gf%Bx`1hqdIHT~KX$*{AyY zRn2mmUwkQJ=V)(NaM}wcKe{`NYJvgKG#eLgY7Z0o%U$7xT+~d}z;o>8d@A~kZTnii z!C_WraAq-4WlpK5szz8pHdqWptsN4tB!^>O<0!8okUGkZ|b+`8ClCvCNk{8 z!Io!Q z9V5k+Q14IIO%eDVFsHkC!5Y-Zw-4=fRJ8g|g%viSa`)?$?CHQwsLx_2RwJ^Lgz7JL zXTVGe6o~^O)0H3IVUNZJ}&u~^onah(fa^|IbFSgoU zx_w7~-hr;+HID-l!3Sdv(CsE!Pj!^#H-Ze@1^!Fo=Vwx9C1Ilj7onZa+At315qF1o8d}0-J%pi7P)Y5 zXIjS?+w-86WhX()`zAkk@PU82ht!Wr>dkKy0?u@mi$t5VcmY?BZ-L9avHG6C@|^`Jpo&^T%7Ufi!gtchgv3 z8M%{vEoT!r$`1Sbv(MrY?r{5b=LT>zz+fGRSg{y3YFign9=N4eB=-2!f5Nok>_e^D zK^m~q9!z#cv2&0C+P$t=82gXcSeFl_{oH#`r69Ep(K0gaGd2EZY5@!;IYQn<1npg` z_GNupTae*D)n^rCn+{+b4=c64O#267p_Qq504l}KDDf8r((5&R~k z{qH@q;ezrvK{&WiX_i`@wNAmh@z!u0W`BP7U}Q;>57p4~uy;OLvl`>-(zIR%{mZYP z?|9ZYeVoPVMHFytUn5GkXN{`wL5-3}2`P~sp3w2j;5Hmtt87*V_3k)WAV$>LGB#eB zwfl@MA`>j559QeyBPW#SQoyjw>XZj)vV^c3MPIRm?P@7(${RgJrjWF^O>C20^vdAy zw<>RU7MfmVGFA`?=Ph_NBG>G+461+R(+>PgtJSYBrmLv=#F# z5lWhdecMMdz1zW7({03)hAPznzyHje_DL0uhHGA>+4Zg6Um1uO5r@UcF?B4KXLD$i zqqSR_AI_lFnHVsto(d-HgZ)2LK}o$}__|+q2uC|ivB=MS7NJ31TQuh$2w4d9U*8G7 zS}m?w6pjr?*;7I17^ngl(EYtb{3`Q>kP2h6z(ZACIQ>@fQTu)dbgC189@i#92Shbv zR%S)2pa{1)yL$Hx001~7gPMKM44tHT3P-+`9qxK4E-ZOXW828x(1mg^r@LdOBd&EB2mFV7l#|3$$k%Y1 zECX0-Tp?k*B*T(w85t!9 zF4v8yN2VwkD=v}yLxIfaSZbBgT#j@DZtvAU)9Q3~`i{z%1P=DoAJWSQCRUWtavwkl zHuuS7!2FgQMP|$cJSvQtd)Lz*n4~o7cz(WTDSTVBTtKaeXz5J(oRt>J*uf` zA(v7gxote{9Xc#65*97g_W`JZ9#Wvk6|jZ2UFFP%yy3s@a64hZYWS$JR;E+%Y^|r> z#H{M`v~`H_0uA;yZD9faqmfH$BaM*pWIj}0f#!4woI^7YN7Y2=m#WxZ4y2vDy!zHz zFGqrVadm6^9&Qp&W$7-M$E2y1dH(MQMQQ_DuLjM3ToXo7v*P&Pl!U+nNqg)d0_PRI zy!TafwV(uQqH)>I)G(8im)~U?)evn6=l>Z9WodjTq&SGYI3i4YoN?zrj<|6l64Ny7 zS64Yg^UfGCARyJ_zZ7xGbJ>?7l$Rq4r;V<_Jq$bY-J=B7ACKZHU=qP=vrg(VV(1!E zAdWUJ7@oWwSdZ=X1k5Vth3@@J64~8PH_W}~>ty?=;4v4bDSnS6y8fTUBg@AlCmoi+ z&AE0?cwX+kuYL=PdZ9~eo7}-p;8{%0PPisx%%Caa!|A-NZs06d57%pKIcn>7G)m?~ z=Pzdxtp>R|=amN(BwG}WK@z|gW?1Hd0F**Cq|BW>yRm8j08||X+&rBDdg3W@w#swY zW4piJrD9J3L1dBz%0hq_w1i<>t>)N8t*PLfcj|!gXKb|@WRvsx z&g@n((gLe;__EQ`!PwErV0X}IBh0&a(^7+!zLvsh-zSYRdW~H{xFeljF&?^LhgJNM z&Zd^{(HWy#kO#QvW}VwJ9XN-TnZm_&z0huvCXHw4sx63#7;^?)XHBHGkIbGZP|#@j zs@9&x46^vpRJ22pv=EGjZvVAz9{hs}Ez)Z#=KHgvfx^daGpbeLtXlfKIrVOGJ^;vfl_m9_ZnJW2lc~twcmWia&?;oCq$kCV#0k(VX7a zzCSb|9tEV^i)h4zfST}pT~?BFouUF7fEtY*HAH@30z=bYsR;rrQr`_$V%k+t6bT(~ zF;Qq)Z7`}GakEBWaLKK%Q>k{1qa*P*m*)4g!GWeHh(#sH`35ErHpq#JZIt%1Ws(X5 zP(W``X}sHuo?|?RPT+U}Cqc=r=FnlKL}7$sJ-?J4;y+1-<@>|wd{d6F!iOi`^|rY| zwVt_7w+hL3CHj)duc6u;MRt63=z~j>rPj-r`e{5lWRH!ZJY+!#Pie>lKG-W`q14^# zVD6zqp98iyD_Hb6mm|#-(DqmNFORjXljYUv2V6kaz>B=~8C$4FOm*ErwYwwSt6_XQ zSAQUP{&BxNt)O(u%Y8b`e!`ZKb!>wD1F~eIsR>x}hm~tkw26trlUAT(Ro~VL)LgbN znM1#9rno!-_oCU})&9RCsVe~F*T7>=kbllp{iasZmOeD^x@ww;;aUk=PHy<>A5y*{9>NMrby+RMmw`RP--E`t z2T2b8?a;90#rFZfT*xx>5OPrmzGPFGn%E#MnhvR%&d^#lDL9VpS+z^p9-6-jSS}zkQ6f`wxiK!AS7!V+b%xe!jZ$awFjN|){9SlqsH!wbH;0U)+r)?{Ewaiemd~dgSi23SqdEYk?|xl{;|G-`!P3{f2@7>v*FhRJHTT{oDGoz$_r(zFLXHm zSH4U(8M_@ZwYpIe&uROydW<8J8!P3&trj_o(jNXG=%Nb51mA$hMB_xU`>PsLG|U?mwlT;OJsloq*54 zR~oXSnk%b*6a|INEo)Mx|^7jg{WL>SWpIB zkvhz+z&04CiR9$pR4>`%(Dgjd&1BGyptSkLb)=e(NVQq?^K*pTTuv^TF@rA{ttFL#J z{`ZaV8$syn;Dp*c-!VPx_#lGa^;y|fn3-E?@Gi3~EgK*}-+83^Db;_?!scmbz?A}t zp=btUQBbQO+Y5+@=t(KsD*|;?k~)uu0|CC5myQei4gzGN0E`#>UW+KCN?5T}XK)#H zImJ%TPG1Kz=*taXTG$)25}dI%M5s;yQ&wtka_8fXEB3W& zww#J)?vAr>-o7}jI2_kPP<$5>`=$D95csX8T6x!K#)I~vT4#S77;7`1pCunE6nNQS z4|+-rO;vsLe7f+UI5;&m{t)Y35CYmsrtfGD2+~+(%}8dkV?g^+~=a@p{s+XUmBj5tGj3dFO~WB{37Q= z@qJNlkv_|`4fVWw&44G6kzfz<{9{P~_f4`)R{LeoMuuzRPCSg=u_i| zzY+Ften==)5bz6@yz{4`WA)x$Ol)za>=CZS9;I$k4~@Rvn=3*!ip2smfNyJ?M%~=SGEE z6F40q5{_n>Bq3xUp|s3|_~k6){ryT_Z{;Sy^DVFN9_csyBQ*wtrD!Lm?m}+UW*%`l zBOHAD!d|GhSIVGe8mYyFv6C7(&c#YN$i`Pdkv1c7w(FR;ewepn)!nL5N_SbPEIsrJ zba}1{9OsOrYcTEnzfPd);j$E8QTveACHW}HGVlJPwIJ3Y8-<6a++icX z=H7C{>zN|2I)0joUlXhfQ0e(NIQP5E2*`wkEBiT|-+_(e!Pmuct#2zbZjdL8%}2uz z6BdLIiayxXQa1MlT(mev<`3E}#@+DF7zAO%#h#e8AxPQgQAm})Dw7(ruQ3-K3<->Q zrIg1D>SsI3dRLIe3dN18+4b2hN+Z8L#Q(m@hl!2<8a7*XI0W<=h- zTHN^VP&<^&QKEtCg9~_#x6X#RqiJJXs|Qji+Knf3bFn6q1W{&gPt<;HEE_WUW6fv~ znlctz)#y@wmvy$81AlpK$)zI#@k>xoANj#Yz-3sM?cg=U{Nia5!988KqVJQaWe1I;GPd9x@2NA#9+oN!-?!j=AO z@jf!Y!w$ip-`%R^nUNNcLNjjL`_`)&pa&ag@X=oYb~1fu!jJ9r_V3hzn^BuFcKrIO z%})aV)bhJQ9HP_^ZRcwU?phXx+$M7gCu8M;eV{}fCxGL{6d5i>dl4%;t zH9-dlmi!t*?bEqX4!nw(&9Q_V#vAkPY+Q4$H658e3CWKJ8GJ*PtbnqRv9%CbcfRy} zc6g0osQD<0CZ%MfC}|kebNkOqU+mQ0EX72h;4a{GK_x11$*p0X zQQpwXNKKQ|DrBeJ_yA@E4Nqc*okdH8^KOUT&vX> zuRUa#T-I%yQ)lm30pWZ^NODev>IV!`9MVDw;N4$IA3QZ9_VP^^4uPin_aU13YC`-z z#{pxQER6+ZOT%uu?-Mb1;b#()b5~Qn7gvYUU3O1I((=(Qt%;0oADfpAjDld@n=%9prF@s!8!j#M zR4+YDtyUElCrhzU;0+>f~o{tb3?8ybJ*y68v~?JH06yrBg@( zA{#=Y<1gq^!k-!fY#o@!Jza$T~DY_y;B3 z!#h`BE=x(+E|3Bez^}sMCz0<_MwVv!&s#CZ?Ym!_5Z=bOuHFpdly0Xsh?#N16*~!> z$pHy|NR=kjL9nY)Eo}vHP;pJD&6?n-a(l-=qUOfu2I;grG=hjaFM%Da9{V3#0du67 zV>hMiNzHqFtS(5P+gfJX^f|JI#Iw#4v5=K4o-oV9q*v0eLQWwn+HC8IO|D)rdbGc z%GTVC3p(peoPEgXFf%2w?XJwMMXn0rLZ_%T{_@|>xa^5^&ombau9D`Zhg!nz5QoRs zNAk-r^*?PerIWLkuC=mQSgzC=tEbB(A#cimnBVy2MN8VjD5}x+udj+1I++RY3#`YG zzqJnoJIjN2CtA+3dyka4Z2qYjtWnz-y~~%L%Cx_-0Dp`PkaO-JRxE+F?SV9`v$&qZ4@AuLM9HA?v;mufhSEUeDjX ze*o>|9?78b-BhX9&U`5UZ`j5HS*y+Wg6}VeVrLG1l=07fyUd!IZ~zJJ-+RV2ps<;v zX9^t*wZ|Tby5c4nl{)Wu?HWn9uyD*)T<-qoM&94@Scy6NTz^nWcSaG_n$IFXOkE&V z30j04K0{P>xy{c6+MkHqrkdqWusIp+49K--wXFCw2o8<6whP^Gp~;!StY}*~Mu5W_ z`1cjeJ^seu)qclU^R#(ms(|kM_5z0wnvs_jYb7x8^>~3K_}1w-gjjNjfAFinASObf zAVQOhR+jfV^@C`=l@OqD*BkuHciC1F!af%^vA>XOqUo%+i1MF5^_DBWV6Hn%>HmE= zPW?9@gWxu6VzY_U68A##Kf-Y*#&cyKK-F>X_qnPrG5bhmcphtdH_$ZfD{iehzD|*$Yn?r#VIqsO`@3`2+|6m^!c>kAJu ziEmp|vOb2V^EfKV?+Vijx+Sv83e9W5DeMt%=d;8D(Y|3W#&5pPcDtJufDi_*h&|~y zd5pRED9$jjfyW3SgtSZ4{hH#da80owi&YIV=Z!T}!`$X-Hp4_R0Jy_-rcOOU#=jRM zmCisPaGP<{=;q%K!i|83A5UtlE!P$`Z&Is*1+E?IXU`xj&j9?*9eZF6Z=|GBCV`PNU|`{~mY~J0aS|D|=SYtr9azbz694k=}wH{*@NJJWJ2W z3?9h?5PrNj;Dl{-nnMdK6nra2X5AM@7g;plkgx2WwdIP&dzZ&CszYCPhj z|Ca$M+)4D2YCf1W@$%wu<6ptB1!`uw^;l!h++c{NOiG= z%VodcVSNP_$x~_ek)9d#Cg=Ze$d*b|O~D#3o!^pG*Qn|u71y?n<9Txd2_QlcS=xs? zz0Fq23+*Qj2|`^!yXU}w)=rffD?1|1x+7d~*i>gzxPG!v_m`l+@@ayRI2Sx_FarBZ zwxviItji`o4!;ytm2ilmuPyZirl=N23crNKsHxE_(H%6{8=QATYk6+QC?++9y#Kb` z77(wj*`OF;UWpB5ZBZ3*es8DeELd3)cBg%%n}zj}9dRNP>a<->n7%Pk;PD6N>9oDl z<&M$~{FZrLg5?I+<{n9NE5}xR3?dOIqFyopmPZ0Tn#%+U_eumR*{X{X*3LO}3xtZD z=78@Jo3K`HMDchvRK0#Wtmg}W(Ty2o7%>*EhJBDA*ALYWb}^$0o9UmOoWv!OW#U`m zS{r2P+s zc(`ejc*J|kn}F@6$6=FiRF-)Ll5aZz4lnBpHYSiSKNVlgb*U;0GK~`DN$NY%P<+H{ z!cwiNDeDvt!ki&=ir`iRsw=kK|Mub#gE+o5mvL4*y+*q`Sg-$h%^~xZ;Q!JO@9azP zzvOE+_)3`A=~LFl;(%l#%;+Xph=JP;Ag}a@!~WuS{Q=kbaf%Na#$@c0y4nJMm>LW_ z#4Mg`K0gY~&balvXp7n2LoF?IUgyfj37%!qcuq?b?u)U9)fO3HwM9Iu`j50vaw`>2 z284p`a~{LbF}Utop+8{!NQej72KD9M`;40`=p+EBuqK)X5xLFACb@loCkVoE_TOaF zXEX?!0n$=#b}zpSvAi?G`!FTbz#ua<%Q*I9sEr66s|sfLzdSDWGngy?P(1m5#Iy?S5GM+ zs`RO;4&KNd2q4hS6IZSYX$a$li2L?4?{{+mainj$_e^XA+8@nB;Q~Mv>8ZXOx{KZf zR<^o>Moh9%dLCGe!~V|9tXJTupS2L2=?vUeB~8GVsHCr59xRjdTvBA;+B`*mp}d`| znsvx!O&9q<@0Vs$ary>D-$v1NQYUuV^U{o&Dd~whb#jTpzesyN+?KMr)%u{y{UTi+wtgV-fPr^^1(s@W z)5nZu@Y#hd%oe8lOqHU*wBJDng$5l#^Wl9-zknpQOY8y|{AJX2{-i21!Ps3*Ge@Va zgNgtM#SmjKvr{>Y^3g)MTLBFLi7Q$6nW1LS(o`3?aL z)S>^$;a`pSP1;Ou^RBNqpa3sY{Wxox7;qTFE~}QI%!%m?&!vejT|C!K8uqnW|(iM(kpA#IK5FysSDZPpi3AyZT-#hb65&@xX=)sYriWU#>>A|F0#{PSknNuM3 z#ePd(pulV}qYG~v+($SUwcIXi9c^m{FsVpho%Bm>=0B4d^%Qqq3`P?^pn60&Gl`t( zzYM%MYtT?FyKEfxW3@9A>b{tTKR=p?VaJu^YS&^=`>*1N3xJP~x)h!^D*Djxu+H*a_lFoIy%CVZb| z>6FwC0-i%_Jv#2rML@875BGA_b)5ny=E-G!rn zXg0uF#w;LezrHVw0_!sygv(LBXQQlRTvUE*{O)G%^A{bxa*aq>#aQR{B<@bAkgBad zW)OBLkjJEd<9oFgKP>tyJbuo3;+dJ6{Np#BNYs;#luhcK1WY_lyp9>`&X5f&)y9B^ z^k2dHL7nyuB+FdH+go$ui1b&0^S`fQWF0}67lJT>iEe_NZZ<|iGI?He+P%~6rhg#% zYIf!>U)~h{MoWuZy$eXNFCDR*%q_b(abiMfB&5hiI7jk|bMt-6R;btVNd)DFk>i&P zX?{5-GB%v;uZa=Ow4(=n&uI!d$y0uJYLgD=Y-jqHTsgQAqi#mbA=$%JH#aV_T+bkN zstv;f@+hN@Y#mUY8w5BGSoO7X%`Zw)hRaHVcs52Plf|ODKfv2D}TJ_;9KG&+MTO{`=_mAl^llR zC8muaj*P40(O@)hs|+iA!2F!oY0ntjE7Kd2ubUUj{q}(Op&oiNAPB#mNe06na*V%z zi|^+L!zB$EnijYR)ZwNE-q*7-+q~&2MQ<*qjAae}N-r?g4EUb#Cfc=?GhEE*9_ez# zzEs3P!$ND}ws<|v*HfpA#!F4XiA0+Rt4%^}$IxeW6FFAwxw|2PunRqI;$vrcGg7H? zNR0OC^*(rzS1!miP7NVTEP@-z5W{i+t%3IXHr!{G$%f;lxBF4+z2T8w zboI)iy=m{~lz~(0Z&SmFPq+|fPg+>uCsAvfgqJ&2tCW>M)H|SWa%2;vY&PYT0(pGkEQ>wSuZ4^#8!j+O60Y-U-g>EAw zeKewbJ!Ae+GN$h>8or?ztb=IU$KN5cqk+lbbGYkCcV+&?CbAE3YL0RPBq!v1~_ zt;@7}_(_k+N1j$i?af~KQb>xk3RHVgnChHsq=c%tfa+ zPdaO%1 z(CmjVM|C*!qy2YLaL)f^1jdek@aPQM3_q$ky)Hsg#Hyl>b|R<$DP3{SU(mx(cdN2E zmdlL|36qItZE6$FgvsT;Lm^LNE96i3RFy+= zpB4!&y!88mWq_F7^yM#t^+&&cE|YIzUdAnSw<~mLvAEP3fauv73iLkXg9nEbKirFz z*v+bMysao-#-`}yzyGv=JqGA)md}v&m{f)n;AdGye+wI0R3M}NA-zHWQ6Y>12~REQ zp?8*$^Zf@ds)S-FTBO?v6eG?C)MnV*rws-^wV#bh&;#hLdLgY&gUm4b3rs1_3bEDF zg6# z*K&U57z7y@2QOg?gLx^enq4m;S0O~tpJ4IEVMHVX+2;K_FpSp|9$;U$3mC$q)tyNRhO$f?x~=qi6jH?p!gNgY z+o90qgU*IMzt^o5t5;yIP!tYvR9}Iy;8GKA4H8+@%YU7G)$;R~7*pW6$&F1+J>!)c z>iMk+tGkHZUQZkz_{`m;g_T^L#f-{^+d&wv8R>jj-SXIrJA!V1T_eFW+38XlH5Zjz zZ5@I}DMg$Jt1|OQ`yLkKGw`90yt>Gz4v_YQQ zR?09Qx*|iVf94;&a_$@h!w1XLaK?eVw8xc|&5+*d%A?CtJ|0J(VY1R6xkA#WA?qAAM-_K5m2_>kA{gPK^U8y&qe1m2dx24CfZCp*zeq%{@_BWI% zsA7(5X}(Rmsbj6pUW7O`0x#cCx!Ke7`M3C<&E=X}1jI*-*CSFj|6fs>CQN!9$(ZkQ z`+CWffPYgJTDZ8>rakS?()(H4&&x)Oul__HX+mcV&tYym>i?2qlXZIW?H%O!X_~IM zKpM+`Q|BQ^`>S}3?bN_l(zGtPiKY>DzGeriFmkXXCM{}+&d20DiU%wlu(?@%Id;^XCE{0;xtnJoH z_YA1fP**NH_9jz=VpB24uv2-L83JdKsuBH@-I1YJs#;ZMS537~BZ3jhJm#0h1H zT|pz99pMny9EK@&p+g8H4#8gwD|sAU=iF3?^uJ}RZ%HpLcyl4*;jSXrw0c87ZZghO z(UuM>i@u9AKZd!V%5=V#nCNt$w#^ZmQ2GNcyhc!Rl0hzZc}|qIpIH~KTEQsDz}4V_ z*=m)<%F>mL`Dq29IFU2F2hL#q0fV$UYs9G!4Q%Cc`~uN*(GWK}&!Wgb+*>P~;Zf0Ww0Foiey?80;D8Ukcv{(^b49;y_H&3(D5 zRqi%;AG70vtdmxAk_{IaA&v94`$a*7%lWmJ9!x#QknLrg{_NP%)ZiVZEZndSv(OS6 zS%edr$U9ci%UfUjR*5tqUf%G$DfJr;Y{<~e$Sh9cE4|AU?#&A_guBqmvA&dfE1-Bd z@6xAi;C&LN@Kh>IC?lR8X?^L{Tg1=u`+U=#H7bQYlLe*f9K!7bZp8`X3e@fddy3_{ z-}%wkLq&$X&&RO3kdo~g3@62b&{5f?le?i;PhZ47X3)g)J*`Jf3{Vwrah92aR~~sK zP);(+=TW#bk0^JWf-VTja5Uv`71#{hy;G*-9VvCe63LcRc+81rr8fmN*cvOD#}^9C z^y+d6Zyr*gQeKipXLRVuDT1^<}s&jqsJ@1YG>O`2%~31^Sk>Z8b4G ze9?n@@%;r`{v>j~UXo5je7{eNu+^gC?BOV9)Fzv(k$rwDtNSWns&@G8UfVzm^L{X( z-1I#_1x+f;8WGv4Uc`|E)42iCjaFbf=L2N};eq497(-o8jNyF2neY&qu0~+`XKz12 z3i+P@j2Z_IR?Nw2`b2y%r7}_&sV7?h{=q1ZtQpiqT+W)A^$)e%e2{mJ@uaDpwR{Ep zQLcq zBQ_$D6uA&N$VuF*ij}XVxn(#Gj?${ViuZ@pLci>8{`c!V9tg=DY_q@g(Ss9I>stLX zZB7vw0y?HO1-Oe)lwMn<7eg{8rTek6aWu7L;3_;_`}W*2O=O+I@= zINec_TkT1kS?XgP|3T#366k@9vT13q*weVKUNzj%Z)Qq#9A=O%Qed1VJ(VUQ&pvSI zKXD0beRM9XycNeHu`kTBZ2$szCCsoi?`+Lp(p5R!fslvq;TBZG`He^^mG~DvpPvbv zb{7*!y*4>M<7ZXluvG_!(_VuQjE)r!m&al|8d&YuPb#!vi7^+xYKYExLghy&k`_5r zdjm1Hok=b_D!mMLdi1pY!>eJNhySfU4s#$dGaSnv7cP%{ zPu$?@Bf2#Okz3VG5G@Qs%6_ViT~_oxRq;YtR{0YnYJZqSqty!X#NWC4ZsR%W_s`=P zn8InU05_64b9oUfM)<~UL+FS_nT^(Fx2KtaYAq=kS~_UDoF=dH8){nEz>K9T7~NY! z&5G=9kL5(4W!>Hr2wsKSZKgH6q!5}^xoOPzej@`%&ec?%kM46!W=Wuww{i0#yS1gb z877HWr1rZxg5|sw@l`LSZaL7IwLukRD0yfjq5W%^@f4G=8i&;~N&tM6PT06=AkgjuSS~Xdn+Pc(d2JR$vRX7i=I)1efFgD?Xt;q8(iViV{*woFb)LD=?koAp4<+vEw z6+)!P`!s@oIGiuUkabsE>e=#36U-z;{ccYaoS@Q}=Vnob`$3zFIE8sVBr}~VB*8h+AQLLpCBq7QF7xZ{CV_^ws|3Y{~=wk z!&b1?Rp5yfPT^{t6_@tmUsgcGG&tj~}sqR!$YG!AfMQ zH|=Xo26Qn_mw4TKFp0XRoXZ28n8$31&LD2B{v>A@62nsj2j-o-L*wQS-@LfTK?$0B zXeD+!RDeAYvrnM>iWZ!Rx8w~2)cs>?G#Zvfvu(WslZXl}3kcXXVt+UkE05q*<`^gR zZK5xY9Pm$b+x<@?Bt*%PH54WWS~#k?S4!7XQL^PNEkoi@FumwBJ7pcAz(+Y8NPjg9 z>fl?FAqI>`x0TMb6a$fVgJP`$&*8H1H^I$E0VJv#I=&l>a@-1^cpfgTIDZcrH4LP- zM~J#u80Tm4pax8>T>M++m~}S0l#b~1!cpG(eqk>I#}}4akv(G9gNqn>YXLl!81lg_mD8Y@u}I6o9)YmCIS)pk9Y;yHw{wa-})`?aI*3$w|^pB z;WBZq*(C_o&81JCuRe{|7UEo7{q+W_rl-b%SN`Mbv|!ux)6~4g^+wlD;(GS21Fbkri$HBx(7*g zRagk+dNSGTGERoTD_^f;B6`H!le@eJaFv}w1>fHV5bPqw+h$jxu=8+@D_|{X{8lzw z%5-nefDMz$h0Tqn5M64{mUvB-Nkg3)kF$(cm#d^K4PS#qd>#vy7vDsq|$lKJS87<$8s+J#oA$2vvui2}bRjI!*3Egkod6FWRPm~IM;JJFJMF^EGwTDC$yOlr_D&j!w+XI;qpc>R**gC`6Xq= z+4Y+r;sY=BER1-pxapYmC3R)7dVY7XfqM2R3&wq9dz-|OFdxoahzN*)!B2N`$nWLS z>m5bn-m8D{Dc4x4XovV#@|{7X<4IFaQ@E;al9KmNR1|A22U6&cO z(L9g0OzyOPEAV{q%D5_j7xpxgL}Cnn;M_A~x&>7Dbd-0%HvzX|5n3W9E zc@&TX#!W*~0P8g8h+EGIXU_Dy`hj`mwBG1D4l z2s&NKX?2s5?$^e{-&=#~Nd5Hun_u589r(FcbGejpPfmIbyJd@+8H-JS|dXO&oql$_noZK7qRjHw%Pz3())Q>AVJWtCwXJtB33 zEM<1EM(+E$yL58S0Y&0&aK?;{uaDf~GuU!T7+#htnpN#uA*=59P2|nENo3LgiaF&S zzf(%6AvAkxzT9~|G z3~H52h#`q(8td;e3cP$;tF`)B!Bw^lk(j&2{1|yKXVxAHmQt*S@(sk0cOag8s7@a$ zll>&9`4&>Px0OAsM>LwP=119iKO8}qQ8%Qi(Yr=le~E^>Ax_QratfVa;tu@i@a zu682tMPLWF!se6GkFx9~6 zNuO=N@s%&KE?EeLwS3A!ppZvQ`8Wu_n=9U%m3Cp_!cx^Lt+!8C3i_JTguDgowk_aR zNX1YIYCV9R>0haji6{Hv3^dhGvO!>7|6+bI<<-CoCkd%;nkL6+Hg#^^oL<)}1oA9d zZ;8d!9i$ik*nTzb-|9o0bk_4FfT(FytM{{mMV>LKOC832<}HSf|IeY{@7%Z%9a#HQ zRaN<-g*rE<{FkcJ%{%giA6O45`ygE`$Mk|Mmy+#5=8*2b@9`Irpd)kbt}+h(fP%Q3 zm0{S9%MZ$M&`;%dDeheymot%6Knqu?>Qf1^z85!`Rhr9XIHEGQwJM$YKHTVPb=(gxSjF@Ng~p#bC}S&}IT`>H z$Ot>yt+Wv=P;g?7f~tYJs*Cdvk0WB%a?F~WTpodz3Dc8+5C|3ltMOXE#(f*MK-QL{ z2rw=pi2l+Kk=!|Gy1l2Rt;P%j*G@x@ozMrCX@k2R_NBUkX8E$T$WDj~IBYZzGg+TF zBF@tC2Z&p1GGNLklNFi1BMHQ_F`~=QsTh+CZ1cXVU?rLhAsVS6jb4?z$7NetK>nz$b?>%CQ++8e~v4T9pc*kn6Mhjm;8@n0vU#T)I2 zzu#xc37^?3jKQAQt3rPbm6A+WE6-wdvekXaL|Fbs2f7133G0u_%YE zR2g@Mo6?eVk!))%RLez;9o=FOCwg~!9A*iSWEsbI5YKlEo(2kTrAKg_+&g=;cLXu% z_ZQbl@zM598?~Y2o>-x*-JOmX35uzB3G9f*+EZqJzL6`j8bA~QAU>h+Yd2|3(a3)r~NF$8)OF~k%5Hq;4eX~H#;UCF#G#@%N2ULkqg%pP?1dK$Y_ zDAxI+ZU+3oK7e-XcM3F-R=6@JV2iS(y(;%pE8R$5L&k1ZNi+*7CQ5Zd!S@MCa%WdSu?xcVb?Mh(7mBh zK{)j_q%7a6BHk1R{J$uDUe+8lW#dbrdn6p3F1olZlj&v@fGLkTx!(p8yEN34(j~7} z-xD&qQ+LX3@2##U#r|@fj3;)=(2mKKu}*(v4ad72#HUI@#_}dzC>_CSz8W)4aC<+r z@7O+m#McgbJX?2jfREp?h)>p7OCG3AoD=i9`4q_M8>k93`AudPl2^v4H5nUb5u6ix zj&ue6nv3D zXwInVSM%d=jr}*?$e|Q}ZF>nf4Ib!~WOUXh?E~Ymgjd>b=E5t*>nC0csNv%^x|!Oh zMv7}~$*rqG^~+!K-tJHYB&TxG2~Tr^XixuFP2h#m1X8)NqYEUFDJB1$FzzQ6h0o9Y z7bXQ=XK)$OcCgNP6doSW!#R~YwO`tnbhhmo{a;Z*Z$C%7QzGOi5VHu~#9rm!nIc^S z4Z`N@Dc|(a6GvZGQx-ylTH$2=C3_m%CM5`+1;L9Z^Gz$L<6Rnxt<&=r8sdJ*LG|3z z5W{~O5`@Miq@15L7pmp>q?cw!vBrXpzVjv<;de4A@t1x3-+GIX4ZnM{ef=RveFyi= zLK^<_4CYV=AYla+@Y|HGRs8(Z9dm~a)z9QtYClNjdgf6CcrjcpJxF2t=^8IA^wHR%DxU=sbf)SV zeyyebxa7m9Appbf-N;X*sW|}#pGE#lbH-Ct3+4p&h33bKjX42=_$~l17d1KF`!$QS z=|)COVTo|Z&=bR~gF6JX#xWsSHJI7eK!Sl+0EuvDMO7KXQ?%ypoVa{FBV@6T`Una_ z!0qqd8`sypA2Jv_hX%^C26q9Pbt8^iG7G+_cpTZT5c7xN)}mj@dSF7}l^`KnX&t~3 zSz}+62cYj+Fe6F_pg7JJ)4LGDb#BNKYc{@UjlKdTW9~i)c+%wZ~K#RI+#J~ zOC|q%`v6%KM(Jn0Ox0s*4Oo>KY?4|i&A!-<`30Lq-E!<=(#`)(yfj-b&#Yy$00F=S zcAd-a!7vz9+aXjU zsVtd0%5|PQR2S@pXdQC5!J}EO4#$BIG{-xF>R{;gq~LOtJ8P5b`~o15{&2vUZITH2 zygOVlqyM$LCFrtcly4N;kE*0=M-943{I_|iNr>V(^&ofypsRa}6fnP*1N0-t3qu}n zBHX<$3n}gctYdau=>|)zgS*t1sVCD`K$|wX*@gdx!ibIKo3%cWbR?U&c(h=%vo@O_9mRR{HG(*p~ZI`l#L@jA{*P4kZktaX{PMZri;XJE> zO{<-~vQ?t%ZO>+85$nvBoSV8mi`YOaDT9&r;zB<={qwF3_lJOI1i#?|0>)ebQGH?e z6*p523oH@2SRsOrz-2J?n}V!&(cV=ty1?!=!A21Jez2*uQ);MzqTW|58hw!?GGM@9 z+f_%~uLws)>%e7MG!rqLJdHu_&Eb|H_v9~&4dbJ6LX*;$M5pTN(b7+Y`O~P*hF3u$ z;(~J3Kw)wHl1k~Pg=b2%Lk~hcFSuKt<7d9aV!S=m z?ZnH5mhJOHDOX-<nh z5JB2!Z&O-1B~;GMt^g7~F&YC#^H1>iF@4&W6Omd^8PnkZCv#BeWU``2blA>_28Z69 zX~51Hp`j!CHcdF6LH?=zDsm*0Bx z9|c3%OMAj=g;)m=V|sy>`#whLHzbfauU+OkGTAV(_KMbU{@+7G|mKPi3SGS*GN=I!Cw$jM4@1D zx6oA#y*Em9;IisD8!BXZuhyJy*o9s% zl9T$~z+-cgifndT9N&2?cp!~13?&Ajx$ULN3s*&jTsrd?yrk&D%U8RdnU;;^8LYs) z_Sl3d%Kj~%jy*Y@<^ZA3n(wgNOI5^qCL_3)d-)JP2NCJB&kfl)^Yu2OWYmfiG_w&w zL4Y{FO4vdH?>$UkTlEqa-}rnjCW+l$W|xi8mZz?sa;M*Z5Yg~WnF1dKJEehHvf>nO za_$TL6bCdY684ng*XBcre8m)<&D0>;z|rd+KDEb_}3q-xLIVNCbw z|K%FSlxd~SpvTq|V;jZjD@J=RIs-l&*i@=2;*0}cH(_6KK)Y>m7J+*Nx=UQ*jVe0h zWS!YyftnQ#ALju3Uk5Ws(Dd~R+qlbEfufwzw!*B){Y-6s$H>V6D1j5|1WArBC1G%jv)izJ?$~)t6op&hu=@RHajpEle-K4-+4W!8#}(YMq6&?=w8q*)Q4ziH*O+>bVM9)^|!$ zGn7p8qFb#or=OwWJ;@sEC!E8G21^ypS`{z6yrKBxE6$h*8YSL!7@gk{5-N;BAYoqe znX07rO7~@;3H_F~Bs9o6ejlLa^OWsfl(1-No5DPi!mRtD!FieDd|rCwNCd~x0M18k zQcRM5_am}r)IlL{&dmGqa>>+f?aq)SS1%7H_Fbv~%PmPwz6vlDJd3`rd@VjzcbF^b zJ=0ztfWyvHo4kYi?t!Z`=4F@^|KYaUxst znaFODo38hbA1+XvoI7^I9+R zCu-i%)S^k9e~A%{9{b9EftT8FnacZMHBdkEyIye@84}e)B~K9PDb&umWbiek53JlC zoYyYivYZ)7X6AE|$_R0qW;8tX6={9vf>a}i6szY9g_{-J4_BLFW90MC&N&EwqTuAp zU5W95k1C-{i2^zxCob>eqK&5BWBEBOSGg>`fhy=XsSx2xwEEGL4liN6X<<=mBRcci4Pg{;tP5LmF?vFg`l6by?Lv$Le^% zk*7C94Cy{5KHTtb)Qd9i1;E$G;4K+Ejo_zT>Bu@PUwZ^3A}FnKv|-a@4R zF6I!MFm4;xO``T{U=$b^8T{C`^jNBse&eel1_(z}t*3~@IbcmF>l5tJM$&(r+G!6^Mg)IMlG{dl3APTNIkK7M+>6HZDV;Qa5_qV-^0 z3f2v~)D_~Wu07Mn%Wi#&4W<9;f$<;q-W|gdc}atT=h8+lNrTF7zO_|2Uj+uK zhgLaclKiK#79V*GybcVa5W3ZBkI0M^SJov~odkIvNO!Uc2I82m{RKw`imW6)xdLJc z8sBbQdpf%%LA;eq#L&eKZZ(Wu(U_j{_F+-ae$4XWjJ5?|!_EhaMn6$pRcUu&uG$#( zs(yXv2XZKf>m;;F_2|Pb<<<*Dfq!(3Z7-xK^ck$$T6A~otpx{ml(5rJs_Dnt(omSF zvWXH~XlzTYR7Z!O?+Ox2mCY6b6gd-SN;dZKX7xQOH23+IM^5a)r5QEXRWG9ih4>>jy^oi@l?h0`)nli)f`$Z)OH||KM9do!J-|iK z%-}U_KUa*jYd^p{;tRr~Ih-s$UEZ__s!}dkSzUWDrT|B-KOW775^v#=CTr5Za7Ng8 zv1C5|;5czR<7y0_4dRE;-2*Sknv1+vk7KGYQVgv^do^WE0&gPkmt~pQ4s)kJQLX>RML<@_y9zj~>^>p3hgC?LUnt#eD_s zHxeAIMC?*UPH5*;)E4h!%R9~vDy!LYDJ1^k`FHK^W^ttf!aY;%2Du8rj!o_{CKc>u z=adgYwwdDmi1C|Jr_EBK`&7_aNwm)AifZ2-dTKvl^WEefkOfA;&b<(97_LF;FIRlg$c?Z)klYN9 zJ=iUy^6-0+@zAw_}1cD1m$+#MFzysG=VcQR&*H~(q7+moaO$mMiz8^{UbWGia}DL0%c+pCk9KyqE=G#>l%v%32Lb2`qygzutd6*8BGx%FH@o8D|S zb}J!W*Kr_H1iC6^C4J*%H!yDQ?zO8 zaS_(1q-(OG5!onH}g>U#(&TCW?Jr6LSru65KHhA>y< zpE97G)pa2`Br#ojc3;GI` zPQ6mpKvB9j_Yv|MUAco6A{spk?c%IX-UMKEO{q7ahaz~qZu=-I8%_q3o=|Y)BIw;} zg56=xm{UI`MTNN$VofDX4pm&SqL7(^~= z@9`xQ*|mi)50)(fNy)_5FS2rba_EglXX3oBM;2BJ$F-~(XYgwJn|yNRa=pFDFVZ)M zEJ*a*3AQ=NiM+w8QihsX*$&MjrwnLm94ihrO?G-e6Jj&j+Mn67g_i456=Kd{KFIQB z1+Jz(e?}uG^A&Fc$Kc|6+R6|1SRO>ym_g(8nRLVn&6l6~upV&3Ua-LL^Yg-TMUGx^ zU-7y_Nz8vST^^D05)PC9CwCzp)>a zI@Fn59DDN*y|Rcchv~UGE;p~wA4u`^TRIZ=d2n-vT%^PLk8{%HHcZQHd{x3;gLlb0 z6`dOTb0%&_{q@l((|p&P}1xVQbPfIT~fi^~&{v|u49bLIRdHNWOA0Ce3fPxe+?!L5hH@v|J0;Pm9xGMLR zzxLO*F0KI|cBZogzYI~O)QHWL0-`9%-pKHF&l_%{A7o)3&s9o3dwg_qr=j{_2LRQS zE*H1G?!1S$wz+7(w%gL{AJHgY9^5a3UMtGl<#HYmjo`^&Y%PKg*2V?*4D zz?}JR)lQOo&%3^nlBFpDtQvs7jPVjDX7PNpD}x)>vPi)Y3rXXazeGzZ}O8YRA=Ir65xAZfW3 z$uI=wZdaI2Ve4wHu!!S=YZfc4=;c9y_yJ_3I zePVFtgfWgny=}YotoW$KGMmv)Z_8$kvN2p+{k()sYR4Wdx!MO-(i!5{qWZnJ#3|vxaP^c!#&Jpt3ZGgE{jGyY@z}?fNkw zRhR9pjbHv-v2pRRE3Ts#`^K@g)W|yvs4O|-pW3cDRDV(ayY^HSE2srz+?;z7COQ>n z-AGf4!#-T)#Pr^ii?LNNF0hLlbDqQg56d|)xyYnj_`|ByJ)}N=6fHdQ+xAvxex16i z)cy~N{TsR|^wR!dr(tMpXq>1deCS?9NtuFDgy?xOdR{a^zWZ%HbOY}rfE2W_#FcV# zanQy+Gl|jdo5o!-&8s#LAmO0d?klDPuzJX@Eu5Z1Q*dZ;tvrKD;&nxSKj(UeBf)c+@GN%7qe>qp(bUe5COvm zFqY9xd`mZU%5q6}3ynxy{8Q zmrit^MdA18gOHS6ZbjC(giUZx_*cxeAB)V_B!oEM@_ls+cAJCsJ(bhS5VvxN82dUB zpQ3xB3`5@(l5Uh+00Md-j{*aWM-1$Tdq%RKxWWbsqQg1BYLwo?&RdhyHgC_9<|M@Nc{GLEeo0g5Xz_gvk#HTLbg z)}}51Vi0Q_V_)}IDTjg zQ$TK#3eJ?33$yR&_L+&p{`$*o&FVpalA@TN_u3YrmDJQ<%Vi7+9IkQ;?_<&uLOh^O zIikOe5X5o8#L6KtX>Pj?v#<~BdM4L9hs=rM-Q$YbX651GIuC!|`rEYx!h|%% zF=hhJS!#(4*aTCG>ax~4Ve14PpUO@ug`uARMqr{yhgX=7S-)W+E0iqdK~0oKih;_G zPXO}|lOo~KAbpEGXFe1DDUxm|gUpxe%KFw1>I~?iY@{UZLum-f&3eN=h$OhbnCH{ZGf07fDla3-YN`d`3 zAKg3Lkkoa*{e<=kZ2?Oz^yoo~x)lN1PC2su9i*>cFTEWYLv7FEsKAP?%ZRwS%w=`B z8~g3dC7Q@bLwJ3i$)G!5vMZ1za5^T}C9R9Gu9ocz>0y9?E< zx&Nct6x9f#d_1Md-144Yr>8sPyaNC$R3>iVzt?Y1%Q86&a8nR7q^H$+9XG)RsAdG+ePHd}gpr;*e0I8A28OOxZrFM%!>@hx=cb!rHuw z??F~-8zK_xG!y1VSSHEo)h+^cswrPrW;{5dtb60Rhd9UEsvQ`CA#rn5v+-5lew}zo zh50PFSPf~2Lc+m!$~TMOFOFtI`NUAo5k1soCCz#LcXZ`78S?>-1ZetY8*Wij86wL- zm_WBsL`IF_iZ=3;$64~|w$cKbV+I-R=2pOukkBd`Z2-PqAqj{{uzNZ?X z3JZ&_)wC%uL~?}P6^SsKx*%f}ItiLSx|@g6wGxzFF8cOCi90domJLP|*s^0to@)f{@Z+S*s zc%a#QZbb%XZx#+xpUplXIw?VZG(mPaq_Q;jZ+C31)XRg?9h5OQ5& z%c}{YVfNvz!eJYtE417}8-nUYeO%Al$dC1^Bdvp;i@=7cQ&UYtwu@dwRA3N;ycc~T zpctOVR1J)O6=tR%x40x0cDwMw7tUSmeU%vnqvWr(7G1)Rj`xdI260R>(pcAS^b^nR zI}Iv$oI5ca)u;*lU`YtQnEEH#!sV%$)UXSm;=^;jNs>@y4fawGisrd!6nn)RKYPvF zNMG7`FzqTAw1cFOrc}{Bw9Zsc((=#S_Ki9x!PH-${&M1k;jYXh@mRW<=s=@>t%mnF z1Jd}258ookl*iKPds(za{b8F}zA%rr7!iO2Z8B){0YtZtm%w;?gFw?rE6^Oumjfw~ z!=WjO4#Kcgh&kNWmG|56a4)-*=mkkXBbj=5Ud6l6ac_w4Dt}X znO?N3AXKW=o{!uCE=E_%Fv`YN@t)>)zpUoQmS5_KM#{{?k@0S<{{Lk0k|= z5tDeL9U@w*0M40J*Tql$TR6ZNx+iv=|MzPKr>&4Qut5JkaE1?H@%uAIHcBvu$Ptzq zVkp{P_u}8hMEKTa(rE|ORNJM+-eimAFce882Oktao5&v*Bpbmy8=XL>r%IV`fsl6+ zv6P)i9UIWctmUgpv?ljPo|(RkcasP-Cbc=*aZg_at)8>0;&wsI>}2q*|R2QoW1s z+`vH%r9daD3GDeEmkAfTQe%j_?UF^Vl)uin!!Agpy6ogFINH+e!^9@==P@`4c>8`v zBt*r=S&aKBGM{F0HPz*F;Ncz@Jtfunh-a8OOES9_v6zJ)a?A&|u=b{Ve}9 z-L4o${_1n|z4F1)NI7vt!QuO>8Ba|dY7s}a9Z%DE_vaMi{-)X&x3>&jjW)o}I%Mnb zBx}X(BSa>8Ic=+#^w?@OwXIC?wUa_gEpTT>UWlpUT-nE}rbU{Hz{LzV&$Q)~&Ml<{ z;M!(^7#Y9xtZK|VU9tq*h0SYzylq#EuZ%Pfm)84-?@0jBBkbj<1*^~yySF3Mx>Y#O zh=^CBDMnfIDelsuTaPWGtmRvUAWZDal(GzwU8-RRQp!g;*;}l%ylFPf!fHEqY7Kf8 zugY~k7yz^d!5*A+fo4ZC;vDC-EWiib0BV_}=yhHFyehFS7!%mp4Q03Iq;q7nwngj?{+sa&D9)3}Bh z*##%I7mIC&94Ue1;~7*8N?e@$10$Qz7sC_~yfBzSzaBbL=s2OTbYLC4Jk_#ez7VGg zL8XL>RSbV_Z>PsGSxLg#f8}L#7O$rG(g(Pee`>_BX_7~|tcG69=nhO?<%AR4yba4907qv4% zST>CH=UbHi?k7_EKyQV|yW{q6C0CF19k-KH729w}txf16&3L_KYe6??#%Uy^Yi z6Iz6?|NYNc-DV0H{iJqghz)HsCG4Zn14O>*4n&Dg5Y-5sdd}WER>!w9F%y|u-LQ5f z7#>)ZuA;z)mtjgOdI99(46G&Qf`6s)6Xdw=X*+)dR1QC!^#C=2QSQGu6xFB3ilLBM z!uRjZ$C*fw#A7!W1+vv{%QfnV>{mYAVI(r2y^pzAufCIg=j*usWa!UU-K&V26fW*x z1%~@aak9nNQn-z|47v?U3ZpP*F-qD4W&P@cCl6qX7X*duEDp29BWLA z6sNLbQy==jtv-DKF5=R;XcLR#b&FLPzP2IBnU~UE9-t;^h>fkWHV54Fc#w_Zsq=~L zJb87w8FKfs-sBxP$)0yG?YDHxIF@o zah6fUxRnwyeWI3gZ+F5zBCzW5#c8rOD1Ov1eemcK{CI_@Ir45t=Q9w1mxUYgJh8LM z7t~GAIg~b;1ZgQxK;Bt~o)K7Pq4zVWL0As!{D~{tj^oSLa&8z_v8liX1LED~EMJl_ z8GM#UquDh_W4Bt7W^QZi-UW*`ZAbXJEVWxc{;p_2IMk&{hNKw>yJZNE30htwFk&f7 z`%(nk_8m+-q6xrM+Kuzq;3*KH?1Nk>v8vdKzRdWU%q}!#=2{G4L7!zcTKaxKNh9jl zw%1E-!iNa-TH`z>H|v}*b7paz5bQS#R5T+HCviYno9 z3{5XjTqgj3S5_@xN`GX`)lJ+fx;>0fnY{0IiMk0(e3|*6*DCSM9`zoiRv9f@0-F^0=JZgR$7)hZ7y|E2t z%IAWJ7)1%&hAgE~uwg@6OG#~Zh|QXbT%Cyj0Irr{tlXmdT}>+eokmnZeXlAlC7=OU z8w3^PU^A8A&e%8lWQnUid)h-ll&5Gk;021t96PomnhC9;WQ$>^krgN_h8bgeBmJrA$y?t%dFl+d3w;Y_Q$CoX2krF9ieaW0UKjfV zx~{R7|3hRaX7@Hm%-&;hC}zH=VwWa`Hg9Rb74VGM54I^;DZ3XGKR)L9Nw6Phx)3Vn zjWdShjwY1=vkF*U4IdM)9M?yyY@b>d<~m^ly$|SsSJZreaeE?x2y1p;GFI>Fxi005 zE8gJ9ezbASgzj=WbTwDc@~}{B+g(wCJrS`-9LoiIebRk$82r9Xnr*(6k0P7D1lz+jI6&(O-l}zSEa%TR*_G{TGuc z#vY8utL~Qctdv4d219%VPLPBl8ev1KBT0g4;6{UKFgT;H4-(NdkLRzbJM9>W%r#Ah zPyk{jS1qD(4L?$2dq521R8CrfPSMQs2KEn@TU9tKcVV8ic*Uo#T*X_r6`OVDDn>4%Yea7y(L~&Q|VxCcgqQ~ zd_i9J$N^5-r?FR3l=sLb)?@Qb)lvf(Tcd>|6)Y1W!mXbh!WtU_Nt4XA3Hh}fE7C=~ zcS{-95QX03l>-FGXNzR+BXXEXrh_OYNti0`eQ6piIWZ@z_|q(V>u^`{cOVo92RXG+w56> zMkLn(yjMA!q{j>&%Ae=Vj6|m@NGBh-ju~cD#h~*7kyRZdd@=vUkX2ctJrZVO_VBU` zR@~ob@obn?N7DY^NM7yvMXXo@Ozjz-JZQw@46A)ufdbsyCCUsWar2Da@lizjGwijR z*{+4Xz!bM#S^AUxKY?elw06Bo*H0%!vtR<~wj;k@@S)yx=oBEhxi!*om60jCGEPOg zUblHU1`R?LV)_5;5kFInMg5JI*Vmg{z`Eb|BW@&MM(v~Mp7s#KE7G*(LtU?*3lt9B z=$k%c8AakAmL;1XVE7)6j20wfAxJNT_yxy|V?C&Y(*U&(%XZ_M5>k-HVGN>w8B%_U z6H(+qOd<>_)|J|e4FCSD`y{LCQ-NMs%=^ZXo=%)|HPvd-GxdBKjr6 zE9WOkRQqqzcuSP{_JY9R@=3yUWI_yOSi{)Mq#(v`f+>)ft#R<7N1m+DZc?x?kI|SL zqjf&+pYD|jWzBj)i-q?bWQMG#H^6F3?cW;w@Jj$A}#*pLQ5+eddx7GAHcf zeExz#fJg)dtYQr@W<+Qka%R9c4@zO<6-mi7EqO3|~=}rw<0iF!3f!^%^ zFY!+iMBTX??lJWH!iwF`AG;`YHMhF}E33pn~CizXxPUJGbC7+pg#R>-}pW@wrorD%p%;VhK~ zt*ZzNS6$q;fPPJth}iBDnIQiS!oc06#eIS0b?-}4-B!VPHCGWM#r`O1ggI57`W_qS zufc$OC}uVn=X3M>ktdIUC*LlimR%nqvC#$KPUz#Dhr(dW!boBw-$OnR4w5K51%qd1 zg?XT5>{#c+K6+%2ybjY*rDv7)J|lX~1VC$$_UTXhPg%d;IeXa)NSf$Q;gDucKgwl6 z9;{X|ov|APUZhu;yw|UiOzU)>;MZt-YbRE`e*>a7UJwyq2cMy6J)K2NhV+1UNU@jp zThE6xeUxa4jJi$d+SrzSIM@@{`^F?z%0Oqg(`}PS8=H9+sLLk|fkdbKtr&=lM@3ge z+}^UzIAz#?tsNa*co)fv5q3-U(*^^7`^+?>$Mx6IXf=M9R`a2$`ic?MNn7PkfIuiCy5U2EqL3<+PCu})HFAKovP2vi0t!+|Ahlw5UeOjHUx4D6AMw@Sn*MG7N|;R57cIf8@aIX9ulYfkE&Dw&jjD5 z?CXjOloZCec9+R-|6L48p#WSOaztYzCbF+hs;7)LXrN!ps((f?nJMPSsB=WCiOYRh z$mYIYqe|dZ5Edc8H8_}$hs8T(gNd6z*$hWR)6QRKZ`mOFta@{}X{ufMU!wMQV*$kC&)4DTXxNd|<6IpRN)%0L`{Yym_t9DI@H5K|Gj5Q08N|u&OURR{4qv%C zkT<1S4Af0Bo8h5%tVdXh=Y*AVnqP_S87FZYf7}>S!?!ZK@*kUuXZK}bSyFb$Qo1*; z_j{obbnF%IEQyZk!f%z%8N@}-`4ZvcHk!Hoj2J7rWWnaP^_{bwxfeTbx3?puncq`p z!KexcUOeS7P;a7w@GmjxZ9WIrCw$r%Hlj7Aq6!RlLcJ1*ZMjkhwEj#SI?4d!MP zqOyBu2bC0lEQ~0hBn?<1vAGbC#xET0!c{K|(&!>q1Ck)Yj=@mFU z=MBgmg3+`Utu3N*JAYNO+qv&-;3_kKdJc-8R8K_O;ZfDYPEFos zyYZgn9Pw}By03dc1XjF=Z(cMD||Ux-0{dK-JvoIT+E92U^6VZMKY;KS{CBL)$+? zMEL7+EYWL0_`s%ipwUsM)I{RUXKgHzJ3EVX;ZQgQ? zXcWEQuzM$8=w|P$y~POM`)r}T>8eVUCdVZ;^cSvkB-CY;ITTmGjwk~FTEP!3D`#}; zS0EbQ$7Ey=%!51j@c=HmYmQYV09?V>G>1K`4qJ87sjg9!g<&32Y<~Qqrywjcy1vTk&)!5F0RA&H2&hIQzynR(~3VlpGHKPELq7&`aGJ)DTA z0GeDU0Kwm``j<)9)_sw)H~_*Uq1$rd6*|TxAT6AUDyrh$kbRyPJt*A#&^qpvSw*@% zOqG=vnK0q~6eq1q_0Be&k45A8dMu=1L_^DS}B6ZsM#oLSV8ha9X zCTX`x@kFf&O^xfBwXkrt<49T7C|4zwI> z$_&9eRiK2~jK|3JsV@oVX2Opr_@=RiX{N0q3iNl#wK!(&yaI)&%>rj?>z8PAT&!sv zQkoj$6tW_d0?Sc`SIVAA{do*9S$Pw|n)R$}QBy(?U=JiQwhuC0f_>-KDyt6RmWS$0 ze-C}JsR9ZJ$%WU3V?H_MWtW9nh=%@`@Tf8hDQ+^HBU%=Nn(^HJCS}tVu{ZDiI6t}C z$R1^=jX5P)HZ;Q%P&tQZXMa5$R(sxJeWP$W-a?#Fu^$$^unV+%DSZBUtWQs)8eFrm z59}4rALIcDcjCpv7~e%m=7Op6JVF@#;4fd22<1!CmL?6@X{47->7Kc*kiJ6OK3D1m zCq1FH-4iTVdmtHapQ)}dS`BUv5QFL+PXJNu&3=gEU!Ug=e{_>t`9R`(rg>(6 zI3dm=MAvIzpth8t#MaL(4Ah3Lgt$9AvaX@i%J&IrYnu^(vnQdp))^h?!=_6 z7Bo?ke7Dc1uw-+B+SryqP@pvMnjDil^m20H=g_uYmMf34DtAe(`rF=77V4xP08sg& z#yc|lg?3rTO{P-8j^~ zQD(8B=8?Iz9Z$=PQ_}8`Rqmi2CAY@1uI<$DBj{OJ@BbP{qb5!c5quTdG8KKm?psJu zpA3AYGkvU1b)EeG^(u!%t5x$Xo++IBcc12;zs}~yf?gCIw0(LdPD{@1kN5?P-6J9z zJ{*Q-zRBvp_!Ay4tFJgzUT9LhKb$Ms{ihZ>g{`||hA`HFWeWonOCNdwwpbURiwuQ6 zcLs)6GMAS}c`KxsnHNyO1LCQSkY?g^4IekH_g*4 z%v*%zqe3HXwiW1Sy(r!rTw~cJx_?OtIVq5I4tW@;uj*w_x?=8~mQqoQQuzrX4hM^F zVKC7!@$W4qe}!*JIN?F8KT0-qaBDKf4E%(YJz1Fwt^%}vGSFvS8R?mSc=DTixd0Rz z%B~b{dql{HzMj^q!d#q}C#Q$Z6K7A#DuPd4#9q!g(T7ouR(9a%;<~4hW0Z&j*?)Ov zclfG!UbD5D#(gEK85CP{d5$GWXh3yG-?OFx=KO+KI-VL4zHpBf-{fK!k}eFTm$$?Z z9*Ib;6Nw;Tx&o%mCO*SY%xC*3sskd5!m5Lpq6X4o?cC8zk|wm?JOk!Ityh zzvh43;jH_6tY@b zKdo-^HNfyQ;OKNo3#`|rt%&R$m&>AnNCT(3?!rd3GI%&D}DcC4$8q8WS1gLqxT<9lN;j2p*Xy@yp|YD*J)@}9G8D`dWJZq4{5Ft@X(_A z_;R!Wjp1Dk?I2q9F?4}X#3XG)lO{vo%5zg}2`B>AvNkYEHvVLN=+H|C8@crLq+>vo zB;jD}c-`MGb`IEmf0U1FoRftBuKji!QbOag{Vb>RAFQrybXiypy9BW%sr~Fn%a=AQ z$Fq2KoPbUt5thMtA?&RA^_(r%-0Sqjl6HHn3CHl%I@Hhye@fK<1K>^HpDZe4*jU2B z#klZ_R!26cMmqq46?siJG3^CgUa(nE4qo&XsOgR;|LCZjK(?DKkn5>e@n11DFVq?` z;6RfGw8s?L0D&IEP8;{K+uCM{J0%8bVJti27l39#`z@Tijic(!lo&WHV3si%Ga4bN zm-xr(53Rl4vKA4$Q>6FU2EX%R%G_oL13WI5?q`N$08u#$44O*Cp)rCQ!~D)xr;fiL zk+2eUvU3|vSUtG#RdK-U;l6P-h+koe9V6`NGNxKBkN5+&h|lMB)JGJXaVh?s^9uHU9!8`_XoeUv^%rgrGtI!F2I2Zs|9D{g zLAB)pzzS8rp}!Z!?)`lS+rLF(>*a!R_!DQmC^yD%nbd1Mgi@fqH2fHm8wpfs1kDJi zHj`#{o8@UN`#X>KA#kt&U&rnOVI2Nby(8 zVn|Kf1HrRM3QV7t=nYC2$8H$s*@7J=riQ?e=~gV+1`9u57-0J<-Chd}>}juX2 z(#NL-qehCN#>AJ==E1=VPe=NqEoyaeb0ce%F&T~M#OvpZk`QRp8y+P7LImmlK^Se8dN8dJ(Z94Dd?=zO!1f_@_F|EpEbd)1OdomCEYNAT^6Y+yVrjV6@8OplqB*+x`bqTy8hAYcAtymi#&44_?yg)kXReRkd)SSe(`V5C)( ze?`TglK4PfBjMFUK+=?Zpyqs7Za_wACrJ6`Ftu5ubm04QZ?v70Ei&pt-rnM>m!E49 zxH%95&K~9IYV-C~{B1iHjgj_pz7Y)cd%SgB-}hPa*;xgMwy zFTh_zn8coln1(`uxD0VouJtzlmNaaYPiN0>VnSO{Ca^wt&{N}*A`pZEo!UOvZhYc0 zbh{JaXct1~XDw7$=RYI}4N7G3%S#vqAe#7h^KZPA%snL=-P$#Z7 z{HT~)VVb$~L!*f;Z*kP0b>NTrkk`l#LO8=+NcmgJGuu9RsbSUbidhJ&#s#azTy6xR z&ktBP%2i8=r0pvuFHMQd9N6^Yg!L@NUReelF6_)S7x~D_i08tP{IM1>Zm07k4D}yS zX~>2I1f}Qe){NZ+{({aJ7$2?;gFXVq2C9Sgp8bKuui??X$Tdp+15Iiy2Pe#>dD0N_ z9xPnj)u$3;$i(5YInT3H*O;R1ttH*q01Al5G^qOw!|@Dvq-eW7JEUTOBQ`z}v|IMt zieTu@zv474C_%wYC7NTjV05t7NUjKn-MC7ak$0n6vfyDTvmZN{@TshyIEUwO%7}H) zBo+TnSycf1;qeu=PxmOP8BFzwKOq%cxta_OSLk-|vZ;EqPA-esn2~uIb#PObU}G_N zS*2?&n{*ZSGMQ?ZD=l`1KR&?`|Ao!d#I4v!e6h5@>pg_-p@?c!c=Q3}0^th#T>}nK z+n8mUC9xf(MzM-%l(KnPLyMO~qn9(!Pkmb~o^@@)Y&$~&435y|tlVo$+I+FYGXb@djH+Z;i z;fvoP{m{s-az#6gN}}tYZVlSp_Og#x;n9=t@`uN~?F1v9+34QDe})5uWVjv4M;b}A zDizLJ;Fe%|{swirqdBtQlJ}RNCw*iT#U|?JrB>_%B-LS37d#TiX-xm$r zU$8YRH(#g$lF?|e1232myp|Ja8-V^qp`BWzS_L881Vkf-IkD2_s%7DENnDTf3zd0K zajL%q3uJ5=^C_R&QzI|;%dhXIc(N==tk$3}*$>hc$I?I3(#BjC=}&DxwKgRjZznj` zGlMwzAG>5~?Ul5ZDq)txyr3rv_=S0g7L1i^b6dV)!j<83&4Zb8T3O6Ck(AjigQE=` z2>7uzV^R&ZWa`18d1@29uLD?>|2loef_gwxI#$k?8{#4R%3dTSS|D_P_?eS#CbU6l zOBzxsYe|+6?a!mHA(+t$83%v>_TL3@gWRwdsH594{kQ}%x()%~_o)J04o$VI%Tq+j zG)1HT@>Yx4eery8+>NQiuByc#8JZ~`ra|>eM&mo&!~LnEH^7JZ2Ol92tcv^s2cmzyJA~%I>rrz&6IeBIp}o&} zAKVnMn7^A-p+$1^{Fy;b0NVgPAUc#>$z%im9tOJML9W3ysp8>5@ ziByiffSI$r9*xg3DT)qi{XvcR;ax=o6e{ZQq5l`{C zn)(rv<}3Aa?{FyZpCF}-6jY(nB8}BDSFrVI%TO@Nlg(5!wKzAsYApw@f=S+|kJhY( z1uvHB4kMke0|%#7ms1Kj8<68X%+OBAPsS*nrhI>V08c_+9@7n@2jL(NH6UBRHo4_% zd1QF3=BEU z&2F{vkjkiPs6c3XD`zu$nJRqiR8A7tRg_b-jJu@DZlbNztl&`t1gPk z`##CAAIOVEqD+=%Kj1tqgd|oft-zGb+IGzV6>EdwYN!Z+Wm6PV1ELNUyIRl)&F@{0f%1F8H^ zpyxV~+bZho+s)AdC%1~v&`ErTDNYU-kH!wKHDUR9n%v~Wb?FR0>4E4ZE*#r#$`@(e zMRh!i|Hcy0c0F0#*y_mSLG7wNKLz;>JKjibo zI#F&=9u%&CstjRhshD7}BlYYqN3IFl-PQ$XT%S^G@-P`SkvFjkEF@EqYtqK2B$}kP z{A;ZPM>}5W(^2R{S)Z2cm|#E$JvnoX?gB;4}+^L+v&JX=envQvm9S`;UfVdwGp%kYb>^<2XYRsjgO@l5bL6{ ziDY_aSoryppY5dvoZVSk8m|JoBHHqx1NCigDzKrsGxV!kR7p)NX!9Uh6hCFUe)I*% z*6;7|#Fqwx;cM!TpxgPpf-~M1pR`P8bE0GNB8Y}w6VUyEtmpB|56Xv`9vXMyTCN=X z*=p8|^#z2-t@*Q-`*wQyADu{q`R1))(-V9PHb1_$%j{h_>cHmBrCG-A!Q3)H5ALKU z8&jcvvs4_>;O@OaYv3iHUV0&Z!a8cNN;jv_tJF&=UfK!BcmCK1FL&<+L>cg@M|uSc zrIX;4EvL0tnD@Slc{<8}eRx~PS073=Grur(NoQJ635dk(^_J^XC^OC>AOLSTRwEPM z*@j1eU#=L^8PK8qm5wji3ASj8zNL5Z$C-~d=shiX7&@Xbb^n>VrzWpCgnlOzJq=kX z{aW;&&^>cZ?NF`!g>`$Y&zJmti7j3bbC~<0h!iint*PjDEnZuzx<*MGYzk?&lZ~fG zeJ0^GEiyz_cbr0Crl1z>+iqEMAtZ|S+88M;}LH7}p>6d1x*sb&8rzX2| zz>{1`4!Me>kXgCp z57kkYzlj>2TEQ;EI;AiWyjEWr>{B&G-R1GbzHSy?9we01s7zAlTxQcyB|^oh7}g3Y zA4l>bephYPE?oo%!N8whJGX-CYJ!k`GK%jbW4Y7np)z?+9g<=EqXOU;Mut>fz^yFX zEeW~iRfnF`&cnNQu7&!*sg*-BHU`**zS5wAb5m^@GKf;_G-zD>xDt&o`46w{Y$OaH zu<#XTx|FVjq&F-WaqAJrM0i)ATQ31Oa6ChjTa?7UV8y3D8438$Vk;8AS1#>Vqm5AQ zCT$~LaX8Ds|2Xl6;%ReL5LDP`OiDk@8z^%kK&Q-n8ARL|rh znqP0mSXCmDc@AV8euHqOqHB;0MNw-aYc(odN)nlS#_1iDR@U1~HM_1U?MkJWm6F3C znQVR8mZ`c4^8=1yL^U7L{o6|ZOV}spZ0!{3`2r7UesSq7F|TsG#w>b#hdqxv%t?AQ zHp@N-Bm)Nxs=@SUH=JTL8*NhXD45Q%Pa<9v-%7mh{{MxIa?io#NE}i5**e@O5M5VX zka69m(NYQ2Zx@Svx!bhP$dLdC3lOXmDWcRqdcR{(k2W51KZe39OvW_*a&aEN(um3l zIp8f90otJ`*;Bi35?5`{OJtB6pLaeZB_gqZf(ay3`FUIm&}5n`Z7a>NmI<50g9J2V zYd$B*j#>;-eIBpY8pp7=IWcGTHe`GzU>DTIwM}V^1>~S!u%s`*v*FR3Uqt zgO-W`9BNbKa(Vvx&LDjyXOh;1wWQ)Phs~g~^wKJu4{)EQWGP`LzS{-bWH!Ldg zRsP4(LJ8@N!JTU{rhKS^?CTgVLg8u+d|$F$`CB3dOPtj;N+9{9a5?hc+dK;Bo%BY{ z+j@!y(s79E!WOzU3EMb=KyNbY{U`~tPla>@FK7^vO;n7gdW*&Ijv36}%P|wC2*w`W zMGQ|lmbk}#&SK~~TidnU0F(f7jb2Az^^w5^L!7qf`{&bPVGIq$_n0W<>vO_26wIvE zm|Jyd|Yg)LT+A!G7==<5KCj@^(!&`=T!gMdP-+}L7AqtU|BAj{b z9|o=8A&UyY(1s~3!YD+iYns^+@)zJ@jez$f4i^1r0+rokD_QrzqqEABcP#8YVKcbG zd2)~a;2x|Z*478H*7Ee$rJi#{LH_=SCVQo1Pi|Cb@XCznZ{iLWL~iiG&0TkivV&Y4 z9{O$F9~Rd!2LTr``$?x+Wf$ZG-<2?`#YmHt&285UfR7DsvnjBio40m66t?h)PIxi8 zxzN|X_ai3{i963GnP)#BQN4B(g>Q! z3Ubl;Uw8J0K&%iw0rrbs06PQ*H_FM-?~vDh^opd%BgZkd?oq{BNeoo ze5V}}ENOuM3piV5O_ARVj-!;lcz=!oqA{i`5q{q7NXO1@On=&tu1VJZ=^J(YET5`R zh3Am6zM%E;T={8xm8){3$iI+IZ?`>=HkI+Rl5mRl(0o?)3cc||19@>|O7)@vyf2iHB?}o4-ti&GiPNbo9n*d5 zw)xMuRJ>D9?XGz4I`b#JB78t{4*$sBf(|&a)27%tRtfyjo6i zA-((38YH0{!3$2dPTEZ&;0iFWcF(4Br%&4JhS<;*pO~#9`N)EKJ1@=r z%*s9RjYp4Y&JktC-tY6v0RC$}n{fBY5859jtrOZU&$sW=LA!82Qt$mhy$xoCH;Ael zV--DvA!!;2Ejr*0`n8UT)_m3QxvuZWJil~|A@VtlcW$FkA44^eK6aZATF=$&UahV%MiZroWpO8ASBO(hBe2 zXt3Wvs2Zpnts!{rpWGKB?&vNO;Jc7QGqt{%=v(tneOrREVXo$XUE%H%j7C{byWP&- zIbG2N>DK<(;BQF6n2}nZ080a_G>wFANk5(7OH`PO8vyblu?wsbeM4tDqI;k=Sq_Ew6w7 z9#HLYlcyMaYsaY9Mj?8&S*$GIwgnFM2jU|BP6(KZA*@AkGbgfit5#1HI-|TKBVNX- z_)n~2@u1x{B)-(VqKL=E@5sZ~u$s8%9~xi2sK?}9tBUNOXS|JT#UrQq6F@pz>p`v^ zbFj@LyM^bqRmkMbx0^*bTRr>^o|;=^KF0=h*Mv`;Ye>OUIZ-g5IPgk|s%MAiXy22j zViAw$jvp_%yhW^hZaqG!MQ(i_)LUSb#E>am<@E^21jpp0uR*^P*z(@`%E_`rwyy2N zJ}xvpqiu^BAxAv|gth@0WchU9&U?99veBJPt|0je1rTq>>9cc#fogLRcYd8vGZ;Wa z{-|<}kWenaV5@zVpC~?kVDjw-w=TA1^latwu=YSu3!00{ij;Phdz!P1VYRsV%>N`? zG3h-QhRPv?-OEX6D6NhYE>;8bsZ?_>f}?`@yRn=S^s`Og4ln}d=3hjBkqN0j?fB=$ zFTh~{JM+y(WZm)F1cukt+XWbOVh^u^OafT0Ff`%@R3)We8FBshQ2H6Zqn-8rv~w6y z??U&<-k4(5lSZ%A$PRkbH)%odmrCZA-FEpR(NGDI=ZiwBr31|(Wt@H z)UuZbA2guYjposMf`!cXl8EvEqyO%1Yb5FexUaU~5yDy*e?P*-i9vGS+tk@NWkn-8{77h+eSJ665dVfNW1fUWuokuTwXgv!GQc@7pU33^Z zBPJzRzozV3MOTkM-mR*R(R2$T+k6Z@a7UWxOB(JwM{k zIg~A2E(*O~Q>r3zo*dg@E#IpeF6->ev2H~?#6iX>JOLrnwb@xLu3sV%e#PBRM!a+lzK;zOOs8XiESio;|qd`@+VA* zlR2IdhSM8+PO^YhFP#w$l?rzjy1>C0vjKe3C?eAOg#0YiaRM zjk5V#UneK+l^>US`SP+v99WViv&jUD9UnG?EAC=%QHx8{$k_MR-!K4~;+3XPm{;lp zuv=-XAuCz4FtWXQyes#+oM8ZE77X~$2bp%$1~Y`jx#Ef>)w>^v3L&4HmbJsgr;Qkii5elDiBsK>tV>%RhUdp)+rSAI{&r&L80xEKMIpa|(*0(h=FD5|k44Ld#cI9cV7&V^nFovxg)JpFhi6Hse zP{rxE903JKn!vkvf1fY}*jW;C21i_<_`G&_yrm;*upb;ZOw5R3=YaI(-STK9%LD82 z{qaCu?``YO;FHx8W4Ap7#+~S4^qYi5RmdMYRLAini|A3}}(!A=dTPEwI0xsWVt=S?~*o8?A#E zaX9nH#LO=cirddwjt^i|8romT%2;Xq$mcM~U6;nYw=goYgo}7;jdlW4--OIA5OTfJbHQiH2u~dwAUcFsl zZ0jkmX+e$?ekL^Zj(L3HTzc64?A3bdOZLCWse2}a>%l%oz81^aXRp1%hF{0Vs%-kI z9RDIDu*n70v!5cx`}KL8O<6hDfCpkhXgxkRMFC#*ci(TRf|P3`flJHNDn&3d9g^nF z7OiP;x8HC`F;ZEj5L{EfiC7#m(ns2Fv`A6xFYpjU(fJg>8xfc6 zHH`b$jtEM6G`VK>A;O@TI8J^1%S|Kjaq_GaU-5;?h(y~dgGKpC?4yUgxK?C7f|zZ# z^0lre2f%dNT>_JJpV?H6R2~;#|6lH6SJe!Q4*A@eb#`g8hU&fP8tf69i~sgu54@}^ zuNx^ZZZ1grbo~v5k$?y-%$#a;@^2yo{5=M1 zc=?4&3!6Uuu(|>gdp1Nh3?5kXL_vx=4M#gP(4fjG_}twVVxW!kbz;<*8Zv}21S8m+uR}4BwxO)TPU$1{Oar4FN;~&0(+4%*GqyrQrL5J znh9c2S1ZN`>ayITCLt!8+qT;UU60QjGA#9^0$`q05I;Bu&7ws@eZRy0Pbiy8DclgE zQ7eLc=ohgGu4Q|OmOXRE&@wsols@7=**j<;-|n7O=1HnO$g`R-UHgB&NibV`8stQl zsA|g!gMgVKe@m0R*34L!!#4Us%;EDLVU2Z@VH#my?!k0ShmorqaaJtyO@$=rT!dj% z=8EVhcB|K+SvKlI+^Qx-hOpfX=HI;aSg{8vrSLJw`1+{u((QqAGU9ZRu6oRig{i&g0^P| zH9E~}%~qx%5%n@Kjw$P#g(=N8@#^^`AYxxRrVS5EwLh4z*Vl(OD~s3y4_%^~HKfd6@_sojZ;P11cNdHEOz4FQrd{Cw7g0!i(5NR>cpGBJ zu?lt}tzil~ty0KW@X}#+#&4d~DDgt59llbx>m^XVe~xe2L@mPOo6LE3OKW?P@1zP8 zC6Xm@ht`Yxu}g4?Lly44KFm!%pey|C_(VaUzyLu&zQ0h!tY9hWt{K=Ib)JPLXmX%X zKyZ^|USGf@pAgPs1~=G&n>aVpTweDrXjTW8k;y!j9K{dOI}bYfwM8YjIv7COP9B+d z)}`WB#^GpfSA&RbxJ_UQRX=&`iSu%j<;GT67?IndpbRhESRX3!^I)E^Q%)||vb_Tj z;U<4A2s3DVuj0YJ9>%>sM5(6<(yh(^<_(!eNzI~6kFH2`;O3a5E0Fr-y+4f&QKX$N z;qs2Z{TKwA>Q=m793uc+X(kF@C>1?%331__I>vL@db#Cp!xI1--*=#Ww&(_AfDSAV z+-)k=4Cnlqt{FjyYk^1bEj%i#4GOR7QHd(@O%M zgo^nDor98^gCGsJle4*LEe$q2$#+cw1ifGEUeo!GqB!9Dsir7E2}VFPZ!(E4yIHk=kdlBcL`{(q(97V=KD|cp?3uJI{;Lv%&>+fW5|e9 zELbcvy#l8h=U@rpe#4M62r{;9U?o~K8RrW|4>L4xccKGnT+>R8N(qv8V*;O`kacbxQq2IB{AHUop}0ZKS;5SGK$%+_ z2Sr=gD)nX@ecAVsn!Gt2>1B8u`(r>X%Oz@{d`CZ<_Ac(wj7>=J91bXo!vqT`pH z$z5(pz=D^ia%%Fz1az02SjIeo2VL6P-h76%gPoEd<3eKgXdixY=ancFuy8y&XJds;! zOr5@TVg^?0IWaQ*@eX)D7|+GZafTu#nNj91JuS47K|1RAAGpr?2LcE+R1V6$E83WA zwq6c4^S9Mz=6CbAew3xWt8~f$szVKpfN&alfw^J>h=pp_(ld<1R0aIY-y2@+rUQe; z2ztjuf;!k42Zrw2aTM>$c}x(6mp{l80b;y$W5-8@MEg|$a&>!#mzTWgP4uW9&zMTi zb|l==$rym$6I&du^q_YbO1WpkI_2h7A5?UzBswL((+4ZV0!yfiKtR#&#{W=@$Yll$ z*7c@cTk)N(_JVXJ8LQ_lE{>?uCOT?7YqKU(k$)gwMU{*p&ZJ`9nhb2X%@G>x2z%Q& zv%jE7ugv*hX*v~YKR?z!rV=EZ>nyVNg5k)-fom5S$h7O5`4WZ*9^s#jsciW`9 zFLeem$7>fnICc;Mmklf!M_u}HWL)99HWgUMALa?GleB_=BBqS9N11x~tKEX_+`@-n zbNBMo`ESfN2Wn-u{XBau7nA@{C>2TGeeZ_`5CsrQdC zN7x9{TiW@wMQ4hUlB*S)@`y@eLWQ?(f2yS@}s&Od0v zvGr9uMW5S56gYAV_7;Ng4+!eO1kyl3Q({VVd|N5+X=me4@fX$rH&~-H&I-^iIcMh? z4?67PX(r57l*g&^fMv%r8nyxW0BBX_fJ`V(!g|+JhQr( z9&JIWFpi?jR|sx?>-*xSnN5J|S;3bC?p1dAF=QYmI0GV#^*!;;-*{SJ)3tq61iSxh zT%YsRrr1iws}7MQuVr3{v`m79Uy5f0I)7kR3a!mp)x!hCySkWIVWlUO9EH3EnLU-z z1~2^YqVMP5v5gQ)br(J|_)rt~L9og-p>u|6XUQu(SdsEzC0RmLCMvet_@q<^FuR^n z!7zf3Rdidhk7{3y3%FEaHe6Wj0yf2saNS@V|0c|NyyW=H_X7*4Dn@iDl_h5N{A+wZ z|B2~%L$-_Kf%DBAS1NV9xE|*_RaH>KeR|UvOrs@`C|G~#5BMg1j+Etp-TtnSuN{MR2}Gvgy$1MD7`b^@ESENYu5AU}2T9QB5J7 z_q&v-cu}SX!W6ch+CFP5j3NWO6F@hgX9``E7INr;tLgGtHL{%gqz=Xj(+3&Bk&JLa zz6ifn9u1R&dpq>zCs{WD02J9#a4{KRCRb#MB1o!vFE=nCYhY&B;c<1Y60vkQSQTh)-UpV}G~1d>$AlRa$_Xo;njKbyW@+ZfDB&EK zGH=1ss9DRMohtX#gfP&CmqR8`+-~#qx$w#ZL;RG_I(Tz19b7;A3w+@*rgP_mFvYtK z_s1bDmhJKlkGXM^Qx>TRni%$ax4BQ7N_+%lYVG|o(pJ`)VCu#zaPE<@fO)OXsqt{* ze|qn_aFDRRhfS5_LY#tRZ>diioD0Y3<#fWlC=+?2d$%dPtjgpn&X?oir5EtYkZM=O zo&^i8Ih|7&{r>FyP9FS-&)HWGi}`X+Jf-@!0wEF{TS>mAw56+R17rvejQ8w))`1(L z6yTBZj4WEv;ek<-`(j||;8|_QpzdHeMj*mW1)6BmO8^K6kPA@DQe&aO)M{VN zpsnoK$BG_M59QXFpa^iO_=6Uo?bQ-6-8+D5W&W!|8c?)Q(q%HPbIc^ZEKFyHLt2h3sQNW^g1`TteSaM*njywzLtxoIz>w5p6v7{y8a5 zCBoGjtky&!rggD%wfF5EN0J*XA0QPlm?G;BiupR%6g;QcCz2}>M;tDg#=+Q5_Enx* z|CdAh7&Qdqx)&Cb(=t}^0o7%zpr?BzyAs%&aM!$}SWG%&C7uAt8tBi4g3dqwSbu*; z7lL@N**2aj8NY~x=hTTRCqe*a)arSGB70lL7E&u#zs(McI@{1B)z*&{ZI+q~SB00s zb3B8H43P1U2uJIQD}D-UJ{`)SZTUoBpX3Lx(|1-e`Kn1+!xZa8{#ir)8L#=%V(!-U zLxP4vJ!x}F>haHFr6U-t_Km2r!elZ|r4s{w&dlUcme5dn`A)UMFgR&L&}InS-ZD~m zqVR!e0-raP>~1Ua97FKpTC|{}WT%t2!cN{zujV?F4TgL)6JH`GRQPeiTURoDX!*2u>~Fi=aer9ipx<@_U0 zX6y$YI>%0Cwae|8_oBpv{^d{p7a%9J?-zLs4YA#Y6knpiUUYvsWu~@OAOAv=&sDXr z$Yc=ViH7y@v15)AvaZxpf#+%d$W)ajtrEjiX7iBisTs$5rmDsVI%TTqN|(gmmZu8? z$v_3$*`-t^9po$f>S!O&ng(poQH8P5_2B3u-&o+gj~dCxj(6Bst!Rl7hL#`IiB^+= z-1}2Z2Sbc>227-R9*Vo9v5i|Z>U`TW$;)y}Nk5})#$8tK&p*b@K2ql)RwWK$=*UiRu+Q~&XGkn=W*595sQsD3PT zl&F@H2}J@=F)P}y0$EhN(NV(*E<-lqC;~~TFiQtSdc4Cw^;;N~Z#bugBSdHwrwR&P zS^SGS<4`^*CJ_K|5fik()H|W2G+sA`H^iB!E{fTQVEB6mtTd{hQf_&>Lo1GzS$F6&rjmi#caV)U?w2~j{B-nVaK9HKd#%AAG8cs)w zlEJo>o%!kS4~~?KuTRjUp)#<}6QV}2OMN^(;up=Bg?gcm@YPNSI4ra5Ekb)8lU3GY|qI`*R^mi9&_8{HThYC%g`-vzqhD>utJ z-R)3$4>jI4xBEy~z{UB^coQnG4)c5hX;YX;f~W8t;x_A>oV-PqW^;*W#eyg}UlW{l zbekaVDPYb;V@XqP2r_nKKUvxV;!xlv^?6BP>%TZsck4ec;N#AUVV$U@1zQG>#s9iK zKCbdug;i0kIT^392D3vXIY2Y{KC#{_zqGg`^& zD;Q)e2uvdmN%=M2Ac70pMPQ?2n#$mA<)sfX`N=htxC((2%hkR`Vsc%_g5Ui=|FUtD z46F0)$uCqexROcmR@JT&h^R*yb~q9=a8+A@Ds{er@YAK8Qozgu){WXt&0+;8okRiz zI&KWJB;_6}#WBK}M^AW!u(1Yp0@h~aE_+Q=1VX6umMBpvy`fcCu$SF(L#;}T&uSe-ww(d zx~HleYW$SQDq*X=^iaZd`OId@ z9-d>0rxM36Rx&Mi(zo}WazGf3Qp${J_&MgZRn2VEs)jP{I`&ff@wK35KDh7fqUocb z)QvB`r@$WMl=Y({(D*SZtjb@^d*%N3CjI7n>x;Z?m3~y^6{q|{EYOuC_~Q)v%)z3h z;U9TN=bo=ut-}1M;Ez?at_T~U{b;I{9fy`&(M!-?21VmT*{iARy*|}m2hH})%Wh!E zL_&bRsDVh9+c5~s29_UezH6MzMtlUa0`B4&?%{w)WpV(3Rf@#`b6E_1mInweDqT|V zII~dIEO#+>A{Uxh*VJK|ciQ|D9*E8@;YYZx^*W;PlRJpeVxg{Ho!E;e0FJaakdjxk zHU(rggw~MnX7Sv1%H9Bz%|)DJhfxA6?EA7FD48bB6Rd5D_l=1>`^8(rnZm7ocN&b3 z?GC*W0?wwXh$1Of`$WcpBB=RFk#I4S{JCa6%Y0qqmLSij+F9uIHDGDR77G7ttK$S_ z|KJ&%(9HnRlFM~3;A2`gSR9<1XNUY|p|K}!=8~J|8uHyF(1ym^d6@u5hAsZiBRv{H zOHg%}8BiKtn(}sMO${q~x+VQZ)7Lb^7eB+4^sHG)8KPysFCxV4<_cEi$|9snYppMh;VEH8GY6OpytFXAE_@$Y($9n{buc+xCN3w#MynO~$vmaEbty4@n>Axb zL(ccy<7a(zvwsZ9a*DR&saxhSk*{-JS<*58^`Y z>Llh1#dwIY_yk#ZBf~-AvK4-kyxI+P!yz@GJWk@ee`+NxbtNNwXSzjiNIPchbi3o- z+0TDx40)u|P@FeWO}5Ao>?O$(W8syqs$14|8rBh^SkSoo&9)eqli<{80h~?=n^r3e zIx~oTP$n{|tIG>aFkgjp^lrhsTOvJ^@bNZcZzRAFRv82kgl%0n-SP|4p=3o}TwyO= z#Jal9YI1F|?0rtB7Vr=d)GeuQwC|#cu$EJqMyFd$h?<3NT%y2WX#ZSpRBFCg!U=@k zviyEdyKp+L7YT|R3IbGy8BF%06v*4xetH_pM9 z+}7c>J-td;9ES#UJMSda#Rj|`{icU(0l(>rXU$Z_Zth8i?E+(BA-><)MI870`E>@< zhb+wKjeXXJVg$nFtZ}&v=@*`aoV@hHb-g&G5(P5!yE}%jM z$Z7luPeCS89G`{n0GICDewxB$F~>YFxULHV1G2+0n1;w-iLZNcnzLJVIJ1IXn4SXmQ^lRZRkKN*^HvFF%zcQGS^*DHG zS#WI@jG&(6f3a|8;FzyanmDB+tR7&duUjGp3LZEdb&A=Nlnmz?0c+HxbJ6DkrO$j^ z_kP&_j>$M>tEpC;;$vFYo}|b?J!Fr05kTvu_VMv0uopQt7d@j1A^c^tgbr03rs-Fn z%jQb%oC{uE-0i^TU=ne5dM0$6X$63LAk`er@0IltUByuctnCTaR|u|ER5*6~Yj{xg zq1u{Y4>Tj@tuT3;Q=cjlhu~W74s$wHUL2AZC?D^OcKu&F{2D=t3Lm;dZ1@G00FoK9 zUQr}D%$MGiQ)t%538~(Dn0oj|%3FA(PZ~+1Qu-(Wjs}vBSU~O#r>jgo%Zgq$bS#@>3YPV~*$FETSwbkXv{HCMbc~mF&3CNKN|eXSaTqO3%vX>21d>rCwAlYY zLp0*5$^pbSIQqgXxYHTW`=WXa#C-WA=zvxho+z5#?24%?)XrH-4;YY{x;KTEN62`- z)VaeXIP9_uL3Eu|c1Z|cn$r(U3~;6&tx>{fCZ*l=AhT?XO_pAkN0%gN& z@5eb?;IV3@;=-IKAh@zhX@lK0?x#l4EelLgs`jDtxn;`=9)+-XIc;Z+B<-wSg~^A} z5EF~a51iT~KJE3(j>-m02WrT?x0&zm0oJO4tl6@QQCIiP3wVNey|>*@SMocwj_WH= zS;CQtGz(jAE)WXhT`4*0@p-Y1QhT~)IQ&`zUsY+Cp*g%C&h?=ROL3VRoj6A8`#(N? zcaxf&gkp%aj>U`?RrM@tjvnT83SDZ)(HjuvqyR!Ox;-V=GziibMG=|Fq(8&tLXQSqPe9nTnoJ}U z_Aii+RN)M`ldiw6XX{~uEbv-550d)gE{2ku13|b9l5iiE4bx&Yta$IM1E3^UtEO9D zo~0j7qg_{Sb^e?;bU20vRRgk2?0i@^<~9y-ye5fWkQ9IzEmfXINV|eEPn}^c2}q1l zgyVraI$%!fM--mze6pq!uUb8dCeUWi?Nq?MoH9&>MMLbYDbi0p+HE@p|ht)eK z$$&kfw^@Z2^AGx6h;oqOSAwgg2m;Aa}qG{xIBd^^Bi` zauW3s4EZi;rd;?ZJY3{(=%bm9SrzJ4v{XVf?$RuV109NsW}Hj zqRyi}jU(Gp;V(YG7S#O^@-A0d^QigR6BP(1IlkAl&dS=dq^~311Vs^yUdlha=cZfS z2GqxY{I>~W@iGTq4oM}&Py3xy)Hl`0zPN#&3vqn;%05Z38Gurj5xcUG$NL8B zygeD(%g~s}w;PQ`9kr#F2F)srOqFXM=W40S6wl0_N~!i(EYLm!7dP#asA9%vg z$_}zwpNjav>&R)rqlIqw63WoN*aYuAK;Ip%8QhVXIonQm2-?q&P_q7fk)QBpInYEG z+EY9QdKT6{<>Y!Nc88&%D}m@4RjARIXkwCd)NBWL$U~F>%^n_{(2!yN#34F1o0l1a z5qRpy7JsGR*9M%DtD7(!&%-$QV**D_;<2psMCWg~pR;wqTm1e401&|PQQL)n(}E>& ziW4BsQ*A^1OyqvTZZ+cFz&Bt@<#u;(Gi*~%H;IbqmD5*ldA0VB6~sxd!)`b} z(mM|g&wQYP#62!>=NBl?u%#DDn6!r{DCQyG$DpKg`aLZ`?fl5{*$lCH!c)EjG%LNX zxHNqXfPd^lXPLTGlQ9kr{{}t zGk6R7kEl&qE+&(LlGO9xw}sA*DQH-5tHab@lK0h|ip{bPPw78P|Yq0m+L`FvQz8dfZf5Gzb2cDy(6R>2D2x@&}7143?TjhR;O`IH;g);NRXGbv% zV%%PlY=5e#6>M^v4M3V_c0ZXe_HfvR&Z%Z|jZR<86Qt6-Lmr+1HzN7A_**K1E_iON zo@g$_CyPiOFdRjRA18_+CxcW^(*TZ0CZ3G$N}V#S0iX!PD!LJ>9AKkLfl4}xjVEgZ zh|7#Vh1l6wOmp#k)oraE)pJ^j`89!~5^lur%CN;nBuT4XlogZZttiIXgAx^7HB+&2 zL($6+7^=Z{9o)Z-x8fpo___I?9;T6D;Dnz8@nyN3#j+5AGDdoTIwzEzggwOffj!|k ziWInlaD1Crq=HX^s%C%JZJ7onv_=3Ut+;$Kq|MC@oQXZ~A8#fC2J{LCZ(S9|`ZEUH z5ShL-<{z*%Cv3ey|W2ZN{L+|y<9xLF) z!eNc3h*TfspK95ewyN9vl4)Nlmd^o^eEfqkakxvUzMQM=7t>frLMk7Dpi}Iu3B1o< zjAkeLC(GV9-FT$ynQy1`)(BY?bKvM!VfJuZgvMmSjq-8^ER?V(f6$-iuzkc+bRu?Q+LSBnQ=!m=E zmdr-y3U6x+Y7MW6bjV>(nE0*ZGnool#ab47L60CdlJXf+&gV69V*O6`es%J+GgO;i zX2qHMB_jnUhWcp)WtkKxS?S7p_iOQtrYh6>uC2x7zg`dmN)ALf0_6bksbp^ch0v>% zBAd7>T!{wC=?Y{Y`bjicTz+~4h@G8bm_h)wQPxp#lUjdBC2093*I@M}cpWJ4e2UIV zlVuT>-@#NMF39FDkp=>ZvT=mss7YbAn`%fVq1Ski^u4h`Yo89FGs($ZU?BuKm0RCB z1i@|0d2DrzV*8WwpO-)!3;p?(d8yK|U^0zc9-Ucyu98^QwA>iLjd%Gl&ym!Zf||@U z$VM_oxXJcsXCJ_U$d;Uf|3xABau(I11V@W`;Q^Nuj%eXgdFz}@`fv3SkX-CP%|f?9 z)U%^GFhAj+5=L-vPvq8u@1?JgAsQQVq2WbuFw+PnomqUvg~3>$i!#J#xK>9`Ta#1B~7P2 zCdC_DEN>Ho`EV#1s6i;RiUM{}!h1P&WzT!50FE5?7Q?_R@0)l{5jwD;_WNNcz+~gE z6_oeiH24%m0|u8@i_uw4yk8<@dHl=ZTOv z4uZs@Mpo5fncBT5-HTT3#CZBxKf?#-_rCO7NqWCcO_o@L?d!lELLzN-5zxB?J6bGm zRgF@2j*EV4HL5{q3YuExq?uaa(Q7OBTXJ%bbP*yfFB*ABs;tRJ^UA2zrgg#XD3vFH zjz%TA87Kzqc!$;1`?pmsA`krf9-f(HLKZ9g^iIJG zbRhoYyuw#LI5_YT!MLF^kxIs>vF^Y8lXp=4izGL#Ui)VTIv+*GL{5B+V7SPYIC9k> z@+Z=5#CI~*p%J@)i}{#(Z$_}GVg1cWQc7-xRHKuy&bVS32IlKk1n~Ub?rT9>sJ2jy zrO30dGVB5mB?FJf^{gP34xO7~RwRHR$&Fy2m7yqnXyF}@Ucujh<(a!P_vrBR z1-}XojMvviQB(q3@2pv@C^O*=F8`N;)C&gcSxvkKVmNH7-G*j_Gc3eRoO_s;W=?#Q zC3FGe(!0pIpVs54;*xTufu4P+j$ps`GbTvmp zH?jtGp+UK2a$^y@JTI-y`?vf)%}BSqu9Eq}o8kTU~v=V^okQ z%dETF^dL*=w?A!PrD{2Qh@69z zXHtVtGBtX(BXv{=G&5$~L-Ezr3Xd=*rP z?Oac?t!|WD)zNGMvqxYJKp~08b{igl)`3O z+I)NhezT^H-_mjN49#rxW~uytfzQ(?3l8q{QAtKvrJexf)(9T5$hhBGZuy>R{BjtB z9af9e0oRGr#mnKb#r=|X1yq@O9y!aVB|k0=ku>0S>U^n*B_NN(@*m&E1N|to_!A*} zBJGUDZU*!aBEFqM_PXC0qZ&^)m7(lb(0dkB8d++A-p`PeeYDpr9 z2*U2*NbL8ek&6UQlxqx$dZQ7*(2_+79N&YeGdsdCcilSCrbdyIS4#mHC7?(|wl;>0 zbU~{0xsRA0pe$QE!{K`H#=F#NZ}7n=yb2?|zW^kr{uJ@5Grl`bt_IICwu-<#VR zgRWbs;p~prZZRCOxip~H6V4l))#s>YUqPtCzGf=CSW7MdD_2|Uy4SQ_+kKE%uwLbQ z4O599V^e%*&;*_aou){uWv~SP`Obs7P(Fc({n*r7c_8J{An6g*UaD)xscG{l!0(K% z@Rd+Hd`x##azE(Z!*q0mEaO%AYceSC?I<{0=2Kc*i>S zF-5cNB(j714Sr9RSN82jv^B(FIS=~j@Pygl+gxVuej^&O-(CpcoW#mB+|QwBYFvrP zIY!VtOHEXbX9p9Z3qgsg1){Kb9X?8cT@B7dx(5Mf9gE3amF$X$#Taw01`a%ohb@-g z>X@`zmSf_(W+t;e*%DeG$j79L!mW?;Y%Ak05~8g~%X*_#;VP%m8l)2%VchFWJ6=i^ zYq?s{K2Da!rrGJ9bPk7^btsv<-o>9hkb)oEpA!PQ^=(@QAE?uMjfI29w4Q98x!yn zJ@O}>;*X48lTJPxA!eyD^anr%p)qJCmR#jlA2m=MUF-BrcX~(*<3upwm6{%hq(LSr zTEV-5vxVew+XE3Efp?Ec_&sfwe!<~WUHM%f z&@B1#q++WgJoyU?@a|}gW`o2Eg(pLnv|sB!2yaqC2jDf8D!_~go4V4@`V#2CPq7?=&^32*&_^jH9sLy3`&W=3a1nCHSEJF1{inJ}n?N*?n8 z@At7)r)tDXtp#E;BaN-`zkNjyI}5sNeoH7BjYa1)AYx?ghSyjo&*q0U^n?<16V0lt zR|H!$Okh!R^eIpqVOknrbS=GtX#jAg>;=gcunbL*jTPRNpx6*va0DYsk-tYE@vEW| z&`{#`wME{xvJ%=d+6!d^8O6#i>8Q$-{e+m?HKahmWVCF5s2C{hdY_Yd=@D{5e;MF@TtBgj_HcKfEBiFxm ztLM~G`5=wV(C9_A}Xj+ER7$(e8tWs%$v@(X19?Z^yCRp zx=Ebo9P2k*NaP_E>C7mzr!RbW1t*H{Xp92^oo&G#9hC-=k`g_{{T;}0KK>UAL&vIC z)#N9qZieyff|2T+&dFR)6i^Cdc;&1+^jJB=0zMwLrjcJtX+I+{oX!9|t76h+cm|w5 zW7DvA`o?Qq9@JHM0>t*WR*UEIG2MaSuoqo$%~fCd7v<#4yS01y;m_32Eh0gPYm#A&&O!+;)#ME%hbuaHe3}B zVXma>^5Vi{d=FGpdZUxl?$gKk%j85@XzTTJd?!kR(uAcC(8=LXON(GLQ(0siMPA&y zOD9IJz~J(uxAHeW<9PhKr>_&2SI+jL;bzl)Ohis~i1e}VsTI3}T46i*_JKBZ;?jvH z%lQjeYaGQgM@mw)IYRfWBFIhRWzRuR@EJYmT-b-iPorSh{kqf#9F~Lw0tYf&t2%&~ z%)5ASs8qe-*vCtkon?3o*^O5|-YXePS*{&+zQ>4+T4MnlBZx>U<2#vz^?PAg2d>`K z_n;|-j~TOVPxHCpHN6YD8?~JaP9`at+zyz*2U^Jwz90+sA~p3QS)M3LYw_>c^AI!U zN?U*x%Ny}YipTm>a3m9naJQ#~0G8&iLPcgH$JO=J2k_z81)>=Wx|mDwi$C~+!CSch zK{p=i9ZwVVzaQok2gru5*xwA|9uRr?sL;cV@jB~@Z|jYgI?ULq>_LQ~akOR(3=eeo z1-fq&F&eGT3CeiKrI!%8Lu!bnC4|t-Gg^2F%SC5XdCF6wyUE5g-Wlf;gAdS-+Z0_T z^6oalF8?qaVLsKMK`ep0iS!i}8PEu4 zM-dr6?3TKR54Ugaba+i5tg6h$}GolCyJDR6Bq_KUXkwBNFC@xE5PZ zfMFBBdZoPhN85O}B>|wQo>>>_7E}sxL@WuB5dvU0%Y=>Ctk`;KP)Q!Y=AJCx@{-Cc zDD@Enf0lBWyk68vtkp28`k4NrU|3aS*S_%mvffx3sY-u3PwUyoPl`48FZ72wGGRf6 z_D<(!+mV8gG>JjfA@KsE{PT}VVxE6VNM%mHSiIp;5Uu0m2K*R|J+1|PZ4)Fm-s~RF zdJD{Ubu0e5_NTA0Y=!OlbuHyA%HT8T=vF04vJjS0+5CDlJd&1s4QXN$cV_jDy?6iTG zvo$)!UG`#-86&~-&*MKCUosuc-h*NHQ}}J49*=3i-OEpj$!$m}YuQC=QSCcEZYrBsU8~%Y=scv>sj8r~x2WW|N&}N>g_ci23B^C&&^IH+gC{ zt~^0Xl9<+3p2rLwjf(dWJf{C@#MVrnghAE%KGreEYo`HS$0!L0KKsZ&hFUo8^Djc?OsUsM_0jk!N@IxQ(iI^ z6i8Y)IzGc;>ae6e?HOvSG+{)~@)fI1)8dhOe^)hbgwOOWI>R)%7BSYR&c1}nF}^0z zGC(UwJo)poLe!97_ytQ7pzy8V{Te59HXd*dEij|toeic1TF0OWe@ak7m~PEqd*+WV z&I_AGol=FaT5cX1D-ScDo#1azoeXh5k8l|`T(I5}A|5i#$FuS;QT{pFzzOJYrw>|y z6hns9sstQRU>mO(;%#~_j-4bqrs{N}uqwFBo%IGT!b(uYqd6>czZ)j^RH)bhvf2@y z{f38c&{J2W@|xbrSTkM_&~>K?9@TFIUD7llgKLp~Zit&Pf6Uq@C+bFT6M;N^1dw$s z|NcHu)q@B8m%UYjjj8|fD2l}>lt_Y%>JFavxE~h(2BtaKH=Z{KG4=0lKO#4>V;?8Q z>w7{uu=2@~U211lSWq-nTaI!KQMAt>@D9JW8f7eFT3<8g^tRpoz>{x>=Ld2R+$gBk z36%jtndSO2F=8^Q(NSF=L1exyKeuQ@&DW&ukz=`+a>ri4-JOx4@o5$liiwYq-jIrU z7qVXi9C3>1b+<$UByw5og5&}<&GQ~Gc0OQ2OT}OO2T;-Q!0B;?Zv3AX5XAsbhh+)5 zCsn`6E;hW0@oQ3$=s{Ks)57KgEp=)ZHe}k?Nrs^$A=9&BcI+=oQq)^-p8Ki)@zt3$ zm8xd8;WyCJM>oW*NO1%u&6xYgBFLJ7jLd=uvDTVVGVKHH@!hD}gmxku8NgFy+3@__ z#r`@#`xiyj#6PFI?fV%)1Q^U2o?A*p>tOoGOHPAS(`j?32Wi8FNPur?8c8nYLM!FK z7FicKJE6h=zIX)i&!WKhw8bEOr}DsF8_W_qa<;4>Od|B>#A}p|nJ%q%l;ir`_eWe1 zvdtdi{#Qf7brw%;?>S%G0;|>lgKH7*ykI&;d|Bw2JIf7SXd}M48rO8hM?ZDUCN{g* z?uWlCVAV2_n|&XNY;A-;S@DJUiC@>Hb6sJ(l&#%GyOlVQEO95q-cUq;xF9{9S=e+FtyC|;M- zH-#5Z^eQBCeN*><>c7-nF`RRbcO)sh)UWmNYWMEm?jlMyWB{qcQ<)+4d4F%>fsm%I zu%Q*Kfl>fm%^X<)^ml?5OPT?04e8(e*!5Ds#mh#<243n)m(;jzwqx2WWXdjfFF#|* zsuc`P=>An-CobP=qiRDc#h91y5+By9lb`ONPeK*PoR&8VUh2#f#Bw}nvTRUz_CG5z zJx4#Um*P>HRb&`aDjpWkO9Qt3WpDB#_K(jwfzLeZPffxx#mRvDGVC32NPYu^ph$z^ zRZ}Bre;4B4lxJ_~aaAvApR3Sw?GsZ4Qu-o}E$&B44*5r~55GWdL%vV;0naMZ(Ux)$8Sl)Mj9kGUROV zW2T<1pc{sM-J7}2Gj`Kw0{hlIE~y52%!c!B?71n}k6Tld0jOFYZ>vff@LOI&d+vZi>7}kV9#Q@r*ND{#mYhA_3dQQ~8(X3qKqRjtw-Fl6& zm92w{0Q#3w$FdN1{-~E_J$(#@1%YP}a7JzYNq%Kc-$byopafu6lKx{=(t zC;FxsCJ9*CDs1#ur6on=>yrDK@tjynNyY|uf(C2iE!_l<);)Aw(arz+JBV-mqQ@g6 zADmvmgPD9m8_#TIX{>*Gi|F7kccPgEl^~LQv2RV*YqAuQAf0VCIC;T=mZ6 z%HvzG!6kk!&aLnplYG|I3~s!OASUM7twaKpx=i>M)D9=9mHoe{Ti%Ug*PEIvB*6v$ zAbCE#(xTgb(0^@8L$OShVJClJZ&M}zzJWBWyp-f1Ovq33pwuv%CXpyPrJ}(`RcctF z-9ayNQTHWV*GSaiKAT_keI=%ob3-#Z_tOX`{uN1W^ieNnJCKTqXL0wnCNg=vjW5r_ z7GHc8sJVb2-{LnMXt6ate>%Pko+ETn6l*5?mkt8Ho=b#udx#DX1G}X1;J3Ht8E1V| zAc@>mDkMUG7P!&D*);?8;NNRhRFAW#nKM}njL|eQRlcFXYjiNi1{fh7c&GXnLdw7A zp{F^`@qaIp)y@!e?%LR1pP(mUx(D!yCtz?C_T_S2+E#29f+ZL79q3 z`^P+icmSYf?&ntj^Rif@pBhYS)(<`bhj%T&AUWyk*>q3C*r-QOeD3v^i)Tl!`9A?*DRA`Ytt4+l=Q>c1?N>!5v;wsXA*U|QQ= z>1WuTRae`?_ye=u2y_8t!(AID!p2iLWDy1W?{~XcV#>NF#cUVIZ99gLx)>!-dsa6o z6c4J_Rc*?u$o}fbmDn?UGL^~F-#H(QEjB{+J=rQ7+7K;5w?!aHV@f6&BTS6I6S~@xU=4VvPP{S zFOoTk8Eqa7ftEIj-<0&@$2JCF*Uw^oZOhtqq z0PhUs3EfO-=1<6h8qjg|bd-NVtJzBiiw5k@{Hb(L2WN)5hB3vQ&JNFD@QO4*>N0NO6QMu<}2#W9y`81wiF^$b)q{->77vMIbPJ)+9o9M8v@Np5|9-@M4t<51y{5au`dq>%$uDoh>9@wUQ=i#TTAh(^szUU~Dq z*7yr8aUJK*&>TOuAfb{XjMV4|k8m1gIV?-+wkfCc^f6+alB-?+KqQK!>rMS=Zo2f3 zm(&0yF$A0sc%a)W(m&dS>wXs^=mQhoh3{+x~q;mVE` zG&ipv!AFscKvENa9>o9tdpe`?Y24rV-)Ja->SnNhJy3k8oM^Q^TH%I}zcMzRLOmB0 z=?r&XJsd~FzUpPu0aHW807(Xr?R(S;hFR7MvXLIi!m5N3zOO~58_LfU@#)doimA9R z0UyQxz|r_H{Ah4&O^r5;FOJrkN&x2^Zl8@gOQ*7UT%b!?ket-|;$=tF`cfn+72#0v~ z2jS6b8x@>whzazLCCC{Ilw7I2Gk!ks$O)&=@V@uE#G+a-too2rW(VqTx&166nZ(j^ ze24Cgl4iuDoG2d$>M>E3-ff{bw0cjc)0%rNP@&IOx@shFEI zEItBR7@x%dP72|j^msOkFlcIwOPs&5tBvZX^i{KlfQ`lPvku+VA2~4(QFMf$KA#5j zw!l-+Q1Fl4Z5>|kifJp?KvJj?%_#AMk~8l54g`bF0KyuWhAA=^e6kTN2ZWu~xeXe2 z22+=Gok%W?>NMK`!8oN6>F*&Lbvs|5ji6HgN}?U~A-%}lxv#6o2ILuc^4GEn0G0hA zz{8&TA6V)Wab&Rv(;;UvU}UYo^NSGzjgoxKpyn5-*S*r*bw5h&rXHyHboq+W{8?&- z5tmBU@a9*uic}~13!1mI>JyoG+2^meL$DIM07V#<;V6|L)+cEM3_H4l4A%sCN{63Z zV#$Sj_c{~5mmD364+x{o|M7i<*8QQ=ylWn99*6!KQ==V+1iytsn!7cAI)q=Q&?>(0 ztDqdVY(H(VlQ>@{PemKC6N$gZGPv7@DHed58e}Ua`4nz`;nw5q9^`ai0zr;>O0bu% zA2r`ufR-}~5U?(z#3ZfJ*r@3-O6}mhe{0h$8yNjhAbcHrra4A0ZYiwD(P+-FGePkn zP*$CR$+G%h+|yKd!C3HpSr%bQUpHS#BoUq$ZS48=UipG;Rj&I9t+1Tcx?ym&FedeN zy3Wh|Dtpb%X!Q6-(Q$cN$KQ~KeF9(|o9by)84}(Hn(mTE|AB*0aSI6>A zMV+CpJ(vRzO@`wdOoPZ=pTUzWg;+uj_ni-08q`Cbf;P!I=8UC*NwAM2yk5T8 zI!JG!FEBvm<9CkfaANUjzqSaCcQV^N&a4$d@1}9Ju7W?B5O@ma2?L0sj7Sy|6X{%2P5xU3X}Bj0&o+pTJ*s;% zr3inpMCY#u;AKZihVa%e*c~8)qgN>gs#RYH5h8`^7&;7Cs%28$`26z9;`)v>uxO_4lXXL2&}AMbPIxSr8nJ-2AdW@Os#M(%#*1N2f~`Q98_ z0e9kKd+?_GXhC3xljC&xq4qsUFGT%Z=){DU9-X6T&AFsEdiw}BN<3TmhKJuzNA#qX z7vC*yU3<1bcqJ(4Fv73G?El!>jLi5j^~9xsO*^o*@pDCC>Au^zlt5B7@>vKAbgQWW znK1Uz_jXmx@X0!4liWU%7hOg4$HQdy*`3GAc-yn?=%A26?(k!jVTS%G2^F1_m%|hu z7i~Edu&`snXhG65Ev6RvtIG*8!yZmBDK!QlEg!kTixf}Q7Dq!8?~HgzvovaT^Vdn^ z!q(B-*J}Pr0L3qzBp0UGiI#oPrH`bAUfQltmFk5*x1hzCxF+S8INP+6cq?sBO%W%<*;)WI1L)AQ2Ab^% zFeC!yuuQN6ZmA1A#<;5bXMHJu(yDLN`JhVm;_hS5P0b2O-$4)R&T2w~#rpBr&6Ll+ zyLpWQv(plX?4ba)MQZ;aJ7JtFW&-Cw}5YT+t*1=-=5Tydr9?4(a=p0va`?(?K$@d>!xwSOgb(s^O z+_G4Ze^*Q5V>|c3W%s7A6(0ifLkPcaNs!WsCI{H@0N7_mWe;*eW6~e0&pZ|UY?94G z8$mK%nr@`--*2pvCz2W1{bziFAHbbK1NnaL+n@m1dHJ~jXQ`us{7ek!d}cj%6J zh}Hxy@qKO!JZ=Eb!DlD%zB3-h%L-aYzR&XlHUqPX$Qb$$}=_j{Sx#s54)@4jXN zw=bR0#{E){DIV9yVd0T4+#nD%IH3CtDIP_u$k|YVKjcjI>lvLy*;l9UkY~Fpa<4r` zz?|o7c>1eGIYIq-9l_6^n#VkB7Q^d%Ic3qtRGFb1pw%BwD^|TYUTjLd@MVN`^tu1P z<*xO2+#p;D3A2SB87rcy_#~Y{azhEy1tE7EQGIoslQL8|2N$CtHs>8t4o zw>B98*#$*Wo(~JY%q$a?^NB;Cv)}>BE1hArz*eF?V(gIz=};1TIQC`DLIMUo`uZ2| zrgbDsfsb2_{YNoAI3U^A%rwgAm_0dv>$YNM zD+gY&aR*?xYfuFLktKKMjs-0ndI&`r4O&f^YP;~lvHeu;*qJF|VEv3NZ1ZKok2s?W zcJJ|J3hloCaHb27J(R8aeT+ez?#NHzF(^kM6jyl=bsxHcB(2z8<=RmFj_1}QSbf8O zI4MqZMw#sfD%<1N2{j5H=k;=uZ{;$DlaDXZh;bf}NoH$FMM^OupuBYn{7rPhDD3iC zDX?W--`BDhtRxwQ%P+A=Z)%l*5Mhx;BDxlx_$P*ArUeZ`U3h-}@QDic~greQ|c;%v}3kUzHE1 zA%IAsvOY(z0jWhvqmQiruWw!6Gpilqw6J`R!95(oij)-&hRi3xWG&jHeTdi6 zilvp+pQw{KK^5e*v(%*7NE@ati-Xp91@OQyeioH5k%V5xU2)EPO&8)CBgU`K>n=+P z!mu$_<;(TyPnmg5eu?IjJ#;Y|IN6fPq-EI=jn?@M_5J)F#gBdg1go#_7#&0?hI2$= znvY4j1BUi1B_weQA^&D`y6_og=182=j0)$A%BxJ1A!O;^apyVn?XV>F!i`{$;ET+P zn86itDOD0ANd`L9PJSZB8h0mf6`p(4-ZkL({{)nLI=-1FU!QPfr#I2k^IM~FTCow? zz>;FA^LL&8(sjJ`LIc1!jZnbP3a1CsASnSof0ut)XC|r`bL;$B zPM7#s;9H^%({C@%F);+_?HCApY53@?VXXe#)zdZLb?omu#~SMEfRY3EEvlRLVOA6k zfwCb^dP_d}LqicE{m8>cF_VWenFzgPBSO}3Lnm$*el^Ub+r?C5la$fyLFt%V$(hAU z7v`f36kEb?!<5jVtVO>)$`jlw1|?XcNV?*pF<>>Xc96+cA7J}8dEEH0^N-!$e{fn| zR2D^4D!v_wi8m$!Crk@aAU1l6dH!7xo?6Am%ms(@|cjXU>%L=MkTuKq+-p9C*r zJl9A>`eqKJ7jAVwQHFbZL;DmWDS^R2!drka`au_#+SX_ouC>OREU~`fac=~nkF$DM z+U?wi^cSps*HdpJ!PN%q1H#jEHxSpVYMhP={NVHrJmhk@2QH2QsD-#_y3&$aXrAa? zj62PLQW4YKqD2X=L?sb|KuBYjZ{FW!|G6|~`*cf1F66C){i$A+%r@YgC#ufjs&l2il{8ty$q?WyMNs|*s_*tAv$ye1)(e4AMc zL8hw{ThCm=lEiDNtA$2@95#(~E3Iv{Pwn?Edk4`}tX-zSh4A)wyowR<&=3Lp?|NS! z1Xv%((*ga;dE!r;hp@OM5^S8VRH`oZ={}&EU$zv*&M+;IcIT<(H*H}Tt_%{{yNdgs zoT3EGb&z#yJfv2=x(z9O>Ew!@H>!Fn#BGl4X3#^tA*-{jSh?3eA#I`6L@KfBI)Q=! z&GJ2=&hVOQIV=#QLEwSFDAnJXL=jOq7H!asl$bjnf{bA+JtfHCL@})ME2b6zM4@qa zqAdACN&%L1v$)_5eOh8S#y@Ibfbhqq@8y%_T-KG^eR&g!qSWG30N;+2kexWrpa1-M zPa9B%_7QRXn&jnux8$+%lP4m;_Q$%J(GRf|d^Z!|aZWqW;`E_%0XW$dCI<9NJMjlm z4$CEb*J8`ONbD2yyRei$x9n~mAhXf?PO!T$q!o3Hqf1h5g?ss`ngjAoRTl=)>Lf3) zQLC3y7lhAR4txz)!eVZD@%fMs;TF@DV2#4hnt>5XIG>j~%4IkOqj`yl5DaqIs0DYcBQK21U#YhRY8k(O7b? zu}@D#B{e-}2P0|}Yyv1vtU3IVCdDc~Km#=0^mTu|HV*L|gb;PppEOrC8%za7+Vmr@j+> z5z=H@3B7z3TO95Pg4<(CG{(aOCSgb=XlYa!k9&8tCu0}Xr^n0yBel8d1>!+OElZbW zZ!eTWCq9zm8=B^-6Vo2oAgby#YGfJVEu_eh6qD)>bfiKJ$n+LQ72X zM!(_$ZZB6VMr~}kZMxQJLT!R(+cOPU(2bl}%F*XO;4J8^o{eE`7aYpCK@KhU#;h3d zGLickO2RiCbPu|fI5Q-g4+Ff@*#X5!L4b0w(sfwCxK3kh6wD8Tu~zTIAjtN6d7kzk z`Rl1oq8u}fa0i-6>#k($X^b^!Lv|FXXGtzq)fq@>_}ThOQ3nlTC#2OEDZ7mL!r(t= zyk%Z8M}U1u81t{swbyd~7?&x-)PA4d*=C7|!aR3IEhoEumg7@oJ~EQ^R!Qf`j@wfRm4T;b$$oo%Lrdo-rJ8#~ z9!9)ShI#|O!tVV}fa{CHp5?oCXS~A_wI@ZUhI2%w?bF+-97SkS&bap(j1qW4Zea2B zM^QYw{UD6~-z6}s6$8$rmf%jt^JlGnUc^LfVEA6t)fE%l~&J8SzSgGR{kwIy7I3E9-bQB0Dis z3iviK-*7^x*GXQkHPt>9WvZ|wsT3@>5^uLaR-)05uS( z7HET=3EZO39A;5m{B3-*qx-bqTTds^`i<-oDC7T6;+BrUcovQ?rr-llk$3G#T~;CD z$`MS43`4tLw%@4%1Hc;MBZ&2(ri?ed({KnBmve6=r|O%)3j z+KY{-9Zk6N$RNu|%dTQ8t!^GD^`+~Cv1SR$lgykW(hL>bY6tijj|Mt%Iyd#R7u{A= zcQYBJ4<$YOVwuPt#!ESF{Y2BHAK%q4gzwXv4 zOE=vqG^)zwtD}N?QS{qdJzjr_hh^z{jXXnvZIzGYG8KYS;vZQGbM0h(I_v@k(sP{S zRq${jS=R)aB4L5%dD(GsHN#*Nd8V{66{R|YQo?TNy4)tRacPLF2l~P*eT40$9p|l4`F;xL2w_7b_|Ac`q>8jiIv>q}g+xyQyd)#p9i~(yozxSSLZ%ynL zK94&F;2-2THoiY7yLlQ2}{Y`N*C6QTUsQM@oXa^y0gZa zKFJ0B_A~Yn|e3xTx6sF6~#I)|%}Q@sXlBnd!zIR&~DcH1I zO{8^tH=UcZmptBs67owZVko5P&j*vDB+OIRE9oY{x1cDUcAM+gxu>Gb}j_p@?^Zir}eT>N(?|WYAs59l;MC{DTxcH#SX?MPwW|tbWjCU5!2K&oOScAroVz;96Q2e97yRt<= z)4l$oS4J)yJ#bKvZ+B}nKu`;{oCW6qE7{gt&5U?VDI3U2*+wbn@gD6tiaaBQoWkNq za+$`F4E^-S*F*E~@&=Jdp(e2UBD{z`aUQhLXzN5dthobjgjCZLf*oGHmw1_(X%2Gh zm-mMThU5_~-7}VP)PjQuKrsjmqpHkDqZEA^0FatrD1YWWiVxtgHV_fQX^giCx|rC&o!e6uUzP0-uo=% z>L(t2DcKnjQo2c^%t+?D6xp9DmLsO8dQp@`zuvBrn#aFoP$|G*d$3rwA&Q)Q+6W3?)2KwjaYbf@Tnd69_@vyuhpJS*EP{54FXr`Ee@h za~X>_Su7VQAHaaA0$~nM|{Wu$D zBgPS7B!`A{sKKtLU1v-wfrV z&v~p%JMnH46u@ble~na?gcT+ZZo1unsvS%&OSh*-5`X-)3YpSnr${JGaJBtsv5PnY zEQMqVPPNYJFp2HxPhTt(TdEV9Y;+;`CO+j(mUNBp#6bi!#sJD26q&<_<~BXUR+CBo zrPC0q5*+9F|7`J3VWEtZ;q>sC!T2=ohlrpa7C?M(XbdSnMylhy4qiEX^N8}}lW$P6 z^$%h{=_ByZA>Z9Bc|!L`F>%gIL7J%Uk9U+(uE;liq@HT&Hawnw3+L%pMPMQuuL@PM zg~T8&v|)|QZ{>I*OWyX*rD|liafv|Qb8KsO)am!je#5_Rumxx*+)24C zyg8c(p8D)(h9fbJR`fohYW#%{3@FL7fRL=+hIBvs_qioN#I9z5HVS$k#tpD^M5j-s zm?}^z&Y_GxV+Eo=@mHJx8H07Pj!o#Af%9bh^1RSwcfT@39N|ZcPA=K%Qvzz?AKfE? zl7s;kpy?MC=_Npj8-Q}4y36XrK<;klUb?Fx(3zgbT}#yW`%!@{vZd|IjbeqM`cCyJ zXSJ<{zwo{jWb=1lrxSnB{*@c*;`rAj%r8~-T=z#K1=VO4BD6GRM298NYBz^wTvOj* zKQW*^D+2LiM+7UW-08{LjsGs+)G@?G@}HgNcrTj!)Kg#M=e%s$&+F|lF#M2*?wl@b z`e5^#Ori#-XMJh%2a3KOTAcf*Uj7_B?Z2aIT^lI4{e#t}mM}ExvZk?90HTpkF*}aI zhv|8MNmTY$)IlRIVPIg zn!8qzg<*BuAU}0D1-NoFx=dM>|6JXr?ZvWOOx6^{-hiyEflP0uGtXNp_5oL-1?v|I zpBe4xx)l-6Ab?l7oIQmL7vH@lnm~jL@;U9T?-P{Xc2GnFJ>zv1iWGM)=+EAq5lp&8 zPu9Gl_xFIMMsE%5g+B(xW4Vy(_Z~{^cY6 zS!Gx3vt#Xm5{nX8-0-j(tn_-YP30ObQ{^Vrlm;5J>dtYyT`{08n~`oG zVCb6|0z>jpRg&zbFXE5lYz?_2`w3VjDd@)=Fs8Pr4#{ttP|(#uIcnl{Mh1B-_bh&6 z{%9+_TJG2*Oh+#NF6x-u=X2QZM|M$jit*ZAtNz(7=EE{mkcuN6_j@KaLs_@t;HrY% zw0Blx83bneUy6}=E$_6*5@ZP>ir;Eo>ScK3k=j!U2x}KnzO&FbM*t!kE?OZs&4-A{ zWF8^0L;yob3jGtdvPoX5UR8g;1^Bv>`?&Nld@}EC| zlBpWiy{+tmh2@_ zCkcB#9oCF2HP&-i#FaxQs14YPJz&lyYK;A@go~JUZGuYxL+r|E>b^*}E8R!-q^bm9 z(AKlocFGU&Z_jZ3jJQ5*r)ovpOPM!J`calMkV(=!l=Hi_G^y-mgK8Dn$?-s8V!b;^ z<56b_FqGFLzK8TlTE}AvI%xNYQp5T6j+M|>xopzGf-X@EKl~h1--Tcitq)=ohFuQ8 z6HNA-Wr5BwTZi zdRIK2jO_0SNbKP{@egU`!{YZDn_#veT-#HQm7GoPB|kYR%f)GfxJF@uUSVx++OPfKFfH42DO3!# zAqZ$M;0u1kip9*WX@FVyPoJ1sIxDYK(mD9pZeDp-_4wn?-ik6l%27D*88c>RQ={5Zx!qh$W0N}J)NL80z^-HC7S^6yH)6=CMeZs;!5)L0zMHQQkhh{Dt03 zXO1gGK%t5aOmJ0?67{S^lm(uj2RZMj8h;@J)q#b$YTHYYGZG_F6=;MSb6&$g*0v;A zYo%zp&kG%^KIdIb4bnU!*p-u&)Xi31A{D}U>--Kae`ZCxptsS(15eo(%XTT64@%(i zMBQW(3Mky?F4c8#>^e>dw2nV2rK_GOZvg@#mILiwKY_@db$Lx`7D8MA7xYx+2>t4c zVF@Jg{kpy)Y$vW&pTkRUOA&1=n+m8trH`HESMNRvlet z8U%LkCGg~QehNCfkv_wC2`3BN*_C-R?mK>%%(o*Ln6Ju60Qvx>u~55ycSNuoQX2e1 zCs@tlV}NRe8dCLtgfEotd@UR7OV5y>OoZ{^; z`EJ}6z7l-8Tn8$DJ0`21!x&)^vq6C@8W8vLQL%jnP5pXR+8;S~Rp=iL;H=T0Z(v8d zeR#T+Eb`{jMcxZ`>|ghAfOV@wWm5%6gK4nZ<;uEZ)B{^Z=gU6Z_5`vOvg`V}v{H`{ z!RZuAjc!0?8~$8%ZaCz86`z50x#)_Sb?!pg{1ANe*?_G}+b}NtYpB@&PD97xi_^W# z#uF+Wm?;+hkSecf z_cNo`#Vt?!gGH>gV3fa$<2)BA5h`>p*M|1qhMVFBXQ(d#R&)TgC#EuhMhd%|uAgJ8 zjdLH6LI#GbfPi>D2eqYFy~O7tItTS&ft4Yl``KGD?jhi-cs={f6VS6N0vPGH7&2-! zw(8_yiTusi@Y13)R~<j8gQ5~Y{ zO$+Bw>qNlYx zaMlIU_NN3+R}!VJz^_zLOhQgZh5fz_<9hhZw^B?hQRngszmu}z)$EZ$ng3Mm0GL7T zkUQ{iyTG^P&)fA^EKy-)&L#@9S`9DTlR(ZjSzoe>2qY=Sc zIs7*+{FuK<=ZN{I9;8(XmA_~BnTFb}Z6mZhl<}KZcwFro#_(e1ITbe{!SB{p;#$Co z6`qt3byr{{HcjJMQ{>eJV=8Y#mOA83YLvzC(&J8aH;icl5h&QFsrjf&4Re4Ys*)hv zpNqqjIN$tz)pM2s{Z>|Ag~%SE3AK2%&dZ`X&g$|6T;pVaa#8EotuKonXu;}}y$V9y z`K<^hZ7wu(XvuNoM)O;q>=0#fm~@NuT8Be)F_jZL3G4lRL|d1YZv?~*g90p;WEqxvGx z<42#@woG-A^s#*P&AS|cF;fY6IZ4^*mbI0AuKX>Sf*qASfwb%SQbk?x1u7OVCi zdl0gdqE924Ui~?r!uNqlah`_G)5wI#G2F+qv|5lD#JGK>u>L*VD4@z{Lt@K;B$TfS zoDm?Rr|E2=#o3LqB(|d0vzu-f+vXp@T^Fr4O_=POpSfJHX=XZ7W=wGI@|9!9f({)- zVP3PX_rp%KV|G{6XwhpVZ}jLwF{h@#r^S7G7-S1hwT-U4_*Vq^lk%#t&oMxgjUKXT z#2j$vR0&7woS)6iWK`yxPqG41*y!06(gy+~+OuO_TTn``?TCra-8uP4m&j6A%kTmM zvT1v}OfY~j6qbPBkb@%(i#5|u$KvCy_IvOMt#TqT-LSloHUgyRd30G~y)WE_p-$SM z5t%3VTM4mYo?JaGI2E_@VImE{DpV`>(dBrVE^TqodS!n!SII6?Y>!1a8`C~8PPPi zs06aC>r99snJ)piZ-TUd&mME+5}v6LRX;A|)om`HUqC`wd)=hfb~FN+@2-AP`NS8D z{LgK1(&-Wuw?e;4PZQHIVekv1*mFduN!!Aa(;~Ew3mj3YY}`RBj}I&7;D$8XH!eR` zD}sO5a&BNvH2R_4R-6Hnfk+hJB>iwZ zx+(;D4#FP3{!-$^e!r{!U#~$Rtf1yR8}MyF#sO1)HvFe_vR`m`w4v3v;jS zp@7pgRBV7t7LK+lKAU*~Qoo`|D&L{EN_yOr8^_3^u>k~YH8J!=-@yR_bl!&Z6p|^V#4&<*UQc8fsx}VKrVmzaSd;qMw$HC(g%#o= zYluX{QIDi?hob3F?j#Wt`;Cm?m$NqA91{5$zzb-xzUHU9hhoFk+GQq81sUv#nPz+^eqMw>WglW@KRijT4>1v$3 zy3BoG7He=Z7-WNAsqiHRCW`ZB;AID}{Z<*?PXqeIM%hsJ3>j32qcW0%i?phl7yLTv z?mzH;lWKA$?DOJ!p~hJKli+;v)gUDn;qiA^lAHlz<7QQh;34)H%Ui#Xid-WeWxtpKob~#qdR`NC6=82_HguJdD!f}fEaIcX->Me}^6zul0G63$wk^KQayRxN^ z#o=Z!RiA{R2LV3+V|L!9)-H>0pI1GhD7Ty|qzB%yl#Z^Pts_pe0tL6ki-!lL>?Kau z;g)U8Fe=jw%dh%beRv^kTv#?5AXDZf2h$*R==ZcGxZar@2KO7H)gVDSvKBK7BV0@t zVQ>U9R+`%D+(I4SgUsRhQK6#G0vqFK4XF9;MD4tWmhejFCkOkd-?K{I0cTJzRh zAJ7;2K)z}~^8tv+fXRs4@vK`c{rYhuM{2LdWmGZ?ETRQ2$PM4hG$l`dD zcbW#=>ia7u<3keeDOUY9SW$K(a%LP?I{w-SN?At z4ZTJkSqlr@*V2p~P9Sy5_-N$T4G235$pY%P-=6^Jz11OH6qF=+PuMp^==D_<`5kaguywM8$Ry(0R+Y?5q6m%AkDDw4t0Mt1 zsDPUqYNB5_tOm6i-;-T6inP`Z!^P>2MKx0Pg5jpwtlltcsJ@Bv6Q`=*R^Lk+G$;Am z4QSqq%=Zk!F28adzcu+J@LQbFhHHDelAHbgoY6Mmt*6|jC=5k4j_HGIV2SM>D4A2f zhj$6*3(5o{0(E`b!i{a&V)x0QG?8-nff=mbGAw+Ippn@oasAN3FAD?a#1l)60kclP z2OO1t%79+71EUOJls!3f?KkX$EvE91c>Tb#fq2MAxHL4K^+-~Y zt`w``i({O6hA>X-;NBl6BGcpPhd=BcRPD-epLFe$X;o?bvo#pwsH$53o5tT6C1y?4 zCo$U_H`6e+!fu$9^K74E!U!lKPw5KY+GDjLt#CB_0~atdQ4x#aN(rO3H}d9+oB69Z z;jMk(N4CF0q^1@#S33R%%C;nEZCS(5DKvGSXai7c9HB6^>T#|&Dt~#q z46Zc-3B@u`MqRngyGlg`(@o7u>ZGYl&<@E@N*k4mmX`qOcM1^dWxhJ`#|c8sSNkHP z4+6>DFOno^Uzx&-p0aPQ{r4;01NnDVFMcp#PWd08oa=1*lBP1p9GO+>EI-Q-eJ;A- z@PV;GkeMmZl{=(!q!@=M@UEJB7r&G4%uY`6Onn{NS-^ zc8_yL%)Xr9k`XlCw~7NlinwW;%XZ0-gLdwzUzDo-kW>dU5Y;;YdEv}JfC3^x+&_8^ zM4}eAA2+bq%-1pDQZxcdJAyto#xW8jykDSeR(d_S4tALAjX;Y=0v&x^|NYPlq8a{F z9H_^(omnt^Wz4yB4YHL{tz?*-mz-A!n*S~mDE+G#nnhO5x!7Ko^weFdn zn5gs_z)72K&L!v-un#f<~I% z10^6p@as~6yGB-dH~$1oz|EEaxIv`Byol&u4QTFgOwwn|G?(Y7@zPChFXQQG>l^K- zwSKO39=gI;VI!O`SJG`!Yvk*jW)f?*_&fFlqZ+J(-?x5{bnTHORiIr+hvAx0U$4a2 z0q|_r_11=!L!~t{cOn=c$(^~cKE$)^Ee`U;JCJtvbi(_k#&JP?+4!v3;?jGPc%>4C zfXS?$lFRoA{wGq~pa=2~j`)t+F_7Evlpf8K(`I+IivAbulIS2elE*Am1yZd%lQtq+ z(~+*}gyB#E0g5S6pFvs;9E3gJbKmJ(yl$y>BwM25G+oU#6|q_%cVVw@%^*|4I2pg0 zi8ZDw+8)H7@^#e2{!4{XyCgi3lZe}N&nv3OARI_VI4?h+{CM#jGFgZb)*U~a@hX@fUXlPT0eh; z9oj8w#GTJ4kzTg{>_S{A2kT%~!|oDI`%65vWYSJGJAuEQM?D+}CUDgWu*?*Bfuf%iW=1E`^+pi)KV2ZR|4C!ZANh|C$KZ0 zM&(OFNu1wr^6<7EHqrWwJj-%nM1xn3Rt3=Kr}6RNT4*%su(cwav%EHm-aIe__Za&i z{D}x|L#OJffQnTx~HdbpsLIr5GRT|X+HbnLVVvzQAO1w;?QkuWxWRLui10JAP9x6g{lm9%W-iZfAXysVlKDy zMPFglB=*lV8ZNa(u(fF3ZskeEa*G%id0wezVO}wJ8SWw3X&Wp~LwXFD8dL)i=Oa;q zBtxi?^_g-s=rrvBglvj=sldW&R|ZWob-3JiHw;NxXosseK=C&=_n7rWwy4j2pF2SoKB`%~ zatjAkV$pN`)jqJi4ZHSyybsKX}v%fDpDWHJ{v>LRau1Igv*;5U1&@1o35d8wo zI9zSnm{7KiFGxFGcpnVFrFx-iLCz)>ah8F~&P%(kOn+W31UCyBEn_XM&u@2mElDzK z=1SQNk{YD;!I{sp@x1tl^FFO%x#&F1qyyvowwT&ieoxRZk_XD3trfpDcV8=EwqO|M zHXZ{9fy92`G?WB(2MLm_^#C8155L$D9wJ;btEA$Up@Llk4%2%+xD{KCOUPg@)h#-T z4k2edwboeH&ke8@_$ zp=y=w`N&39iWtH4K)WS&@)%X<&fhHv3W)y}6BsM(*V3BZnNUyyRZ-;U>aV6^2WhW5 zB;LzYfk_!o04U$wl4*toTbimAM2>=U`6fOnFr4@rINI4D3|rYi!953aQs?-6XBH*@ zgj-);-oMKGE^SsT#|$(!SZ-D&FlsD2-{jGaEqB*>k!it74?SNc3RFC^U6c? zsu3U=A&geIhq<40&0tBZ_sS{SDD*0&BnV&C)pubry0M}8;n}n2X;E|nk;*uyS-zr!S-7AdW>I_H ztJ7|VFUI|GVUxk;wbZ_i1_GLNT;|J9Y*|Ai-3Uq}e*sNlCtQ2()I?>^#mR{QRZ&2e ze8&r>x(9i)2y+V8agKoRy3xdP)jxoi;}G*{ErPmJdDj=nK|=%1937V{0#fgu%bwLs zL!mD;&j?ATZuxKbvtu^2#)5{gnF|^3oUmXN(3$H(BV7>le#zTgVUZ`Fthkl}@xyTB zS-)B)K7XM0?mHd=QbnGnF(qYoJj63x1b^4!olo5Adjz@`);zlb^|(57`1GcVmA87g z1bdFRW%Fz)qMF9^l=4bT5@+VZu*R;-L6Ho*e{!Nw#Xle^jL90yGB%%4@Lj0KhposR zrt3JJ6Gmm=~$Y_Zc+D3{@T<1^5h7?%D-Q32QfW$MXR2%T;Wqc=vn1Ez%ZjV z^A`hnN@55;Z2BcX4HcdSE=$P}O8c3B5IX}(3*(LF4QPl_^Km7c!;MXi z^78_M&Qu<>_HhtimKALJ1fI^w_a2GZ&Z&Tf@&A~3Lz75i^y_ktyqA!lki4X14$FO@ z6x69}%u&j+<_!vm`I$PRp^d$&9Y;46qThJ+Vqlwy00;Z*10LG+U?62HZu{$BavHKU z+~`N>WGOQpdbVlB78E=Z&*lT?NXWPit|FQiJLtSaGu?hKj?L_SqZJStJ#n)zIaWyX0P_Kc~jur+*LOqHGBq6GF&~tdE zk*S6E#I?fk-WBqs;z!n=Jq!t{@~OlG@Zk>V=M1J(+V84=0$1Mn!vnFRZCAbxoKF?3 zxe^DyjsEHI{m0AtedJb`?9xG7RUVkOO^3X-%rZU&V>ygb4%t_n=i8pEGNUC(TOUjV6b@VAAgUz`1Xl>LWuruL zsP)tUIY7q0k4OP4avC`&y(frk8c%+oM}Vo{DcYr=VFnE=V=gFv0tsG0bq@MfsOn8o zZNKUbQevdMtz)qug>TCTBzPw5)_x8t)@Zo>KH|E3BP`6uu<EYXt7M0G6@ z3L%AK42B!QX&fIrrYcTMyz!zR{a%*52GV5zyyKmwi|)1|45DyId#DZm(n&mihwm1# zCH9y4wdrZZu)8Qocn24T@zpt%?ho|wOqYct?p^?#^(4#CBE#z0hUrub??!6F5b(}rvBw1gnX8Af zuqN>^HJwf%LFNCEdD>dsbCURhPi4E!x+v;4V?x&!W!(8#?w|k~?CHyz7ig-Jl|QhO z`ELaIDX;T0cI>ehK;+Vs>W6()38dgC?Q?fs&u57Jr4EW4M{Ua4(Ts}+sK>D4<$!DP zhP{?9Z*Ah*=7BI`KjXs=ZfzDPY&+scfI@xB{_OJv6>HX_>xGW^t3Gz;EIf<4YeLce z?A}OyuUX?)NjtGOV=0z{?MZbozcqo@!mBp+AgLRHRVvm4Rnkr8rWSYb>pfI)ue2Mj z6^nei`m2lIeXSM>PDXn`em5&fRC_6+#w9G;yD}#p@F&dTX!zl*Cm#9TrS_RIxbm886;APj1~litmo zK_-hgDpJA7K0UpzBo5@qrXx>RmH$=uw7q`sgwCO(F-$t&Qla6zE)tO^VPvSUIs`qK z_pDw2*w%r*Elus3{b7_`1oB6$hBChy5iJSE2Q?gJ%LF_)WAH-S8cX>Zu)OW13ewRJ zM~B2T6fjl2Nd`a@Uf9&n9@=?nxjH6bBjT45Yg4t46BJ4X(_sXX2%II1qfKnDE-i_r zqJCMSJZ;Bz49BP<+ZS%uJ8ER$0r!eQqRwxE3yc`NqTYrZQ1(CnOz7{QGaK=BY%ZJB zR5?;eWbKL?Q)g&$?Ie8EO}ZGg?K?Apk{aQ23d!ZdRW-7iuI7Qog<~*L(y4x=FuvT` zzXkZvX9E;GPf3B3p`AzJgd)JDB8GcWB|Xl zzB*%Mq&%dT)%)8ml6^B6ps)exEF$nOaKMUE0lIB^r+y3xW#4HQaA-L{Wc zu{2Shu3pwQs1UrPrp9e3*y*m!T1_)=1#!-4OIv(GYm;=R^Z=&#UgD^T$DALYRKI`j z(o3hPtcbR*lx=~h8lpE1umzm2Cr8UtsPxn0Vf-_8>ZTpFQl^rfN)4Wam3Ib)qbcfV zP%(yDvj{Ox4tNaUY!5rI3`|!Jyng(`9GE-s{vcj9rybGc^kP-7>PfPsWVP&~F>Jwo z8nh9}p7NczDWa|e*4?a$>L>}l&ib7Dn)OnlZVpj!vaG{$6PT0g+;idwjmF^G_UDyk z9~&BGH05Z6&uDW?OeFpW4TzvcLc#;}?m_v!6$|mkv0O`h8)9w13kAG2&jF1VL+@3_AzSe;%$ z#^7TnSe7=sUwRIBy`ry9b@h~&Wd%@7rBt>!8@gW{GsE0va2>XwZj3rz|3=l&(NM+$ zk>(Qc@TI-nGBHCUt!ok-y6@k3n98-PTBnWN4gbi=HuLrT&oub-;J|Xb$yUhsesOmS zRDjM`;APva^Kqw}v28OPHsH(02T>-gx-w<4XJhLTExcnt=^4z6kuE@Rr*}Jpmt%)F>2^k`a3r`Q_cp>7OBR;pWtW7XRDRB6BkyfIIx_)Z%wolYQD+Oub?nk`{63%I!W2N$}8NMAqWxC;HD85)}mk&jeD z$RolsElyoUq1!%zzut?C$)(y?lBxp8+>+D;A`mj-bo%H{@q5&h*J z$II!lq(QuaAG%6>WJl(J9tFzeqDbO=di$c}w||$Rg;~PnOmRhE!*nZ zi-eA3pBd?Sj@6`a$QOxirN##~f;fD)62Dq0L?Xx4N&E7M1+1I68<~zlSN}=eC?&5@ z_JNw3^{hhi!Wvt7iz(;~3|M;O(SWN?ZA}{5izeSpKKu5T_PnMRT&J)i&e&^|>cE#jyoY?- zZGu&w1^6(3q7rQPF$u>`7g6HEngd5?N3N2SFZ?>F$3uLEN+`yDaNgy4cf%2rq zZ57%0;isAX&hfYs9vH>y)-DIa$A?4yh!gACT>nv}RDZjh2?VxsqfgH1d)vpc_P=wW zMC|HLmf4yyZ(ZGlc})6&C#z33Hm8<=I2E`TO0IgayVt`tC@0UxkRfUYqWaU-T7Va& zHj@dI!YwJ<9yMXq`%VU+v5q^3!0)V$N8IJVV3@Vkk6q=Yf_c(DN`K_EIzDu>`_>sH zWlVU<#IBsFFk4VC>?{?8$97H0ldWz0NH-VYgX~_vZbIkC$U*tK(m>;n3)y8U{u>~D z9{zlCFA71ksmS&W^@NzlT7&)Y)vx=}Y+irqDp<|O>hZwlo~Svern&~{y^9geu;AxZ zt)C5E@p^dLt1Hx)9+1=wLahwcJUeq1JNb$iaH@4Tk2G}W$M$cg*7udc-x?!*XlD)- zWe}1d2#-y4Fl&_A=&4z1-ZW#pa+z^XV-+bztO#QOSDwmboeBOqgmDAdO+D3gsPf<* zMBQWZi~rOqrY-EzlkBR^F|;iHOEQ;PG81lKlr757TMmBXlndb{j4uXoNkDo)F4ad) z1J57LQPxa-`j=e%_ZEnscszAq>Fkb_}<~RXDW+}OlK>>U?=I-#-s3;pWbztx3g5DeIfnyQwO_xt z#hdcGz`LYdwr3!Wlm@ut10F&3cS5&?smaYWj^i0dYV?^kWn|<7SwzD3R2xx7dA973 z3$;^30u|OId7G~BmpC4XJDbf9KDZ5p83S~JS%&*!#%2;CrrvHpj$O% zBcA)F^Be{iWTL05HjDmdw+>woL;~WK<@)U!ubQKyCGEXeSX1^WFu-|!c5gY8?;yh2 zyjl4_(CVn}3O*yCTyh*Zh=S*wjoyEa+dxvb$ncFF)UwMpR%jNiIWfZe;JR`}@I$pmRMir8|wJ-shF#U4~l) zlC|=F4ggTd4C^q9YEdcsRW`+T(4LIo(+)S3Qqw;G;r|FyfHL`sx;kdy@$Z_($2$IE zvxfe-kbY7O2|Hi>y`EKskzZ*mTaWXp_l8uj zV&UO%*$LpSB@F7ovw-9Blq5&}gJuA%qhe7C3}k0}n-dM!lSU6r`KD)aTxecgt1BWz zYmBW6b4h!!Dx;<^xMGb#cVVHq-32BO1gxBn#xnC`Uip(`-o+3ku&q0*Bw+hrq`PlT zoc6qz7K`NAf3cNkPCMNI^DXh00ezQZBpyUU3q8W5pUQCm>d4>1eo%YpY}$=D`yPLU zllZ37as=R-f?Xar-D0PFcA-T?S})$Cl~0f5B6US)bUi!7X@CmceFIc5;BZKA=$>$5 z3vsTz8}ZA5(tV#gBE2MZp#57B{<0jA_MbfU+SwQeGxEW&M93zH8d2bsjsq_>%S4mu=C_Ikk6x$CuG*KE^9vww^ux&XhBo@Iba zhGeR;zuR7A)c6n5R!7!%;A@~wmf+T*h>Gfaa!#_Iijs!EqID0893k>5#A-9164 z6#Y5={)75)g#&Kz=0n?M$Wp) zSSp*>%F_D)PkNpa1ooXS{)NAjYR$kb4Ri}rErO_*2^zUu4z+5+b;MapzKNW|L1|IykTWP+80t}c$zl6;tEvq^kt^fZA0Av`Q;#4Pc&>~vz!QD z!MzV@LtJ4uY_h|^p+InY%$`G!HW^jUUp7>!x1XBv<@BLgND zxXP=@qF#0DJo@RPR!mb97s%GdROY=*YscLf7|nqM*B@wk3~G8&F1BV&JD49b*RCn0w8O_FqrjqsuE>!5WyadY5wzvz zE57gRrGMM}CH_sI9_R~903-tWq^~8KFAvns*i4fu0-skbTSUJs6YrTyGuFH~uJ^x+ zt5_=JTcDS{9Yqusy>Ei=oscaxLokhtL2;wm9&^bgu)#;2o??!Mgug+ob&YZcYpu%q z5E3X4EnUodgmPyA1fl5-BcgE)gOQ;HTC}>0L0rYB^oGBxoFY<1o4?awkYDa5u-Ry8y{PH+vr1K)S1urEX04QTk$0Ab3@a~8? z0PQ#yg6mH6|Clwx+jH-G)M5pnnb@PJLWiwE#%37k?wh7$)w3d5%LZ{{l~rCeF1kSH zPpvVAKYOBma6tjX|5TBW+VAUswEyE1pD1#fs~HKqmfk`8`Du49bNTN{ zFKTaWHij)_hbD5KYvKHO0u?D|O3dvbMTh|J6_Z^HGrT7y=D-VYC+eDzmDJ-k~kMEkRwx4 z0+m)iO<>FB4fc(%kO%bv_WDAW!%gzcId`+D^59m$Wrz2_$JH6#qiVZTL|}@4w%4{K z@K$sXP{|)pMXEAoQ*ah(acRSf7WpB3TC%CCcffO9EtL``kiv`f--$)F?ZHzC69%U0 zE4vPIy9%?Z97|Ww*V0i>Ov01nJm6$h?F{;+fZ-8S7@??@=^}hSh}JQ(*@T6=8;V>! zq0Ikq@`m2W7*;2&c4*;~_Q4eMz!8~@am7Hnu&7}*(y82O6*-%0S>4bp-^oAYNY=DK zAyS(K&_q`TY;sIcNr>i--mq@=p>TU(?W7{k4a4;yP?5ag8GfDD^#vD(kq`Diii!K1 z%l`2w=ff9ipc?Jf)uH{DEaDrSyLhHJtN1XH*RTY{HPQ!ci-~X>Y)i_VaLFJ$)h&0V z`}->BXe#ZFW{4zoU@n2^;8aXev_-Qmpn#&w)oKt477qG4^B`-0pNuzh|3*mDaD}#i zrxFyQ09^C&PmWBfxa@mxnOy$-26b;)v(qRwG&A?tBwx!wXNF&p6ye+&^vvL38b2x1 zF2iz5pusTdJDUfamVhV{ER#BF&-uf<$0mm@(|`)#S+uSBpcU7i4R%MQ43VL$cMvJz zipmYVv#8IG92(9jsklk$NxAb>b8Xl+6|d>p--C;ETeD6N`b^YAfnHb2mz2zO#FM&{ zRoMiWG4_v=(;px$oXP3pb~SN`{71|E`NMmgoRVIqcjL_d4i(!(dem&~Xo-;Gq24Ps zft>Vc=f8OhsLftNfJH0HtPWKNtP(45nQbW1#Na(OO{C|SG2{^LB0}qQqtdq&-1;IO zWqgo2cgwHuMt}1nfbBW`8TsrM=plFg59m5Z@^E~ z3jw2RF0{k`4SyJiH|PEu&=b0opSQZeCdy=f7Bc2c+$GrVLU5Df@q5)vM#1k*z$#~H zbVRGIf`C8h27X`go4<_?ZC_E-lTn5TxX4n?Q~Do8++R=I)VHDFs>N?*nZS>B%GE$< z7^P31iBQ09=d+f(>^0{!sa2EDSd>&X^6deMxMi7ohadje`g;iBzg6!cA{q-CaaGXl z9Z`3V@_%bm4={|LMe<(rS4dnAFOVvj(6+M(vgFs2Ivp{4W|e?{Mq*q(Wc02WU1Xs% z^yDxl$QQZ3$Z?va>&}Bb`r5_4q9=8f=Nk~VKpX4=`7QqE9;=m5E3uOaq`a zD_5_m5QEj)9-^OEJ-gYDiZdubRQ0aUl66(8R4*4&h}eWuThsbQpP`TUNGX`-X5{u* z`Xcbe!kXX1egKo$x7M!E3^qObc{RFkG37tb7?)`!Kd+&7h?o^@JzY$l-QhPGtj(>z z*%&7<*rn3zTKYDKWU^Dbs66}t{m;Y?Z(0w+ZGig!?OBcp2yHRus}yR`O#Hamwj%%D z-$Hr=${&goD98UUHOf01`KGs;c3V6@qEks7sL}j!g_#iK8^1DDg-z*W;!YbF8z5D6 zwg%e?jab99Ws8tNuE5Yd4KK$$8on;KF$wRsbwpq&{Tto!@BvmYi+RtF(UyLQGisK9 zyOGp4jm!T8vQh2q+Q`Q4+h_W7RU{iCw2+apzKFt%XIgn_M?uc_^2+jP2r^ZcBV08z zC?_9OtlRv~ulN)A^j#e}ha=@m`7h{WlyAiU?0wv2zrNfBm;C+y>@%>pK;qCA7Hfv8 z3IvL9qovVY;ICd0NQ7%G^qsVG%mx<&%{;6MNf7Ml zWF&?LsQsS~kIvUvoS^S~yU`MtZhw@+w{ZPN=a6a-iBqyQX=G zfgTcwDDAoMB=rh1o$vTco_RIm);PFCJjcc$%OD`K4||CVDa}C(>Te{2s>o6X(|S6^ zT`iU`!cwCpW;$wH(p9bZYb9n`u@59DsavZjkm?~dC~Z4@+lY+B&|`%L5&*&U|v zX;wo)$dBz6bblIo$qR}aQB;hoQYrRwH{ArRZ~3Ci!`MfRPjaO6VU6JW0arc|Fz9$W z$6G)?v3xfV;id7BI^5gj#Cn`$n`>RwJ-ZVUm*26bn@l5K?jS{n; zWu$(94vKRS1I?f)P-$WWF+kryxdFgZhNyv?_(E3#2UIjDNn5BTYuKg`Yqms$4)F68 z^#;yDUEOc{bp##HMZ-%=+NvdY`MeH}2V{3+U!HM9+S;)GRgMfc2}vRi1AFoP$(!lZ zjv?6*dCOYD$=Nqas?LQq-ow`)-Q6}Dpn-5N=!6yY8Iq`hDK>&ZQa%ZO9dDeGs}H z-A@an9I(jmY@8qqy3+UoAM%?EU=#PUFVqWU!Y)-d=Ys)35|87yX$1iu(p3MuBdud? z8;!~LH~;C^Z{)VxJ#(^CphRUYIRxwIXVn*#+*h!J(qr@|6}_<5pEA&0l2T-_Z<9Zb z)%Z&LaUo3R*ykGlLtbo_?7;BZZf<6X=b?i3&>0A1oXc8yksW`DxKpzeO~eeP6HWiF!@CEj|{O zj*sZ$lRVQLKUnIVBk%B!6aZeBKTz%&gNggnDY(03?U`F4)vMeEnA7_91LVy6tK~wu z_E>&g$mS1+E8yXFXlF$m?Fx^)>2JL1O>O^(&J)ge6G;Z{Pff>TpPzk#h0sIEiTk*v zOX8 zHQAlf?mK0E#A(gDZm*$v4ovx%L6?BIsGD&g`20p9e8O>Hz9XtL-1xh+6fO{1V8Q*Q zgcOU~4_`2nQzS#0$;MYJn47)>VL6h@O|I<=En~S!cgIK$g;Kh?u~lkXj0p!wIVJK< zs!4Gkam==et8;Yu>d|mbO{R{W50hYW(Fk}+w>%8ln3md9Juz6v&Jso-G|AP$k}d*u z;WDtF#f0^!vFWtw{-*yA=z_Pta;uu#2lPg-LZBXso`hK7!p;0skpS3Ju?YLh5SS*37Moxzl zR5DI8bZuT|7)X=nQp#$+&W0N=y_%6J6x;oB#PhwQP&OSEeg2XfbmCXH6+4T^Q}8m1 zWtW`rBeiGfJ06`c@fxm+6qx6t#Rw2T-3vXD(c+;czIAT7?aFl7w^Nf?q}%DlR0UAY z(d}7>(;ECecp{JA%pIt8o#PNLGh-e7%=W-8k$`T@(=eV9w(e(&%UJL0AJSz#e=P}I zUMA58s9FSvLoF=dCBka~1E}M3yz5vpi)#HUYHDkC^xf0~oSWZ0YTFQ;6S}aDoDJrXZR= zr|yaUOCV|{2`v`qII3M;?4-AwFPLOh@*$%POwKLN z$+f9;wa%I#Aem-te4F$Fd`?a)J@-}p#it;VcA73QBE*FtDGd#r;jpt(l|EN6 z2W`(8o@g>;;Vm-B!QwWjuC?P5N_M2;_aNWzf^FvdJaW&v55!lDJg*!x=mjema zL<_|6*N6kCgj?bHJaJPhE@llD@F~gi;u-s)L(mtBRnqNnOv#U>U)%m#3a^SaK- zTW!i5SrhG36TPH~(iAvZn?{oXpQJ86NFD}xD$jlAnWhQYx_yYjeMai3R*W9V&G`8> zw{J`&D=Swl!}0kd-mClvFuj;H25~u>W_Xxq1L8@>{94>uO!K3RAMmSm(aEv+bc-eU zH-JiL`5K9BUF}ds3ItrjP7+>)RSk)wRN)s9@A3`1+ZbaOyO>n{K61Ou;F<0KC`OjV zlimLy)3Bt3GBw_ZJjLuQOA5A)j(~wn!cbs^KOg*=v}y z6%?AM`0f9SYWmm;bR4ycGQkYCko8klAd{pesg z2)qIvA6Vl^|Mp&=0pHH$`!jg^-{JfIxs+Tg5SEqP%Ozf$XuRaZOHtGId<4;fPXck4Vt~ZaaE|0eLJo=7ywA?ieq)w^ zNPOxPJxZZZWn?$^1I59-dTQ(Y^XEqS8oTR&!=JVcz1GhxlulEbr=UDihZX6*+{80) z_He8OQ@rki3-*i&;N}ta3KPhvU0n)tKJdereUtCn$aypysvspUF^3>$a3q5oQL-Xr z2*GsEiDX(LIgyb(WH==$AM9{GT@X#BF7xozAz-+4>zZ^ZIG4xWzQnA6Z^+yNX>uef z_jGSLAVw91UtJTXLOum53{g~ppN(j&#gw{0PoZKe1bBVu_uucJsFq7N}6Zt**2 z)=8qK0MfdBHf82v?!~XST;Oy1-%Z8*^;~#Hs6`%pn>YvR@5dDEMl3&8J|ZFjjb`id zleG`SO>ew4hOZ*9iVU>x*ba@I={GCMDfqwhFD4&|y!1n>oB(21`~nQ6@ozBx5nFR= z-v^iu1H5)fR=Y#+0l5Jh5gC(ASTgk}y@ws34q+8j%FXn~&ZJi4_=+)i@SHRHLVSeO zZvpLn+To~2lOcz{WTD+K_xM;~f-q)<$Fa=I)4ykO$n`#L(imrEEJoX@{f%!P>-d!h zvoA7qm8o!kfq#(qW+#u~Cw%~7@os1sBFz(cKoghH-1^qt%0JX&wZ)$49drMc4RfJZ z=Yi@4wj&>Iq})_Z$BR;nUiAZ9y7~dmp*!7yN6`sIN&bIb6)S1b5=Fb~b8R7k&1`nr zTgzxp3i37T4s4v(x2WRZS_Lj3a0~fv9VD*cR>3s-s?LQEbfDVF65u|%zU6609MV1` zv0)M6S!-;q)?Ts#UOo7t=5=1QJg%D$=E=ON#Wx?1ZZR5tj-}56i%Kf5;#Bc0O{`0Q z%KN!gc~qsapCg&5C%tlqpqGcT+)wJUu}l}6_!zBul?PWaQh%v>Q%ukfphsyV!tb$}Dl$CPLm*;v6!Hti zCiGo#5(vb!<&VBi9=~3>Jy|W$VO8mZ`J#XI@T~C6JtYSf1aW5W#c1ses=Xqh(B=7A zT5ublKq!VXju>Vj$`_u14!J-6t3DP0`dFaBs~7d|05Y2Gd-JHE_Drv&n!xQ8+_wy9 zG-P`*o?$efR>8^qvqiJzVG z#?Aq2R0E-b&mF9>d0pWLR+6HxwQ>C&bQx_c*Y87lgoLemLwNF)RTwzLyqz}8dbB!t zYHGb4p^XLa$9IkL9v^P0;pf~a^E)#8ZFtm^V+bkJz#YJ0?O9K6d5xPL$&|wd?!0FuZIemY+eppOw1f}DyB@GICA!N5osw{TpyQms{T z{PICAKF^!w+(Jax9d^=DYK_(CqE5cST*K$I6YhSxnb$PkDT2K03?`I+M`+B6v2+%m zZnCHwPjSUmOK$G+`x@0ki`Fe3fmC52{A8$<_KASC_7XU@rV5>b)MtaRY~)ieSv3%8Y511k3i@fZF4gxSCDFy6=Xq z3CEZgN^IeqBF(Q$!fPsM;8C_&$*`PZUvM)UKJ0ohaUNX?7Ym&&H4(7QGueRegfKlh z8`J?+Kta?K*iG!(bPsT8qI$cof9=9}sOAD7`{tjS7tpGef5DGYFKkBXI~WE z@vlJ%JT3tvZ3NgmA_9Z5%96wZdf}iwKCmFv&H%9=gkO4)BaI8UQ2#8R8@6sORQ?cP0xmH^-Kk zIXaWv%4dZUyAQjUwzO-$55xlW%al*5lix({O9MWM8S?URtveehfl*p&USy+DC4c*( zWoHX(1))D6RkZeG8C$Y!?9Aa@90u0jtbC*oa{5?isn^r>g<+nH{EdvXnJY(sycRe zuPMo*_1}por6*g)S+!hF$8(y4G@7NPun4COU@WqS5BaRg_XED z{&Ra82lVy!FEX*x%(I~-?bW^;DH)=xXkb15>g?8UYZoF#h?%p)!l4@x`Q7^e-9wbu z=MqCP0T?n$oY}GBU-{s2UOm}i;{Afyvp4KhPJ^L8pwc`(3%7s79kwc}>_+M`@4&)G zA%M?`KATCP*{s!7=Qt9_R@5p6FPtR9#37=r!vql$>O*saZ&x+jVd8dItJ&3p= z;o_SyvIA$@=&K$QLo)mw8JNmwjCgG2K~it!!GKLTx$%vAdK*o4H>4TuvkIkG@GvAz zKJZ(v+VrBHTf|@hXUhNE$GQUOnSwHrRD-#XJRh>+g@I;p-Q1xEw4F7rR0KD!Ub=SG zDZo^6zzIjmS$xJ(1zKgyj6VZpgf@xK;!++SVM1=vE2 zo*TvLC-?r2B(|hW*0oU`#rN;9Pde6ySkd*s8WIPg1ZNLeVqn%{_kI_iaXOw82d|s- z`98(&`C@D@slH|(KcaW)rV;3_Fgz)oGmjCRgX<~P-Y`-jBk_*NJ5_jxw8V5n%M+ze zFohWr*w3<}UEVT0yANXXWI&k7*3B;7MrsFpod?_=>AIjZ!(BDl{v|3@Yh1sQsIqeS z5s5UD^U-P;5j^FMHyzC$C^e$SC*SjsAhZX{8x6H z2xc424xP0QC4dX|w5iZYSs|^6ofXZXm+7__Op1*K6_?GH+KeLsFZy2Jv2?kQOy2gM!lj7Y84U3K|M&=R)DkIkQ+q9j zkBDW~e1Yj9=HgCX%c;JLj`4VL?w4=+j|;83hfez#G4R1tEtKeLdvct{)E99d5tAb3 z-I#E1{J|g=-xCaI@|x$Rr6|N2XocBh;d02?Y1D;p>qEHEA_dG;fUe zAUIdV6VxZ!j$u`2v0j+$=A&ulbrJ_A1Oem{p7rD8v2N1IP)VI?z1RGei#7TyGMzTj zzLBqpCwOK;Yt`dn5&X_A?Z2J%EUCnR6N2r9@R?n0U@C~sKkVpBgF zYD1IF4UjoOt;2_3EcgTd$S;VfA!F1(rFiF*gZ*gp6HJ!d+q2vd83zgx=s9k8LTBaY zopvES>31o%Kk0~ugt>NvH-UGH5u5h4WwHlKY$QTrmhr@|x)9^Jekwj0iFls8;jVYZk8=oC8)cVb}fL99i(C&d43LE@}cWC028mPRyKi0S7@GkF|K?%|1x zl+`9>@Wd_IHE*%o4mqCQS_KFj@#16%f=KFmM{}INb{>X&#cuMxR4#4M`E>n<95KEQ z0SkZShIC#lDb~T9kX^?CJRaKq;l=op+i&9cjjoDEM1z!r#pST9-`}fV?&O9^_j5x{ zQ_0u}Ci4}FJk;-jL3IV?JIu=lNiOlz}J5 zk?;zvHG5q(uRx2J8jkuT*{7$J=FrQ}jJ_5OT>xT+JK+cQ_=$Y1Tqg9}U=NnGX3;-X zh+fk7v3P!v{tM2PcPMhowWd@j0+ zb%@>C)mi4<6cXC2we%n;%qvWOc=U(|-t3oY*)?IN8AwQFLv@kmUrnN`4=3YdhwP&+ zrBx}K{n4z@h2eD!NK;bNlr+Nb=sM;VV%iUVV@9}8H6;NcY99=aV1|`UcqXi$Wo@Im zBx+RBdJ?*gmv6LmdT}#K(jgKgP^~vfToHg!hvS)*|7v9JDsvX&BP-$P$%+GZEH%m- zq&_5fYNa#;OGn04H66D)P#ZvLkF-eKJ~JR^1Y=!5`;qd{a4o8LDZzs4Kcsf0P1%pY z1#3t)(7jkXfQ4VxhPdgCSh(>mnSgU8&) zaZDvD>=@yZcA}4280`cToT~;V1old3k0v?0)JN8H#`(XIx@%*3A;x=4ARLhR1g$pda&FyDX6=i&z@Z$^|+z1wZDi@=fqvBTW#=9}_G z@iUBVCQ*XhQE0PT=&dOaIi|6YryTJEaD ze1Gl{eVl{OGH4=y5DO3aqcvc4Sb_c&C3C{F!q>vkuM3h>Z51Lwb+;i`c34YPc&ncF znSQhe2sUoDfA*zzb^xCmp(vYpdoqIHffW%Li0A$b@@CG<~Ld#wCxkQHQKO)7!PDNdQ^j)4IUDOz;P|A+m3v7nwhl+Dom;N`lrp(Z;&-+7sC z43hUtr0~0RmqDN_0#jmMJY%8J=?bPMgDBQ|O}Kng7qM^V>??y9JC~~Uk%U3_SGLN` zymdc5iY|z;ZyNSj{+&>n6y8OK+unKUVx(5^G~9&YFDWV%)%tW>4$+o879(`?{TEbY z`zZX`1|7h^`$JVa5ca+6r`f?f<@eaQ&hvCO#Gqw)*z4DODdP6K3n0EGLa)BoCU zUqGCb4=9Mh*k>_gRi)*%k4kEyA>OU zaX}+39X;lvbB9*1(l&!ly3kdg8!z(9+e+9Z8N`xSFa1h<@4D+DFHbXe8a>S~dHI#l z+1v>ryyBxc!EXWZ)ouwM2>fvbTKd!CxWgvBgd1)t9IXLz5{SQ_RF{M+2q#MX{g}Q* za{lW@_q|_^;*8P5%New@ept_#!RZqG~)hSPr{Z}Ij6qeFl#_WU9kIUF* z?pP5Pyk$5W$qRytPx{uSV%&x0ngR*m(WPxKBVBk^51E?q5})19RRfS$I2&zfxKLyZ zkk#f#C%k2=|8^X{dwK`C+4NF{C}CTIY@;;YNGZ!9bUE1$i0gBgb^tm9ZvffG$q@7m8W-&=a@LA6t~;Pf z6_Pe__xR%hEf)~Ui<>|%N+(0u1zMDTX>{RdG5+yin23uPyL0c31n?~AKKKN}!V&3? zTwxU@8THJ%v*)#O%#&>w-fOIV#>9*LP#ws0FR>frn+TM8WULpu>-I!_(vJh~)+C-M z>Gw7xx9a*ZK%hP>oP)QUk&z`&Ys9py=)4KX7mUJ>oiI8k32hCf-3f~CwKkB%y*&8rEaZj)h=@w1oQx8{j(X12cFY83PKs4c{*d$e$xrL#n zN2VC;NX*yWf_>o+0ecR6_mmdZI0_mq1Z;L`fgDwD-23(M7rqtpRXY&|`>qRryJ8fg zJyF4wiV5AS@M<3QC-Yc3&uyMhU$X_>k8Jhz01MA*&N}4Z?yC+CPuI^=EN%NVA0Aw| z$+fXO2%~DyTX&Ah*s-e0Kp+$WpVU#$;`7%fQZekgPT0|J?b7wfBUooU#vy<`XPV#9 zSUKBx#D;xv>p@c3s53cjCplPHCnt8Lj1*JS{}oW?bAc4ObkPKUYXv1?h3ZaPe+t13 zRdPgZH0U_Z>CEIR!$%*5cgvpLXZVEW|B~8VO#h<@HC;u`kMm2yycjEzlLsMgp#^kp z7VEA00dsF<$qQ<~7F!4xkv4<@GdGBcWZv?z5gy6nJ3r3UpAx8)K9yR@l5YZ*KP)aY zF}=Qnxz{7Xl{77Ke`4PMW@oo#%1m69<@jbiai+ub1b9Mz@y%pq(VY)KeUu#28iakEsgwXofRc@Pw zcXa_RY3;!BlA$p#?dCC-i62@$DV9&48G4pSF#G;C9&!4l`o5g4;sMd)AFr|`Z-%+s zETvhC5Fvej4m7Q8(mfbj>i|7K!oMGIX!p#Tb#TBlpC2tNO7t5pY*#|xb{QjgFpDvy z;reeCDU~VqsfX{OHf+pKYAJpu?~}uGLfsuZMK?AsIKr=LM5oRR$$ACnyashlp|bzT zUlQ1pUmg@3TcpJVsAPW3W+#8`|HjRZRn$Wd+k~RicsBMA!mT&1;iA= z4#$v0TEJ{xqGm!xf5&xL?A{(@bk0#ttLJ{4!Ts~vLI~vDbag)J(7wsxoZ`=!np-5T z-xNFSV%x|3Vq#=he(k2K4iC0?z^%=qDzq#9-92_9D3IzbJkBsa$gl+*%%J2$9C4yJ z`}ETAT{v&c@5&1K{xJSBa0%|?BaxaNEu)E?l9 z@MLhDI2x@yRB`}q#XBTi3NBkmr)0I?Qd^8o=xmZPuipJk;FZ=W!m8o7t(PT@4^vIG6(=HYRJt@@Cgvc?pZ5j+26C1v+(scm_f;n=cAQRiX zk1*dfB~4p`x?BKmCQm$8YbpYv#N^|tV0n_~%`9@rhi7}*(l0ZA2usWN6#o*gbNqpn z1&FAO{(#?LvSMy-80A>o^+{ma5R{63n=Cy{n?jRtb$0$9g_3^ju4nZ+{-uDHM0cWm zfMphNt3Oa?5d@y&db6+P5Aff3uX-)*5m&dine@)vQ4xYX>VJXteY$X@*k!u3Yipy@ zM~>E24XcPwY9(8~OkdX>SAy@QwL>D%ylYRHhcCZq42sG$ih>2A)>*>fZ!MUgDziZ; zfY%h`eS1bI`%zOnS{I&GHUhhDIL$vl-dcWDvG9;J<19q%&yP8yOujX|11M&tZHr$?pFaJbIy77$Vgk(-w@-=l=IvK zZjWyzh5$}`8wfD|?3SatXY_a_1rj@&K=eDDK@C}1S%D1<`UF`Xw<6V81erFK+MbHc zd3q9<;72t26;@?zO{3u%)%weAi|@raYOe>n3xAzWx80dP@iGKrzC5)!@Lh zLb`;3F3)`wHOIpYx{5IA>kJAym}ZTQ6Ch>;&7}ic%?C^ONzRoiKcy=;jwoBd*7fv} zX+oY_`?}3V$Vve8 z`n>E0Yq_!SDbWXOhmy6pTWz1={%EAlr8QnN3f;9R>6KS4UbJ0Amg^ArF}_$4MK92i z>ogNKaXumxZu*kb(sl&&5Q&jnvQl-TV{!)OG*?^u*n*L5>!qq9OxPbg^=>F`hzJ+l zAR)~A|DYLoak{NuO_ew~0FN9F>D&>b>p=nbjm-B%B<$n#p6=cP-K!1cwH)9_qFI&> zKY%Ny`*oSAdM*@AbVH9lZK?dOE8cw57DL@AaAn98gtluo3e9JfRuF5DX3Wu?80Az2 z`b+6j*FEBSVAeU5&oa^L``IFm^LRjGMg=fJt17rBaV>U+2LtONwZ(+Bvh=b~w88kL zo@`gU!nIApd3J*1@g7_zCarSrojYD9y8%bg6}B0<8y}@*xdiMo?+)g%ElE3kb6tT? z(tb^r#{|);$woS%;;!f}B48aC96fDq&hbW&3OF~C@_~t1*>D*tecr&am8@ulxS)nP zI4knrM!2MP!pX+WVPPl(EPNTa{%ng;Hd$3>zpeh`2pYg7n-F&9kb5>}U`I`kQvTA0 z<#H9FKJLPE@;fY8OJmyY-t`|9&GXZcD z@J1z!7x9hlt0-a9rBo;nbi_N&QmxyeXDdZA=X}v36jd70YvsYAft-a#<%{pE(zF-0 zXD>#8GJp`_kzg_=d7^=LWK5o+Hw)mxprcfG`+6s1TR?VaF*4{vymzh7utURryLVD= zLv?O8AW!l~Yn7-jn-jPP@*PcpaqmfMFSGl=jnT#bP`4Idm9kF2A_k7G#u}jF_8Zrn zW#su!yz)(vzTu6AFCm zs3t_EBxvZE6JTCdo&u92!6AFc3`<|`23c!|)SLBLY0Q_Uf-57rEQri=0o2mMKn?P( zspy~31^YyQ;Jdf{x?eZiBSgUCZMqld|*A6TKyTg`CLtnSw7jL1#4}q5DpUa z;2j`YkU8$GWv4VP5^49`o*g9996i~64V@`qj+}BPZZ%yz)I$-$0XhVA53_3XD^xgk4C0TA=tfC)#K|<)rks)?IeJN>nwX1B7CYx^E4E*rX4VU{gUE1+}Y_h?2#UMXaI3){SphCVnD>PF{W>i5C~^1Pqop+Ga8fBlyq*GSGz> z_UUiawVqvFY+agQ8PZv7m$=@mU}KMybsR1Fp06C!{3-^Kv0_5-1)2)sxgsfpK)Rf8 z9P(DeRvPh5o@#38qi;!LBoN0iI@u-Ot6bOJ!ac$)? zvJa)P{A$3f?S=;k!~{KA8;Z=Z3B!YLWGmb(!i?XPqIK7ybvrE?B^=niHBqv|%T>od zsR`?z>FA88K7#9Ls8VEo8b=>(f`nJ+M1VD9FZ zz|M#psYy2nm)+}*EAP^%Ujzka!Lt-WWk=NS$RG8g?E+Rlvw=+Ap}r@(a2P>xHM(~R zAI06qvMpO=ld|3r3C_05)6%lO-9#>)jIq=dP5a{@`NN9>3VK3w+G-8HwIJ5b&k4-Y zakSLg8%)*Dz>zZqdto!C|3F)Pup(&+p=GXDlCokPicmxmss?%w6TY3Gk#QY&#GLBq zP`FCeRw#FTDd0j}H7j(C`>Slc6eVoTOldp#EAHFh^?Ah!WU)Sp?8ajECKd!M`Mqx@ zB{~jrOL?^@-k?&XSnQk;TFxhDZRB@oO~21tT;0opJ^lStM$J zW{3G?V77BLXI;;jnU+UN=UJ;uYy4)jipe-e)AnEG+5;-0wb`lqOEt?kLm?^*r4(WW zzt;+cZOOx@?JyDBqD1F|d?Xgo1wRAnk=GHEvG^sne)XaX(;CPS`FBbwa;Az|3O8%Z zC##Y%u68q(0F@0geKt_rQaQ)eG@|=YQT~-u?^*G}?@u`RO=2ls0~n^M`0(CQ$!!=` z#nS>B+;WH@$eDz)NlucPdAOH3QZwu5Mg7D9&O7Pfp#{9>}<}+2I4AQJ3aIn zinC%c`4?#?8Zas@&cJ*pOp@0`phw3*l{E2s6!8@DLdL2!Ddb&&9M=zyhTP6D2bU4m zXz$1N|D7FRSRk4gX}UJ`&}F{QJ49}7B|Z3oI!h~p#Og%;YxM<)BtdScE^3qZx#k%M z)Fp`+KnDS|n(-UUaey(};~OS|39)7-PNPoO$D|FPx+hC4r!^5$HLbCl42?C3vQxhOCD4D|hDXu7VBo|6t!J^t(xs1=sUlovYgY zMN;g6u!2o0g8dkA%e7tVt+L_nodyKiCGGTR7s#B;FxL0gjhs`J7ISWsVbD_NtYV;K z>5DyxoXg#N^UR$$f7lM$5uK0-J3ER>_%q+cIYJXcqI}GsJ$7!Z0;LS`ur&R!r~>2q zTc{-STz{Hp6Pn0KE6tDPAOVB2Iz;Jw4KUT^h=&IyyQu1;1AwkBQfJ}9qW83zIxHB& zjiwmmZEPpqrxEq3hKe#EopjrSD|sfA{82UaP2}!TSM@J0ODeLqgZGG~qN7qBI{%kA zVPbPNEkesX5fG3m0x7drV$Hvj4FESYwJR&_A3krQL+)E2@B;a7lUydc3s3xu54mtC zhYL^i-rNg(m>SC*O!h_iHk$MO+z{Y`_OG; za$?u&@G>N&T}dL@%5-lmMteMCgj4f8J#0$EW49lAKRYQsy{?*X`|&09QTFlbX#k4= z?%bK=0nZf;FW6t^+0uu|rJKo7Oy~6$xaG~X8Y=A7tcKT!40XPS16~=@+oj<-T$|y*ih$OTO>doW%mQ0b z&i|j|-~hDTrD1vj%{Eb#T)2JSwi=sgV77d!B9a7gb_jY)@R?YtGMnh`#7kH;-x;De zJwLD(>d~@qSvuyL7g0DWwlFY6l1*p1S1*RSld z-={$%GDWREq@6HeAF2V|-WU&G-u#Of=gabDeSmxSJ9#PIPHtVWDF9dlZ5~1w@!WjZ zPU=TXSaiv6CG?{!riKcV&m+Wedu>aKv$o;N9tk3XC7D*K_RMx*-x zQUkuYbdi)ZFD1Uef-qp@Xa@4l79lcj;5{=C9>|5%3W;z7+oc!*hUZaz|NV6sSj7^g zKd9`2-l?m$0NJBLMy-5y*b+Ys_y_U3E1HN4dQ47f{KVGxKj2;KK+PEo{thc1xcahG0}+h&@!WY$!YjfXu>%`lMXF-{|t| zo?*~i2l+-tELKuZFG5c%Ico!>XJ!-&?>uc+fE($CdRJQ_{`0=(bOZ~7KOLqWhv9Rl ze-J}|>Tt4Hq`H`EW38*H+asJDiRd9MKgmHR201tCVcYi8!7lkWJ+RS?1q1 zSece<)V@NjS#Em z1onq(YAy8D3!&^QSStq1Y@}?<1jv;~6!!`KCYH2R>)}pOjy9obbH+kWqV>f=DecWT zEZ4f%V(5+&sTbU#DpW39R_zioT)_>4#8(Zp*FzajZn?M8aZmeJ;kF*s;VPLvl;;N2 zf<4Uspnk%*=%6TM4`$jeP~$ttApq54z8Ap7v;r$ry9sQR9id5B3sgU3N6pGCDLTam zDBdsq-h(=#Gu|I_4qm5pZ55iDIZ_hznXEY*@r9 zBs2ShyeN!r1I;N<~pQFR7HWP0$0IlTXim=-I*rx-# z9Rc5YR4>?1LrY<@3kl9PCVeB_qgHg$0$+>bY8)f@v(cTyn^@Qi1A!cSE$&z_tv!~= z`PT~TJ0qsGE>%v9m2lh9O{_3)ZKns-$~1*Y7BFQMMA@|UHq|SIU&-i#M02=1Nz82O z%}aRH0*0sH9rEf-KK~WfjYT%7-@YfI!sDSZolQEmzXvjN0F7VDgDY(Gu!C`Ga6yoq zU{D)mu*_*lyc@{EebSZnSPm+>>xy{WvrUwGd*{>1&CWPZp|%b84`aWHRyGs8Aa**4 zU`s4&Iz(q5vnsNqW})sYgg+Eie{5)bKT>n%XTHGO#R+uj8@?71baGSQ>!ZD>Y&J&Y z#Eg-_Zt=1x6Zg+kOr0D<`hmxA7L{Hqpj&rLyv0=_;3|_g5x$!&#gl_-7TaK%@WN?R zMT?Z_$MA_YZz2264OGge%49Bhc`o>wg)h8uK+bMJwbq8A7xLc&jU^y?24j zo@Mo{i&HG=JmMUQ4$A`)93O+;p|7jpzTI`aes$U1z?i09td z_k=~N${xLdN|3I-dA&aQHaEE<}kT_*X zpgKf@u&$`_>Sv33?XE~#uCo(^zDFWD>DZ4qs_yg-I3e=J8TK-C2 zeS%L4HO@T2!V5B+VaMW1Ux}rMELb=WRVWvM-2p3p>fZ21^K8+W9mer31veyVvF&WY z9o2g(V;3hexZ)Z$<(m8Dgm*H23ociPpH_$kItrzH63Z z+oeq#A}u9UaPIb#de>Q=JUI~IEI#+kEswMG(NmP~g`Y?`o?f(%Ylbc4M&U5*BhkvZ zbu{G@!I)Rte4~Imkf%k29h4hNy;hx|@JopMKIFpG{Ly=IX#0V%$PHLdIk$TS%hJJ_ zH+I%Nw>qGo8$c~Ljkn>U8y8b!X%B8yh*yDK5tmrTuBI?#h*iqabV$7i*V(zTuY1%4 zg_7REI{~h;DKNfow6o!5ma?+45)Sa${YfYUD@~0H62r{QNP_s;vfxH@ViDhF(wdUz zzerJhQj%kI8xOLIedMS+kGp(?+}YFToaP!rE{H{MzZHB20`GK)Uk$7_AQIm&Bxf7^ zJ4kylp4Gl4D^NC?N{j&+3Gq$a0W~h`ZDGa@FE-5aX4ZIX)-2gS!o@jQ$-QH;N5YoV z7#BYv;@ggIPLMTB94Jk=cLqG()t=K-1LD>ob}xmu34BNbe^T_VM^ZQ*J>v)mb_xin zyT#u9#xqR^sZa~r5loGWSzipF$OB!*ODupJF~u+c4&rZmXsR#xds_hKQtgvvWeQ>} zEE2hAqv6Su>11gcSt$4n$M929(o6+%$ zy<1`d5z9zFb5jAqz?iN&@wVL@Zo|4*x~2R0rTgb*og@rYJjR5bkuE-M;b+3w2qJ`E z0;lQYAYNl@tT$+|6?e9mLs8&s6C#-C1CXw4YsAQ1GL4x1x-vd-jufK2d$4=8p}=)| zAcoMQIg!*wa{c>-s^Ru|6sUnKpyi<-urkFyp56;`PG4JA)sxiKAgkWDe-l{cvd`ag zF$IE^7bW4u;Bqj9G;_5+u6hn81}LOEfpW?855wG(j0%;iRsF<}Pi^@1ykK1{g2T4j4tkqNl zbu)>m8wIqX6~C@K@GZgP?-?{YI@-{FrbS*Fa)`Xwxt3hpui0DX=ENa0<&gA?mW>eC zC3qahpA4$N4B79Yl=rMqaL_IpH^Mo=EkYJv@}s&R6H|J`NR3zrVS`7F2XK(6sKVt} z+!sZ@n$*;7gVp{iQxLFdM@yBd&gyK@h9$o@UHpFy*)=htJ%X3X>_0vOXBX%mx)0LNtY_G_%QWTL7qv)Q z8J75=9B3-C5gUmEEb?TdlyR{F>9)FKUq8V2%2SPHh>X7e+`i9AfjY+%6~*r9rLg0w zy({aXTQ*I>*KlUMXPrdcq6tT8a-j`_TL8owqBwQI8yf_U^HS5)R7Lfdb>vyJwSQCf zYxPjgfhkaB*a8~KZ_r5_`5v6%s3Tu|I;~1Fpr&WQ{5}5;*eki1z&b&B;VHkL7ogQ& z=d#;@;EGE;RN5;;(phm#0Sr2>@5vn8q*oJgi&+kwWrpomtjg#yw?0Z(W(+fj=iIukm_)o6@}Y#@};8)!3N*^I6SX82TuV?Mgke9^11~=Y?x8A-s0*mqRf_}(_%7LyBJ$S4BN0bkGRY?NzgG6z zE`pybB8dAiw)~o4$Y=db?^wCXO`VIbsN_38dK8j??*>uE;C;2_S97hb6mBJr5Jlb&g^!Dg-XNwk2%* zFyn0Ya*1qNean-0DO4}J@xtMmW$((_6snc)e?ten_hhF|0=W3iY0MOtwWNb8A8j1! znf)5z?nx|gndaPLBNq2~zP*&>7UE#Jy9okU;s3syWBFKjVBL5{FU*l4jE2xx4%XBq zFIF0La&4o`ZgofsV`&za55R1+=cc~V_`KtHpr><5fpQuMl%zoj%mtyY1R9A=6phAB zfCTmI`=$%0ZGma$0LhPpl!x1g2E2C9qhty)iuDswyc#E-Y)n>XY==w1U{bPnd$=>1 z7Ge9j*N}ylNFg#;yXSv$+j~yJo9cQqeF0~+`Mp1eejnao#&$jzKikA7CMa-Dpz^j& zP8@;HZQe%@G(i0nqwzmFXi&{_!4xiuPm}linO!nnu83BgCVTPaqNS$7C9R|y&Z@L8 zvd8#)4sa*&)5(RzA3ot^I5p!{Z6B3}k%tmmwqz&J1N?2=cI|NPq(#rt<5r!L3+5_6 zDVY}j!ChGpPrXyzev=Gy3H|T@5C$A*!Mj^oSb%^u|Jhr2(&YeZ-w~D&=7emn%L?i4 zAEWS4uXLhx0M=|a`e~;3f+&%^3}_=z4FbO*SUdR(kaPrFs&hy6Kx^D~O}`Z*-X$6n zZQ&YG^2_9?NZH~0VrO@oDfMUp9KtJ86&KJsiQlJ|D%~-$hzgpf6ZuKuvVv2-2rc?L zFws@01thjwN2q}<&WyAFHi;_~I_A!2)<;?j!&I?=>TWE<-d!xOMaRIY8(UhEKYe9F zA9RNP^8~ox>tFo+l*~Fb!Kl@^)E~G1`)DM-zJL9bZ)>nJ4|5$4vidfaTaz=hweYii z;KzT`<`N0G#(0&>W&GaeM*1wbGa}5ua5ivEudrG(5i-PDfMUWpvBznE zUXxFnrjJ>yL~eDYn0V-_I_y-R)@~VDOF}VBN7^Z%f@^Zlg+;7qCz_M=j&F?Ghd>ft2xgGPfC~QBi~Vr-x{$-WiFLBdBW-VrxHv4L^rQdw^Ne) ziD6$f6hvoR&CLnJXhv(B zX>Tz$s(z%;elNK4QZ1=IQ9^=_tsm*RB$UnY{vET!bcbEikFuLokSAfD}*j!P_tM-V!Z`GgVYd46! zCH${88iN1fEhTyt*L;Rs>){%7UJpqAX>;FsH-%aO7c1lUFo6(ki<+AGvg02>{uFXI zeWO-ZzIz-SGOkXyBtSNpL{=Xs`Bfz_)TL*;7N1~n3@5>CM90m@p=#an+O4mU{z#c; zUeAFtXjUO3>iVO7=;+C9l;y*3=-M6}ik%g_N;Qs4bRGLAw4=08zFQ&}$}NUAERS`} z%~qlC`EpA?6r(^9!~g+iC<}09^Wf_#Qe?tH45}Ivd^>!i6DZj&mV(sb$AlN66ZcVa zaugbfFWm^Po0MmicNVkbFO}_G=iA;Rl!w#^tyH6dv>u#&3%(){Tiy$So2!_ddGy;~ zNc@PC3KJx0N6D@NA0lbev>UGGJIx%oyzu2kl+QxCUy%HDcWy&hbsH5w3OeDXP)lyv zmSK9Ik|$PLgoE`9^8gD2IrO>5pqxj_84SCB|94g`*_;n)M&w#0d;>FsUW!2)u^=qloYh0fyzx2vGAjj0YUYfR&Q9MK=(UgV^x-eRD+o zzxpn8^0fXec`>RnAG(6wzVKRX+vLKXZ zwsi+0M8t0pGo05W=-cD=1Nk*B^U>unvUFEwIaVM~;E9#W4b-i^ol|0mJ&&HeMr%6L zuh;(w78^-pz46ACz$E?>GX+fyS`YhMYn&(;1>FwoQxoiahZdJ5;pSRID#wRYkdXr} zk|uf)MT}idV75`HG<4IDyZS?F%VhXHX~sl>DEuK_nbZW@Wj!jX#9{*1Y?nu$zPviu zRrL0HUrdT&6u4{u>bp~hUC3r;)}6K=&fOh)VqHYz9NQ~6alz+)0-by+tR~N6l8%Ho zb=R7_&z&`z))?Nzv2b6*frf+{!T@XBt%6p6E2^{KU=-%DU&ZM*zjarc9+TuGA1GF? zoe#j+NcqWiH7F(k<_q*g=T#8WHFIAUi)3fPKPRmefAZ%A18|FJy_7zS-c{*8J;jBh zk}^K3oq~?f%n9%n*d9H9V-eKmGrU8q44~N%xmc@SfNv09$|>$jc1aAqu}zkFUu+d4 z-a=24bC&c7*H}PxSrNAeI3BH0 z%z$^}I^F#H;4$5V8Ug+&i9cXh)79ZOK7`tsRoNEjBpj3`hp5&3aVEm0f)pFCXTTvj*7*Ii);1mba5G)_=*Y| zIE7KqxZ|R%?>H@4zY(j)I1Qe*t=owoBOt`69tqxouD;SmzB?_h1HguX^d(AWk|BOO zppzzsxlt4vXYrZqBK-zL?VfPF0G&>UEWcvW_H0lKg ztlMi%=D7-+^anKT?t_Jjdiu7@gOG-CIy@IxE;BBi<&i-OvV@fACppiSL&hZ5F zaE2i0NKbNtdl0@3Oqiiq$whWicX+yv!2X{91#82oEt`Z8K-31}jGZP2psBb(#*BqC zHHiw;d5Qys&YL@a(4BC#lhbZ{oLm1al+;K7u?7(8_OD0KF*{NU3`k~se$lOLC!rcB z#Di~a)}W1scmSrP`tt7j+viG&awt2g{6m&`hN?cthl^8%&uyo+TdW&XEN&y%_^f|- zC2vICo!7WlP2v3Z5bIjnm4S^5>CS^Y&dBst9cxreP3*lti?Zk-45%Rrm;_)CLv;G9 zeo|IZIk&{~-N>D#vxZ*TvWiq4IVcp}nMse&QW&C|5g)5sJ9^z35aQTkXDbQAm zWLB)$1U#Gbyapc@kBPxT$6PuyKwz8t@v}seBSfh$*21GaYjdB7DS_S5J2@FNY<>gmqn}`Q58?+?o6m>l+y)W%AY7)?kaH{N$M+KmTcWp+pcXv z0slBL>0*MSxc0Kl_{jq~C)P)A6%rgazDz=I%<^-cOMI*2@_M_9+~CCLTsG2ehxkPm zW%V!Tx_vbzfhvdnh5TMiX|&+^eY9W@is3KMP_%>IgmhS5WE!9q%yDski<3-cc%-yf zXm9Kx2|*Wl+taB13jeR4CsQ{o;cnM+qx>*~;AK4916@KxI5Z_!TtC5gww?N@*p}pz$XcTI z=)^DM!_w?+85CgUQ6oiH)3HoVKECCPfR9QV04mM6f=@WMDIcFWHv!m+iOu19Kv=yk z4Luz+zSV5CHRkUKBYr7pC#2I_^DNU4Z>Y*yoDC$j$8{oA)jU zzX=g}pR=dx=ey)a#HhM8e2tz4Zjn?bPNZwhJhGKrP3b9a!lCWS5#uSkL=kUmK;cnN zDfjqd;^N3i>}OaTboqg|g!5N!4hmD_Y{p6jZYpbA(IEu|0x<1ZXz(B|`X>=6AY}jz z-?Dg5I)q60+yi4T5f!^CF)nqOk!j4)m`6s9(Wrv_nM@0%t4vC;BjWw4V=jRRZQn!E zuu6=(_HpJ1>>~=TS?;g1D!MLM$#w7u5}mLt%Yx^Bn_@-ghe;LR!_|Dg3gi?5GYr?4 z?Xx_KvJPN9#ONxI5H68yAwBAjrITNMuD84_Zip15ooM98N~T1obY_#f`?(4mbS1Gu zL1qlTBnR7ZwPWTs|9_%Py=9TJO*8XGs3-*E6XQ^}G-u&pl9udf9zpfOw4_V^fYC__ z8A=}^`a!7eW$D6&OvG|z{N#~z-K9gF2!)m6zOuiQU|8p#I9UMcLAs-#pK_9;6go<> z?$i}b5(rXR5uvHBK<>1kmL>UW?(GyY!^pF7j3E9`ECWnec=Nv%*MGEx4xhODb^)Aw z3!ux#s>Jo^zKth;X1hwv!Ez=g>7(-(hzfyn(qhqOzBi)0za0=hiFh{xIy8(W=d6%p z`d)=}0nrZM10Lv~(i%W~;r#0_dFup8Te9kJFU$_yKb}}8ylQJb#P?`k`G2^< z_#Y#-pa*}eu>WHdIIXXN5O;t@03LjZzy_4bD`_5e{RoXQ1&$V z=8G%oogs+$G63X=q(0p$a5d07*Ys2<2~RVMT{K*Huv^jdyADAOg#=R16Loj}8@-W< zDH#(N#)9vKW0Idg@Vn_iduVWzOKz_J>%$DQ6*VyhlVDhpcu(>jC`6;{iHv3;3FT;BE3;Ho9OY$;_u4ar-)z zx=+7XoQHgGK&{=2hZh{}uu0b%mR)5jgdYt1SzHxLs`s?)q9 zMQNQ35h@Hr2bHtaQ1{c}6gf4yr+5=t{`w~Xj@~w*^O`Ytj z#cO&a)WDO~8$a&5VXlG>Lg0Zk8V)?CE)O5(dG+ITGhKdlQ3_Aix-v-jFjkdgn=>FZ zU+8RgTsT5^aKlDNSgl0ZoBqCQUnEIkrvkAR3n4}CHNDSPCGxh(aR~%Npb#Z1N^dD3 zS|hHvQJJA=cBP+n>MdJ?R5XYu!zOt(+;#)^u#p_%1jC72eIN=P|Jg+I0Qo3lY)Pjg z;0wr{X7laWa8^>WHWt0VdC$UlTnT`*P8vsrz@@HZEV%xI9vcS5!4R)%5VO3{f|rt_ z$mHgvBJHTO)Kl1Al)cy7S0adh#o-Uyjd|mnZ}VFK;<`l>_$6&C`}bbk@DBUhbJps# zwtKncxo^>Z1`?{#2r<{cmafWQ2vy7S*SM&g{0s`T*~$DD7g}h(lna~Dc{rNL(A701 z`b3e2ae9uLB_)I80c1jMB){N;ik>#iPK)em+Tn=pOx~D(0PPKo8$a)=z7W&yP=NKj zM9}k%K2%M!OdvXMly&Q^L7Iib1bG0I+3%+&NqGT$o;#~pDURPls`-P?yIM;@K3Me8 z3#xARnm286+VQ@;Yl~ATuoY)NYpkjL>TqCLfQma9=ni;0rR=liqmU}DIbS5Pn#SaP zAkMHWD7k5IwI!(1ZRGrpJ$&rs0EoE!e8;RrprpcH-#bgp!4(2t6We z@PVpC7$W_8Y+(@HUeZNJ%)jl$F^u<9YbhI>Z(3e4N?9byK+RQ<|IX==SCzN^3X7y4 z)j>eq-i-!$3};&Kra`wz9ST07wwIgG44(8x{2|PYzAmG6k5!&$j}ig~5d}+O`>liT zW}IK%UtfC!t+q;{a!wfBrw9N{WV$D9Car6Rx+!P9g=?}i;)X1T1zkp)5a+D)?)7tMZwiG(C2Iy__&K zQ036#Ujy~I@GY}d!1#!?LTG9{(?DlG=gR&!mN$)O5GtIo{^J6XYFO2v#;R)Q4R#7Jk6c2#Up zTjAQyvg_68UX4J24y}AmwlD&H#yk3_u8(}3UH}F6>(Di5=HFV2Nr#gp!|sI|v2lGZ zsK$GVxa%~=4zyu&LD^N-HcusW3GF-`Bdj2ZUX!cq6XYq|3_UJU~IBDDDxl^q*Ge{0sX7{ZIB4?RZLz-&R=O2)4{BW4f)6q@toO}o0Q zc2UkxA}yP1hG=RZpMi#NSZ?m6DDt>%4six0jW*m1kgD=~Eo1PL%jP_grA|l`+oPAY zF%@;EMT3n*4aezKq~kijwhNtuS&fsa$?@|hoDt&gJ^t!Mj?ZRvl`7bGO~ehRuO27` zUfN*><~&De`flK6~lX~nkVvTMo{F$CP%AayutS<-?*C*+q`AN0WWJiC~IfyUDrg)!7irehmtzek}g23;udC z_MgSswgIrC$SQB?$>6R%psMNpFz(Cb;nr!%040&w;@aZ* zV2|$XYLo@nBc8)g)lAo+H3JX{@TrEirSdjgnmlm)Nv+n_)^ZV%A4m!!n88)#gHeGr)m7UYlp2cp5aWsG=+k3ej;|s{z-AaCj;saU)d6TMY4d#b?APTc z!ByRS8AGPjX!90SPL(!gDQ3|in04=|P^Snm-r|w;x*4M5@c-EM6F2**BAVut+(j#M zYv@AOu;hPWgy}w?I}V`0n3evju`lvztg0skoNGvSqmWK;cf)CbNgaob9Ct=A`HA=y zcBYw!W9T;ic1dx^B_rcaMW%g?8)@0^0(+Dl)7o!aXq*&Gdv=meFzQ7b96oeg^GSc_ z!duQ&9Wy7({%ybh%S{iYhL>g44E-ljwPH}_YX#Y2DQnw|g&2)^{kwt!IgV;9R~nQ5 zpEfvAWSZ)!fw8vJBr4k8?5Xk?z9p^i-?-$%DNA-hqsZ^nGXhukBdYL$py&=~f!DRr z&_#KBqs77684c*&W1SJo^Ms;>ywkuuUKSJU9}2U$$RP<|EZwR66)W}$HGVDKOJEFU z55G5KTubf_tN8I{9*&>H!%jFIW+px!cceV+$%*|Qo~=|=Dr77mASn{Qwi5H|&52}2 zUl;d0;M~|zAZ8OyT#4a4h1bB7WC8wa6Q$_&9vv-X&nic4vG3VTSn{zc$aK7}sz5%C z$n+7;u2Ol+kt_&6L~ngzpp2^J2T7U=lF_Wp0w#Qf(2CL^ZX9?kG$ugS(Mm(s-M0Si z7{sLx`QL2Wj_ypto&3>|`_)kI)dnTw6!ZVR>JLlAVP^QxOe6q&0Dj7L($08he#?Dp zTxbRw{hFNH8G!!Mt+t#xp?e?Sp8o$dI{THkLIyn?MH^U7j62!9ByZ-1RXW}S_EEXe zWwtHMi9ZrNk=En0Lln`&t0&b^^u=u%5+alGA#B&7v&e)}n4R=b=%A~(HJXsg_H4{3 zG%#`;0a)MjE$QQ`NTKrkNMd+#Y`lXOe3=TQCO=c2?07_KSPXJ}=8$ZjmW{r;S;tBE z_!c&C?W+Fg`~G_TG^11-WrzZaQKM%O(ONakIQj-<5AW?Qu$IIrAGCI|AE%uju>qXV zMX2_nyRDgQw64O@F$}f2I_*6c++3FgasmWTY^BRlmwTY0Tt8{SoZMfgrb%fnE5ltd zNL<^$=!oes!8L7IwIFCU;%fw%T44E{Q~$19@Z+1ANu%jjwNk=MFNM#liDY!CSN zO`&C-Io3V-&=Fb#C^3x80ZV&G{~LIKtSE}XJ0Dwv{B8hk8llr~f)`{4HKgv?q)ajv z`;W&O*zy4z9iCMuCQ?}jvHoVl$^%>Z{m#~l-mOh0Z zrQt-Wy=OuM`}H#|0mGxVQa7Wya3D!9VjK9Efk?Rcv!fWYO`gPH$0ZyONfVw-AdydmI+*l%vT{KZbqG08dW;Dzz0Wh}NN)xtl z5|Obd1`OnRM1~O331aHH!?196xvvo$P(Xh-sob%;XakB2AC>*t@!If-;M6tN4>!>VF`WnZ@F+(JhSAV zyrM4fn9PEuZ9j!lkwGFv${`5_zm^)a8RzI^EAq=fN^e_jLf!w9?`c>x*o~+#{|gzG z*Jx3)L3jEEG|w*=L=h97V&DBB7%ymCk@-~U6l`miTb9X8xS)na^lTPP3hb~fD_*$$ zr58j=caQrkC;ovr^ZT#xsOlay&_xhFM>_e}9B_FLUZWmTzh;1tdjCLRMrg z4F;-TC8|Nz9CpapCDPt-Xr1IdRI_LBrDEPeCAQR`UYl&m4LV!YMOR`D{xM3gAIiG1 z&kJ*4x|1$|e3M@Wj;}8jnLm|;E7n~miD2MD4uOcHjNib@03_NzC6))nVc*v?Mq%|OMe|R7-FN#JI$PyRt zi!-FvmD^SUed|ucUe8>A|IW^hX$6&riwGdSOH4E+`)a4wT!kqgjYt$rT6?MW`q2(U z)<6$#w+W{jzCrNPmrxgO@4=uM`7){dgO<&_L7vN)lH9bM8(u16!B-If-KnIj3zZj}C!lY0Y`&q23FGl7| ztQ>5-CNO(;e;>i-NTRTxsTz7FJ=YWUHTr9MT3=AtQ3+z%v&{i+na z^9E;ga&X{L@9F^d5gW?(6YdjR@wt*!l=PT)gOf>5B&9y7E}3CbOw6=5_WXCw4-@g; zPlebl>FzFZ3K{}aipZTpp&dxn`W>yz?F0(;UI$IUt=m-no$wR&aai0^3h0N}%K#T#{r?)# z`AEA+*0Jr0Gh9!R;o=e{%!r(nIl$at2_=HxkY)5MnCGxL)?4X=6ISN zs`GG~=1g*zunVRb2HtN)&_Z`ZT?=VCxNaXXOOt4_G^NmYGv@^=IPbi3(I$)^gYX!= z-y@Dm=Q?jIY44c%3rRynpCX=0AB4XNRR^ayVh%V}`Y+#71*6-+p=kItY(OYtAYu=cI69MhQhf@rC^dcTD0yhH~n zXQkm{G~nItM=%4>4;iJm%9S@U#Oxl@lz0U*m~!(UAdibEHd1u$Tzlylb13)uE&{Jh z;@^mqz(%0s>+=iY7ZU$}PVY#|r;tg*>sj;#S{z0O{23ynpObMPY!~$71H*FWUKfR5 zpxk9I2x3|!`;2!o9-5!Lzi%&nXftD)Pm1X-l`FLUfIbjLnIqG1h6BL13Fk9N@qNP7 zQQFV39%!zF#ifSaL=X(jk3xg6R8K6Y$>~zL*%CJk zk?m}op(jRGpFtX_+7!r!(LuB|ZLWd(zCRaI9t1~f0$G=Js!UEDjQ-@op^(_N-N#mh zdj=aKt(Odw2ebus(B=o=%FqNJ2^U|DZ1kprTMU660*x&*6?&UU+h%bTO-04GBRr|* zpAfq`qy~>C7U5FNG}PV6OP7v3_evifAQ)@aPi$s{bgWQS8FN4{$fRZRvBfDHrdov*RZwzm%{FBMWBG;KwJu49~CW z0{L^L|M(}igU>SCwS7SDNfxRH9d(qFtq{iM-C-J1W7hEFJ>&8r@@u*Qdz8|yEl&V+_LE3DCmhx_IDD%XhgjfLiq0qDz1gnVkYKd-h#s9n;|M)SHP^ddNx~W` z?pEsaLIe1X!OG&F08976?lM{KDBKkLC)|fC6e!X3-i!F*=>nS^9bUvNvauy~Dv*C2 zT~t)C7S`BiEYBco^pYdZhtzA9QJ?xwLXJI$2GAOHD!$kOKeIu6L?MB8M8^c=k=9;x zGz}0FybNCpGd(|;uA@2CD)*PE39#6QG)Sx`fn~Lpo3vtZCO$5~-Vl$k|NMeo-NDOw zy=w&iX#0=vauoUs+J%%Ik_EM(n$F{}X7bhN3PzZa)v#=*h2lt;pq5EI@sl*YBRc2pky9nQ4sMjs6uE8UA%6kq6Bn_|MT~GyInGe&0LF{^Ih@ z2wCg4@9xD;pNHo#KSdV~I&NP25RZP9EPxE+mqKpX`r0c;M7wk(3r%0TC#NZkoZZgW z3$hsZX$n}7^FfPBLkUBg)hdA)Ge8EscC)H;79&vGfpE(%8)83WWLrh8-8Nvy0LuUZ zg^ki3NzhfMN3q$>Q16T{hsy{#e~j>?`zZPtc}26oV`;z5!=6>bs>@a|@mn3R6R9fH zN+=B}7Z7i{1X(DZYpcrn-w?5TK`!*0fYy~%AuTo|hy|vvwlPl|5(;$0Dt2}OGakdq z{*-UzNIGkA&smAHyAkCec!c>{1@3ha3%mw1v90^&oK1QQ1rrq1|AxT(u`^7Juv3B; zyF;U#sH;pq=(?s^tje_LrN$WTQQ=XX$5j)dqThRaXSMw_!Y}W$_rYG~b$oS2VxB!m`Bq32)MaaF3D+MHGc>?22~Y&pbuXU$*KL1@hHv6Z7C?G|+BxTg$Y z)vorUUIHYzlgLNU+YZ2ad)=%5TAW(MbcC6{|0AIS;{_^^q1`^ z_p!mmZHG^Yss=$YKTt09>=n$?x1dq;@K5T+xdP?ZldpWsuv1Bnr0^W5C@Rz20qxoC zLo_%whHOYU>vvo2o`g2xr^?Jc{r1eR2f+I{P>tx{-qQ)YL$BC9NJd?u%i2UTs{D`) z8$eKQ$d>KodtdY_Kz!^6CM1U))ku#u_Y}i>R?k>_jzmCS&qYmrxSdxiQPEgRb=uqI>osi|Ps}*T2gp%3kd~rm8K#g~F7-yV zaJM#~++tXJ*A3{p(nXSwUN-11W27PkNhzn^m3`HbBRDxyhXp&Q^h;7cZKtay5pbb< z+OCT0x|jE|U=rbr8nz3x1=-N1I6dRlOaxp|VO;R8dr3jBtT@k4tmW!5fg=d&8eZk3 z_FsUfGdW}-dpkTyBL{CDsmPxoUWI!;9oT}syc(?wZaP&Z%({JQ@f9E1g>gHWWOg%= zm*s4eMY$?$`Axy5@%6mk6or%C6F_KsWR1S?XpU^++SW=>Ij;y7X#13AvazlsJN?*8 zz*y-M>UNMOj}aorTH!+usn~D>S8yrV7$zKa`r`qguOgjkxHl#H;5))T)Clllps!XE zQaMv04Ocx9lY&FaweEt@L%`VvrD3CW2@}c}mrO!mSlOIUoD}`O85}NXtjgt^rd3+v zG*8u&4;p)frVA|RP9W4ed7kW8>|5|3zKhwT2Tg3XZd+aT8pb~iUnhCA@>E{;8A6XX zRLIE}Nv9LajaIQ$84fkhQ)*^8pd^!XNv)@;vuVOh9wbnpy=;~U;CW6t!~?TopOFn6 zjwgU7BQSe3KBnWR5kDe?{A! z+yqe*_A{+g3dsi$q=ToCXwoHNh4`waCr)*h)3%v;g`vD;zs|7#(`>o_TE)#N8z?Q7 ze@C0xC!@O;AR5cWWu#8pUqCHCNsI{HW{h*a{=`~TmpclRo3LnM%-+?X2ZAwbusSWEUhz~?X}x-Bf^2uMUX8PGJj#`o9?V%nd!ZIZ9bGmVk6%tbRu3OPcI-T4r~C=`PO-DzRWV(C9u%hGuN z2n_*(S9soxFuAryBG-^0OiIisiH#L!inQ7P`l)1ILjpyT>wylw3=)FKlv%bhNl0W4Re0EUj{<-a z;(G<%*bLfKhPNi3`g~~`i8e1S>J9;I31oLj`|E;hC=ML5Ai~y)OV|9VQ8}d~?@UGT z8c+IOGMy`X)yXXd%5&?^E;C0=_+p7_y7az!1+TjYltO017TRvSJMT8*$v*021M3|f zE2I@4pOt5@g6ou9OW03bm-Bd2MBwAD{yHGx(Lxb7ZJ_C z`J=106EN!GE}Ov|h{Ht1mB9_}5WqsG5y2vj_qte&c4s-jKtw5`#0ZB8#ON(e(Ih)p zvsyE#2vHy}zA5@`eT>irSSS8(lZ4GXZ3#JalooZa(=^o>x_-{FWmC3ocvr-CrFJy3 zVvCU;rr+anC=#a9$`R$F8Ioi_x*;1QrHxA!!eT)? zU&oZCwCpOp^OJ^nFvZ}n$#;+c8M@>sbpvdxZKVpJ<>=4#5&%9p{7P!D7dO}~ZP+zi z!9WLA-9SD)x`1~_YH_N(j4@=cd_+Ln&%kJXx|8P3BoXphR=`-h$Pa#vB&kYK zt882XMEW(tp0eT;71HsdM*0h^6$+`DT<7uD-NebOlzaOZhe{_Y_`Qo72G-DKr zAT?M**^~qv@FM`@OsnoA9eR7-3$9U*NRZS{h~N%DBd1xqQqujvzj@D9qy+U@=S4^afw{?Sf=LAdW1U()W zCwG%qq|MCAP_BVR@~GcpT-v%MG-2pTa#N<*Q~)yClcO%CCS36N%wWpetqS}B%rY0U z^G5M7qqdD@{G)?_dV|%X?qMS3DT>%Sr&_tc2>mA%8ICC&;7epXLv?=?T0%A+>d@t` z>hUkL-4BP@(C$j(F=skO#ag(g7ah|3H6Dt8AjcXDzn=^+FNC_FKPl6fu=+Y%m5YIW&sy`d`kawB?eE3e3UWz65Dk%aWjYp*!Nqx(} z`RLS>K+C)sarC_H$)(nXx?feJxkL!Af7rrlyyc5~bG)6!@GzRH^|#Dvt~TQB5LVpR z1iHc^;~iDr0ORxcfILZ3Qy$F2;Edk_Q3ny)x!M2eU+HRjOGiU7gwaPty+u%PW{2%Gvc`*EH-+>{;PqxC^+*}Xjz&L5N)Ji1A*W*ie#iReaThiqe zbLQvZ;T+kVSP^Vx+Yh8ejo_)BOPZ>Iny%zv8C6lpS$Nvq0OD>UrvH|cyA+0Z53O9D zIe<`}gY-{307%Vhk;2BxsSm`6uG^sTr1T4%z`+{gnO~KqxYYQZgm(PkGN3d~$MU95 z1-fz-lY}9sh9td(oR6HR4)FMY?2O`H5mnHop8U4*)C3Ha!Tlka2|b290%6eRt*Hux z!*6sCw1$Tw1{aZveAyDOEFD%SBVdBG=A5o0KXIJ?#2 z5^ir_tc;Ge9hq7KSU5TvZkAqD2^MkjU}Q+Qz{Vx|z9z>KlF`<=YY`X$hGM@eD=$1E zO7DjMFVOi21~+(FY}OU8m zm^Wkq3gQ1SO+hFYyNtBJ&@4v=6}}|Uxv7UaJQEB9oL!V%bi#4r&gW*Pw{+#7Dkb$Q zb%2cL!pq~W2|PdNK!2h#hr@IWt{-=Ej3;LyepGXbsO_w)2l7*iFf<1a7TKD?+RWr| zDhv>`tXXWs$Ua|nC3byUd~#Wy!#|YnPUNTr97|?N@QiHdyv%t}MdT*!fs2+gP*zF! zrlf(r79A*tNw`!%#6JABP_u2pGzRG11tpWlC&|*`@6*DhFz>hi%Rv%?)9Et7YNMI2 z9+-nTax$s`=MrM?ISnC2{$6XdhpKSX)XSrX2>8!dE_0E@k21<~N|#bGaI&Q%d4T?Z zV#szV`{!-C1hPB-imAv-3E4%zqCe(*EwZ_l!!bW65Ms zdL`;|Ic}{j-bwkhUh$`!MQ>t+6%kX>e{zhv=F3e9T|z2;1+yzI%y`muyeO8d0KsY? zdh0)5bse_wEa1M_fIW2eivKQIT*>!X!0;d4-Iv8Pn(Kgrk``!Gb;QC672-5pZo`Jm z%2*c{I1or2mdXRCLZAcoWdZq=49N(Xp$Y8PCdEQ~THPYJm^(eSE??2x_$-Js7ugYU zvdg7<_+01UAr__!JvQk}+v=y(`*Jru?It#CiBw<>-(mq;MS?Epp`Y`;sgfN1bb~n~ zs2IYna@-G}H7!7!VgJ4J$*4Y{+oLvjGOsirfgXFYd$Ch&R*~h!M2+rNTTlUm%yW&e zzlWZj3WMp9O^@swe?;y^=()5yk1AtXr2(y!K+ zAW#F7i@Ht&V|2chcHhiG>G~z1PUu`P3kl6CLAKczWeE4rq~;)&#yJN_Dk?iNSQI3X zgXFIoJ+VS`+nKWGvXp1_!?9MjR7ioD#+AYEb3~no^Nkn}z9@UJN~Bpw{5w)+s@(D( zS6rI4C{bSvh#0~QH~%?V7w8@XaIhcx@2R3`wTZ0w#ZX&|iowY$2J7Uu;2_s9^lnDV zVCUNnUEE-c!b?Acy#FZO6h)V5f&0CHD71o%cx@b=2RHqBq%HD9JE$FM$I%oA(%F7! zu`$MWa0~x0Bz|s{KYb7*;{7KXBkUhn#p#0H=Rrm~vY*h!LC_U69HwW>9OvWZI$?4_ z0%_}2PVA7eqOLd2aSoyN`Fqr{;f3Cz-Tzl!+2+QzbI1+2u_JwQSG^}YjIvGTp$+TB z#cL7t%p4Nt-|eEE&bsLq+&XMR0JH*&7PgnRQE5&3nM^J#W%QIejv0QH1!we`Nt^TW z^{c${SALlAWFXa-c>_tloA7~jU7;Dm|GdTf`JVe~zJqNP0p=6MI-kp;%=;0F$KrLQ zVgu|iI}sR!&rcU*hVl1wjKz>-CT0zFIiZSztNg_>?!p#wswiOn`|kh0RJrQWXQ3ot z8bPEEIO_pP@x0!=5dA;?$hw*PKO6nDyQ^~mdRQ?TPI3M4O6~8;Emx@&$u}G-t8nzE zS4RaqOuafK=H(EOy=X_B1RS_(9oDCj;PQ}cx|+5_CxEg22DFZ)_%L<#V(aHZh+ObCNl^XbV%2a0#$&8B z?w7|Hp_qoG=fF>FE1K4NuBr|*d+lodA2Y`(HQj564zG3~AVaTzh1K$b%Rn50WuY2G z{OPm;uTCXPyJ((PUF>@o?Nd{V5{083a+18D@H@v!zDE_`Up~jWFppcz=7dJfN9+l@ z{?2%wl+JloN*I$J)&chON%iQyN;j(a2GG&77M)+Pea87EF-CD4y>fJ}?k+qkV5 z&ISM@NlV)LnV_Q4p>NpRM9Zh!w`c#QbVYBIsuyNdu(}lCII7m~0;mGe>xw3*p+{uW zPSpWQeBEwXp&VSFBqxK=?@&9fdl{=qE2&jGURcScZB+0%KC@K$vl6!trN2OqTWBj05sK41m zfH`>>%8bbHiT$X&2Nrp19B=0wQt~gBI5W?H<^fx>{taKju8gY)HD#a0r-#}6?-?JP zlHOETs=byFNcezrUD=C#8sbeU1Bk{GjP6?3fRS3O}<7x zDi;arx8^75ShwTBG198hOzWs<^vUcWRL< zXW!2J*TJ!mV%=sxR+9Yr#BmQL#E zc}58ha>$xzH@+e%5`hLM9@2I}woeEfmlf{RVHVM$yNX~Vt&E?yABBrTr~{5x1bqrh z!W}6$Agf2<#*PDh6655Cp=zbU-lBINhFA21a9*|5W<>G_{2_Dd11nNvo+yPG8sv|> zyj`bK+`uT}u_0#b-2ATNf7Fi&9#d*6r-XqujH4Ks^o67Ic|pkw1dKcxQ>laomO8q_ zfjmw^SH|L1(L%8lJ61yJi~Iz^2a=12l|WpU7c(!+-rbbJKPY@m_c6{W!L%Ral^l0CWs zIT#$XcuiYc`yT=233qH99DgK*u`zw)P={EYUqVP5q*0cHx}|D8SU%+^16i z`pqKp+N31^W!U5jewH`okZvNPzYKi3uePCl>@%U&+5+$WCkV$qqg;N&^Zbo6M*OeY zVQwA5vK?R5u$)c~w6B4RY2ZC+P;QP|gwbLjk-w)FxVd4!1*@IYTLnXrPg)THQi>~+ zK77+iB(@BBmXLblr*D*ZnWBNq7XLMeLqNF<%Y4?((yvdDhMYQym%N!=k4$>CHqLx7 zF9op27S!=g!YJf@CaiyIT9>zIe*A$>sb3=#zmYsxIE^j)@ICa@K0Kh=S_9Spv@m{x zxgBZrUZ(;>{znrzrUTM$68`?Gfz?$)Y(s&Dxu4rHKgsXj5EEe@14|4rUj_f8C=h7ey))nQ$ezT!r9!S z$?mkeXRWFr6O*~A@JM~tnZes9xjZM4wW{d$AO-71_qMAbU#e|yN?8;r+1oVT+6xs} z(g|n;R-YN~M~-K=Pn3*ME?aqKk;8*Tv)`2#xFbqO9oIOIP;-Ex;_&+^u29H8%l@aGDbA~IC4xNq8JMfvBUbN+(^9eU5ALN6p|L3+y z{c-31w#}j4H&1g!C8!8JjR3ay|EYFBsTb71*l_7`~!cS1G$1^VQs2sowrh1YE;;F87*QZOt%}w{=I_pu_7(=*dYg3 zo?2^#h3b)rdHggo0m9D7nqpR&>|7hAnNCm=)l=OR(}5W@YdNP}f}_I)B7GN2{iCSk zx6d)G@WP`N;A*DqAZcQ}gT>Z&d~_Z9H6m^CMrKNw*>-04DQm)u zF49!8nF-nHY%#whF8kaUP+hQtjIrrTj9ygyh&T?gP38DDZYAUcs?z0p$0~b2CUmDi6mwvyUw@#Aie*zbScA_PBCf2OY$O+pPN#$JqUfz8W^!=W@$ejxI= zkP16O!OXD&0AIQDFt441oC`@wy7CUIy84gbDn)CZfR_LYVWbUrzmgL78Ox6dW%{3@ zaEn!10G3ETe=6zW*uyL0>`V!!zmv`4>Uq>h6xalt73rvm=&31k zh8|9FP_!6a*$ih_y5i>fmvDvKPum0}6(Kd)oWw zw+&%MeBZ+LzTjY@|3=LkfwX3r60Ycu<1n*A^Domniru3VCuZa*?)YC8xw4Xyr0?a! zx`O&-h3%UeTU=8E!C>|Ie?DoOV-47Q@Q0OIEz1>Iv2KNx zW_;Fy^lI|**KcR_5*ir;R^My7v-qlD%kYd{H3?8#9xjnkl}x$Lq9shUX_EfMUIE+0 zh`aF`eg0PwB5M8FB1mNsrpj?O0a7OO@&;gzdJqosXWhpjo!If6#K`{HA(<@o|j(qb4lPPuD~ z800UKezNk(=cyG5e#%!)Wm~vAwA?0xu4FNVT~s{rEL(=$cm#0XIdZJe49s2Rlkyv@ zPJ~j9f(U^@FA#AG^8(zuA3gpICj0nh706mA4J9+Hn=a@KQ@8RGY~(jTGJ;w)15A05 zFJ1eW_2ssE6I)Ei-}&q3V=?MM(+8RaUExKL)NLDC3LE5q|7kL4{7N|+*>&yIG_Wax zWu@-ndtlYKD4z2gfI$n{%Aa~h`V@A)PVh-g=OlS4pD~N!hOVa$!d1HYB(b_I0rjDA zTPJ7kT;V9FT_iI2wntO+?SOp66ujOtNc}_OvwPb~?@`GQzl?6mn~PUWdOQioNJLv6 zp+p!aO8o~!$7Gr%d6?pmW3In!1 z$aLNkznHmG!#@gMan$~kHT#x?=Wl$MG{43r3OW_Otb=l1x21ME!Be4oAE|O;XO!SA{X0SdNcom zmeNstJ?`c!(v=TinszM~tIpHEFZU!s9Qz=6F#Ug7iknTc*?IaA=-~qTR_>zOWttAz z1HW8#JxJJfEC4>l1MDfBdODI9?LS1hzNX)I49c?OCg3tLa+vvNqxz+x+^gJ;5yB!va=#1QOKPlqL6dydVpXH zQR+aK9q(oSspuMV!K7PPRj5ukNwXfu%UGi@);u~V^@$cNe0uu|pJPY+fNo!t&s=XG z*%c1|C8NC-36jH1NAoY5?wYIGu7~mH#y$nfNk!SDG&Wzu4UrX$>@^a|s?#xgLf3_( z=JQgeN4^-q&5osNqViF6Rc9j@h>tqs=QNaOGE<`^JRfKYj^jm8D04-}TM^lFa!)om z2;tdurW*?upuC>DvO5nnur6%L$ckf*_tW_dj!G`9U_f){nCei=>s9pKq|s2aV+W5J zkWwWZBRe=Tg(QQcl-?9%bP+OlcXRa23N;)cYIVOxNU8GYg`CBlcOSt3=2yWw5~q1Q z&O-lf-o?mvMe`gM-rq<^Q&3JTn|=0TNMfaB6#hg%{wW=0ITH5t>US!+iPs@MkGy_9k ze0a4)^(m&dn}n*^u>x&xJx*O^Ifa6cNsL8c&doI7FK|+n>vN=I>-+?VS4^%b!^H*6 z)xskAzG~9Y7ko}58~&H5->^E7c=D8>;&9fU3TJFD6c+hN%CANmzGjCTr=zhwkf?K* zK4-k3;hedht%!tWpF4ic4N00xR4p;CZGPIS5=O1h2Zxiw5W`Ju-+B^G(c=KFRO zW!r>qG#O3OBQUj93cOd+kpZas%Kr_j&HH92my;B$`+r2ns_qpkKzmUKxrt`(cU$h{ zU72tQka`T(P|wOr?9{>@rA5+&rq3yIsG{J1-y*{{>XKHd&)GFt-Y1Ygn`5);>*yOm-P;B=H)|GrTBmb0EN>QE7r<6+3ir6_-5Y|g#N!hLlgh3^vQgEe6ijZZKgBe??sp2KZaQ- z)tgerUJaVg!_0GtbJ?du`-nA-kqGdR{+s72PjE-YNxqo(e#hM`LFE#mI1F`87T9J> zXDLc|G5Nd<^Mm?Ypo_>4r#p)c;KbQC^b&tjeL6Z4*s@#AmQQ$s_AF7nL%`6QLiNjE zpKy{>4FaprNGEBsx-*2|K`m@Uh1ZdLgT#U0gMXI|2?S!s>*JTSF*wAtkXt(+db=H| zZVxvxsW^d8yjfALDqsppLac=_ZpotFDN#1r03WeJ@3+FdL=zP;?P6OYK(s1E;l)h} zt@e_3r;8C6SsZUNgr2SV>Slw-Z{Z~wp8nHWQ9k~E(dOz5R3i02MFq_-wEvZY7hywE zS#=%P$G44sH2GS3L=^L-mX_(CYUpOXrWvP9OW2Lj>0se|3?#3kYsNR?++hjZfn4|0 z=slzHzMMGis+>+E(MqE?Uf>Y3I_ip&m0~l=&PL}oG=jsN=|b%T&VVU=RKmV{lBk4M zZ01!`^y-Y8o-J5dTPQRW1BOH0v;P!!b-Q&X&iT97PfQtBCGINnLm-F0dx(FZMoU$< zcag&owJLMK=_ug|{boWua3dJ(G{Lg%7}+$Uy+ql&(W@ihY+&@?JRB)pS__m8ROD($=k z3qct6@Ez2##-sCBt5xSu85ra-q0f4_cfMlZ`ph_ zxyGC9ts#cm)p`4Muo=RVE{MEv-deNF#A&~E0G}+w6y;FbtE|)+CPPsjT(L;oA+G0; z*j2}Fd|w+ScUuhl8V05|KF<;!jt5&-ioLgusP!`WID>i7rjSvPOov-uzOJ+ros{1b z1Q{=WyG?fdMc%S6EOiCps}-MB%o|<{XJ5SjDnK$Zd^LHbk7VP;dvp{JM5d^n2K;{5 z&wA&6K()s9L9LMUt*oA9(TNFi=$!pGB4fO+lbt3?y?V`} zimD>((v%69rYG(^gh&&7u}-rF&=Um}>SDBt_nIX0Pecxm(Pg|btGo4T{AQf_AhDwL z>l+{+8AGx9fI=`;+s}UHEQCDqAOh)j5Yd?mAR26=?u5}9Q3%QtEs&^Sy9YZh^R*D{ z@b%OQI;33PnBZfsEG;ESd(hu+@2nu2)X-i6=#v~)C@6-AZ{{yj^_87_w;TCBC->bA?W3X;3Q`$K zicqaU()q|tvqn2ztJh1H@=3n+aJh{AiqaLMLr&hFW|K^lw)NiG{i2ug+W-J)^Ks#Mom(_z7;Un0dO39GgV8wh)Xw#SabMVnF;B*)37wsFw zP)8;CWFW2d@ph$glRw13(b)J{LX^tRE`<83@jiy(D}jnAHg+R==(kTXH_}3mJYwc} z_Bnc1GLBhlYg^Iw+KCzlllT}*5ji0~z5-sj|353!Z6Bx0R;1xWua7iwP^_!}^*xbBU7cn28Cs?y=!&e$xRHg}adnCZ!^r6Zf6lp*<)w5;r~rHWwGdyaS+{+Q&*yMBFIY z?Z8HY@`7k_xUU(c?n;{~*dGurQMD0S&wEU6ybvSQTVg2 zXmb}=KO3NQufMkiLottUXkVD0<@PZ@h<)9bC`)s2#J#_PW?D(zFh3E)DUQ%u-gTFr z;>DKop1U<8WE((Q1(Au#9}%JeNMj4)K6*cRuyk7kU+&OLXMW_q4>4?@tWV^z0E~P^ zqst#sQ&1|Z69HRs&cb(7|NOP~hY+MculL8v!p_XhEOUEG6RYO60%B-|BKfWLlfhM7JzBvahhiIUE{OuZUEIe!8&+=!{T`344G_?!4e9G9li5422^NHWMU^2k-sbxAr-3`Vf^-HZGCCXLyq&GH^jfG+g?H)KDm)Z2JHvPK8N)QaRJ^ zVErkCBh+0T;Ms3aQh_+bb^8_e4SBmKJBzPDoi><3RZMMk+qBJ%-qqQadl6smXKsXTwyGg;e|GEZv>bXP3;rvr28dA8{Zqv5RUCm z(8cy##=wz0)$*DkRVosT&5nk^+sK~-IRh#`?%zL{ek)pRYF*M?lZN2D?3)d5q(kSW z>{K^@7akT2rr;Tcmd7v{Wy!uaL)xMd@F_%*S_gc|c#;3|q9gP4xB%DVZVnX|4B4Uv z={L`zia^*)#O$21z93I8v<+`qHl6{owaG~%*YWby4u%J6Vq&>e9v3#e2Ba@XbN!Ko zJ!9rm_@h(fJ3o1!aL3V^_Fc_rYt|gUPA^gN15oj=h_uwIq9ZZgIblag<*vP7Lfkv? zI&lQkZ<>D1w@2tmt`a=}N)k|6+Ga+I()|HW zT}g8BAtP;GeJ*dly_KW`M`TkcHbxDJJ2OsNC!l`+(B&w}g>WD^DR&SQ zb3ba;e6l?$d3G&BR=-C;5ADE>ICpjN&*?ElJnN~&7JUJQL@g}wu0*eSh-5>}Jzk^A zACiPLv-mn8Q?>*sC~-d*ajsyRHvKf^1A2RrZ{Z@H^D*M(1$XJa)3kN6C5F!`0%=qI zy9Px9B^CxWri9cwt@>rb$zbzAEiQCQ%HGJ|zS2_OENLBdbE|u%T4dFdaPN257wtdS z$XmtWy3xtDbfClPJ$Z=^7~*8Q|81;KkIcvLqN!)eJvn*^zWm{e067UQr8`Zo;uJF5 zqsoXmd4|_lX&1l=pedFg`c350d8y*8BpVnsuBVk+lcnn}WzO^UF9W3@XjK4p7xo2n zS6s$jfD^?(a(msvAYdGXi+*>rXz*{C zE=SzQ#2}1g=l_h<#=jkDYMc}BsRBuXO08-n&!Rop71-R~v}f8DPSc}`INZnW%tHAg zlCyE7-|Oy}b02oFY2(vdu@>F2Ktnk?n#5X-o16I#o=IcGE2%OksXYqDu!zThOJ&EL z%a`I5aSui-;-0ChNy@-Y9k%=K8zvWB?$fBv3OAN=yy>2|4|M+Bdti2sXrVjvUYnh5 zd2GxdjbVM{f^Df0Q0Q5bg1I3%Kj>MMd0L7#NwAV4h2azn%y}L3T*{(}u2iC>QZw26 zu<_?c%butBP zN3wDsxc#Neq;69!DhUSPfA~gRE=(qSgGs2_kN>hQbFmtyFGl@{Fm6r8E=VMVntZAD{_v( zALY2$3Vt2Mn2dxBLAs$iM2A{9nuee_EIR`HV^HR+&fSnvM>Q> zD9spa-V4okImQFO+^NX`fxgks#p=)Ju-dY-Ol{?^a16r9#xA{ z(_~J)aj{6hYAm^ySqnr&Ql$_0!NM{E9^tA$C3|GRMdf*V5Mgov8+|5eASUHpcO;zL zib2!z>AQ1&jpd?or~Kkh4qo|%OS8j!NcY2HPdF0)of{U}$z3=LS}M=5P%kV}O}qI8 zB*?1W@bo!^E8C1Moa{~|>^0J74}$9vWYEai8PO2kGnDUaO|0q-T( zDzzI`5AV(C&xd7`{sG--JYFeEbm@AuATg+zrpkAzm9yTW@Czzaz`W0>xx&<>qJLMU z4jHcVf^46u(eAovlcup*@{({szFWEp)uVNfWhPDmOPoo~OWyA?PvY8OnB*%{ppT{J zd8r1HxmUdgJ2Gz1t?d^h1`H%tG2U^z0}2p$ls|ISN&V^^BP*c`<0Jm3s#$mLrx; zh@^L5o+Si^eDXL;yV{GSWYW10WXoRy*PX4uvazfE%&g=ZJWRw^zPqwL#XWrheiDVu zdB%fjQdTYesOysm(!1aG&-PT?>brn?r`jZ|k!!i)}_-c?cPF={A$N;m_k8j#l|%c6x|i{9xGh=kH*{byk;Z7Cs~fXE z|KyFvLGi$d)AV?8c#4x(>yb7i@2VawA`*M|FfGor!CQN0(dU9UMYSu1{SFdXuzKD&5;M26R7z zgao0+ey#(VOSQ1~+tYb&b3Mk|Ol_}pZhZ)b*;nUr3zL!@n9pqc*{6YS@{f3FBBs?A zJhq0%hdxx{d3%VK|DUwYMpp|UhdNW3s7#_qx^S|iQo11vv{B+*V?X~_OOMI?4ps+E zIYdH^*04lDm^)OcPcGfV4{KkK4vEXZ?+!TM(GPxvXRTD8moD%%p3WofP7uEY|3==X zA|uB_QzRp8B7=&pT0k;-`3)57Wc@G4Htc4eV4%MZy_C_CJDk7wd@ ze-2Yb?L5aKI0BW99z&_!oK6aWp%p42xpJ3MUDK1Kq=a8Upwv%f_%v&Dk&#(K zlZ4>mU%=-dDf+dVya36g37NQAQ^hu*OE*K2T6a&((16{J3;}o*&o6`VFj*>t9trE5`;K zIbMq*%BOvBG;N^*PpWBVRzTE#5&&FlfUfw!cu|m=tXIv^KZ|_fjwKDLJE6B;)}sD{7vyX_htnU=wP$PtrRTmB z;(PB)Wb7TpEZ?NSz{Dq;MV{*V@xSpB!IBhq_lJq^Ws;#1Z0D(XCh|!e^=4 zpr6`KrDEydY@rXE$6P!U6@~U2&YRYBA$BIFsH;w`KO1;3f`L>QYHyxt;K%h6lu-@3 z{U+<^if``kvN@*qMAD*$PMVmv4n(pct1=StUo*FYR5)@caPfU88>gi5_joH{6<&)A z7AGS|v@4Wq!zXNI1{|(5?b-_i^wJNM!R@#b7}~nkdA@AItP=fyIAJE|+mt|JeaOs2 zBG28>0ZN*}OTb#QF?HqYye6xoUi!$4ol+l%z{RHUOazFz{I zJuhTFysdC#F=W?~GIOP;j7*DmVd|w7#|xBAuZ0B*(Km9mjy0M^hYWZ~zqv5Hx7rkE zFlj%ELFDztv)Y})KI8Bi*sakRa7GF&(kD>erPU2XE=2iM$LZk`Ou!PqtHfLl>U|9m z_Vn+l&fYu^(vudAAP+cyf83%1RX>LS`6YfW7KXE1DMagL8~clA3Kyy8o#d{| zH31~?W*~7Y%DySC(80`!^j$~I)4}I1&-6=8Lpfo_}!;#mWq5` z5u`feJ~RUuPDpbM#@1&BFwH=6Pv9~^psiO*%M{}cI3*$=^|tN>5+To?j)d!8h%3z+ z@*eKbG)w9aAphKf_NGn{X-F`AfQ5wveR{58hFPD1{c7U&%^bj6g&;Z-LTlx)j{j!U z!*D!o;05K#9rJMjLzHaNKWY*)p`m6iyzCr5=QOH5(ANJ_D}!zWcCYB{-O{c0GBDCe z3tljxuS(+w)VjYOIccH%{j)@T@wCR>O=q^ClcpvbNZW3bawn*XMd(X0f>Ae;N0L7K z=1HCHp3vP_QU;-H6HNzNsEDI}R~J68mq}OP9iBJ0=C6y##A%WY#VN8$izAG_4m3*8~b_(v%jcw)P&2v>np_s{W}$ zjv~&=9rJM6G%Kv0o6e7n%)IiZ#Lg0p9qGVtMoNJr|Cel3Of{)E5X7zSYwWA{&rE$} zUE4;Ij}Q>FK1_}=w3PQ3$f;_2#QVb{B+H7 zNNc1^CtH4PwB-F@yqcJybZ-?D157h38UTcsoKb2;OYK;=AgM!X1d*|b4P=^d8iO+L z?pS-0{J;M>XL3t1wKu>5)1wZJ83tpoVP8($QLdW|P|&gQ=9klT053XPfufRdUFn9* zyUQH|3hEcmf=W!qBYMwVp2shO`yJoWi8W43NoWZ_z=l6t-V8UK_c~7qb;kW9{;3t0cyeR|uzCa7Mf3}+!TbQP>WGc$&8D;v44b0% z`<;<^afzXjr9=%u3;%~g>w3ch#eCDJ^T`qvGyMfGtO-re*>)uH3xKX#K*TH$;u6CINh?p zQrF9S?*PaYR13p?sG-zR_FMOhfZ>Z5YFwLieeT$rcj*57Hn6r%#p~XqF9@pal3gjL zp7oJpRq@;=-q(sBS@aqS^xo^Hdo(5&%v%y{SbeEu9L$dptTH{j?zX)oqbwefmh+-YNri(qkGr(G6;9&_(8B2L*qI7-5 zka*x56TpuW5_MngAF^v!gP;)oblHp@aHtt65gNAn1h=p#GTL`ayMk)5~XO;XuByQ7`@drr&BuZeIbRt#lb_0V~XiO`+S z>4@@g@|XJb$}^EcUE2YTBfm6ADwK>x>n{clj@S{|5WjR%JKh)PU$Cx_6gdZ9h? z>(0En|<8tWa5%`;ANfh0hIAH$%)*ak_fJEqBSRE+0Xq1#%-|P=v8bA^y6Y z*IyN9X5{ELMLpw2S59fo#F)th zD&HjseHsnv-bxLcj*q!<{_G)SFz}@xg3(@C={4GMQ$M8|IJKFefg@`gu)b{k_o6&x zmNfhBT?n<1qE~`ZCJ&=0uuf>WaSBi6`1YRY%yOj%|GNso5v@7U6)!-e_e;yz@*TEr zVh_!mHGl!|mFTE8%IyvBD&KUjuF>WrL9W0oomTWzJuV?nCU?Ynsm3RETr_Otwn+_` zlkdk}i*_h^zbM!=j`KAui^obFDOFf+-}>XO7&mY>Yizq!T`Ohy`QB?|gl7Hlk1UG? zn2%U!VA?V4&dJ2==6ld;LOCbGSH6CJ#I45|=J6~qbyzHzjt8zO#ytE?^Dqb9pg1b{ z=X9_N!5A1ORW?;=gVdV^848{*mmiPqOZ77V47|61=)J}tHgW*}0OX{w?b1v}hs6)Z z1<1ZLspAH3!@8zaEm}NlrQ4T#>D|V38raxg*O^3AqP-yQMoBEjCjaK)QT+e2S{cI@ z0ro6g-g?OqsC)-!KBxuM7=A^rUh zg*C!M!AK=ad-Wwr=>43D>dwZeSvh)j&(0FG4R5;pj%YWGPP#X9S4ek<$N`JpieoPT zHR9mI{-$XcxHORN0r`VEnFD=?gM`nF9Gsq{6@+t6%M>Tz27L*a)-R0Sd@TGj3`%1S zqlYX+>oH6L4(s|O4uiIHv-O2yd@lWWdrP16vF%vgN6>l*;je43;76!`4hS7TIXwXL zDygMQ2HGA9nMMDg?h_`EN9gCfRKhqrE|iW@1vzq>BPxqHXCPkuZ*EGh&~*%B>wjMX z^G8)U&p#;kf|Jtl4AisOzYY^_R(hpQ-)-0mS*~DXp?TSP?09Xs4MYo^IP|8 z%%P(@!jO!VUhwY!a^EKzCc(f6Wcs5V)LllLM%#Gt@ePXfFW4h%;mY)yk^M@Q^c(Z} zfJCV-LA(LH=0I3pi&&{`jKk^FuzTX*;z$O;6emg@4Zm?H>#$8_so(9=LMp>+v*J99 z!X4ti0-y#VHJ|-}2#MOAHz5#j9opOooko67<%~yDLSXyF%^7p)PVCK67>Pn0cS;)g z*bDM>{#X2m5)qrPDKWaur28{1%;BEmw0R2TNBK!u{L9fh0vjSeI`jl?QbI@*G&NAT zStBpt8asZmlZmMHsZeAw`xWhO4)Z(`muia>;(jsR7XOf&$ac>VIM=561+)(DU!tA2 zg!n)Dhf^ALW?r8?re2UdOdO*s!@|9@okz;qc>v~y?boNizdFdTJanm8a*-da1gPM% zAIRel3qVQUd0DmJquA~m3`z2uVYu`%GjS{)_pqDLtQDaWY%jdksserZIb*X%Lo!sG zFjaf8m~cJ*rHRlLVTHyB4_H3Df2Gc&%^3GcQC#UGym+P$w;*f_u1!d*pPDs;tVWy^ zM7k^Wjnek|e4>(e5M5@E2YX8FMuGk4YPO#kj`o9JHE>5ZkPpcslHXG%vlZF7m%+2T zkKr%5=~Vv6i|3G3Y)_z3TigLiPi6Ry=m$(o2{9qn(lT0V00zU1ti%7*sMudpCDdK& zMB`)1mPZgI*esj2K$Lt@Am2RgZg@AIAB#I2!ATtpT@I7%@7W?XFtw*_O8t+_q{yd(*!#@ZbE=*P2wy?%A>T`xn=@(%K?bdda^J zPR@JIy4L;n6Fpc&B9YRE5v+U`uOV9w!?To5(SWbxD^bEd?KuC-@7g}~8nXMUVo6@2 z`&NNfTNtv<#|r5+K_5~Vy#zB2A``E~-U`hH4{N~e4U*vq{qHq?#KneM{$#k*-|A`> zxIKe1nG^Mwp*S1<4g?hL*?PTXmbKE31hj)bbMYoMd-XmF4Di&+jM!s%ZQ{m3(8QX> z>yVLRs$kupsfqWQ6SS6n-M{=^Q!Z(LREwK;7c-cN80njmwPHV}j3)man71sHOZ|OD z9O)W;Xt0_yCPh<}ZkpX+^B3-b$GD`sj(J0cvJ?~`2Db50zgLno=rI83BVuZ|VHNZ= z^Jn1D13-LE-m7#~j7T8avR|n!bI@cuVjMC5Z(?=oWdsOrz}Wv8xPOI>%0fyS%eozW zKoP->*N%4>4J=oMFUHj_<00PK{5F_~RS5hd%__`mg91-DBs0<R*!jUJ({c;$YIV6Sw_7wFsn6XlY_ z#5nI_h+z}++VyU|j{Fva8Ei#jRShw8LZpN?0|AO$KeDw1(Y%;`An6xFeb*mUq^VjQ zP5{Fk6F7yeVfFb(Q&O~H)N#kt3eE-@y~mAdGoUt1fY>JF*XwrJAp5NF3`>!T|6(ZZ zs1Y-(w(IF&rX?IW39tkkM;BF-5_5@>p8R!IpZ-F+qe?#yE_PKdf{}wpkf@8MuQUlN zTzyKKV@0AC8xqwY=pJHEgMl(+)+9QW2Iuc#V;~5s(aTX+VEm#s#W{1Ee6HJpF}E;o zb8eZDjJndc=bb>VBRaLmUSC7fRv9uin7NwjHm)_fv}0n^XE}Zm9OKBB!ag1=vMRV7 zpB}#(ZYh24W@qXRMw;40&?Szj;H38|aP&iPF*;c$QT8CY0TymXFZBBjYv(Z^`GXLB z{Epop_+wrGUjVcG*|i06-8fC-T3njZe zD6T^Als742Z5P{J^K4&rrNvXua^D!+S!_Yj$l2^$FF+rn{lX8JAG!LwSM7Ii?!9wn z#b%0IXT0u?aAxKuIV*w{RAd@~yJYTn(|~1*+Hk->e@8hB2<{#1m_ym@(zI|BL+RQ4 zaWZe^;&u-Nv`)ByPhm&0t>ZKT2E%~(e&Qdn{nW*GZ6c`Yl$gH0YRYyQg%I=BSh8`L zkJ2=Y9woM$H&DBzK@*Lj$B0shSnU{uVmJ?Z^*@om&YT=)A>SpDRXY~C(S=#lDnG-y zHHKc5GC9}%0ROwd#2Cs0#wQ+A-J64;QvKLSRd3T?y`Ra{&64U>XpnT#=BmZHFwq>7 z$L{+6!=5=Pgj)|TYzreir-sB7OrBsE)I%OPsPopW%)bamJ4I`*tcbuk#kyq9A6X&? zn&W4Ss5)Evk~JDy9933JES>Z{87&lu`LWoQq6RWNi2K@0rPHi0*Hmh3y>P6}3sm8G z&&}h_ZB;qeE;pHCI__T*8vKOi_Em0%%zKSkJf8;JxD=nsgJ8d>FL|=3Qw-+M?3S-% zv?Y6o3}KJ~_PuR7k#nGQv<0CMgpq(nAS$r6#uQ$rfjYN8{G_x{If49ldOWSQd-jkZ znQC|-MpJDag=vNRL##t5;{~EhP5#EmXFLqsCQ?2Uj0ambJ=ni>l@>X~2=v3eAi@$9D&__{r6RcXbXs+~;u=Cf((8cMlk zu12xZ$#kz2s%|O=(%0aa=yggtTcOKzOwq4BOr;~EkWTr7Fc?-q(MD8)0iFu<`F^vR z{?t4p4gxYgY+-wcs?kS-R1LN*cj`kblWZ8NosK!$aYUpRKZqWoL^; zV3QV@{hru3^vrncctTGFS2zuenhny=A&ra&G>!-&P;NnK7+!6UJaD=s1kGuUjHgc$ z#I{5ZcP`=(h=#2j1B`8}1eMAD_myqk{F5vMj6iNaxS^|_5!LSYVg*p&?JUHS9RB9- z9lZmB9#1u_x7@^{8z-t9z4-;$@%94(J7$MsJ}R6Ei(nVBB>SEKmr6>^JLGjBn<94? zJ`?Q6^Q^9QX>BR8_gr-XA7^-~hOYesIF=%;f1qkQ^gAI?|3BDuilgdEvz&K1LpQm} zh(1)2Q#HdNb>?d`8vsd5KR$Rj-N^@Df1#eBE z=eJg#N1*BiGxeo=??%czsEp;42BSva9RA}38(8GfHYQrp8XV^ewfQavo!+g77A+uhj^FdA6VI!BH%YjZ_i{cI6cvtRH4I$Q^n9?3Jz);C zMKPAn4IoO6i#Qfj&xkzFGk1zD?MGQNw~Gp7$HIu^YD< zg$aX>#oD)+2((QVHL^-OO+LTF=^=sdILy-@_b$Q) z_@qGz3fe@9oE7IDukkCS|56!PV*pDKf@rZLaRowteqU#v0L`jYS>jl_7$40Q_$vbF zYj#k`1!L(*q*_e_h69`tBN%y_DTc=DO&c#+)OKK<<2VyN-^J=GWsNjDbVSwZs*aHO z$9b%#I{h7;T07e4ET`bsI}J9(osbuKp*>-f{pliJ8)JJns+b~3TJpMB%K!Yax`-_OW9U~aYD!&`JZtYAEHLFO zg5Qp9c0aIkbp(81Zz%)~n5+});gw6B9(RQWkE+g1TD6ND(XF?v7CYXzWGO#+TS0R= z!_#hD<%Wp*8*M&h3f9zOb=b*!ftmK+Je!1wl$BI8WOsUg<6hq9vwM6yrJai=xhHfV z&^4wKRF(QO5+6k6pWl>E8A55U8rrDN2#SN|!9Bcnom-^fvB7@|EwvwcDi-i4xbVsd z6~lEvk&Hp0!jBhVchNeiZ4uc^+6`w&z;ZmT7;eGX#f2jDTjFn~X3{1o6FrBKKA6dIUTR zBdhnVaIB+YCWky1Gfj)l^a(s3%8EBQhNeARUo5KAa3oSIbUU@yBF=VP1;)>hc}l2c zL6M$d4=GLJsxQ`7*yEctxFIa~P@X;QzKED#5naPU+9C8aZP>ESVy2!cp>Q zPdKhu8u2k*OGK^n31G^!?XfY~sLG#jwkiOOq~jZ@Fo0@8+kp8kIE%#^q--mYVC&0c zFW%w*rNMJ$aOH@c0Chd3DZ&v32W^@+p7IvrrBOeXxc5y`vrlk6ODWaiApib8B=IzR z+@Lp%Bcb^~9-S3Xgp+_Z#Q6uQYVO-w+_EMs7&k;K?-ee_VRU{EhV5{~(298Ax1YJ~ zB)^twedw%E8NDoY>A%{r;{LRft)XVU`LbqK$IPOrfHgoIPaNhd{r!6Nx)W*?3zr#M4KB_ekkvoa*GH6MU< zH`*jXG1!GNCc|9XqI%OoP0ek&5ijeatF&oQBLpwU6Jp7&>q1g)4@Ke6#=J>l1afm1 zfvtT6W=FR%3kFsJuSzZCs!51gBFI!Lw=1g`cedIA?V8vTHJxUOV#pu@U0vEfFGzxL zKzAWs${my9v9VXzp|=uZOVbSlY}X!^E+EhAjvnXZX)A3aW?gV_X&> z%0V*iVICZgx2}Q#OE>gvwO<1BM|m6-M46F;_Io@|?mi^rABDJa84K|(q7g+=P__V%?tu`bu+n<^-PfO5TpsAS7qgmgoD{8V5S7 zi=c@5U&jsd-$nX`YqdYUj?o;9aBj2AXRxt&sVAoTog7T@?I!@l8zd$|!#hYC%>4Hl%;pv>va$d&gLR{R73GW1w?CyRb9cwUW5<^D+ZZ1{da=1pD1W^>CK&lS<)ovK%U(Ps!XY%w?{ z_*XH;4&PqoY`Jx~{oLL8D_|dO!x5agjMSrzav39QFbBv~o#%+#qwCqDWQCJdoI^^q zJhVVmw)(=fiB69>LXcH`znHp}b7P}%^kUEycMm@rL~mUHX1>{&TuI(riHt&0$ZVpKgVWQ%}Om#EBHT1GAJ%T40dB##J4h`YGPEq^|yD z+Vh%NdgBqHH}jO>O;jd1>SF@V2PB!MZ7!Q1lp1(sCR5et@TV$hSe>x0WZ%Ypan0of zkb=l%2_3a9Py$JJh#RY3I@ngmtPVz)`-?AC$<2-zw_@*MiIfGW%9zHm0S|G5$AOmm z9e*a=Fz)6x5`^pbC&X6toLr&;xMJF@nhi~Iu$y~Z5t2&dvu_d%&#$wn2nYz2;G zZMM%8yoLKs?bs$SKi48pTPK-g4$KKi#rUrEb`|nZTk_-i)lYECEF4B?C zHWqe|Z~ROM`o-d(%L{S0M+JkA?IizrzuqNjEUG4;Y>k8|_ZlOJ8h`np@iWTyr3Mp{URqBqtiY z5(9Qes_A#yQwIk7!jMZ3(9*rfNrzlRyK-C74#x=@NknAm?V&U+nqS9>m;;dH_Uf`5 zoR+VaDe`Tr-p_4Bb3*`Z6A$I4c@;d1!L7sUCq_=^p6}rTA1eM5Pp8Dp)Htu0Sp=gR0X%B#%rEoMxiACy)y-UMoidgfRfK$^u`kBS-!Fm_A3;#=jLY)vfe0_=qTBZ)(%j7%Mc}0U<5iTGk ze|=1@@B09`O0VlXH2?g}T>D5Ppq8fVh*uqXM{otM#;SWkAc@QnkU=O&~ zWae5vnACnF-(I}|QjWA`cJ}zf=~bj(5}`l*%VPDnURnadil0*mcf7sZIT5hI+c0;e zz^@9qB6UKQziC!qaplBSACE++W_kLJ(mW0(ND&0Ttl12i8nC(7# zmaWFu>f=gUm7@Jyie?#hSbQeQvY^ua#&md87Nb9}Ao803Qr+^&Ly05>4Tjcz%?!~R zyrxqZpt$J%aZl8$1W#N++d}x$WTh)@ickM=C*W|(?-8-b%^b>O0t#6cis0o$@OCA) zeV>viSdyW(k>p@;o#3T+{k%(H`Bl~HnWiIUuXPvJWAo$In-65Mrew-ZjY<;h?A)G= z*ZWg#z^ndz}L)`F3Y^ zT@Ezr;>TDVJXaSEH6^eKS3z+X{oU172w#B8qi?3@QK-8Q21#CZn$<#PMSgsZyQlsm z47986v5y&cMk3*b4`~dGaeX&l_)SWzy*zYOS5E8f ze(?Py#z_B+=eKt+Y%Xt1ppKr<H@)J- zp0kYl5xSkM^n|TK_>1S>whecLiHRJ!Sa0Ge;!bChc5bS|>r`3Yv^yCHZs0@dfNRv? zIQ;`OGj=G9e|>NoQhY0nx8()&W}X`m?34EOs!8{OM&yM{3N>+8AUU)0>QENzI&pmM z)aqe+`qOm63ezoE+3F8noPYvk<4zR}oLe87a*kTy)T}&`!m;xA^LGGa-*0h-R%@^uh877jZC1y2oo(eUo?4MYnb7I2U*U-3!bTlRTewaupV`8r`UlfvPFA15*X%_W)pC ze?3TYhUIwYaPW(Qlr`5`&4`d&Pzd5PTNDKaK9V#&(#II+X4dB>E(V4HQ3UM&7$a$+ z=P5_`zM!rMnkOFzDs|fHMj9u2{SA?qvqUaJ9qiD37g$NQDjg zW4;E2F3=1#FC?U0%EzvXIMm=8Sm0S?XSn0^Z}D-dUC&-dfiG32d7iQIS7YrPxJ2uA z%-(Q1_eD#>)5U>>vVFqrQ9sm6@m8NVPC$d|F_KWtYjn& z1-{>|dL&!eY>Fzs3D4@CFT1{)Ntg&?6xLcbXmw&sBl(ueHAz2zPJT+F5K!RU+8R|JDe_=+P^iFJ*I+P^CMx^d||y-iE{I z@L)rL9gu)7nAewR@Y!xoCy-FbHRFdjf3U}5e2K|>b#e1W!Pl6?8a&a5AedqcXKTrG6Lv3V$FHH775pf(flY-$ zA{pjt1zr;h_OP_?!g7AXah${aHjXG-LPW8@T;_(r|K$es#q)nokg3jtzUm2%D*#k4 z`;(sxc{~4V4p(08YODozU1~XF$(L^I;L5VX{#$LHTjK+!oZ2Ycfsb7-i3~67%jJ7T z8BJNua!f_RDow21PMpZNOPUa`J`tZeyb~2*$Zvi>)zY7j+A**jA5fGj9#>J#N`7_1 z`Jt6a`cC)ZeB;SS`71~T|0`Npl?O|06)w?ew_w>!+!D!^GmqqmIKZ&%B*(D|Y3DYT zARxN0Y@@+I&7;MYkQA#R)Tp!AL{!ZZy98E6Ne%l>Wg#uX#Kn*;-pxT^OS9E((r+ap z8U?7XL{CrrbjbK1C#jz9U{|blVU&<9n)i59V=35Q1;+y>j^?hh%u%g&>Cp=E*`UCo}Gn4h$*7mzp3={u3nX?V0eMK3&wq{NU7cGQ?eo^fKc1LRb5yL zTsG;#bIv?8=&y#B+PojBFRVI4sR0k1A%=hIW>rqL`nkJL)O`~hNb00a%!ox}`gqW8 zjX~DdjQHvnM$Ba;IriG1Y##`8A1fkhStZX%-TTTn_luH!Qavz0U%_|O8yDBh4g=h+ zlscK_)lgq8fR2{ARCr^lhG47$q@Ym{magh72UHVE zW`}(3YJ{lyXc-o#Cx#`a?T2e^2)ENx);DXp1zE<$v;#IWsvV& zoWGo#>fHc1H-X;^b-k73*a<%BzQNI8AJV&dy$e0PXS`w7mX4Qdybry-elnpXt$T4Fj) z>LOIlE*m!KWVtbE)N*-RRq9|m9EmvHxkZ=0C>OkQEAM{a+kGV-sa{!+S@C)e_y!&6 zIt~Yzbzj-_*>6Idx8>=|I1wA)cvFe=S^|99Pdr`)vYJmzy~MLjT_{zmBj2$6_XmCn z$dV^%hB_qUAgj8UP4O&E#AB8m5_iQ&Jf|HFuK#ft7w-?H4ARpZ8O@#>+o4(iP0m(W za4>JOzbd0gu2*xXNVCX!GrO7zJz^(USJj#_v{WPXnNIpQgeQDGf|M{U7QN?mvc!f z@`>3&S3GDW_q163=$MIB20y#Cyp)HD5Ie039EaKNK}PSi>dUxW+YAQ{YnMt;&Fr(X z82FS#eE_eH3Lp`<5M)H(lhYg-yfNZ?5r~={@?chn(oZdd(AVRIAB?FtYtZPgc?j9W zbdtA{=Ie%I8-gZj&Tp2I6ms$+1Y?lx(}VjF)^UHuQe@on z^b4%EB~SYHCpH6p>NGCy^6CTB5d++W9=zL62QlM!QzhiMhh$r2bETg)RNZ3M|EtL{ z^m)m?;nW->{dpDT>guT8RdMW4SSrMlpKHGEpKP;owX3}JUypoAY=M;f+}zG^5ZXPf z=#DzLaIsyu=XzRsjGq8iy)&Gzl8nz_ATrsS^MbdpL8XLY_9F|c8I4hmuF@NwXflv; z=DbadeF~rQ;2`~pNuH#uI>tSwq(g+(q(WDh2k-SoMNPBBxgXhRzmXDDwiI4yP5p!? zFOB1m((K~5WF4bjZ?-KcyEB3Q2Sg{TIM2pYOrN+;vNHpP$kyDISq{M0` z6bcnBv!SO0Jqn%#q`?^Wx+;)M2Y{Xm{8hLc5=K$Umyt%n!l$BU36-4LwdRr;jPYW! zx;*h^9+>$2tw!pF1MH)K$YLSz=*wO%_DAE3=q7%GUX}4lv3Xx;B$*cV?5v}wrL=}K zh^Om)_0=7Fx=%0S52LQ(_H2JYT*r^>%pg~=Pq93vvXWfC1L62@O~*xGgSH~Wdum$t zC+vEBdq}d>pPmGc|)&IAN{QPvz})Jf+rYWGaKN zeXl*i3yCDE|2AhC$)NGGPA9`@NEx=hah71b71d4$jm{$!Qdj0H$2h4*S{yODfXU28 z$eRLCGurJ~aSO{fL`IPp5!BxEDBdlcm&i&!xu{mZ#NQUSBK*dSg^!#0%LD*=Qv#I(YX`a*XQu!T|OFV|HXUWCd z8;z-Gi_!`h6xZ$ysAgb6M$M867@$rD=+a8OyF57)V*@_Yc?+hvpoOGf@$cG+A+&Jc zN0;nyM&^Injx(y&CvV;{uT<^)%$P|39}V9v&$aH0E|rDanpnuGA_@j385PMZ+tW!# z(Q3x1yc>7B;k)O8Zkgv&|qAXi*1;63fzuUMvJc@E#L!2k^d3jG^+_W0rf&ktGG zKvy_hl~H+96l+vXeO~=H2RnaXdYRavoGdg9ftxU&R^C2`^;|4YXK4b{cj({T-lUb5 znH#vVYnBKkV7tW0yE3I{tMQ`GMkhAG6BO58D8!Ohfbl7OY%a+n=fHu2VL2~XZUSfH zTcG1JV_lCyoot4^i3onaKNhsd)gU>qDnHKC9bC{>H~$pL z_4H6CU-~{f3V;Nifl4?e?}M#z;2w&9u15{28jiYFi!MZlQ-@J`ocPk|P@A#n|6A%Y zF&}+`Ih$(GZ85-9vL|x}&rskBSTPT%hcXKsXEBdogT_k;iRBb2mfA>PXV?gqz_3j~ zXzP!+;oL0Mu+l{41Z?&oKfF3+1f|yBcb;jacR`hc&&y`sk7%Awwxc~_7 zLyV)rN;Khm(AdCPhg#OOTvKFwsF&m2NGq5ugN)ZVL-Cgf5|8vW>{rxn*IF@zX-q2kBpGo_Ts1ga} zK%f;v#vDfb^c*)>X}Un67Qo0>BoK7LNrH>{z>rtN5`uiMuH--jc=tjrv`H!=EqzQ2 z#DW9i2uh5}iJ*luO}{J@->M$_=uc#-ZN^N?KfB1phyNc+ZV%`^OnKWZ)$B@1J?EgC zS|_G#32a%Zdt~$JT;Y?|s20d&3t{&h3F{odQ&05+F=CZN2D5^3l;a|?*KFlCmWilMi0){Zb+vG4CWN)ps?c>BXsa3hN*LSD_G&Q#B< zYN*KG{HJGc*+~moph@emZlCvc--wgn;7J2)sn==ei;%=C7q!sK6_|=oaiq^z<1axX z#f1ROoo0C`C*z5nyjK|`;@zS?M&G zLywmBX&|IgJi+8>Q1s5Nh7=Q@1h|+lI9nM$caJ;z=_oY7$|*Z6q1e~Qh6+a>nB|zG zi!wP}lt6R4m%NIkveHNbC+;gXDWt6?+yMQEXnSE`9$X^vs&ZOK&8*jN9OQzOXNC^0=M(2{d3th zw!EuDwz7dOBu>KyurYwu`_<<;HkDct*iEcM{JP0MX_DN7BGw$zY{=rPHCx&@chOgt zspO{m;L1~skP?rh1DkVMyx|*VJmtbM z%SSZ#`L8iAP;@Jjp47|_o%rI200Q{hdo zSX|s0Gmb?Yk(W^>;Ok&Xf2cj3Wb566xsoi^^a#RpkvTd?eF%wcl;U@#PQN1c=@NIm zl+o=u<>XJ6P394KO{mhx61Spv-3n0TMLL~3Rj$OIKP?yG_5ejdy1yGw10Z(T zG&r8fwkW$@mA;G>Kp1~`+d_`69@=^eipI8wn2CV-PZ+mK<%Pu#pLx16N7T@Twqe^- zv!u!~*&aCa!sw9_ZNJP72!6{OT(v0j`dr96+ZnUJ{#W^pJ@$g<`JkFpmV)}#*jHti zL&a8p#Y*PpQKh{wf7aAbmP;6wp?`lU@=qlnvPyU*D2l+{HVwz&@2&Yb_^9L5@sJzy zjqL}d_PJ*7q^A=C@PNL6=k@6M2^Vpwa)tzfOg-G$zTgr(ppsE6e+liTTWT)SazhnO zR?F21XfWDJI@fMoRW{ZEd=lQ=|9>=a(KbB*2nEZ|kj(2AMY=az&Se}^bR4?&6>NE$ z0t3IUNHv#|&+-h4zu_aCFETi|@R|>FUs@}bu)1MUe~)pbQ^P;9)JiS2%O)yO@eCvu zYS`F_Cw+5%Ufv6p%0{dGcZ4SIWI#CcUQS4&vbh=K5ZA4191>IsuYZYA+0wbb#AL)g zVks&j#3`0rs&5{3e!_w-tn9o^gMbzlu9krLi zF6SNfxi`#WWfJ2g*Ikx7zw@*U3+^V{iv2a;rzT%>U&fR0c7i(4bMFFXNJA?+?dr7C zFR?eU`)i2CNqYpi>NhAj5xq*in0_E-xTj7G@Qfpqd(08?zQS9i{+g zLy1peR!tllU}d*oMPWTGXca1wDMa9Mk^jD93D#=-u*18Q|D3?G>?ouf2FfOWmk8B$V&q*=>8KrP0@? zV43ON7eNZe49TS%eVOyKq)A~(U6SPeiQvS7#l-CQC26^=Sw164lEWy^d11(RWuO?Vf?-w zR&TWtYRYXxxOyn`ek)r|gw5ajNJZVweXer9dZRgtSH`Jb-ClS~%$;netV60D9`EQt z`#)$k#B^!U^WlO&8Ax!n8ahR9%5@|OoB)59Yle}3zbH=>Oc;0*ZdnX`9U(5r;^i_JOu7cgg({t z;ReMI|Kw**xqZlznQ6zxOzxS;`TyfMEU_#g1C+A9L3BDN;=QOE`_F*szAU@ulMCxq zrtqkb+v2cLW`8l~*%Zg?%kXXWJ@I|$vr9=(O-IPOeF~uNE|q>tt#|EV1%bw%uJKSP z9ke!)L{!1rOt2b`pOYtC;&{wWmv-H+hwx@(>M69o`LjyX@Z;(~{l=eOz_l|^iGiTF zfyEtLJyKD*q4h;&H}EQ$(ueazc_!a|+k? zZKtgbO%#lXK$PE0mEYC^3ZSW;;US5KOJ9N`qg z{wX7}6|!IJveJfJ5bDqGQFesLk8_wo3U5Om42hQ6HcZ`|jSbzn+S0GCV~aYGTlFp8-d2$`f)6FB^# zqI`EIL{6dVcq7=!SJ`Y2s!GxZ+gt> zIJ4ip6Yv7UpBsH%J5Q=${YVgbE~Psa z2{>Noy=A*+&lZ6q&^+_e&A8ZpMUAEEl0IwnN4-H$C#HB{I=!{_XF|*rxs~^&p8U=# zo^bXQa?MF;h09RLH2Tql&o3L%>OcCXL`^)5t>Hm|hg=I?p=dxwCR zq{t`0kq!RzPf{-%L;&rFgB|3SKn2q6pSqG@l~cU}M9Tyrr-_mqO%H)ZhQ3wyY}$`a z_GUHF^vS$S9jnAri~MOIdzkK{*2F;}4b@g|QGd2i(Owga?I|v)l>wRBTImBbC$uI} zQAC6BJ=G^Lk^@fQp3FaiX5_vSpo|684ac;|I%G<_LdZ7#f}gEtSg(zHnx7ZMn||Aj zij#9=9IicR?YXh~aDll=9cmp7_B~LxUV(2R*kp`$(F%6m&4)3>VT-!(HFjc=gOvUI zm;d}|4Mta7=>>z77IoaHgd#_5Qp_=C`XR|5>cAOE5)hvgA~ z6hFO=qS~GgzIOYTDF@ZNR%R+A1KfHz;G@9QI+gA?TSu1X z8o>qT%R6<^?;jKg&|h8XZ7U3K<;Qh|TXRu(e!KWh{aUY>@EoqWyhRc=y1&w~Sb)&? zjnJ@^hCpoMOiM{;G5xi&tITg3_39oh;Iu4{l1(avu)3q?UXDCy&k=}OEr;T=^X0E9 zya8L1nSjuaM3dNUh*Sh-%ehA{$muCMbP+vdT*=co_K+Kt$Te9*a6-`~x~FTsAlRk! zOHH9(1ASU5dKS(2_c=hfZohqyWwqnYl(J4ZQXK7WS`4?CGdKNKL zK3b)Sm?`xi4BPoc2pJ;Mr!e=Hg$d0Vd+*JjBIV>#e0esI{oBJerD=>4A($2330`J^ zj6uB@-Drb83N1l!L-)kgdHAYKB3KH5r%FEwjN-x8?^?2OVqlRyz$pvHq<$ZC<=^{o z;2la_CuHV(uv`^Q9nA~{@7JU8keM3s4x66QbWUSkC|fwu8k>#aHuCGj>hji>DrU6v zld_-QbMz&iwkt9cV`$Q7w~Nw93fhFR0*6hYz5`M|SM$M>BY#_nr+t&}iz*a6_Jc9v zF2bWBLH8*;vNwRYsUx%i8AXsgM-K-tcWJxgI4&3>o8xldlw{dzdj{bt2`EQ$|3X6Y zJGXJY^7uZVueVv@PS3D=weXp~>aGz+qp!yY(?lzeBl65U=RLz*{#6DRS;lh}YhB_f zy`oc;X_~t6ij*~yDUYrrmmNIP<6zcoclj4+Hlf&+k!$}*bjk`|36si3+~1QU`c}O@ zWY`og!-z>EGm#`Tp#||ET@^rVE^CyrOBRGOJWb+j=i7xOrJ922TNpKKgfp*swzGSU z3MzW63zvHRc069eYd2Zg|3Y)XE-gjY8svWqiKV>MNdRI0@|1H;8i5#|HWY^JYfCf- z#jA#h$~3BC4;x%3w_*Cmop6Lu#3PH+sOA2&fM#=EaO}ANM9LQ?epqSVzocK4^*;W_ zWV>BZmxB*-n4Ipc4}kE=`|MsEddddubI2JR@OscClE1P_pjuLz&-Vh=FQh$gq~dh{ z?OK7wwei0*hrlRg{ZyU*)zgAv4Vv)uKc8u1X9@^dtlm-}uaonuqpNZZXLP_^-WDS`BuuXSdFvO5GNz-U8*lvkgNO-gcH z)H@m=@nCBujNa*&6JjU5@06-Ai|JKVd*|kGS{MfV`z+6Rc|Zoom8{2$1gdj!shW*v zT6U+Uonulcz6RBW*|ozj%LF(Y@v7>WWgiV;B{S1~2AHySy(W;M!KXomX4Yj-bj7FfPPd=w~(=1d7V?eOi~?kq8=b9Kq9%Gym&R zrzj&JG&kxTY5h$NULwF+;1bb`gU|2HoprMQbV@`;099>CEQFo6!k& zzD^?MF05;7MA)a|8=j2WulZv%KWp9CBh|LF?K@U(UN70o3(4+%4j9j|MsjTq%&^X`Q7#XUJ7qF)s22Vt3MWi!?p zfq`NQl0)IqrKv;Y7W&34$!W)Eu4gmSRAiw^hr_}`1$rfw-f3j|2w>SsseRk&3}?bz zzX)4?=Gf{37o$}A^bU!8r zIPO^g9^{+*Og661ckfA1E8v7;b9qA*?eYm8#*n3{Zz@bbVEBfMy583d(UM>gc@q@d zNAA*)Qt2ZL7iL%s4K*_yG=U7G+31!EW|ky4Q~h7rJ0aavxLZ?0NS|(owG5{mPk?KG|{c@jVz2#;!%2O-n(* z?tyog;)nY9jn7<qO|l>%Wj)-56pv7^m^a>u{~%gvY(5>={oDfh9aS}ftn0F!0&odEENoL4v1)e2BA zz|HC{(Zp>A>q>)B5~Q^O;6;CyKeho=L=5NGm*M*JUD#UMI+C}7;qj_&mjn)j5JAJ$ z5(3_Mn`T0INdq6^qd+$I_yo49Te$IKS~S(edpPhfpAc?diMGFd@E1Fu9>KJ-n$gR& zn=g8s8wCMk_s>6L+%+TA$4~E|08tLIr6;Z+9` z$x{PM@(*;nHMl4@`3C4zS9m_~r=e^%0)^r#v{*|p0L_9!+zRalC*X}SkJr?S%E!~g z83lCa4akwYs=sb^5RdYo06sL}PUyTDI7MpW!?R!dY%G=@4eIpIG7OQcxJ@`zbQ^bF zxPw620ekb_B+hsz+^%G%b8uR^kT6hNDui>}a}A(?^+_W8@~=j}t|m?O;?VW9n3mq^ z;h!&1m)a(DcTw}YDQ*ZyeDPwK2DyL>Wi55Ow+_INQO{LQB!3L8YSd51g;x#3mbzoJvX34KpyP5imBViao8t`T#M&*)6-xALa0ca57VZbQ3JlCw@ z3_x%}9!pHm1|^q}A=C_4$CNDs%qDBMRU`q^Ux<2ksbP-%ZKDD;w`OwXR4Pr1>{A?b zlGhBkLuK`7vcgQ`B{30fbpDv?@P%AA#3itYJzQevww^sdNW1F~Db;dQ8xTg6%D=$V zoJn=rJgDGx^u#o41T&Y>lyFZOvyC7t#UZ1usMs@*&pi_6qSxry(}GNfn;x}P(tQM} zG1NG<2q!rvR;ld<&iAB%@42Bpz}AuMiBQt5Nd$!}F+uO;tQt3L`NV6}TeJOcN45z! z<#gEpeU`1uM`!dw|DC zX^j@rB4{n|dz&Q|Rkqf0FG+_gi?np5hE-#Kb9LI+oIIsLOMT5aU)KsGQyhPXT0?4r z2R|~^F4{in%ROjnfQgem^`qAtb*OekD{OJHKUb->6YEiyZO7Wi>E*?pj*Lv)wXL_L z#=U6VFBSP8_Bl#Hpfb2NvFEn=w+jx{_CId4{{b{HH~)M1pDJCO$js)aX$gCCk#ij=i zsvQrf6)I%X7u^`I8&jX0ug<84ioAN9GtLKgIK8xeuxJ*Dfv!|so3Cb_-eoObc!aO+ z77MYgk;d21Xc=4ptCp`6s~$fw#Y}*N1KjWwr}GD0%pbC>$B^O9 z_$Hqlp)NClT9x+c#j`^5KhxCaSPZ=qSPzlpQSJGU$3};i*FQ&#-D=vbCR{jqiRC64 z?Mr!KtL}E=)`yb}(mI>%@EG<~4-~|9ATP*ua|kUh7@o8k5Z0}Ji@lFEz)pR!$e$me z5q+A?nE-cLVmc1`omVYq_S)C}rQ{}^Q>K;nGfiY8vshB1>R}jkA6w=qtopQT>l~Sf~;F=MSSgtkR6N%0biE9 z+;1O=S$$*pD#N-#sKlnA2{#KXR}*$q{?Tx*ESRON?r}kB213lPWk#=VTa-&>C2-j^ zF7%BPlg;x_``?PMqRSLcU8qgxRtBGi4LSdvQRCJ8k|r-JQ{9;3+AtWS}%NfE~r$&yF&YEPvud6WFGQD zo&QpiKfm1OtFy}bgiF>TFt6@tn_*Zwn(q9)7<~!<=|N7|L-O`;d!}fVfK8~eyD9m# zK4J;eoIC*hUCK=T7ru(U+-=Z;!SB25pbA1WVGGf3NJJ1%0Bn3#XTQIcidWO8`>x(xC`cu3y|!wW|Zzgusvhan0wi_(2;Xgi8skGM+! z0c{{u<5cR0DH!ONCG02A1_td5ue&e&o-C)g0(Q=%0ic;$Z!eU2!}QIWnPH^cjpTpP zdqhGnF-_sZ)=-mPm_=}cR%8@~F=!3T18u$0Gh0ef9H43lOHo;@(@!aF*MFt?putlY zf0Xi5ya&fKUX(}LuGz)-MiDp!AETQoKnAgjpK+iyrwsq8N5OjwuDUnmFllhnNvU00 z#o93O8kAnt{i2SOq%Z3>%83wtfyBLRahzIG94IIrTC;ALA9NSya93&>H3y0zQ3Bs{ zP$lRKBvN-6mV(afA9eOKuX`{C-o*(zMc<*kD=7F9?)^&e?CvgCr!n-z&egNjSW+V& zoEzQc1a+^(4))@JaJ#D8AyQWC(^$`A8Z;3iT{fifW;ouXESt_y$~`J@^C!mZGo1di!vN_xgaA zh*Jc{Y6X(LpHHJZC-r>wxo032;yF2i-Ix)=T`fj5ZvAQ!fbOx9!YE{clc&sf^3s(k zZH7wIdMC>vHcY%+hG3)uPy9wt4Olh@3F%H&de(>9;l(i}eqsI}bM-X5x4iCbUPU{F zNN;|2PmYv2{-JqphjM!GVO(|>p1m}t(K)uY7$^giq5$9bGodr@9#4}^k{C&59=b9s z@gC_nvrdApiq``nYMySFiDfUG;>G1GJUGsw5K`tJd5j;hE!U9-z`+$8K&N!3Eflwx z?nb6-G9aUj=X3S6T70jB$_;V$9`y}m zTY?vC5#7H)iW79uVa4}wt$*wNN8=L9(Xz5(82hZ+%Cn<9tW&etoP zeJS-(QSS7&NN+od>(9U5l4p(#+dh(`9MPHuj+N8x?ri!x@MK!cO~VQ#s4Fj>cGPBZPY>(ozwjp#2%6 zKI@^PxhZ=V!XJ}N?kWn zvI*y{E4yBrq>%B2*#4h8AFJGC;5_#-nvDJ%lA!Wl$4Mlv0kw1#niN4fw1>S@0})I_ zBwYYM2g35%Sltg|TkgatbGPx3uj)Z$N#tm!pg_&`U-|N&o3d&hZnr(9GNAB*uD&fN zM&C+k=IFbLuQeF=B<-m+)Gpj^wE>(KVTMFAP1OKEzp@Nkt|WJ1E9ySKQg`JW=`{C~ zRJ1KGU#Gja{Eg;~lGd~$&W{P4#l``eO?%q&?bfe1qKqu%7WutVH>=s49}LH}@HjqG zc)8kzm3qFyv~guNZMNGN@WRM%aKFVU6=uJDX=|{ENo=LxvyxiRiFMp8n3Wu%g|TO7 zw$enK4V4KHWcT~dcHi#$981~kguBtiE!wrY_oGZK?zD{2R@8KF&AuYnzrg@iH|n5) zm(wzy9O8V6-2{@&>u#H6qN`lND9>X&Ma~8W7o!NoPct^S_49rcXs`CVm;z)PIhv1b z%cV8(Yt&vZXtA6S%cFPao7MEBgsOdpkCmEiOtbP~W_%T_(lZI&C137_4$(rOcZi)V zo#BB|Ei}d{w)#5pk75}<2u1mo`E+W%n?)|i28#aZRf43lK*)PFlOqgakhaF~hP!`J zXm1ZHeIoT12)bRTp(7r)XC&D=b@S@h8BsR;U|;Zb!uyF;Y*cimGZuw-EzLR^-}02N zPelZF4zpt16Uu@i!RUsfBrE6?85%d5{89qP9j6tu7b;os*FnS);KDzRg8M)XI^7ED z!yJN%HNI8}L|b(vTGM3rOBO~L)kASzonuRE;R7hI=IK;hLMcpwFsINpoJuvMU4BO} z3oOvdhG|C?f6oz=Ud#r-4V3R@QE=5RNw^ybdLMeQ!5&A3J``NwWc-q*z za^%LfF&vq!XiQJM=7}54+~lY8odGthnV-$PEX>{XtU}vxoBwYZfEFMrg-&A?zXCcH zXYUpc{?hdrIFeXa^ivVVN|e+0%*6Nsy{u5pAGMdN?b+zLTo)UL8n|capSPv4qvwvi z-uC0RY|cv;=dV)Y0oLt`+WjCrJ23ECxP9H=Ub_xKUB@uGf#N!jdrks-twv8m zlOtGMVVvsJG9AfTd*gFrdY}^fh6xmJaCZ22iI*@P7F*DZq*|4Jh$3lySRT=Utq~ze%%1)YmV`SlBJ`hdr1%_c(TDf5eWwEq&|zTq|63+%0q^imf2t6906Q0ubUY`r`6$%&^RGOM$fws5w zokNPuYBDi8*2WkHFC#I4X6`yolM>RFaYiJEFD`;zHjk8#kb}29OhsSa{K8%p3 zmp+k*SVwJ!wR>%9kc^@SSt!>+M=bsJ+;?U+z>y~bg$t}WpEf*j*}2wwL=$N%V-tGD z>4K!5U8)9~QW+y%5z~TZ!93;gR`EM|AIdofXYbHGxS%>`=%mmwb~ZVI6U)deDhX#1 z__5uss&)kRfa=ksPA3%x>x6v3L?Mi*xs*y@JBOnYrkC^b#YQ9dX!4WQb=55n_5YTY9){iH`W5A4GY&aqrTP3#+GxScaibZVz&y%%*9YKi^$wYk zKt6N7uScCg!XFX-<&nc)e0o{VztbIS8c@PxLt=I&q-XDQ5q|?{z&VBu3N^gaOr~oimnY@DWvqfj`j3;wc|n6c)Z z(JK~^73%hukq6RG@(L@WzHTfbAUm)98fBkTx^(5~eHrYEr@mAK=98!AYQw!%^ul-5 zZ&=Q~Sz`haZ=h5){-}^nNk3W-?tVA-I-Ot2uFg#G{iWozH6Ju^BS{=rOv#S^ zC$7BE)7ZSIQTRUUlQJ@YD+KvrOeMF;0$30Dk0ssLP@41d?6t+f;5K_X_&3|hs&4|% zX!J2OD{6~HZxvnQ7AEo4zQ0EH5i$7L98 z-_Y_5e-5W7oQ{TiWWQHJ@~iH#5v8=QHbBx44}ZW=GHtrqRICuo#orN9JsZLRTQGzCCjxl&r=-VsIGNKvy;|fMC(sFE&m&_Z({u3nhXCNbeL#;~e*v zX-b)Mc?SUmzP7=;>0#RY-ej;Jc?sUV?5?@Bhai15lM9X^9~ukdppgUn8`hZ(xo7e8 z-Zeov9b$%JU7KR&Ee{yLR^)RStSbIW+8)YsD8ahb8(02US4X;fz*IYp

K@wriSq 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%0D!~#{S_Z~(#1(G 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 B3V{Fs literal 0 HcmV?d00001 -- Gitee