* [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 @ 2014-06-04 12:43 Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 001/118] target-ppc: Fix target_disas Alexander Graf ` (75 more replies) 0 siblings, 76 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel Hi Peter, This is my current patch queue for ppc. Please pull. Alex The following changes since commit e00fcfeab3d452cba3d0a08991a39ab15df66424: Merge remote-tracking branch 'remotes/awilliam/tags/vfio-pci-for-qemu-20140602.0' into staging (2014-06-03 14:37:43 +0100) are available in the git repository at: git://github.com/agraf/qemu.git tags/signed-ppc-for-upstream for you to fetch changes up to fbe4d727461729382e651279388400b1382caac6: PPC: spapr: Expose /hypervisor node in device tree (2014-06-04 14:38:17 +0200) ---------------------------------------------------------------- Patch queue for ppc - 2014-06-04 This pull request brings a lot of fun things. Among others we have - e500: u-boot firmware support - sPAPR: magic page enablement - sPAPR: add "compat" CPU option to support older guests - sPAPR: refactorings in preparation for VFIO - mac99: expose bus frequency - little endian core dump, gdb and disas support - new ppc64le-linux-user target - DFP emulation - bug fixes ---------------------------------------------------------------- Alex Zuepke (1): PPC: e500: Fix MMUCSR0 emulation Alexander Graf (21): KVM: PPC: Don't secretly add 1T segment feature to CPU PPC: Fix TCG chunks that don't free their temps PPC: Fail on leaking temporaries PPC: Make all e500 CPUs SVR aware PPC: Add definitions for GIVORs PPC: Fix SPR access control of L1CFG0 PPC: Add L1CFG1 SPR emulation PPC: Properly emulate L1CSR0 and L1CSR1 PPC: Add dcbtls emulation PPC: e500: Expose kernel load address in dt PPC: Add u-boot firmware for e500 PPC: e500: Move to u-boot as firmware PPC: openpic_kvm: Implement reset macio ide: Do remainder access asynchronously macio: Fix timer endianness PPC: e500: Fix TLB lookup for 32bit CPUs PPC: SPE: Fix high-bits bitmask linux-headers: include psci.h linux-headers: update linux headers to kvm/next KVM: PPC: Expose fixup hcall capability PPC: spapr: Expose /hypervisor node in device tree Alexey Kardashevskiy (28): spapr_nvram: Correct max nvram size target-ppc: Create versionless CPU class per family if KVM target-ppc: Move alias lookup after class lookup target-ppc: Remove redundant POWER7 declarations spapr_pci: Fix number of returned vectors in ibm, change-msi target-ppc: Remove PVR check from migration spapr_pci: fix MSI limit spapr: Add support for time base offset migration spapr: Add ibm, chip-id property in device tree target-ppc: Add "compat" CPU option spapr: Move SMT-related properties out of skeleton fdt target-ppc: Implement "compat" CPU option target-ppc: Define Processor Compatibility Masks spapr: Add ibm, client-architecture-support call spapr: Rework spapr_fixup_cpu_dt() spapr: Limit threads per core according to current compatibility mode spapr: Implement processor compatibility in ibm, client-architecture-support KVM: PPC: Enable compatibility mode spapr_iommu: Replace @instance_id with LIOBN for migration spapr: Enable dynamic change of the supported hypercalls list spapr_iommu: Enable multiple TCE requests spapr_pci: Introduce a finish_realize() callback spapr_pci: spapr_iommu: Make DMA window a subregion spapr_pci: Allow multiple TCE tables per PHB spapr_iommu: Convert old qdev_init_nofail() to object_property_set_bool spapr_iommu: Get rid of window_size in sPAPRTCETable spapr_iommu: Introduce page_shift in sPAPRTCETable spapr_iommu: Introduce bus_offset in sPAPRTCETable BALATON Zoltan (1): mac99: Added FW_CFG_PPC_BUSFREQ to match CLOCKFREQ and TBFREQ already there Bharat Bhushan (2): PPC: e500: some pci related cleanup PPC: e500: implement PCI INTx routing Bharata B Rao (3): dump: Make DumpState and endian conversion routines available for arch-specific dump code target-ppc: Support dump for little endian ppc64 target-ppc: Set the correct endianness in ELF dump header Doug Kwan (3): target-ppc: Support little-endian PPC64 in user mode. target-ppc: Allow little-endian user mode. target-ppc: Add a new user mode target for little-endian PPC64. Fabien Chouteau (1): Fix typo in eTSEC Ethernet controller Greg Kurz (2): spapr-pci: remove io ports workaround target-ppc: Introduce callback for interrupt endianness Mark Cave-Ayland (1): macio: handle non-block ATAPI DMA transfers Paul Janzen (2): openpic: Move definition of openpic_reset openpic: Reset IRQ source private members Peter Maydell (1): hw/pci-host/ppce500: Fix typo in vmstate definition Thomas Falcon (2): target-ppc: extract register length calculation in gdbstub target-ppc: gdbstub allow byte swapping for reading/writing registers Tom Musta (50): target-ppc: Fix target_disas monitor: QEMU Monitor Instruction Disassembly Incorrect for PowerPC LE Mode target-ppc: Eliminate Magic Number MSR Masks libdecnumber: Introduce libdecnumber Code libdecnumber: Eliminate #include *Symbols.h libdecnumber: Prepare libdecnumber for QEMU include structure libdecnumber: Modify dconfig.h to Integrate with QEMU libdecnumber: Change gstdint.h to stdint.h libdecnumber: Eliminate redundant declarations libdecnumber: Eliminate Unused Variable in decSetSubnormal target-ppc: Enable Building of libdecnumber libdecnumber: Introduce decNumberFrom[U]Int64 libdecnumber: Introduce decNumberIntegralToInt64 libdecnumber: Fix decNumberSetBCD target-ppc: Define FPR Pointer Type for Helpers target-ppc: Introduce Generator Macros for DFP Arithmetic Forms target-ppc: Introduce Decoder Macros for DFP target-ppc: Introduce DFP Helper Utilities target-ppc: Introduce DFP Post Processor Utilities target-ppc: Introduce DFP Add target-ppc: Introduce DFP Subtract target-ppc: Introduce DFP Multiply target-ppc: Introduce DFP Divide target-ppc: Introduce DFP Compares target-ppc: Introduce DFP Test Data Class target-ppc: Introduce DFP Test Data Group target-ppc: Introduce DFP Test Exponent target-ppc: Introduce DFP Test Significance target-ppc: Introduce DFP Quantize target-ppc: Introduce DFP Reround target-ppc: Introduce DFP Round to Integer target-ppc: Introduce DFP Convert to Long/Extended target-ppc: Introduce Round to DFP Short/Long target-ppc: Introduce DFP Convert to Fixed target-ppc: Introduce DFP Convert to Fixed target-ppc: Introduce DFP Decode DPD to BCD target-ppc: Introduce DFP Encode BCD to DPD target-ppc: Introduce DFP Extract Biased Exponent target-ppc: Introduce DFP Insert Biased Exponent target-ppc: Introduce DFP Shift Significand util: Add S-Box and InvS-Box Arrays to Common AES Utils util: Add AES ShiftRows and InvShiftRows Tables util: Add InvMixColumns target-i386: Use Common ShiftRows and InvShiftRows Tables target-arm: Use Common Tables in AES Instructions target-ppc: Refactor AES Instructions target-ppc: Fix popcntb Opcode Bug target-ppc: Support VSX in PPC User Mode target-ppc: Confirm That .bss Pages Are Valid target-ppc: Store Quadword Conditional Drops Size Bit .gitmodules | 3 + Makefile.target | 6 + configure | 6 + default-configs/ppc-linux-user.mak | 1 + default-configs/ppc-softmmu.mak | 1 + default-configs/ppc64-linux-user.mak | 1 + default-configs/ppc64-softmmu.mak | 1 + default-configs/ppc64abi32-linux-user.mak | 1 + default-configs/ppc64le-linux-user.mak | 2 + default-configs/ppcemb-softmmu.mak | 1 + disas.c | 21 +- dump.c | 227 +- hw/ide/macio.c | 71 +- hw/intc/openpic.c | 99 +- hw/intc/openpic_kvm.c | 15 +- hw/misc/macio/mac_dbdma.c | 6 + hw/misc/macio/macio.c | 2 +- hw/net/fsl_etsec/rings.c | 2 +- hw/nvram/spapr_nvram.c | 2 +- hw/pci-host/ppce500.c | 41 +- hw/ppc/e500.c | 147 +- hw/ppc/mac_newworld.c | 5 +- hw/ppc/mac_oldworld.c | 5 +- hw/ppc/ppc.c | 79 + hw/ppc/spapr.c | 194 +- hw/ppc/spapr_hcall.c | 127 + hw/ppc/spapr_iommu.c | 179 +- hw/ppc/spapr_pci.c | 128 +- hw/ppc/spapr_vio.c | 6 +- include/elf.h | 5 + include/hw/pci-host/spapr.h | 22 +- include/hw/ppc/mac_dbdma.h | 5 + include/hw/ppc/ppc.h | 2 + include/hw/ppc/spapr.h | 17 +- include/libdecnumber/dconfig.h | 40 + include/libdecnumber/decContext.h | 257 + include/libdecnumber/decDPD.h | 1214 +++++ include/libdecnumber/decNumber.h | 202 + include/libdecnumber/decNumberLocal.h | 665 +++ include/libdecnumber/dpd/decimal128.h | 100 + include/libdecnumber/dpd/decimal128Local.h | 47 + include/libdecnumber/dpd/decimal32.h | 98 + include/libdecnumber/dpd/decimal64.h | 100 + include/qemu/aes.h | 14 + include/sysemu/dump-arch.h | 28 + include/sysemu/dump.h | 47 +- libdecnumber/decContext.c | 433 ++ libdecnumber/decNumber.c | 8194 ++++++++++++++++++++++++++++ libdecnumber/dpd/decimal128.c | 564 ++ libdecnumber/dpd/decimal128Local.h | 42 + libdecnumber/dpd/decimal32.c | 489 ++ libdecnumber/dpd/decimal64.c | 850 +++ linux-headers/asm-arm/kvm.h | 10 +- linux-headers/asm-arm64/kvm.h | 13 +- linux-headers/asm-mips/kvm.h | 35 + linux-headers/asm-powerpc/kvm.h | 2 +- linux-headers/asm-powerpc/kvm_para.h | 6 + linux-headers/linux/kvm.h | 10 + linux-headers/linux/psci.h | 90 + linux-user/elfload.c | 24 +- linux-user/main.c | 10 +- linux-user/ppc/syscall.h | 4 + monitor.c | 4 + pc-bios/README | 5 + pc-bios/u-boot.e500 | Bin 0 -> 330260 bytes roms/Makefile | 9 + roms/u-boot | 1 + scripts/update-linux-headers.sh | 3 +- stubs/dump.c | 2 +- target-arm/crypto_helper.c | 79 +- target-i386/ops_sse.h | 32 +- target-ppc/Makefile.objs | 1 + target-ppc/arch_dump.c | 107 +- target-ppc/cpu-models.c | 32 +- target-ppc/cpu-models.h | 12 +- target-ppc/cpu-qom.h | 22 + target-ppc/cpu.h | 31 + target-ppc/dfp_helper.c | 1317 +++++ target-ppc/gdbstub.c | 124 +- target-ppc/helper.h | 57 +- target-ppc/int_helper.c | 292 +- target-ppc/kvm.c | 57 +- target-ppc/kvm_ppc.h | 20 +- target-ppc/machine.c | 8 +- target-ppc/mem_helper.c | 26 +- target-ppc/mmu_helper.c | 7 +- target-ppc/translate.c | 569 +- target-ppc/translate_init.c | 1046 +++- trace-events | 13 + util/aes.c | 343 ++ 90 files changed, 18203 insertions(+), 1034 deletions(-) create mode 100644 default-configs/ppc64le-linux-user.mak create mode 100644 include/libdecnumber/dconfig.h create mode 100644 include/libdecnumber/decContext.h create mode 100644 include/libdecnumber/decDPD.h create mode 100644 include/libdecnumber/decNumber.h create mode 100644 include/libdecnumber/decNumberLocal.h create mode 100644 include/libdecnumber/dpd/decimal128.h create mode 100644 include/libdecnumber/dpd/decimal128Local.h create mode 100644 include/libdecnumber/dpd/decimal32.h create mode 100644 include/libdecnumber/dpd/decimal64.h create mode 100644 include/sysemu/dump-arch.h create mode 100644 libdecnumber/decContext.c create mode 100644 libdecnumber/decNumber.c create mode 100644 libdecnumber/dpd/decimal128.c create mode 100644 libdecnumber/dpd/decimal128Local.h create mode 100644 libdecnumber/dpd/decimal32.c create mode 100644 libdecnumber/dpd/decimal64.c create mode 100644 linux-headers/linux/psci.h create mode 100755 pc-bios/u-boot.e500 create mode 160000 roms/u-boot create mode 100644 target-ppc/dfp_helper.c ^ permalink raw reply [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 001/118] target-ppc: Fix target_disas 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 002/118] monitor: QEMU Monitor Instruction Disassembly Incorrect for PowerPC LE Mode Alexander Graf ` (74 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Inspect only bit 16 for the Little Endian test. Correct comment preceding the target_disas() function. Correct grammar in comment for flags processing. Signed-off-by: Tom Musta <tommusta@gmail.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Alexander Graf <agraf@suse.de> --- disas.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/disas.c b/disas.c index 79e6944..1397167 100644 --- a/disas.c +++ b/disas.c @@ -191,7 +191,8 @@ static int print_insn_od_target(bfd_vma pc, disassemble_info *info) values: i386 - 1 means 16 bit code, 2 means 64 bit code arm - bit 0 = thumb, bit 1 = reverse endian, bit 2 = A64 - ppc - nonzero means little endian + ppc - bits 0:15 specify (optionally) the machine instruction set; + bit 16 indicates little endian. other targets - unused */ void target_disas(FILE *out, CPUArchState *env, target_ulong code, @@ -251,11 +252,11 @@ void target_disas(FILE *out, CPUArchState *env, target_ulong code, s.info.mach = bfd_mach_sparc_v9b; #endif #elif defined(TARGET_PPC) - if (flags >> 16) { + if ((flags >> 16) & 1) { s.info.endian = BFD_ENDIAN_LITTLE; } if (flags & 0xFFFF) { - /* If we have a precise definitions of the instructions set, use it */ + /* If we have a precise definition of the instruction set, use it. */ s.info.mach = flags & 0xFFFF; } else { #ifdef TARGET_PPC64 -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 002/118] monitor: QEMU Monitor Instruction Disassembly Incorrect for PowerPC LE Mode 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 001/118] target-ppc: Fix target_disas Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 003/118] Fix typo in eTSEC Ethernet controller Alexander Graf ` (73 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> The monitor support for disassembling instructions does not honor the MSR[LE] bit for PowerPC processors. This change enhances the monitor_disas() routine by supporting a flag bit for Little Endian mode. Bit 16 is used since that bit was used in the analagous guest disassembly routine target_disas(). Also, to be consistent with target_disas(), the disassembler bfd_mach field can be passed in the flags argument. Reported-by: Anton Blanchard <anton@samba.org> Signed-off-by: Tom Musta <tommusta@gmail.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Alexander Graf <agraf@suse.de> --- disas.c | 14 ++++++++++++-- monitor.c | 4 ++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/disas.c b/disas.c index 1397167..44a019a 100644 --- a/disas.c +++ b/disas.c @@ -445,6 +445,8 @@ monitor_fprintf(FILE *stream, const char *fmt, ...) return 0; } +/* Disassembler for the monitor. + See target_disas for a description of flags. */ void monitor_disas(Monitor *mon, CPUArchState *env, target_ulong pc, int nb_insn, int is_physical, int flags) { @@ -485,11 +487,19 @@ void monitor_disas(Monitor *mon, CPUArchState *env, s.info.mach = bfd_mach_sparc_v9b; #endif #elif defined(TARGET_PPC) + if (flags & 0xFFFF) { + /* If we have a precise definition of the instruction set, use it. */ + s.info.mach = flags & 0xFFFF; + } else { #ifdef TARGET_PPC64 - s.info.mach = bfd_mach_ppc64; + s.info.mach = bfd_mach_ppc64; #else - s.info.mach = bfd_mach_ppc; + s.info.mach = bfd_mach_ppc; #endif + } + if ((flags >> 16) & 1) { + s.info.endian = BFD_ENDIAN_LITTLE; + } print_insn = print_insn_ppc; #elif defined(TARGET_M68K) print_insn = print_insn_m68k; diff --git a/monitor.c b/monitor.c index 593679a..a7a0f85 100644 --- a/monitor.c +++ b/monitor.c @@ -1283,6 +1283,10 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize, } } #endif +#ifdef TARGET_PPC + flags = msr_le << 16; + flags |= env->bfd_mach; +#endif monitor_disas(mon, env, addr, count, is_physical, flags); return; } -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 003/118] Fix typo in eTSEC Ethernet controller 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 001/118] target-ppc: Fix target_disas Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 002/118] monitor: QEMU Monitor Instruction Disassembly Incorrect for PowerPC LE Mode Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 004/118] spapr_nvram: Correct max nvram size Alexander Graf ` (72 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel, Fabien Chouteau From: Fabien Chouteau <chouteau@adacore.com> IRQ are lowered when ievent bit is cleared, so irq_pulse makes no sense here... Signed-off-by: Fabien Chouteau <chouteau@adacore.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/net/fsl_etsec/rings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c index e36cfbe..d4a494f 100644 --- a/hw/net/fsl_etsec/rings.c +++ b/hw/net/fsl_etsec/rings.c @@ -159,7 +159,7 @@ static void ievent_set(eTSEC *etsec, if ((flags & IEVENT_RXB && etsec->regs[IMASK].value & IMASK_RXBEN) || (flags & IEVENT_RXF && etsec->regs[IMASK].value & IMASK_RXFEN)) { - qemu_irq_pulse(etsec->rx_irq); + qemu_irq_raise(etsec->rx_irq); RING_DEBUG("%s Raise Rx IRQ\n", __func__); } } -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 004/118] spapr_nvram: Correct max nvram size 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (2 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 003/118] Fix typo in eTSEC Ethernet controller Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 005/118] target-ppc: extract register length calculation in gdbstub Alexander Graf ` (71 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Alexey Kardashevskiy, qemu-devel From: Alexey Kardashevskiy <aik@ozlabs.ru> Currently it is UINT16_MAX*16 = 65536*16 = 1048560 which is not a round number and therefore a bit confusing. This defines MAX_NVRAM_SIZE precisely as 1MB. Suggested-by: Thomas Huth <thuth@linux.vnet.ibm.com> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/nvram/spapr_nvram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c index 635713e..af49c46 100644 --- a/hw/nvram/spapr_nvram.c +++ b/hw/nvram/spapr_nvram.c @@ -42,7 +42,7 @@ typedef struct sPAPRNVRAM { #define MIN_NVRAM_SIZE 8192 #define DEFAULT_NVRAM_SIZE 65536 -#define MAX_NVRAM_SIZE (UINT16_MAX * 16) +#define MAX_NVRAM_SIZE 1048576 static void rtas_nvram_fetch(PowerPCCPU *cpu, sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 005/118] target-ppc: extract register length calculation in gdbstub 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (3 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 004/118] spapr_nvram: Correct max nvram size Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 006/118] target-ppc: gdbstub allow byte swapping for reading/writing registers Alexander Graf ` (70 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Thomas Falcon, qemu-devel From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com> This patch extracts the method to determine a register's size into a separate function. Reviewed-by: Andreas Färber <afaerber@suse.de> Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/gdbstub.c | 105 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 34 deletions(-) diff --git a/target-ppc/gdbstub.c b/target-ppc/gdbstub.c index 1c91090..0740af8 100644 --- a/target-ppc/gdbstub.c +++ b/target-ppc/gdbstub.c @@ -21,6 +21,44 @@ #include "qemu-common.h" #include "exec/gdbstub.h" +static int ppc_gdb_register_len(int n) +{ + switch (n) { + case 0 ... 31: + /* gprs */ + return sizeof(target_ulong); + case 32 ... 63: + /* fprs */ + if (gdb_has_xml) { + return 0; + } + return 8; + case 66: + /* cr */ + return 4; + case 64: + /* nip */ + case 65: + /* msr */ + case 67: + /* lr */ + case 68: + /* ctr */ + case 69: + /* xer */ + return sizeof(target_ulong); + case 70: + /* fpscr */ + if (gdb_has_xml) { + return 0; + } + return sizeof(target_ulong); + default: + return 0; + } +} + + /* Old gdb always expects FP registers. Newer (xml-aware) gdb only * expects whatever the target description contains. Due to a * historical mishap the FP registers appear in between core integer @@ -32,23 +70,26 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) { PowerPCCPU *cpu = POWERPC_CPU(cs); CPUPPCState *env = &cpu->env; + int r = ppc_gdb_register_len(n); + + if (!r) { + return r; + } if (n < 32) { /* gprs */ - return gdb_get_regl(mem_buf, env->gpr[n]); + gdb_get_regl(mem_buf, env->gpr[n]); } else if (n < 64) { /* fprs */ - if (gdb_has_xml) { - return 0; - } stfq_p(mem_buf, env->fpr[n-32]); - return 8; } else { switch (n) { case 64: - return gdb_get_regl(mem_buf, env->nip); + gdb_get_regl(mem_buf, env->nip); + break; case 65: - return gdb_get_regl(mem_buf, env->msr); + gdb_get_regl(mem_buf, env->msr); + break; case 66: { uint32_t cr = 0; @@ -56,50 +97,49 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) for (i = 0; i < 8; i++) { cr |= env->crf[i] << (32 - ((i + 1) * 4)); } - return gdb_get_reg32(mem_buf, cr); + gdb_get_reg32(mem_buf, cr); + break; } case 67: - return gdb_get_regl(mem_buf, env->lr); + gdb_get_regl(mem_buf, env->lr); + break; case 68: - return gdb_get_regl(mem_buf, env->ctr); + gdb_get_regl(mem_buf, env->ctr); + break; case 69: - return gdb_get_regl(mem_buf, env->xer); + gdb_get_regl(mem_buf, env->xer); + break; case 70: - { - if (gdb_has_xml) { - return 0; - } - return gdb_get_reg32(mem_buf, env->fpscr); - } + gdb_get_reg32(mem_buf, env->fpscr); + break; } } - return 0; + return r; } int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { PowerPCCPU *cpu = POWERPC_CPU(cs); CPUPPCState *env = &cpu->env; + int r = ppc_gdb_register_len(n); + if (!r) { + return r; + } if (n < 32) { /* gprs */ env->gpr[n] = ldtul_p(mem_buf); - return sizeof(target_ulong); } else if (n < 64) { /* fprs */ - if (gdb_has_xml) { - return 0; - } env->fpr[n-32] = ldfq_p(mem_buf); - return 8; } else { switch (n) { case 64: env->nip = ldtul_p(mem_buf); - return sizeof(target_ulong); + break; case 65: ppc_store_msr(env, ldtul_p(mem_buf)); - return sizeof(target_ulong); + break; case 66: { uint32_t cr = ldl_p(mem_buf); @@ -107,25 +147,22 @@ int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) for (i = 0; i < 8; i++) { env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF; } - return 4; + break; } case 67: env->lr = ldtul_p(mem_buf); - return sizeof(target_ulong); + break; case 68: env->ctr = ldtul_p(mem_buf); - return sizeof(target_ulong); + break; case 69: env->xer = ldtul_p(mem_buf); - return sizeof(target_ulong); + break; case 70: /* fpscr */ - if (gdb_has_xml) { - return 0; - } store_fpscr(env, ldtul_p(mem_buf), 0xffffffff); - return sizeof(target_ulong); + break; } } - return 0; + return r; } -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 006/118] target-ppc: gdbstub allow byte swapping for reading/writing registers 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (4 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 005/118] target-ppc: extract register length calculation in gdbstub Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 007/118] target-ppc: Create versionless CPU class per family if KVM Alexander Graf ` (69 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Thomas Falcon, qemu-devel From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com> This patch allows registers to be properly read from and written to when using the gdbstub to debug a ppc guest running in little endian mode. Reviewed-by: Andreas Färber <afaerber@suse.de> Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/gdbstub.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/target-ppc/gdbstub.c b/target-ppc/gdbstub.c index 0740af8..381a3c7 100644 --- a/target-ppc/gdbstub.c +++ b/target-ppc/gdbstub.c @@ -59,6 +59,17 @@ static int ppc_gdb_register_len(int n) } +static void ppc_gdb_swap_register(uint8_t *mem_buf, int n, int len) +{ + if (len == 4) { + bswap32s((uint32_t *)mem_buf); + } else if (len == 8) { + bswap64s((uint64_t *)mem_buf); + } else { + g_assert_not_reached(); + } +} + /* Old gdb always expects FP registers. Newer (xml-aware) gdb only * expects whatever the target description contains. Due to a * historical mishap the FP registers appear in between core integer @@ -114,6 +125,10 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) break; } } + if (msr_le) { + /* If cpu is in LE mode, convert memory contents to LE. */ + ppc_gdb_swap_register(mem_buf, n, r); + } return r; } @@ -126,6 +141,10 @@ int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) if (!r) { return r; } + if (msr_le) { + /* If cpu is in LE mode, convert memory contents to LE. */ + ppc_gdb_swap_register(mem_buf, n, r); + } if (n < 32) { /* gprs */ env->gpr[n] = ldtul_p(mem_buf); -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 007/118] target-ppc: Create versionless CPU class per family if KVM 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (5 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 006/118] target-ppc: gdbstub allow byte swapping for reading/writing registers Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 008/118] target-ppc: Move alias lookup after class lookup Alexander Graf ` (68 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Alexey Kardashevskiy, qemu-devel From: Alexey Kardashevskiy <aik@ozlabs.ru> At the moment generic version-less CPUs are supported via hardcoded aliases. For example, POWER7 is an alias for POWER7_v2.1. So when QEMU is started with -cpu POWER7, the POWER7_v2.1 class instance is created. This approach works for TCG and KVMs other than HV KVM. HV KVM cannot emulate PVR value so the guest always sees the real PVR. HV KVM will not allow setting PVR other that the host PVR because of that (the kernel patch for it is on its way). So in most cases it is impossible to run QEMU with -cpu POWER7 unless the host PVR is exactly the same as the one from the alias (which is now POWER7_v2.3). It was decided that under HV KVM QEMU should use -cpu host. Using "host" CPU type creates a problem for management tools such as libvirt because they want to know in advance if the destination guest can possibly run on the destination. Since the "host" type is really not a type and will always work with any KVM, there is no way for libvirt to know if the migration will success. This registers additional CPU class derived from the host CPU family. The name for it is taken from @desc field of the CPU family class. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/kvm.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 8ff1777..3569367 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -1761,6 +1761,18 @@ bool kvmppc_has_cap_htab_fd(void) return cap_htab_fd; } +static PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc) +{ + ObjectClass *oc = OBJECT_CLASS(pcc); + + while (oc && !object_class_is_abstract(oc)) { + oc = object_class_get_parent(oc); + } + assert(oc); + + return POWERPC_CPU_CLASS(oc); +} + static int kvm_ppc_register_host_cpu_type(void) { TypeInfo type_info = { @@ -1770,6 +1782,7 @@ static int kvm_ppc_register_host_cpu_type(void) }; uint32_t host_pvr = mfpvr(); PowerPCCPUClass *pvr_pcc; + DeviceClass *dc; pvr_pcc = ppc_cpu_class_by_pvr(host_pvr); if (pvr_pcc == NULL) { @@ -1780,6 +1793,14 @@ static int kvm_ppc_register_host_cpu_type(void) } type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); type_register(&type_info); + + /* Register generic family CPU class for a family */ + pvr_pcc = ppc_cpu_get_family_class(pvr_pcc); + dc = DEVICE_CLASS(pvr_pcc); + type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc)); + type_info.name = g_strdup_printf("%s-"TYPE_POWERPC_CPU, dc->desc); + type_register(&type_info); + return 0; } -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 008/118] target-ppc: Move alias lookup after class lookup 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (6 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 007/118] target-ppc: Create versionless CPU class per family if KVM Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 009/118] target-ppc: Remove redundant POWER7 declarations Alexander Graf ` (67 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Alexey Kardashevskiy, qemu-devel From: Alexey Kardashevskiy <aik@ozlabs.ru> This moves aliases lookup after CPU class lookup. This is to let new generic CPU to be found first if it is present and only if it is not (TCG case), use aliases. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/translate_init.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 4d94015..823c63c 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -8218,12 +8218,6 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name) } } - for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) { - if (strcmp(ppc_cpu_aliases[i].alias, name) == 0) { - return ppc_cpu_class_by_alias(&ppc_cpu_aliases[i]); - } - } - list = object_class_get_list(TYPE_POWERPC_CPU, false); item = g_slist_find_custom(list, name, ppc_cpu_compare_class_name); if (item != NULL) { @@ -8231,7 +8225,17 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name) } g_slist_free(list); - return ret; + if (ret) { + return ret; + } + + for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) { + if (strcmp(ppc_cpu_aliases[i].alias, name) == 0) { + return ppc_cpu_class_by_alias(&ppc_cpu_aliases[i]); + } + } + + return NULL; } PowerPCCPU *cpu_ppc_init(const char *cpu_model) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 009/118] target-ppc: Remove redundant POWER7 declarations 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (7 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 008/118] target-ppc: Move alias lookup after class lookup Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 010/118] spapr-pci: remove io ports workaround Alexander Graf ` (66 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Alexey Kardashevskiy, qemu-devel From: Alexey Kardashevskiy <aik@ozlabs.ru> At the moment there are 3 versions of POWER7 CPUs defined. However we do not emulate these CPUs diffent and it does not make much sense to keep them all. This removes POWER7_v2.0 and POWER7_v2.1 and leaves just one versioned CPU per family which is POWER7_v2.3 with POWER7 alias. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/cpu-models.c | 4 ---- target-ppc/cpu-models.h | 2 -- 2 files changed, 6 deletions(-) diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c index f6c9b3a..57cb4e4 100644 --- a/target-ppc/cpu-models.c +++ b/target-ppc/cpu-models.c @@ -1134,10 +1134,6 @@ POWERPC_DEF("POWER6A", CPU_POWERPC_POWER6A, POWER6, "POWER6A") #endif - POWERPC_DEF("POWER7_v2.0", CPU_POWERPC_POWER7_v20, POWER7, - "POWER7 v2.0") - POWERPC_DEF("POWER7_v2.1", CPU_POWERPC_POWER7_v21, POWER7, - "POWER7 v2.1") POWERPC_DEF("POWER7_v2.3", CPU_POWERPC_POWER7_v23, POWER7, "POWER7 v2.3") POWERPC_DEF("POWER7+_v2.1", CPU_POWERPC_POWER7P_v21, POWER7P, diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h index 644a126..9a003b4 100644 --- a/target-ppc/cpu-models.h +++ b/target-ppc/cpu-models.h @@ -555,8 +555,6 @@ enum { CPU_POWERPC_POWER6A = 0x0F000002, CPU_POWERPC_POWER7_BASE = 0x003F0000, CPU_POWERPC_POWER7_MASK = 0xFFFF0000, - CPU_POWERPC_POWER7_v20 = 0x003F0200, - CPU_POWERPC_POWER7_v21 = 0x003F0201, CPU_POWERPC_POWER7_v23 = 0x003F0203, CPU_POWERPC_POWER7P_BASE = 0x004A0000, CPU_POWERPC_POWER7P_MASK = 0xFFFF0000, -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 010/118] spapr-pci: remove io ports workaround 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (8 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 009/118] target-ppc: Remove redundant POWER7 declarations Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 011/118] spapr_pci: Fix number of returned vectors in ibm, change-msi Alexander Graf ` (65 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel, Greg Kurz From: Greg Kurz <gkurz@linux.vnet.ibm.com> In the past, IO space could not be mapped into the memory address space so we introduced a workaround for that. Nowadays it does not look necessary so we can remove the workaround and make sPAPR PCI configuration simplier. Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com> Acked-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/ppc/spapr_pci.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index cbef095..b6dc18a 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -575,23 +575,14 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr, &sphb->memwindow); - /* On ppc, we only have MMIO no specific IO space from the CPU - * perspective. In theory we ought to be able to embed the PCI IO - * memory region direction in the system memory space. However, - * if any of the IO BAR subregions use the old_portio mechanism, - * that won't be processed properly unless accessed from the - * system io address space. This hack to bounce things via - * system_io works around the problem until all the users of - * old_portion are updated */ + /* Initialize IO regions */ sprintf(namebuf, "%s.io", sphb->dtbusname); memory_region_init(&sphb->iospace, OBJECT(sphb), namebuf, SPAPR_PCI_IO_WIN_SIZE); - /* FIXME: fix to support multiple PHBs */ - memory_region_add_subregion(get_system_io(), 0, &sphb->iospace); sprintf(namebuf, "%s.io-alias", sphb->dtbusname); memory_region_init_alias(&sphb->iowindow, OBJECT(sphb), namebuf, - get_system_io(), 0, SPAPR_PCI_IO_WIN_SIZE); + &sphb->iospace, 0, SPAPR_PCI_IO_WIN_SIZE); memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, &sphb->iowindow); -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 011/118] spapr_pci: Fix number of returned vectors in ibm, change-msi 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (9 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 010/118] spapr-pci: remove io ports workaround Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 012/118] target-ppc: Eliminate Magic Number MSR Masks Alexander Graf ` (64 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Alexey Kardashevskiy, qemu-devel, qemu-stable From: Alexey Kardashevskiy <aik@ozlabs.ru> Current guest kernels try allocating as many vectors as the quota is. For example, in the case of virtio-net (which has just 3 vectors) the guest requests 4 vectors (that is the quota in the test) and the existing ibm,change-msi handler returns 4. But before it returns, it calls msix_set_message() in a loop and corrupts memory behind the end of msix_table. This limits the number of vectors returned by ibm,change-msi to the maximum supported by the actual device. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Cc: qemu-stable@nongnu.org [agraf: squash in bugfix from aik] Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/ppc/spapr_pci.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index b6dc18a..c052917 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -343,6 +343,21 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr, /* There is no cached config, allocate MSIs */ if (!phb->msi_table[ndev].nvec) { + int max_irqs = 0; + if (ret_intr_type == RTAS_TYPE_MSI) { + max_irqs = msi_nr_vectors_allocated(pdev); + } else if (ret_intr_type == RTAS_TYPE_MSIX) { + max_irqs = pdev->msix_entries_nr; + } + if (!max_irqs) { + error_report("Requested interrupt type %d is not enabled for device#%d", + ret_intr_type, ndev); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + if (req_num > max_irqs) { + req_num = max_irqs; + } irq = spapr_allocate_irq_block(req_num, false, ret_intr_type == RTAS_TYPE_MSI); if (irq < 0) { -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 012/118] target-ppc: Eliminate Magic Number MSR Masks 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (10 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 011/118] spapr_pci: Fix number of returned vectors in ibm, change-msi Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 013/118] target-ppc: Remove PVR check from migration Alexander Graf ` (63 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Use MSR mnemonics from cpu.h instead of magic numbers for the CPUPPCState.msr_mask initialization. There is one bit in the 401x2 (and subsequent) model that I could not find any documentation for. It is open coded at little endian bit position 20: pcc->msr_mask = (1ull << 20) | (1ull << MSR_KEY) | (1ull << MSR_POW) | (1ull << MSR_CE) | ... Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/translate_init.c | 830 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 776 insertions(+), 54 deletions(-) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 823c63c..1d64ec9 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -3156,7 +3156,15 @@ POWERPC_FAMILY(401)(ObjectClass *oc, void *data) PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_4xx_COMMON | PPC_40x_EXCP; - pcc->msr_mask = 0x00000000000FD201ULL; + pcc->msr_mask = (1ull << MSR_KEY) | + (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_ME) | + (1ull << MSR_DE) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_REAL; pcc->excp_model = POWERPC_EXCP_40x; pcc->bus_model = PPC_FLAGS_INPUT_401; @@ -3203,7 +3211,18 @@ POWERPC_FAMILY(401x2)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | PPC_4xx_COMMON | PPC_40x_EXCP; - pcc->msr_mask = 0x00000000001FD231ULL; + pcc->msr_mask = (1ull << 20) | + (1ull << MSR_KEY) | + (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_ME) | + (1ull << MSR_DE) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z; pcc->excp_model = POWERPC_EXCP_40x; pcc->bus_model = PPC_FLAGS_INPUT_401; @@ -3244,7 +3263,19 @@ POWERPC_FAMILY(401x3)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | PPC_4xx_COMMON | PPC_40x_EXCP; - pcc->msr_mask = 0x00000000001FD631ULL; + pcc->msr_mask = (1ull << 20) | + (1ull << MSR_KEY) | + (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_ME) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z; pcc->excp_model = POWERPC_EXCP_40x; pcc->bus_model = PPC_FLAGS_INPUT_401; @@ -3291,7 +3322,18 @@ POWERPC_FAMILY(IOP480)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | PPC_4xx_COMMON | PPC_40x_EXCP; - pcc->msr_mask = 0x00000000001FD231ULL; + pcc->msr_mask = (1ull << 20) | + (1ull << MSR_KEY) | + (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_ME) | + (1ull << MSR_DE) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z; pcc->excp_model = POWERPC_EXCP_40x; pcc->bus_model = PPC_FLAGS_INPUT_401; @@ -3330,7 +3372,15 @@ POWERPC_FAMILY(403)(ObjectClass *oc, void *data) PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_4xx_COMMON | PPC_40x_EXCP; - pcc->msr_mask = 0x000000000007D00DULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_ME) | + (1ull << MSR_PE) | + (1ull << MSR_PX) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_REAL; pcc->excp_model = POWERPC_EXCP_40x; pcc->bus_model = PPC_FLAGS_INPUT_401; @@ -3389,7 +3439,15 @@ POWERPC_FAMILY(403GCX)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | PPC_4xx_COMMON | PPC_40x_EXCP; - pcc->msr_mask = 0x000000000007D00DULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_ME) | + (1ull << MSR_PE) | + (1ull << MSR_PX) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z; pcc->excp_model = POWERPC_EXCP_40x; pcc->bus_model = PPC_FLAGS_INPUT_401; @@ -3447,7 +3505,15 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | PPC_4xx_COMMON | PPC_405_MAC | PPC_40x_EXCP; - pcc->msr_mask = 0x000000000006E630ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_SOFT_4xx; pcc->excp_model = POWERPC_EXCP_40x; pcc->bus_model = PPC_FLAGS_INPUT_405; @@ -3540,7 +3606,18 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data) PPC_MEM_TLBSYNC | PPC_MFTB | PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | PPC_440_SPEC; - pcc->msr_mask = 0x000000000006FF30ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_BOOKE; pcc->excp_model = POWERPC_EXCP_BOOKE; pcc->bus_model = PPC_FLAGS_INPUT_BookE; @@ -3612,7 +3689,18 @@ POWERPC_FAMILY(440GP)(ObjectClass *oc, void *data) PPC_MEM_TLBSYNC | PPC_TLBIVA | PPC_MFTB | PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | PPC_440_SPEC; - pcc->msr_mask = 0x000000000006FF30ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_BOOKE; pcc->excp_model = POWERPC_EXCP_BOOKE; pcc->bus_model = PPC_FLAGS_INPUT_BookE; @@ -3684,7 +3772,18 @@ POWERPC_FAMILY(440x4)(ObjectClass *oc, void *data) PPC_MEM_TLBSYNC | PPC_MFTB | PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | PPC_440_SPEC; - pcc->msr_mask = 0x000000000006FF30ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_BOOKE; pcc->excp_model = POWERPC_EXCP_BOOKE; pcc->bus_model = PPC_FLAGS_INPUT_BookE; @@ -3774,7 +3873,18 @@ POWERPC_FAMILY(440x5)(ObjectClass *oc, void *data) PPC_MEM_TLBSYNC | PPC_MFTB | PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | PPC_440_SPEC; - pcc->msr_mask = 0x000000000006FF30ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_BOOKE; pcc->excp_model = POWERPC_EXCP_BOOKE; pcc->bus_model = PPC_FLAGS_INPUT_BookE; @@ -3870,7 +3980,18 @@ POWERPC_FAMILY(460)(ObjectClass *oc, void *data) PPC_MEM_TLBSYNC | PPC_TLBIVA | PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | PPC_440_SPEC; - pcc->msr_mask = 0x000000000006FF30ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_BOOKE; pcc->excp_model = POWERPC_EXCP_BOOKE; pcc->bus_model = PPC_FLAGS_INPUT_BookE; @@ -3969,7 +4090,18 @@ POWERPC_FAMILY(460F)(ObjectClass *oc, void *data) PPC_MEM_TLBSYNC | PPC_TLBIVA | PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | PPC_440_SPEC; - pcc->msr_mask = 0x000000000006FF30ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_BOOKE; pcc->excp_model = POWERPC_EXCP_BOOKE; pcc->bus_model = PPC_FLAGS_INPUT_BookE; @@ -4002,7 +4134,18 @@ POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void *data) PPC_MEM_EIEIO | PPC_MEM_SYNC | PPC_CACHE_ICBI | PPC_FLOAT | PPC_FLOAT_STFIWX | PPC_MFTB; - pcc->msr_mask = 0x000000000001FF43ULL; + pcc->msr_mask = (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_REAL; pcc->excp_model = POWERPC_EXCP_603; pcc->bus_model = PPC_FLAGS_INPUT_RCPU; @@ -4034,7 +4177,18 @@ POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void *data) pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MEM_EIEIO | PPC_MEM_SYNC | PPC_CACHE_ICBI | PPC_MFTB; - pcc->msr_mask = 0x000000000001F673ULL; + pcc->msr_mask = (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_MPC8xx; pcc->excp_model = POWERPC_EXCP_603; pcc->bus_model = PPC_FLAGS_INPUT_RCPU; @@ -4100,7 +4254,21 @@ POWERPC_FAMILY(G2)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000006FFF2ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_TGPR) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_AL) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_RI); pcc->mmu_model = POWERPC_MMU_SOFT_6xx; pcc->excp_model = POWERPC_EXCP_G2; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -4191,7 +4359,23 @@ POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000007FFF3ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_TGPR) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_AL) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_6xx; pcc->excp_model = POWERPC_EXCP_G2; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -4331,7 +4515,20 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void *data) PPC_CACHE_DCBZ | PPC_CACHE_DCBA | PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_BOOKE; - pcc->msr_mask = 0x000000000606FF30ULL; + pcc->msr_mask = (1ull << MSR_UCLE) | + (1ull << MSR_SPE) | + (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_BOOKE206; pcc->excp_model = POWERPC_EXCP_BOOKE; pcc->bus_model = PPC_FLAGS_INPUT_BookE; @@ -4389,7 +4586,23 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000007FFF3ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_TGPR) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_AL) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_6xx; pcc->excp_model = POWERPC_EXCP_603; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -4628,7 +4841,20 @@ POWERPC_FAMILY(e500v1)(ObjectClass *oc, void *data) PPC_CACHE_DCBZ | PPC_CACHE_DCBA | PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC; pcc->insns_flags2 = PPC2_BOOKE206; - pcc->msr_mask = 0x000000000606FF30ULL; + pcc->msr_mask = (1ull << MSR_UCLE) | + (1ull << MSR_SPE) | + (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_BOOKE206; pcc->excp_model = POWERPC_EXCP_BOOKE; pcc->bus_model = PPC_FLAGS_INPUT_BookE; @@ -4658,7 +4884,20 @@ POWERPC_FAMILY(e500v2)(ObjectClass *oc, void *data) PPC_CACHE_DCBZ | PPC_CACHE_DCBA | PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC; pcc->insns_flags2 = PPC2_BOOKE206; - pcc->msr_mask = 0x000000000606FF30ULL; + pcc->msr_mask = (1ull << MSR_UCLE) | + (1ull << MSR_SPE) | + (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_BOOKE206; pcc->excp_model = POWERPC_EXCP_BOOKE; pcc->bus_model = PPC_FLAGS_INPUT_BookE; @@ -4690,7 +4929,20 @@ POWERPC_FAMILY(e500mc)(ObjectClass *oc, void *data) PPC_FLOAT_STFIWX | PPC_WAIT | PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC; pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL; - pcc->msr_mask = 0x000000001402FB36ULL; + pcc->msr_mask = (1ull << MSR_GS) | + (1ull << MSR_UCLE) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PX) | + (1ull << MSR_RI); pcc->mmu_model = POWERPC_MMU_BOOKE206; pcc->excp_model = POWERPC_EXCP_BOOKE; pcc->bus_model = PPC_FLAGS_INPUT_BookE; @@ -4724,7 +4976,21 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data) PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC | PPC_64B | PPC_POPCNTB | PPC_POPCNTWD; pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_PERM_ISA206; - pcc->msr_mask = 0x000000009402FB36ULL; + pcc->msr_mask = (1ull << MSR_CM) | + (1ull << MSR_GS) | + (1ull << MSR_UCLE) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PX) | + (1ull << MSR_RI); pcc->mmu_model = POWERPC_MMU_BOOKE206; pcc->excp_model = POWERPC_EXCP_BOOKE; pcc->bus_model = PPC_FLAGS_INPUT_BookE; @@ -4746,7 +5012,17 @@ POWERPC_FAMILY(POWER)(ObjectClass *oc, void *data) dc->desc = "POWER"; /* pcc->insns_flags = XXX_TODO; */ /* POWER RSC (from RAD6000) */ - pcc->msr_mask = 0x00000000FEF0ULL; + pcc->msr_mask = (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_AL) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR); } #define POWERPC_MSRR_601 (0x0000000000001040ULL) @@ -4801,7 +5077,16 @@ POWERPC_FAMILY(601)(ObjectClass *oc, void *data) PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000000FD70ULL; + pcc->msr_mask = (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_601; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -4837,7 +5122,16 @@ POWERPC_FAMILY(601v)(ObjectClass *oc, void *data) PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000000FD70ULL; + pcc->msr_mask = (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR); pcc->mmu_model = POWERPC_MMU_601; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -4889,7 +5183,24 @@ POWERPC_FAMILY(602)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_6xx_TLB | PPC_MEM_TLBSYNC | PPC_SEGMENT | PPC_602_SPEC; - pcc->msr_mask = 0x0000000000C7FF73ULL; + pcc->msr_mask = (1ull << MSR_VSX) | + (1ull << MSR_SA) | + (1ull << MSR_POW) | + (1ull << MSR_TGPR) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_RI) | + (1ull << MSR_LE); /* XXX: 602 MMU is quite specific. Should add a special case */ pcc->mmu_model = POWERPC_MMU_SOFT_6xx; pcc->excp_model = POWERPC_EXCP_602; @@ -4941,7 +5252,22 @@ POWERPC_FAMILY(603)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000007FF73ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_TGPR) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_6xx; pcc->excp_model = POWERPC_EXCP_603; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -4992,7 +5318,22 @@ POWERPC_FAMILY(603E)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000007FF73ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_TGPR) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_6xx; pcc->excp_model = POWERPC_EXCP_603E; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -5037,7 +5378,22 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000005FF77ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -5105,7 +5461,22 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000005FF77ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -5160,7 +5531,22 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000005FF77ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -5223,7 +5609,22 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000005FF77ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -5409,7 +5810,22 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000005FF77ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -5476,7 +5892,22 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000005FF77ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -5548,7 +5979,22 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000005FF77ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -5620,7 +6066,22 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000005FF77ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -5683,7 +6144,22 @@ POWERPC_FAMILY(745)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000005FF77ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_6xx; pcc->excp_model = POWERPC_EXCP_7x5; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -5754,7 +6230,22 @@ POWERPC_FAMILY(755)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | PPC_SEGMENT | PPC_EXTERN; - pcc->msr_mask = 0x000000000005FF77ULL; + pcc->msr_mask = (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_6xx; pcc->excp_model = POWERPC_EXCP_7x5; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -5812,7 +6303,23 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void *data) PPC_MEM_TLBIA | PPC_SEGMENT | PPC_EXTERN | PPC_ALTIVEC; - pcc->msr_mask = 0x000000000205FF77ULL; + pcc->msr_mask = (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -5880,7 +6387,23 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void *data) PPC_MEM_TLBIA | PPC_SEGMENT | PPC_EXTERN | PPC_ALTIVEC; - pcc->msr_mask = 0x000000000205FF77ULL; + pcc->msr_mask = (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -5974,7 +6497,23 @@ POWERPC_FAMILY(7440)(ObjectClass *oc, void *data) PPC_MEM_TLBIA | PPC_74xx_TLB | PPC_SEGMENT | PPC_EXTERN | PPC_ALTIVEC; - pcc->msr_mask = 0x000000000205FF77ULL; + pcc->msr_mask = (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_74xx; pcc->excp_model = POWERPC_EXCP_74xx; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -6091,7 +6630,23 @@ POWERPC_FAMILY(7450)(ObjectClass *oc, void *data) PPC_MEM_TLBIA | PPC_74xx_TLB | PPC_SEGMENT | PPC_EXTERN | PPC_ALTIVEC; - pcc->msr_mask = 0x000000000205FF77ULL; + pcc->msr_mask = (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_74xx; pcc->excp_model = POWERPC_EXCP_74xx; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -6211,7 +6766,23 @@ POWERPC_FAMILY(7445)(ObjectClass *oc, void *data) PPC_MEM_TLBIA | PPC_74xx_TLB | PPC_SEGMENT | PPC_EXTERN | PPC_ALTIVEC; - pcc->msr_mask = 0x000000000205FF77ULL; + pcc->msr_mask = (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_74xx; pcc->excp_model = POWERPC_EXCP_74xx; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -6333,7 +6904,23 @@ POWERPC_FAMILY(7455)(ObjectClass *oc, void *data) PPC_MEM_TLBIA | PPC_74xx_TLB | PPC_SEGMENT | PPC_EXTERN | PPC_ALTIVEC; - pcc->msr_mask = 0x000000000205FF77ULL; + pcc->msr_mask = (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_74xx; pcc->excp_model = POWERPC_EXCP_74xx; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -6479,7 +7066,23 @@ POWERPC_FAMILY(7457)(ObjectClass *oc, void *data) PPC_MEM_TLBIA | PPC_74xx_TLB | PPC_SEGMENT | PPC_EXTERN | PPC_ALTIVEC; - pcc->msr_mask = 0x000000000205FF77ULL; + pcc->msr_mask = (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_SOFT_74xx; pcc->excp_model = POWERPC_EXCP_74xx; pcc->bus_model = PPC_FLAGS_INPUT_6xx; @@ -6601,7 +7204,23 @@ POWERPC_FAMILY(e600)(ObjectClass *oc, void *data) PPC_SEGMENT | PPC_EXTERN | PPC_ALTIVEC; pcc->insns_flags2 = PPC_NONE; - pcc->msr_mask = 0x000000000205FF77ULL; + pcc->msr_mask = (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_ILE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_EP) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_32B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; @@ -6688,7 +7307,22 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data) PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_64B | PPC_ALTIVEC | PPC_SEGMENT_64B | PPC_SLBI; - pcc->msr_mask = 0x900000000204FF36ULL; + pcc->msr_mask = (1ull << MSR_SF) | + (1ull << MSR_SHV) | + (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI); pcc->mmu_model = POWERPC_MMU_64B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; @@ -6782,7 +7416,21 @@ POWERPC_FAMILY(970FX)(ObjectClass *oc, void *data) PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_64B | PPC_ALTIVEC | PPC_SEGMENT_64B | PPC_SLBI; - pcc->msr_mask = 0x800000000204FF36ULL; + pcc->msr_mask = (1ull << MSR_SF) | + (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI); pcc->mmu_model = POWERPC_MMU_64B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; @@ -6870,7 +7518,22 @@ POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data) PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_64B | PPC_ALTIVEC | PPC_SEGMENT_64B | PPC_SLBI; - pcc->msr_mask = 0x900000000204FF36ULL; + pcc->msr_mask = (1ull << MSR_SF) | + (1ull << MSR_SHV) | + (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI); pcc->mmu_model = POWERPC_MMU_64B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; @@ -6962,7 +7625,21 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data) PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_64B | PPC_SEGMENT_64B | PPC_SLBI; - pcc->msr_mask = 0x800000000204FF36ULL; + pcc->msr_mask = (1ull << MSR_SF) | + (1ull << MSR_VR) | + (1ull << MSR_POW) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI); pcc->mmu_model = POWERPC_MMU_64B; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; @@ -7083,7 +7760,22 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206; - pcc->msr_mask = 0x800000000280FF37ULL; + pcc->msr_mask = (1ull << MSR_SF) | + (1ull << MSR_VR) | + (1ull << MSR_VSX) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_2_06; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; @@ -7126,7 +7818,22 @@ POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data) PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206; - pcc->msr_mask = 0x800000000280FF37ULL; + pcc->msr_mask = (1ull << MSR_SF) | + (1ull << MSR_VR) | + (1ull << MSR_VSX) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_2_06; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; @@ -7183,7 +7890,22 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data) PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | PPC2_ISA205 | PPC2_ISA207S; - pcc->msr_mask = 0x800000000280FF37ULL; + pcc->msr_mask = (1ull << MSR_SF) | + (1ull << MSR_VR) | + (1ull << MSR_VSX) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_SE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR) | + (1ull << MSR_PMM) | + (1ull << MSR_RI) | + (1ull << MSR_LE); pcc->mmu_model = POWERPC_MMU_2_06; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 013/118] target-ppc: Remove PVR check from migration 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (11 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 012/118] target-ppc: Eliminate Magic Number MSR Masks Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 014/118] mac99: Added FW_CFG_PPC_BUSFREQ to match CLOCKFREQ and TBFREQ already there Alexander Graf ` (62 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Alexey Kardashevskiy, qemu-devel From: Alexey Kardashevskiy <aik@ozlabs.ru> Currently migration fails if CPU version (PVR register) is different even a bit. This check is performed at the very end of migration when device states are sent. This is too late for management software and we need to provide a way for the user to make sure that migration will succeed if QEMU is started with appropritate command line parameters. This removes the PVR check. This resets PVR to the default value as the existing VMSTATE record for SPR array sends all 1024 registers unconditionally and overwrites the destination PVR. If the user wants some guarantees for migration to succeed, then a CPU name or "host" CPU with a "compat" option (on its way to upsteam) should be used and KVM or TCG is expected to fail on unsupported values at the moment of QEMU start. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/machine.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/target-ppc/machine.c b/target-ppc/machine.c index 063b379..df7cfc5 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -160,6 +160,11 @@ static int cpu_post_load(void *opaque, int version_id) CPUPPCState *env = &cpu->env; int i; + /* + * We always ignore the source PVR. The user or management + * software has to take care of running QEMU in a compatible mode. + */ + env->spr[SPR_PVR] = env->spr_cb[SPR_PVR].default_value; env->lr = env->spr[SPR_LR]; env->ctr = env->spr[SPR_CTR]; env->xer = env->spr[SPR_XER]; @@ -471,8 +476,7 @@ const VMStateDescription vmstate_ppc_cpu = { .pre_save = cpu_pre_save, .post_load = cpu_post_load, .fields = (VMStateField []) { - /* Verify we haven't changed the pvr */ - VMSTATE_UINTTL_EQUAL(env.spr[SPR_PVR], PowerPCCPU), + VMSTATE_UNUSED(sizeof(target_ulong)), /* was _EQUAL(env.spr[SPR_PVR]) */ /* User mode architected state */ VMSTATE_UINTTL_ARRAY(env.gpr, PowerPCCPU, 32), -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 014/118] mac99: Added FW_CFG_PPC_BUSFREQ to match CLOCKFREQ and TBFREQ already there 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (12 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 013/118] target-ppc: Remove PVR check from migration Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 015/118] libdecnumber: Introduce libdecnumber Code Alexander Graf ` (61 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel From: BALATON Zoltan <balaton@eik.bme.hu> While there, also moved the hard coded value for CLOCKFREQ to a #define. Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu> Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/ppc/mac_newworld.c | 5 ++++- hw/ppc/mac_oldworld.c | 5 ++++- include/hw/ppc/ppc.h | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 4bdaa8d..e493dc1 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -72,6 +72,8 @@ #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 #define TBFREQ (100UL * 1000UL * 1000UL) +#define CLOCKFREQ (266UL * 1000UL * 1000UL) +#define BUSFREQ (100UL * 1000UL * 1000UL) /* debug UniNorth */ //#define DEBUG_UNIN @@ -467,7 +469,8 @@ static void ppc_core99_init(MachineState *machine) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ); } /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ - fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ); qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); } diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 77598e4..4b5e905 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -46,6 +46,8 @@ #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 #define TBFREQ 16600000UL +#define CLOCKFREQ 266000000UL +#define BUSFREQ 66000000UL static int fw_cfg_boot_set(void *opaque, const char *boot_device) { @@ -337,7 +339,8 @@ static void ppc_heathrow_init(MachineState *machine) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ); } /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ - fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ); qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); } diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h index d71bd07..7e16e2e 100644 --- a/include/hw/ppc/ppc.h +++ b/include/hw/ppc/ppc.h @@ -92,6 +92,8 @@ enum { #define FW_CFG_PPC_IS_KVM (FW_CFG_ARCH_LOCAL + 0x05) #define FW_CFG_PPC_KVM_HC (FW_CFG_ARCH_LOCAL + 0x06) #define FW_CFG_PPC_KVM_PID (FW_CFG_ARCH_LOCAL + 0x07) +/* OpenBIOS has FW_CFG_PPC_NVRAM_ADDR as +0x08 */ +#define FW_CFG_PPC_BUSFREQ (FW_CFG_ARCH_LOCAL + 0x09) #define PPC_SERIAL_MM_BAUDBASE 399193 -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 015/118] libdecnumber: Introduce libdecnumber Code 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (13 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 014/118] mac99: Added FW_CFG_PPC_BUSFREQ to match CLOCKFREQ and TBFREQ already there Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 016/118] libdecnumber: Eliminate #include *Symbols.h Alexander Graf ` (60 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add files from the libdecnumber decimal floating point library to QEMU. The libdecnumber library was originally part of GCC and contains code that is useful in emulating the PowerPC decimal floating point (DFP) instructions. This particular copy of the source comes from GCC 4.3 and is licensed at GPLv2+. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- include/libdecnumber/dconfig.h | 52 + include/libdecnumber/decContext.h | 258 + include/libdecnumber/decDPD.h | 1215 +++++ include/libdecnumber/decNumber.h | 200 + include/libdecnumber/decNumberLocal.h | 667 +++ include/libdecnumber/dpd/decimal128.h | 101 + include/libdecnumber/dpd/decimal128Local.h | 47 + include/libdecnumber/dpd/decimal32.h | 99 + include/libdecnumber/dpd/decimal64.h | 101 + libdecnumber/decContext.c | 431 ++ libdecnumber/decNumber.c | 8122 ++++++++++++++++++++++++++++ libdecnumber/dpd/decimal128.c | 566 ++ libdecnumber/dpd/decimal128Local.h | 42 + libdecnumber/dpd/decimal32.c | 491 ++ libdecnumber/dpd/decimal64.c | 852 +++ 15 files changed, 13244 insertions(+) create mode 100644 include/libdecnumber/dconfig.h create mode 100644 include/libdecnumber/decContext.h create mode 100644 include/libdecnumber/decDPD.h create mode 100644 include/libdecnumber/decNumber.h create mode 100644 include/libdecnumber/decNumberLocal.h create mode 100644 include/libdecnumber/dpd/decimal128.h create mode 100644 include/libdecnumber/dpd/decimal128Local.h create mode 100644 include/libdecnumber/dpd/decimal32.h create mode 100644 include/libdecnumber/dpd/decimal64.h create mode 100644 libdecnumber/decContext.c create mode 100644 libdecnumber/decNumber.c create mode 100644 libdecnumber/dpd/decimal128.c create mode 100644 libdecnumber/dpd/decimal128Local.h create mode 100644 libdecnumber/dpd/decimal32.c create mode 100644 libdecnumber/dpd/decimal64.c diff --git a/include/libdecnumber/dconfig.h b/include/libdecnumber/dconfig.h new file mode 100644 index 0000000..ffbad25 --- /dev/null +++ b/include/libdecnumber/dconfig.h @@ -0,0 +1,52 @@ +/* Configure decNumber for either host or target. + Copyright (C) 2008 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifdef IN_LIBGCC2 + +#include "tconfig.h" +#include "coretypes.h" +#include "tm.h" + +#ifndef LIBGCC2_WORDS_BIG_ENDIAN +#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN +#endif + +#ifndef LIBGCC2_FLOAT_WORDS_BIG_ENDIAN +#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN LIBGCC2_WORDS_BIG_ENDIAN +#endif + +#if LIBGCC2_FLOAT_WORDS_BIG_ENDIAN +#define WORDS_BIGENDIAN 1 +#endif + +#else + +#include "config.h" + +#endif diff --git a/include/libdecnumber/decContext.h b/include/libdecnumber/decContext.h new file mode 100644 index 0000000..f80d03c --- /dev/null +++ b/include/libdecnumber/decContext.h @@ -0,0 +1,258 @@ +/* Decimal context header module for the decNumber C Library. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------ */ +/* Decimal Context module header */ +/* ------------------------------------------------------------------ */ +/* */ +/* Context variables must always have valid values: */ +/* */ +/* status -- [any bits may be cleared, but not set, by user] */ +/* round -- must be one of the enumerated rounding modes */ +/* */ +/* The following variables are implied for fixed size formats (i.e., */ +/* they are ignored) but should still be set correctly in case used */ +/* with decNumber functions: */ +/* */ +/* clamp -- must be either 0 or 1 */ +/* digits -- must be in the range 1 through 999999999 */ +/* emax -- must be in the range 0 through 999999999 */ +/* emin -- must be in the range 0 through -999999999 */ +/* extended -- must be either 0 or 1 [present only if DECSUBSET] */ +/* traps -- only defined bits may be set */ +/* */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECCONTEXT) + #define DECCONTEXT + #define DECCNAME "decContext" /* Short name */ + #define DECCFULLNAME "Decimal Context Descriptor" /* Verbose name */ + #define DECCAUTHOR "Mike Cowlishaw" /* Who to blame */ + + #include "gstdint.h" /* C99 standard integers */ + #include <stdio.h> /* for printf, etc. */ + #include <signal.h> /* for traps */ + + /* Extended flags setting -- set this to 0 to use only IEEE flags */ + #define DECEXTFLAG 1 /* 1=enable extended flags */ + + /* Conditional code flag -- set this to 0 for best performance */ + #define DECSUBSET 0 /* 1=enable subset arithmetic */ + + /* Context for operations, with associated constants */ + enum rounding { + DEC_ROUND_CEILING, /* round towards +infinity */ + DEC_ROUND_UP, /* round away from 0 */ + DEC_ROUND_HALF_UP, /* 0.5 rounds up */ + DEC_ROUND_HALF_EVEN, /* 0.5 rounds to nearest even */ + DEC_ROUND_HALF_DOWN, /* 0.5 rounds down */ + DEC_ROUND_DOWN, /* round towards 0 (truncate) */ + DEC_ROUND_FLOOR, /* round towards -infinity */ + DEC_ROUND_05UP, /* round for reround */ + DEC_ROUND_MAX /* enum must be less than this */ + }; + #define DEC_ROUND_DEFAULT DEC_ROUND_HALF_EVEN; + + typedef struct { + int32_t digits; /* working precision */ + int32_t emax; /* maximum positive exponent */ + int32_t emin; /* minimum negative exponent */ + enum rounding round; /* rounding mode */ + uint32_t traps; /* trap-enabler flags */ + uint32_t status; /* status flags */ + uint8_t clamp; /* flag: apply IEEE exponent clamp */ + #if DECSUBSET + uint8_t extended; /* flag: special-values allowed */ + #endif + } decContext; + + /* Maxima and Minima for context settings */ + #define DEC_MAX_DIGITS 999999999 + #define DEC_MIN_DIGITS 1 + #define DEC_MAX_EMAX 999999999 + #define DEC_MIN_EMAX 0 + #define DEC_MAX_EMIN 0 + #define DEC_MIN_EMIN -999999999 + #define DEC_MAX_MATH 999999 /* max emax, etc., for math funcs. */ + + /* Classifications for decimal numbers, aligned with 754r (note */ + /* that 'normal' and 'subnormal' are meaningful only with a */ + /* decContext or a fixed size format). */ + enum decClass { + DEC_CLASS_SNAN, + DEC_CLASS_QNAN, + DEC_CLASS_NEG_INF, + DEC_CLASS_NEG_NORMAL, + DEC_CLASS_NEG_SUBNORMAL, + DEC_CLASS_NEG_ZERO, + DEC_CLASS_POS_ZERO, + DEC_CLASS_POS_SUBNORMAL, + DEC_CLASS_POS_NORMAL, + DEC_CLASS_POS_INF + }; + /* Strings for the decClasses */ + #define DEC_ClassString_SN "sNaN" + #define DEC_ClassString_QN "NaN" + #define DEC_ClassString_NI "-Infinity" + #define DEC_ClassString_NN "-Normal" + #define DEC_ClassString_NS "-Subnormal" + #define DEC_ClassString_NZ "-Zero" + #define DEC_ClassString_PZ "+Zero" + #define DEC_ClassString_PS "+Subnormal" + #define DEC_ClassString_PN "+Normal" + #define DEC_ClassString_PI "+Infinity" + #define DEC_ClassString_UN "Invalid" + + /* Trap-enabler and Status flags (exceptional conditions), and */ + /* their names. The top byte is reserved for internal use */ + #if DECEXTFLAG + /* Extended flags */ + #define DEC_Conversion_syntax 0x00000001 + #define DEC_Division_by_zero 0x00000002 + #define DEC_Division_impossible 0x00000004 + #define DEC_Division_undefined 0x00000008 + #define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */ + #define DEC_Inexact 0x00000020 + #define DEC_Invalid_context 0x00000040 + #define DEC_Invalid_operation 0x00000080 + #if DECSUBSET + #define DEC_Lost_digits 0x00000100 + #endif + #define DEC_Overflow 0x00000200 + #define DEC_Clamped 0x00000400 + #define DEC_Rounded 0x00000800 + #define DEC_Subnormal 0x00001000 + #define DEC_Underflow 0x00002000 + #else + /* IEEE flags only */ + #define DEC_Conversion_syntax 0x00000010 + #define DEC_Division_by_zero 0x00000002 + #define DEC_Division_impossible 0x00000010 + #define DEC_Division_undefined 0x00000010 + #define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */ + #define DEC_Inexact 0x00000001 + #define DEC_Invalid_context 0x00000010 + #define DEC_Invalid_operation 0x00000010 + #if DECSUBSET + #define DEC_Lost_digits 0x00000000 + #endif + #define DEC_Overflow 0x00000008 + #define DEC_Clamped 0x00000000 + #define DEC_Rounded 0x00000000 + #define DEC_Subnormal 0x00000000 + #define DEC_Underflow 0x00000004 + #endif + + /* IEEE 854 groupings for the flags */ + /* [DEC_Clamped, DEC_Lost_digits, DEC_Rounded, and DEC_Subnormal */ + /* are not in IEEE 854] */ + #define DEC_IEEE_854_Division_by_zero (DEC_Division_by_zero) + #if DECSUBSET + #define DEC_IEEE_854_Inexact (DEC_Inexact | DEC_Lost_digits) + #else + #define DEC_IEEE_854_Inexact (DEC_Inexact) + #endif + #define DEC_IEEE_854_Invalid_operation (DEC_Conversion_syntax | \ + DEC_Division_impossible | \ + DEC_Division_undefined | \ + DEC_Insufficient_storage | \ + DEC_Invalid_context | \ + DEC_Invalid_operation) + #define DEC_IEEE_854_Overflow (DEC_Overflow) + #define DEC_IEEE_854_Underflow (DEC_Underflow) + + /* flags which are normally errors (result is qNaN, infinite, or 0) */ + #define DEC_Errors (DEC_IEEE_854_Division_by_zero | \ + DEC_IEEE_854_Invalid_operation | \ + DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow) + /* flags which cause a result to become qNaN */ + #define DEC_NaNs DEC_IEEE_854_Invalid_operation + + /* flags which are normally for information only (finite results) */ + #if DECSUBSET + #define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact \ + | DEC_Lost_digits) + #else + #define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact) + #endif + + /* Name strings for the exceptional conditions */ + #define DEC_Condition_CS "Conversion syntax" + #define DEC_Condition_DZ "Division by zero" + #define DEC_Condition_DI "Division impossible" + #define DEC_Condition_DU "Division undefined" + #define DEC_Condition_IE "Inexact" + #define DEC_Condition_IS "Insufficient storage" + #define DEC_Condition_IC "Invalid context" + #define DEC_Condition_IO "Invalid operation" + #if DECSUBSET + #define DEC_Condition_LD "Lost digits" + #endif + #define DEC_Condition_OV "Overflow" + #define DEC_Condition_PA "Clamped" + #define DEC_Condition_RO "Rounded" + #define DEC_Condition_SU "Subnormal" + #define DEC_Condition_UN "Underflow" + #define DEC_Condition_ZE "No status" + #define DEC_Condition_MU "Multiple status" + #define DEC_Condition_Length 21 /* length of the longest string, */ + /* including terminator */ + + /* Initialization descriptors, used by decContextDefault */ + #define DEC_INIT_BASE 0 + #define DEC_INIT_DECIMAL32 32 + #define DEC_INIT_DECIMAL64 64 + #define DEC_INIT_DECIMAL128 128 + /* Synonyms */ + #define DEC_INIT_DECSINGLE DEC_INIT_DECIMAL32 + #define DEC_INIT_DECDOUBLE DEC_INIT_DECIMAL64 + #define DEC_INIT_DECQUAD DEC_INIT_DECIMAL128 + + /* decContext routines */ + + #include "decContextSymbols.h" + + extern decContext * decContextClearStatus(decContext *, uint32_t); + extern decContext * decContextDefault(decContext *, int32_t); + extern enum rounding decContextGetRounding(decContext *); + extern uint32_t decContextGetStatus(decContext *); + extern decContext * decContextRestoreStatus(decContext *, uint32_t, uint32_t); + extern uint32_t decContextSaveStatus(decContext *, uint32_t); + extern decContext * decContextSetRounding(decContext *, enum rounding); + extern decContext * decContextSetStatus(decContext *, uint32_t); + extern decContext * decContextSetStatusFromString(decContext *, const char *); + extern decContext * decContextSetStatusFromStringQuiet(decContext *, const char *); + extern decContext * decContextSetStatusQuiet(decContext *, uint32_t); + extern const char * decContextStatusToString(const decContext *); + extern uint32_t decContextTestSavedStatus(uint32_t, uint32_t); + extern uint32_t decContextTestStatus(decContext *, uint32_t); + extern decContext * decContextZeroStatus(decContext *); + +#endif diff --git a/include/libdecnumber/decDPD.h b/include/libdecnumber/decDPD.h new file mode 100644 index 0000000..3cc1d63 --- /dev/null +++ b/include/libdecnumber/decDPD.h @@ -0,0 +1,1215 @@ +/* Conversion lookup tables for the decNumber C Library. + Copyright (C) 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------------ */ +/* Binary Coded Decimal and Densely Packed Decimal conversion lookup tables */ +/* [Automatically generated -- do not edit. 2007.05.05] */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ +/* For details, see: http://www2.hursley.ibm.com/decimal/DPDecimal.html */ + +#include "decDPDSymbols.h" + +/* This include file defines several DPD and BCD conversion tables: */ +/* */ +/* uint16_t BCD2DPD[2458]; -- BCD -> DPD (0x999 => 2457) */ +/* uint16_t BIN2DPD[1000]; -- Bin -> DPD (999 => 2457) */ +/* uint8_t BIN2CHAR[4001]; -- Bin -> CHAR (999 => '\3' '9' '9' '9') */ +/* uint8_t BIN2BCD8[4000]; -- Bin -> bytes (999 => 9 9 9 3) */ +/* uint16_t DPD2BCD[1024]; -- DPD -> BCD (0x3FF => 0x999) */ +/* uint16_t DPD2BIN[1024]; -- DPD -> BIN (0x3FF => 999) */ +/* uint32_t DPD2BINK[1024]; -- DPD -> BIN * 1000 (0x3FF => 999000) */ +/* uint32_t DPD2BINM[1024]; -- DPD -> BIN * 1E+6 (0x3FF => 999000000) */ +/* uint8_t DPD2BCD8[4096]; -- DPD -> bytes (x3FF => 9 9 9 3) */ +/* */ +/* In all cases the result (10 bits or 12 bits, or binary) is right-aligned */ +/* in the table entry. BIN2CHAR entries are a single byte length (0 for */ +/* value 0) followed by three digit characters; a trailing terminator is */ +/* included to allow 4-char moves always. BIN2BCD8 and DPD2BCD8 entries */ +/* are similar with the three BCD8 digits followed by a one-byte length */ +/* (again, length=0 for value 0). */ +/* */ +/* To use a table, its name, prefixed with DEC_, must be defined with a */ +/* value of 1 before this header file is included. For example: */ +/* #define DEC_BCD2DPD 1 */ +/* This mechanism allows software to only include tables that are needed. */ +/* ------------------------------------------------------------------------ */ + +#if defined(DEC_BCD2DPD) && DEC_BCD2DPD==1 && !defined(DECBCD2DPD) +#define DECBCD2DPD + +const uint16_t BCD2DPD[2458]={ 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 0, 0, 0, 0, 0, 0, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 0, 0, 0, 0, 0, + 0, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 0, 0, + 0, 0, 0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 0, 0, 0, 0, 0, 0, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 0, 0, 0, 0, 0, 0, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 0, 0, 0, 0, 0, 0, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 0, 0, 0, + 0, 0, 0, 10, 11, 42, 43, 74, 75, 106, 107, 78, 79, + 0, 0, 0, 0, 0, 0, 26, 27, 58, 59, 90, 91, 122, + 123, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 0, 0, + 0, 0, 0, 0, 144, 145, 146, 147, 148, 149, 150, 151, 152, + 153, 0, 0, 0, 0, 0, 0, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 0, 0, 0, 0, 0, 0, 176, 177, 178, + 179, 180, 181, 182, 183, 184, 185, 0, 0, 0, 0, 0, 0, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 0, 0, 0, + 0, 0, 0, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + 0, 0, 0, 0, 0, 0, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 0, 0, 0, 0, 0, 0, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 0, 0, 0, 0, 0, 0, 138, + 139, 170, 171, 202, 203, 234, 235, 206, 207, 0, 0, 0, 0, + 0, 0, 154, 155, 186, 187, 218, 219, 250, 251, 222, 223, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 257, 258, + 259, 260, 261, 262, 263, 264, 265, 0, 0, 0, 0, 0, 0, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 0, 0, 0, + 0, 0, 0, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, + 0, 0, 0, 0, 0, 0, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 0, 0, 0, 0, 0, 0, 320, 321, 322, 323, + 324, 325, 326, 327, 328, 329, 0, 0, 0, 0, 0, 0, 336, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 0, 0, 0, 0, + 0, 0, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 0, 0, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 0, 0, 0, 0, 0, 0, 266, 267, 298, 299, 330, + 331, 362, 363, 334, 335, 0, 0, 0, 0, 0, 0, 282, 283, + 314, 315, 346, 347, 378, 379, 350, 351, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 384, 385, 386, 387, 388, 389, 390, + 391, 392, 393, 0, 0, 0, 0, 0, 0, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 0, 0, 0, 0, 0, 0, 416, + 417, 418, 419, 420, 421, 422, 423, 424, 425, 0, 0, 0, 0, + 0, 0, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 0, + 0, 0, 0, 0, 0, 448, 449, 450, 451, 452, 453, 454, 455, + 456, 457, 0, 0, 0, 0, 0, 0, 464, 465, 466, 467, 468, + 469, 470, 471, 472, 473, 0, 0, 0, 0, 0, 0, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 0, 0, 0, 0, 0, + 0, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 0, 0, + 0, 0, 0, 0, 394, 395, 426, 427, 458, 459, 490, 491, 462, + 463, 0, 0, 0, 0, 0, 0, 410, 411, 442, 443, 474, 475, + 506, 507, 478, 479, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 0, + 0, 0, 0, 0, 0, 528, 529, 530, 531, 532, 533, 534, 535, + 536, 537, 0, 0, 0, 0, 0, 0, 544, 545, 546, 547, 548, + 549, 550, 551, 552, 553, 0, 0, 0, 0, 0, 0, 560, 561, + 562, 563, 564, 565, 566, 567, 568, 569, 0, 0, 0, 0, 0, + 0, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 0, 0, + 0, 0, 0, 0, 592, 593, 594, 595, 596, 597, 598, 599, 600, + 601, 0, 0, 0, 0, 0, 0, 608, 609, 610, 611, 612, 613, + 614, 615, 616, 617, 0, 0, 0, 0, 0, 0, 624, 625, 626, + 627, 628, 629, 630, 631, 632, 633, 0, 0, 0, 0, 0, 0, + 522, 523, 554, 555, 586, 587, 618, 619, 590, 591, 0, 0, 0, + 0, 0, 0, 538, 539, 570, 571, 602, 603, 634, 635, 606, 607, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 640, 641, + 642, 643, 644, 645, 646, 647, 648, 649, 0, 0, 0, 0, 0, + 0, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 0, 0, + 0, 0, 0, 0, 672, 673, 674, 675, 676, 677, 678, 679, 680, + 681, 0, 0, 0, 0, 0, 0, 688, 689, 690, 691, 692, 693, + 694, 695, 696, 697, 0, 0, 0, 0, 0, 0, 704, 705, 706, + 707, 708, 709, 710, 711, 712, 713, 0, 0, 0, 0, 0, 0, + 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 0, 0, 0, + 0, 0, 0, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, + 0, 0, 0, 0, 0, 0, 752, 753, 754, 755, 756, 757, 758, + 759, 760, 761, 0, 0, 0, 0, 0, 0, 650, 651, 682, 683, + 714, 715, 746, 747, 718, 719, 0, 0, 0, 0, 0, 0, 666, + 667, 698, 699, 730, 731, 762, 763, 734, 735, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 768, 769, 770, 771, 772, 773, + 774, 775, 776, 777, 0, 0, 0, 0, 0, 0, 784, 785, 786, + 787, 788, 789, 790, 791, 792, 793, 0, 0, 0, 0, 0, 0, + 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 0, 0, 0, + 0, 0, 0, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, + 0, 0, 0, 0, 0, 0, 832, 833, 834, 835, 836, 837, 838, + 839, 840, 841, 0, 0, 0, 0, 0, 0, 848, 849, 850, 851, + 852, 853, 854, 855, 856, 857, 0, 0, 0, 0, 0, 0, 864, + 865, 866, 867, 868, 869, 870, 871, 872, 873, 0, 0, 0, 0, + 0, 0, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 0, + 0, 0, 0, 0, 0, 778, 779, 810, 811, 842, 843, 874, 875, + 846, 847, 0, 0, 0, 0, 0, 0, 794, 795, 826, 827, 858, + 859, 890, 891, 862, 863, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, + 0, 0, 0, 0, 0, 0, 912, 913, 914, 915, 916, 917, 918, + 919, 920, 921, 0, 0, 0, 0, 0, 0, 928, 929, 930, 931, + 932, 933, 934, 935, 936, 937, 0, 0, 0, 0, 0, 0, 944, + 945, 946, 947, 948, 949, 950, 951, 952, 953, 0, 0, 0, 0, + 0, 0, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 0, + 0, 0, 0, 0, 0, 976, 977, 978, 979, 980, 981, 982, 983, + 984, 985, 0, 0, 0, 0, 0, 0, 992, 993, 994, 995, 996, + 997, 998, 999, 1000, 1001, 0, 0, 0, 0, 0, 0, 1008, 1009, + 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 0, 0, 0, 0, 0, + 0, 906, 907, 938, 939, 970, 971, 1002, 1003, 974, 975, 0, 0, + 0, 0, 0, 0, 922, 923, 954, 955, 986, 987, 1018, 1019, 990, + 991, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 13, 268, 269, 524, 525, 780, 781, 46, 47, 0, 0, 0, 0, + 0, 0, 28, 29, 284, 285, 540, 541, 796, 797, 62, 63, 0, + 0, 0, 0, 0, 0, 44, 45, 300, 301, 556, 557, 812, 813, + 302, 303, 0, 0, 0, 0, 0, 0, 60, 61, 316, 317, 572, + 573, 828, 829, 318, 319, 0, 0, 0, 0, 0, 0, 76, 77, + 332, 333, 588, 589, 844, 845, 558, 559, 0, 0, 0, 0, 0, + 0, 92, 93, 348, 349, 604, 605, 860, 861, 574, 575, 0, 0, + 0, 0, 0, 0, 108, 109, 364, 365, 620, 621, 876, 877, 814, + 815, 0, 0, 0, 0, 0, 0, 124, 125, 380, 381, 636, 637, + 892, 893, 830, 831, 0, 0, 0, 0, 0, 0, 14, 15, 270, + 271, 526, 527, 782, 783, 110, 111, 0, 0, 0, 0, 0, 0, + 30, 31, 286, 287, 542, 543, 798, 799, 126, 127, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 140, 141, 396, 397, 652, + 653, 908, 909, 174, 175, 0, 0, 0, 0, 0, 0, 156, 157, + 412, 413, 668, 669, 924, 925, 190, 191, 0, 0, 0, 0, 0, + 0, 172, 173, 428, 429, 684, 685, 940, 941, 430, 431, 0, 0, + 0, 0, 0, 0, 188, 189, 444, 445, 700, 701, 956, 957, 446, + 447, 0, 0, 0, 0, 0, 0, 204, 205, 460, 461, 716, 717, + 972, 973, 686, 687, 0, 0, 0, 0, 0, 0, 220, 221, 476, + 477, 732, 733, 988, 989, 702, 703, 0, 0, 0, 0, 0, 0, + 236, 237, 492, 493, 748, 749, 1004, 1005, 942, 943, 0, 0, 0, + 0, 0, 0, 252, 253, 508, 509, 764, 765, 1020, 1021, 958, 959, + 0, 0, 0, 0, 0, 0, 142, 143, 398, 399, 654, 655, 910, + 911, 238, 239, 0, 0, 0, 0, 0, 0, 158, 159, 414, 415, + 670, 671, 926, 927, 254, 255}; +#endif + +#if defined(DEC_DPD2BCD) && DEC_DPD2BCD==1 && !defined(DECDPD2BCD) +#define DECDPD2BCD + +const uint16_t DPD2BCD[1024]={ 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 128, 129, 2048, 2049, 2176, 2177, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 144, 145, 2064, 2065, 2192, 2193, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 130, 131, 2080, 2081, 2056, + 2057, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 146, 147, + 2096, 2097, 2072, 2073, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 132, 133, 2112, 2113, 136, 137, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 148, 149, 2128, 2129, 152, 153, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 134, 135, 2144, 2145, 2184, 2185, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 150, 151, 2160, + 2161, 2200, 2201, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 384, 385, 2304, 2305, 2432, 2433, 272, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 400, 401, 2320, 2321, 2448, 2449, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 386, 387, 2336, 2337, 2312, 2313, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 402, 403, 2352, 2353, + 2328, 2329, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 388, + 389, 2368, 2369, 392, 393, 336, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 404, 405, 2384, 2385, 408, 409, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 390, 391, 2400, 2401, 2440, 2441, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 406, 407, 2416, 2417, 2456, + 2457, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 640, 641, + 2050, 2051, 2178, 2179, 528, 529, 530, 531, 532, 533, 534, 535, 536, + 537, 656, 657, 2066, 2067, 2194, 2195, 544, 545, 546, 547, 548, 549, + 550, 551, 552, 553, 642, 643, 2082, 2083, 2088, 2089, 560, 561, 562, + 563, 564, 565, 566, 567, 568, 569, 658, 659, 2098, 2099, 2104, 2105, + 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 644, 645, 2114, + 2115, 648, 649, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, + 660, 661, 2130, 2131, 664, 665, 608, 609, 610, 611, 612, 613, 614, + 615, 616, 617, 646, 647, 2146, 2147, 2184, 2185, 624, 625, 626, 627, + 628, 629, 630, 631, 632, 633, 662, 663, 2162, 2163, 2200, 2201, 768, + 769, 770, 771, 772, 773, 774, 775, 776, 777, 896, 897, 2306, 2307, + 2434, 2435, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 912, + 913, 2322, 2323, 2450, 2451, 800, 801, 802, 803, 804, 805, 806, 807, + 808, 809, 898, 899, 2338, 2339, 2344, 2345, 816, 817, 818, 819, 820, + 821, 822, 823, 824, 825, 914, 915, 2354, 2355, 2360, 2361, 832, 833, + 834, 835, 836, 837, 838, 839, 840, 841, 900, 901, 2370, 2371, 904, + 905, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 916, 917, + 2386, 2387, 920, 921, 864, 865, 866, 867, 868, 869, 870, 871, 872, + 873, 902, 903, 2402, 2403, 2440, 2441, 880, 881, 882, 883, 884, 885, + 886, 887, 888, 889, 918, 919, 2418, 2419, 2456, 2457, 1024, 1025, 1026, + 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1152, 1153, 2052, 2053, 2180, 2181, + 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1168, 1169, 2068, + 2069, 2196, 2197, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, + 1154, 1155, 2084, 2085, 2120, 2121, 1072, 1073, 1074, 1075, 1076, 1077, 1078, + 1079, 1080, 1081, 1170, 1171, 2100, 2101, 2136, 2137, 1088, 1089, 1090, 1091, + 1092, 1093, 1094, 1095, 1096, 1097, 1156, 1157, 2116, 2117, 1160, 1161, 1104, + 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1172, 1173, 2132, 2133, + 1176, 1177, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1158, + 1159, 2148, 2149, 2184, 2185, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, + 1144, 1145, 1174, 1175, 2164, 2165, 2200, 2201, 1280, 1281, 1282, 1283, 1284, + 1285, 1286, 1287, 1288, 1289, 1408, 1409, 2308, 2309, 2436, 2437, 1296, 1297, + 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1424, 1425, 2324, 2325, 2452, + 2453, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1410, 1411, + 2340, 2341, 2376, 2377, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, + 1337, 1426, 1427, 2356, 2357, 2392, 2393, 1344, 1345, 1346, 1347, 1348, 1349, + 1350, 1351, 1352, 1353, 1412, 1413, 2372, 2373, 1416, 1417, 1360, 1361, 1362, + 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1428, 1429, 2388, 2389, 1432, 1433, + 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1414, 1415, 2404, + 2405, 2440, 2441, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, + 1430, 1431, 2420, 2421, 2456, 2457, 1536, 1537, 1538, 1539, 1540, 1541, 1542, + 1543, 1544, 1545, 1664, 1665, 2054, 2055, 2182, 2183, 1552, 1553, 1554, 1555, + 1556, 1557, 1558, 1559, 1560, 1561, 1680, 1681, 2070, 2071, 2198, 2199, 1568, + 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1666, 1667, 2086, 2087, + 2152, 2153, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1682, + 1683, 2102, 2103, 2168, 2169, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, + 1608, 1609, 1668, 1669, 2118, 2119, 1672, 1673, 1616, 1617, 1618, 1619, 1620, + 1621, 1622, 1623, 1624, 1625, 1684, 1685, 2134, 2135, 1688, 1689, 1632, 1633, + 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1670, 1671, 2150, 2151, 2184, + 2185, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1686, 1687, + 2166, 2167, 2200, 2201, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, + 1801, 1920, 1921, 2310, 2311, 2438, 2439, 1808, 1809, 1810, 1811, 1812, 1813, + 1814, 1815, 1816, 1817, 1936, 1937, 2326, 2327, 2454, 2455, 1824, 1825, 1826, + 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1922, 1923, 2342, 2343, 2408, 2409, + 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1938, 1939, 2358, + 2359, 2424, 2425, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, + 1924, 1925, 2374, 2375, 1928, 1929, 1872, 1873, 1874, 1875, 1876, 1877, 1878, + 1879, 1880, 1881, 1940, 1941, 2390, 2391, 1944, 1945, 1888, 1889, 1890, 1891, + 1892, 1893, 1894, 1895, 1896, 1897, 1926, 1927, 2406, 2407, 2440, 2441, 1904, + 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1942, 1943, 2422, 2423, + 2456, 2457}; +#endif + +#if defined(DEC_BIN2DPD) && DEC_BIN2DPD==1 && !defined(DECBIN2DPD) +#define DECBIN2DPD + +const uint16_t BIN2DPD[1000]={ 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 10, 11, 42, 43, 74, 75, + 106, 107, 78, 79, 26, 27, 58, 59, 90, 91, 122, 123, 94, + 95, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 144, 145, + 146, 147, 148, 149, 150, 151, 152, 153, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, 224, 225, 226, 227, + 228, 229, 230, 231, 232, 233, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 138, 139, 170, 171, 202, 203, 234, 235, 206, 207, + 154, 155, 186, 187, 218, 219, 250, 251, 222, 223, 256, 257, 258, + 259, 260, 261, 262, 263, 264, 265, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 288, 289, 290, 291, 292, 293, 294, 295, 296, + 297, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 320, 321, + 322, 323, 324, 325, 326, 327, 328, 329, 336, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 361, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 266, + 267, 298, 299, 330, 331, 362, 363, 334, 335, 282, 283, 314, 315, + 346, 347, 378, 379, 350, 351, 384, 385, 386, 387, 388, 389, 390, + 391, 392, 393, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 432, 433, 434, + 435, 436, 437, 438, 439, 440, 441, 448, 449, 450, 451, 452, 453, + 454, 455, 456, 457, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 496, 497, + 498, 499, 500, 501, 502, 503, 504, 505, 394, 395, 426, 427, 458, + 459, 490, 491, 462, 463, 410, 411, 442, 443, 474, 475, 506, 507, + 478, 479, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 528, + 529, 530, 531, 532, 533, 534, 535, 536, 537, 544, 545, 546, 547, + 548, 549, 550, 551, 552, 553, 560, 561, 562, 563, 564, 565, 566, + 567, 568, 569, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, + 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 608, 609, 610, + 611, 612, 613, 614, 615, 616, 617, 624, 625, 626, 627, 628, 629, + 630, 631, 632, 633, 522, 523, 554, 555, 586, 587, 618, 619, 590, + 591, 538, 539, 570, 571, 602, 603, 634, 635, 606, 607, 640, 641, + 642, 643, 644, 645, 646, 647, 648, 649, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 672, 673, 674, 675, 676, 677, 678, 679, + 680, 681, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 704, + 705, 706, 707, 708, 709, 710, 711, 712, 713, 720, 721, 722, 723, + 724, 725, 726, 727, 728, 729, 736, 737, 738, 739, 740, 741, 742, + 743, 744, 745, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, + 650, 651, 682, 683, 714, 715, 746, 747, 718, 719, 666, 667, 698, + 699, 730, 731, 762, 763, 734, 735, 768, 769, 770, 771, 772, 773, + 774, 775, 776, 777, 784, 785, 786, 787, 788, 789, 790, 791, 792, + 793, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 816, 817, + 818, 819, 820, 821, 822, 823, 824, 825, 832, 833, 834, 835, 836, + 837, 838, 839, 840, 841, 848, 849, 850, 851, 852, 853, 854, 855, + 856, 857, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 880, + 881, 882, 883, 884, 885, 886, 887, 888, 889, 778, 779, 810, 811, + 842, 843, 874, 875, 846, 847, 794, 795, 826, 827, 858, 859, 890, + 891, 862, 863, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, + 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 928, 929, 930, + 931, 932, 933, 934, 935, 936, 937, 944, 945, 946, 947, 948, 949, + 950, 951, 952, 953, 960, 961, 962, 963, 964, 965, 966, 967, 968, + 969, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 992, 993, + 994, 995, 996, 997, 998, 999, 1000, 1001, 1008, 1009, 1010, 1011, 1012, + 1013, 1014, 1015, 1016, 1017, 906, 907, 938, 939, 970, 971, 1002, 1003, + 974, 975, 922, 923, 954, 955, 986, 987, 1018, 1019, 990, 991, 12, + 13, 268, 269, 524, 525, 780, 781, 46, 47, 28, 29, 284, 285, + 540, 541, 796, 797, 62, 63, 44, 45, 300, 301, 556, 557, 812, + 813, 302, 303, 60, 61, 316, 317, 572, 573, 828, 829, 318, 319, + 76, 77, 332, 333, 588, 589, 844, 845, 558, 559, 92, 93, 348, + 349, 604, 605, 860, 861, 574, 575, 108, 109, 364, 365, 620, 621, + 876, 877, 814, 815, 124, 125, 380, 381, 636, 637, 892, 893, 830, + 831, 14, 15, 270, 271, 526, 527, 782, 783, 110, 111, 30, 31, + 286, 287, 542, 543, 798, 799, 126, 127, 140, 141, 396, 397, 652, + 653, 908, 909, 174, 175, 156, 157, 412, 413, 668, 669, 924, 925, + 190, 191, 172, 173, 428, 429, 684, 685, 940, 941, 430, 431, 188, + 189, 444, 445, 700, 701, 956, 957, 446, 447, 204, 205, 460, 461, + 716, 717, 972, 973, 686, 687, 220, 221, 476, 477, 732, 733, 988, + 989, 702, 703, 236, 237, 492, 493, 748, 749, 1004, 1005, 942, 943, + 252, 253, 508, 509, 764, 765, 1020, 1021, 958, 959, 142, 143, 398, + 399, 654, 655, 910, 911, 238, 239, 158, 159, 414, 415, 670, 671, + 926, 927, 254, 255}; +#endif + +#if defined(DEC_DPD2BIN) && DEC_DPD2BIN==1 && !defined(DECDPD2BIN) +#define DECDPD2BIN + +const uint16_t DPD2BIN[1024]={ 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 80, 81, 800, 801, 880, 881, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 90, 91, 810, 811, 890, 891, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 82, 83, 820, 821, 808, + 809, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 92, 93, + 830, 831, 818, 819, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 84, 85, 840, 841, 88, 89, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 94, 95, 850, 851, 98, 99, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 86, 87, 860, 861, 888, 889, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 96, 97, 870, + 871, 898, 899, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 180, 181, 900, 901, 980, 981, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 190, 191, 910, 911, 990, 991, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 182, 183, 920, 921, 908, 909, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 192, 193, 930, 931, + 918, 919, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 184, + 185, 940, 941, 188, 189, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 194, 195, 950, 951, 198, 199, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 186, 187, 960, 961, 988, 989, 170, 171, + 172, 173, 174, 175, 176, 177, 178, 179, 196, 197, 970, 971, 998, + 999, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 280, 281, + 802, 803, 882, 883, 210, 211, 212, 213, 214, 215, 216, 217, 218, + 219, 290, 291, 812, 813, 892, 893, 220, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 282, 283, 822, 823, 828, 829, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 292, 293, 832, 833, 838, 839, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 284, 285, 842, + 843, 288, 289, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 294, 295, 852, 853, 298, 299, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 286, 287, 862, 863, 888, 889, 270, 271, 272, 273, + 274, 275, 276, 277, 278, 279, 296, 297, 872, 873, 898, 899, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, 380, 381, 902, 903, + 982, 983, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 390, + 391, 912, 913, 992, 993, 320, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 382, 383, 922, 923, 928, 929, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 392, 393, 932, 933, 938, 939, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, 384, 385, 942, 943, 388, + 389, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 394, 395, + 952, 953, 398, 399, 360, 361, 362, 363, 364, 365, 366, 367, 368, + 369, 386, 387, 962, 963, 988, 989, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 396, 397, 972, 973, 998, 999, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 480, 481, 804, 805, 884, 885, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 490, 491, 814, + 815, 894, 895, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, + 482, 483, 824, 825, 848, 849, 430, 431, 432, 433, 434, 435, 436, + 437, 438, 439, 492, 493, 834, 835, 858, 859, 440, 441, 442, 443, + 444, 445, 446, 447, 448, 449, 484, 485, 844, 845, 488, 489, 450, + 451, 452, 453, 454, 455, 456, 457, 458, 459, 494, 495, 854, 855, + 498, 499, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 486, + 487, 864, 865, 888, 889, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 496, 497, 874, 875, 898, 899, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 580, 581, 904, 905, 984, 985, 510, 511, + 512, 513, 514, 515, 516, 517, 518, 519, 590, 591, 914, 915, 994, + 995, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 582, 583, + 924, 925, 948, 949, 530, 531, 532, 533, 534, 535, 536, 537, 538, + 539, 592, 593, 934, 935, 958, 959, 540, 541, 542, 543, 544, 545, + 546, 547, 548, 549, 584, 585, 944, 945, 588, 589, 550, 551, 552, + 553, 554, 555, 556, 557, 558, 559, 594, 595, 954, 955, 598, 599, + 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 586, 587, 964, + 965, 988, 989, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, + 596, 597, 974, 975, 998, 999, 600, 601, 602, 603, 604, 605, 606, + 607, 608, 609, 680, 681, 806, 807, 886, 887, 610, 611, 612, 613, + 614, 615, 616, 617, 618, 619, 690, 691, 816, 817, 896, 897, 620, + 621, 622, 623, 624, 625, 626, 627, 628, 629, 682, 683, 826, 827, + 868, 869, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 692, + 693, 836, 837, 878, 879, 640, 641, 642, 643, 644, 645, 646, 647, + 648, 649, 684, 685, 846, 847, 688, 689, 650, 651, 652, 653, 654, + 655, 656, 657, 658, 659, 694, 695, 856, 857, 698, 699, 660, 661, + 662, 663, 664, 665, 666, 667, 668, 669, 686, 687, 866, 867, 888, + 889, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 696, 697, + 876, 877, 898, 899, 700, 701, 702, 703, 704, 705, 706, 707, 708, + 709, 780, 781, 906, 907, 986, 987, 710, 711, 712, 713, 714, 715, + 716, 717, 718, 719, 790, 791, 916, 917, 996, 997, 720, 721, 722, + 723, 724, 725, 726, 727, 728, 729, 782, 783, 926, 927, 968, 969, + 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 792, 793, 936, + 937, 978, 979, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, + 784, 785, 946, 947, 788, 789, 750, 751, 752, 753, 754, 755, 756, + 757, 758, 759, 794, 795, 956, 957, 798, 799, 760, 761, 762, 763, + 764, 765, 766, 767, 768, 769, 786, 787, 966, 967, 988, 989, 770, + 771, 772, 773, 774, 775, 776, 777, 778, 779, 796, 797, 976, 977, + 998, 999}; +#endif + +#if defined(DEC_DPD2BINK) && DEC_DPD2BINK==1 && !defined(DECDPD2BINK) +#define DECDPD2BINK + +const uint32_t DPD2BINK[1024]={ 0, 1000, 2000, 3000, 4000, 5000, + 6000, 7000, 8000, 9000, 80000, 81000, 800000, 801000, 880000, 881000, + 10000, 11000, 12000, 13000, 14000, 15000, 16000, 17000, 18000, 19000, + 90000, 91000, 810000, 811000, 890000, 891000, 20000, 21000, 22000, 23000, + 24000, 25000, 26000, 27000, 28000, 29000, 82000, 83000, 820000, 821000, + 808000, 809000, 30000, 31000, 32000, 33000, 34000, 35000, 36000, 37000, + 38000, 39000, 92000, 93000, 830000, 831000, 818000, 819000, 40000, 41000, + 42000, 43000, 44000, 45000, 46000, 47000, 48000, 49000, 84000, 85000, + 840000, 841000, 88000, 89000, 50000, 51000, 52000, 53000, 54000, 55000, + 56000, 57000, 58000, 59000, 94000, 95000, 850000, 851000, 98000, 99000, + 60000, 61000, 62000, 63000, 64000, 65000, 66000, 67000, 68000, 69000, + 86000, 87000, 860000, 861000, 888000, 889000, 70000, 71000, 72000, 73000, + 74000, 75000, 76000, 77000, 78000, 79000, 96000, 97000, 870000, 871000, + 898000, 899000, 100000, 101000, 102000, 103000, 104000, 105000, 106000, 107000, + 108000, 109000, 180000, 181000, 900000, 901000, 980000, 981000, 110000, 111000, + 112000, 113000, 114000, 115000, 116000, 117000, 118000, 119000, 190000, 191000, + 910000, 911000, 990000, 991000, 120000, 121000, 122000, 123000, 124000, 125000, + 126000, 127000, 128000, 129000, 182000, 183000, 920000, 921000, 908000, 909000, + 130000, 131000, 132000, 133000, 134000, 135000, 136000, 137000, 138000, 139000, + 192000, 193000, 930000, 931000, 918000, 919000, 140000, 141000, 142000, 143000, + 144000, 145000, 146000, 147000, 148000, 149000, 184000, 185000, 940000, 941000, + 188000, 189000, 150000, 151000, 152000, 153000, 154000, 155000, 156000, 157000, + 158000, 159000, 194000, 195000, 950000, 951000, 198000, 199000, 160000, 161000, + 162000, 163000, 164000, 165000, 166000, 167000, 168000, 169000, 186000, 187000, + 960000, 961000, 988000, 989000, 170000, 171000, 172000, 173000, 174000, 175000, + 176000, 177000, 178000, 179000, 196000, 197000, 970000, 971000, 998000, 999000, + 200000, 201000, 202000, 203000, 204000, 205000, 206000, 207000, 208000, 209000, + 280000, 281000, 802000, 803000, 882000, 883000, 210000, 211000, 212000, 213000, + 214000, 215000, 216000, 217000, 218000, 219000, 290000, 291000, 812000, 813000, + 892000, 893000, 220000, 221000, 222000, 223000, 224000, 225000, 226000, 227000, + 228000, 229000, 282000, 283000, 822000, 823000, 828000, 829000, 230000, 231000, + 232000, 233000, 234000, 235000, 236000, 237000, 238000, 239000, 292000, 293000, + 832000, 833000, 838000, 839000, 240000, 241000, 242000, 243000, 244000, 245000, + 246000, 247000, 248000, 249000, 284000, 285000, 842000, 843000, 288000, 289000, + 250000, 251000, 252000, 253000, 254000, 255000, 256000, 257000, 258000, 259000, + 294000, 295000, 852000, 853000, 298000, 299000, 260000, 261000, 262000, 263000, + 264000, 265000, 266000, 267000, 268000, 269000, 286000, 287000, 862000, 863000, + 888000, 889000, 270000, 271000, 272000, 273000, 274000, 275000, 276000, 277000, + 278000, 279000, 296000, 297000, 872000, 873000, 898000, 899000, 300000, 301000, + 302000, 303000, 304000, 305000, 306000, 307000, 308000, 309000, 380000, 381000, + 902000, 903000, 982000, 983000, 310000, 311000, 312000, 313000, 314000, 315000, + 316000, 317000, 318000, 319000, 390000, 391000, 912000, 913000, 992000, 993000, + 320000, 321000, 322000, 323000, 324000, 325000, 326000, 327000, 328000, 329000, + 382000, 383000, 922000, 923000, 928000, 929000, 330000, 331000, 332000, 333000, + 334000, 335000, 336000, 337000, 338000, 339000, 392000, 393000, 932000, 933000, + 938000, 939000, 340000, 341000, 342000, 343000, 344000, 345000, 346000, 347000, + 348000, 349000, 384000, 385000, 942000, 943000, 388000, 389000, 350000, 351000, + 352000, 353000, 354000, 355000, 356000, 357000, 358000, 359000, 394000, 395000, + 952000, 953000, 398000, 399000, 360000, 361000, 362000, 363000, 364000, 365000, + 366000, 367000, 368000, 369000, 386000, 387000, 962000, 963000, 988000, 989000, + 370000, 371000, 372000, 373000, 374000, 375000, 376000, 377000, 378000, 379000, + 396000, 397000, 972000, 973000, 998000, 999000, 400000, 401000, 402000, 403000, + 404000, 405000, 406000, 407000, 408000, 409000, 480000, 481000, 804000, 805000, + 884000, 885000, 410000, 411000, 412000, 413000, 414000, 415000, 416000, 417000, + 418000, 419000, 490000, 491000, 814000, 815000, 894000, 895000, 420000, 421000, + 422000, 423000, 424000, 425000, 426000, 427000, 428000, 429000, 482000, 483000, + 824000, 825000, 848000, 849000, 430000, 431000, 432000, 433000, 434000, 435000, + 436000, 437000, 438000, 439000, 492000, 493000, 834000, 835000, 858000, 859000, + 440000, 441000, 442000, 443000, 444000, 445000, 446000, 447000, 448000, 449000, + 484000, 485000, 844000, 845000, 488000, 489000, 450000, 451000, 452000, 453000, + 454000, 455000, 456000, 457000, 458000, 459000, 494000, 495000, 854000, 855000, + 498000, 499000, 460000, 461000, 462000, 463000, 464000, 465000, 466000, 467000, + 468000, 469000, 486000, 487000, 864000, 865000, 888000, 889000, 470000, 471000, + 472000, 473000, 474000, 475000, 476000, 477000, 478000, 479000, 496000, 497000, + 874000, 875000, 898000, 899000, 500000, 501000, 502000, 503000, 504000, 505000, + 506000, 507000, 508000, 509000, 580000, 581000, 904000, 905000, 984000, 985000, + 510000, 511000, 512000, 513000, 514000, 515000, 516000, 517000, 518000, 519000, + 590000, 591000, 914000, 915000, 994000, 995000, 520000, 521000, 522000, 523000, + 524000, 525000, 526000, 527000, 528000, 529000, 582000, 583000, 924000, 925000, + 948000, 949000, 530000, 531000, 532000, 533000, 534000, 535000, 536000, 537000, + 538000, 539000, 592000, 593000, 934000, 935000, 958000, 959000, 540000, 541000, + 542000, 543000, 544000, 545000, 546000, 547000, 548000, 549000, 584000, 585000, + 944000, 945000, 588000, 589000, 550000, 551000, 552000, 553000, 554000, 555000, + 556000, 557000, 558000, 559000, 594000, 595000, 954000, 955000, 598000, 599000, + 560000, 561000, 562000, 563000, 564000, 565000, 566000, 567000, 568000, 569000, + 586000, 587000, 964000, 965000, 988000, 989000, 570000, 571000, 572000, 573000, + 574000, 575000, 576000, 577000, 578000, 579000, 596000, 597000, 974000, 975000, + 998000, 999000, 600000, 601000, 602000, 603000, 604000, 605000, 606000, 607000, + 608000, 609000, 680000, 681000, 806000, 807000, 886000, 887000, 610000, 611000, + 612000, 613000, 614000, 615000, 616000, 617000, 618000, 619000, 690000, 691000, + 816000, 817000, 896000, 897000, 620000, 621000, 622000, 623000, 624000, 625000, + 626000, 627000, 628000, 629000, 682000, 683000, 826000, 827000, 868000, 869000, + 630000, 631000, 632000, 633000, 634000, 635000, 636000, 637000, 638000, 639000, + 692000, 693000, 836000, 837000, 878000, 879000, 640000, 641000, 642000, 643000, + 644000, 645000, 646000, 647000, 648000, 649000, 684000, 685000, 846000, 847000, + 688000, 689000, 650000, 651000, 652000, 653000, 654000, 655000, 656000, 657000, + 658000, 659000, 694000, 695000, 856000, 857000, 698000, 699000, 660000, 661000, + 662000, 663000, 664000, 665000, 666000, 667000, 668000, 669000, 686000, 687000, + 866000, 867000, 888000, 889000, 670000, 671000, 672000, 673000, 674000, 675000, + 676000, 677000, 678000, 679000, 696000, 697000, 876000, 877000, 898000, 899000, + 700000, 701000, 702000, 703000, 704000, 705000, 706000, 707000, 708000, 709000, + 780000, 781000, 906000, 907000, 986000, 987000, 710000, 711000, 712000, 713000, + 714000, 715000, 716000, 717000, 718000, 719000, 790000, 791000, 916000, 917000, + 996000, 997000, 720000, 721000, 722000, 723000, 724000, 725000, 726000, 727000, + 728000, 729000, 782000, 783000, 926000, 927000, 968000, 969000, 730000, 731000, + 732000, 733000, 734000, 735000, 736000, 737000, 738000, 739000, 792000, 793000, + 936000, 937000, 978000, 979000, 740000, 741000, 742000, 743000, 744000, 745000, + 746000, 747000, 748000, 749000, 784000, 785000, 946000, 947000, 788000, 789000, + 750000, 751000, 752000, 753000, 754000, 755000, 756000, 757000, 758000, 759000, + 794000, 795000, 956000, 957000, 798000, 799000, 760000, 761000, 762000, 763000, + 764000, 765000, 766000, 767000, 768000, 769000, 786000, 787000, 966000, 967000, + 988000, 989000, 770000, 771000, 772000, 773000, 774000, 775000, 776000, 777000, + 778000, 779000, 796000, 797000, 976000, 977000, 998000, 999000}; +#endif + +#if defined(DEC_DPD2BINM) && DEC_DPD2BINM==1 && !defined(DECDPD2BINM) +#define DECDPD2BINM + +const uint32_t DPD2BINM[1024]={0, 1000000, 2000000, 3000000, 4000000, + 5000000, 6000000, 7000000, 8000000, 9000000, 80000000, 81000000, + 800000000, 801000000, 880000000, 881000000, 10000000, 11000000, 12000000, + 13000000, 14000000, 15000000, 16000000, 17000000, 18000000, 19000000, + 90000000, 91000000, 810000000, 811000000, 890000000, 891000000, 20000000, + 21000000, 22000000, 23000000, 24000000, 25000000, 26000000, 27000000, + 28000000, 29000000, 82000000, 83000000, 820000000, 821000000, 808000000, + 809000000, 30000000, 31000000, 32000000, 33000000, 34000000, 35000000, + 36000000, 37000000, 38000000, 39000000, 92000000, 93000000, 830000000, + 831000000, 818000000, 819000000, 40000000, 41000000, 42000000, 43000000, + 44000000, 45000000, 46000000, 47000000, 48000000, 49000000, 84000000, + 85000000, 840000000, 841000000, 88000000, 89000000, 50000000, 51000000, + 52000000, 53000000, 54000000, 55000000, 56000000, 57000000, 58000000, + 59000000, 94000000, 95000000, 850000000, 851000000, 98000000, 99000000, + 60000000, 61000000, 62000000, 63000000, 64000000, 65000000, 66000000, + 67000000, 68000000, 69000000, 86000000, 87000000, 860000000, 861000000, + 888000000, 889000000, 70000000, 71000000, 72000000, 73000000, 74000000, + 75000000, 76000000, 77000000, 78000000, 79000000, 96000000, 97000000, + 870000000, 871000000, 898000000, 899000000, 100000000, 101000000, 102000000, + 103000000, 104000000, 105000000, 106000000, 107000000, 108000000, 109000000, + 180000000, 181000000, 900000000, 901000000, 980000000, 981000000, 110000000, + 111000000, 112000000, 113000000, 114000000, 115000000, 116000000, 117000000, + 118000000, 119000000, 190000000, 191000000, 910000000, 911000000, 990000000, + 991000000, 120000000, 121000000, 122000000, 123000000, 124000000, 125000000, + 126000000, 127000000, 128000000, 129000000, 182000000, 183000000, 920000000, + 921000000, 908000000, 909000000, 130000000, 131000000, 132000000, 133000000, + 134000000, 135000000, 136000000, 137000000, 138000000, 139000000, 192000000, + 193000000, 930000000, 931000000, 918000000, 919000000, 140000000, 141000000, + 142000000, 143000000, 144000000, 145000000, 146000000, 147000000, 148000000, + 149000000, 184000000, 185000000, 940000000, 941000000, 188000000, 189000000, + 150000000, 151000000, 152000000, 153000000, 154000000, 155000000, 156000000, + 157000000, 158000000, 159000000, 194000000, 195000000, 950000000, 951000000, + 198000000, 199000000, 160000000, 161000000, 162000000, 163000000, 164000000, + 165000000, 166000000, 167000000, 168000000, 169000000, 186000000, 187000000, + 960000000, 961000000, 988000000, 989000000, 170000000, 171000000, 172000000, + 173000000, 174000000, 175000000, 176000000, 177000000, 178000000, 179000000, + 196000000, 197000000, 970000000, 971000000, 998000000, 999000000, 200000000, + 201000000, 202000000, 203000000, 204000000, 205000000, 206000000, 207000000, + 208000000, 209000000, 280000000, 281000000, 802000000, 803000000, 882000000, + 883000000, 210000000, 211000000, 212000000, 213000000, 214000000, 215000000, + 216000000, 217000000, 218000000, 219000000, 290000000, 291000000, 812000000, + 813000000, 892000000, 893000000, 220000000, 221000000, 222000000, 223000000, + 224000000, 225000000, 226000000, 227000000, 228000000, 229000000, 282000000, + 283000000, 822000000, 823000000, 828000000, 829000000, 230000000, 231000000, + 232000000, 233000000, 234000000, 235000000, 236000000, 237000000, 238000000, + 239000000, 292000000, 293000000, 832000000, 833000000, 838000000, 839000000, + 240000000, 241000000, 242000000, 243000000, 244000000, 245000000, 246000000, + 247000000, 248000000, 249000000, 284000000, 285000000, 842000000, 843000000, + 288000000, 289000000, 250000000, 251000000, 252000000, 253000000, 254000000, + 255000000, 256000000, 257000000, 258000000, 259000000, 294000000, 295000000, + 852000000, 853000000, 298000000, 299000000, 260000000, 261000000, 262000000, + 263000000, 264000000, 265000000, 266000000, 267000000, 268000000, 269000000, + 286000000, 287000000, 862000000, 863000000, 888000000, 889000000, 270000000, + 271000000, 272000000, 273000000, 274000000, 275000000, 276000000, 277000000, + 278000000, 279000000, 296000000, 297000000, 872000000, 873000000, 898000000, + 899000000, 300000000, 301000000, 302000000, 303000000, 304000000, 305000000, + 306000000, 307000000, 308000000, 309000000, 380000000, 381000000, 902000000, + 903000000, 982000000, 983000000, 310000000, 311000000, 312000000, 313000000, + 314000000, 315000000, 316000000, 317000000, 318000000, 319000000, 390000000, + 391000000, 912000000, 913000000, 992000000, 993000000, 320000000, 321000000, + 322000000, 323000000, 324000000, 325000000, 326000000, 327000000, 328000000, + 329000000, 382000000, 383000000, 922000000, 923000000, 928000000, 929000000, + 330000000, 331000000, 332000000, 333000000, 334000000, 335000000, 336000000, + 337000000, 338000000, 339000000, 392000000, 393000000, 932000000, 933000000, + 938000000, 939000000, 340000000, 341000000, 342000000, 343000000, 344000000, + 345000000, 346000000, 347000000, 348000000, 349000000, 384000000, 385000000, + 942000000, 943000000, 388000000, 389000000, 350000000, 351000000, 352000000, + 353000000, 354000000, 355000000, 356000000, 357000000, 358000000, 359000000, + 394000000, 395000000, 952000000, 953000000, 398000000, 399000000, 360000000, + 361000000, 362000000, 363000000, 364000000, 365000000, 366000000, 367000000, + 368000000, 369000000, 386000000, 387000000, 962000000, 963000000, 988000000, + 989000000, 370000000, 371000000, 372000000, 373000000, 374000000, 375000000, + 376000000, 377000000, 378000000, 379000000, 396000000, 397000000, 972000000, + 973000000, 998000000, 999000000, 400000000, 401000000, 402000000, 403000000, + 404000000, 405000000, 406000000, 407000000, 408000000, 409000000, 480000000, + 481000000, 804000000, 805000000, 884000000, 885000000, 410000000, 411000000, + 412000000, 413000000, 414000000, 415000000, 416000000, 417000000, 418000000, + 419000000, 490000000, 491000000, 814000000, 815000000, 894000000, 895000000, + 420000000, 421000000, 422000000, 423000000, 424000000, 425000000, 426000000, + 427000000, 428000000, 429000000, 482000000, 483000000, 824000000, 825000000, + 848000000, 849000000, 430000000, 431000000, 432000000, 433000000, 434000000, + 435000000, 436000000, 437000000, 438000000, 439000000, 492000000, 493000000, + 834000000, 835000000, 858000000, 859000000, 440000000, 441000000, 442000000, + 443000000, 444000000, 445000000, 446000000, 447000000, 448000000, 449000000, + 484000000, 485000000, 844000000, 845000000, 488000000, 489000000, 450000000, + 451000000, 452000000, 453000000, 454000000, 455000000, 456000000, 457000000, + 458000000, 459000000, 494000000, 495000000, 854000000, 855000000, 498000000, + 499000000, 460000000, 461000000, 462000000, 463000000, 464000000, 465000000, + 466000000, 467000000, 468000000, 469000000, 486000000, 487000000, 864000000, + 865000000, 888000000, 889000000, 470000000, 471000000, 472000000, 473000000, + 474000000, 475000000, 476000000, 477000000, 478000000, 479000000, 496000000, + 497000000, 874000000, 875000000, 898000000, 899000000, 500000000, 501000000, + 502000000, 503000000, 504000000, 505000000, 506000000, 507000000, 508000000, + 509000000, 580000000, 581000000, 904000000, 905000000, 984000000, 985000000, + 510000000, 511000000, 512000000, 513000000, 514000000, 515000000, 516000000, + 517000000, 518000000, 519000000, 590000000, 591000000, 914000000, 915000000, + 994000000, 995000000, 520000000, 521000000, 522000000, 523000000, 524000000, + 525000000, 526000000, 527000000, 528000000, 529000000, 582000000, 583000000, + 924000000, 925000000, 948000000, 949000000, 530000000, 531000000, 532000000, + 533000000, 534000000, 535000000, 536000000, 537000000, 538000000, 539000000, + 592000000, 593000000, 934000000, 935000000, 958000000, 959000000, 540000000, + 541000000, 542000000, 543000000, 544000000, 545000000, 546000000, 547000000, + 548000000, 549000000, 584000000, 585000000, 944000000, 945000000, 588000000, + 589000000, 550000000, 551000000, 552000000, 553000000, 554000000, 555000000, + 556000000, 557000000, 558000000, 559000000, 594000000, 595000000, 954000000, + 955000000, 598000000, 599000000, 560000000, 561000000, 562000000, 563000000, + 564000000, 565000000, 566000000, 567000000, 568000000, 569000000, 586000000, + 587000000, 964000000, 965000000, 988000000, 989000000, 570000000, 571000000, + 572000000, 573000000, 574000000, 575000000, 576000000, 577000000, 578000000, + 579000000, 596000000, 597000000, 974000000, 975000000, 998000000, 999000000, + 600000000, 601000000, 602000000, 603000000, 604000000, 605000000, 606000000, + 607000000, 608000000, 609000000, 680000000, 681000000, 806000000, 807000000, + 886000000, 887000000, 610000000, 611000000, 612000000, 613000000, 614000000, + 615000000, 616000000, 617000000, 618000000, 619000000, 690000000, 691000000, + 816000000, 817000000, 896000000, 897000000, 620000000, 621000000, 622000000, + 623000000, 624000000, 625000000, 626000000, 627000000, 628000000, 629000000, + 682000000, 683000000, 826000000, 827000000, 868000000, 869000000, 630000000, + 631000000, 632000000, 633000000, 634000000, 635000000, 636000000, 637000000, + 638000000, 639000000, 692000000, 693000000, 836000000, 837000000, 878000000, + 879000000, 640000000, 641000000, 642000000, 643000000, 644000000, 645000000, + 646000000, 647000000, 648000000, 649000000, 684000000, 685000000, 846000000, + 847000000, 688000000, 689000000, 650000000, 651000000, 652000000, 653000000, + 654000000, 655000000, 656000000, 657000000, 658000000, 659000000, 694000000, + 695000000, 856000000, 857000000, 698000000, 699000000, 660000000, 661000000, + 662000000, 663000000, 664000000, 665000000, 666000000, 667000000, 668000000, + 669000000, 686000000, 687000000, 866000000, 867000000, 888000000, 889000000, + 670000000, 671000000, 672000000, 673000000, 674000000, 675000000, 676000000, + 677000000, 678000000, 679000000, 696000000, 697000000, 876000000, 877000000, + 898000000, 899000000, 700000000, 701000000, 702000000, 703000000, 704000000, + 705000000, 706000000, 707000000, 708000000, 709000000, 780000000, 781000000, + 906000000, 907000000, 986000000, 987000000, 710000000, 711000000, 712000000, + 713000000, 714000000, 715000000, 716000000, 717000000, 718000000, 719000000, + 790000000, 791000000, 916000000, 917000000, 996000000, 997000000, 720000000, + 721000000, 722000000, 723000000, 724000000, 725000000, 726000000, 727000000, + 728000000, 729000000, 782000000, 783000000, 926000000, 927000000, 968000000, + 969000000, 730000000, 731000000, 732000000, 733000000, 734000000, 735000000, + 736000000, 737000000, 738000000, 739000000, 792000000, 793000000, 936000000, + 937000000, 978000000, 979000000, 740000000, 741000000, 742000000, 743000000, + 744000000, 745000000, 746000000, 747000000, 748000000, 749000000, 784000000, + 785000000, 946000000, 947000000, 788000000, 789000000, 750000000, 751000000, + 752000000, 753000000, 754000000, 755000000, 756000000, 757000000, 758000000, + 759000000, 794000000, 795000000, 956000000, 957000000, 798000000, 799000000, + 760000000, 761000000, 762000000, 763000000, 764000000, 765000000, 766000000, + 767000000, 768000000, 769000000, 786000000, 787000000, 966000000, 967000000, + 988000000, 989000000, 770000000, 771000000, 772000000, 773000000, 774000000, + 775000000, 776000000, 777000000, 778000000, 779000000, 796000000, 797000000, + 976000000, 977000000, 998000000, 999000000}; +#endif + +#if defined(DEC_BIN2CHAR) && DEC_BIN2CHAR==1 && !defined(DECBIN2CHAR) +#define DECBIN2CHAR + +const uint8_t BIN2CHAR[4001]={ + '\0','0','0','0', '\1','0','0','1', '\1','0','0','2', '\1','0','0','3', '\1','0','0','4', + '\1','0','0','5', '\1','0','0','6', '\1','0','0','7', '\1','0','0','8', '\1','0','0','9', + '\2','0','1','0', '\2','0','1','1', '\2','0','1','2', '\2','0','1','3', '\2','0','1','4', + '\2','0','1','5', '\2','0','1','6', '\2','0','1','7', '\2','0','1','8', '\2','0','1','9', + '\2','0','2','0', '\2','0','2','1', '\2','0','2','2', '\2','0','2','3', '\2','0','2','4', + '\2','0','2','5', '\2','0','2','6', '\2','0','2','7', '\2','0','2','8', '\2','0','2','9', + '\2','0','3','0', '\2','0','3','1', '\2','0','3','2', '\2','0','3','3', '\2','0','3','4', + '\2','0','3','5', '\2','0','3','6', '\2','0','3','7', '\2','0','3','8', '\2','0','3','9', + '\2','0','4','0', '\2','0','4','1', '\2','0','4','2', '\2','0','4','3', '\2','0','4','4', + '\2','0','4','5', '\2','0','4','6', '\2','0','4','7', '\2','0','4','8', '\2','0','4','9', + '\2','0','5','0', '\2','0','5','1', '\2','0','5','2', '\2','0','5','3', '\2','0','5','4', + '\2','0','5','5', '\2','0','5','6', '\2','0','5','7', '\2','0','5','8', '\2','0','5','9', + '\2','0','6','0', '\2','0','6','1', '\2','0','6','2', '\2','0','6','3', '\2','0','6','4', + '\2','0','6','5', '\2','0','6','6', '\2','0','6','7', '\2','0','6','8', '\2','0','6','9', + '\2','0','7','0', '\2','0','7','1', '\2','0','7','2', '\2','0','7','3', '\2','0','7','4', + '\2','0','7','5', '\2','0','7','6', '\2','0','7','7', '\2','0','7','8', '\2','0','7','9', + '\2','0','8','0', '\2','0','8','1', '\2','0','8','2', '\2','0','8','3', '\2','0','8','4', + '\2','0','8','5', '\2','0','8','6', '\2','0','8','7', '\2','0','8','8', '\2','0','8','9', + '\2','0','9','0', '\2','0','9','1', '\2','0','9','2', '\2','0','9','3', '\2','0','9','4', + '\2','0','9','5', '\2','0','9','6', '\2','0','9','7', '\2','0','9','8', '\2','0','9','9', + '\3','1','0','0', '\3','1','0','1', '\3','1','0','2', '\3','1','0','3', '\3','1','0','4', + '\3','1','0','5', '\3','1','0','6', '\3','1','0','7', '\3','1','0','8', '\3','1','0','9', + '\3','1','1','0', '\3','1','1','1', '\3','1','1','2', '\3','1','1','3', '\3','1','1','4', + '\3','1','1','5', '\3','1','1','6', '\3','1','1','7', '\3','1','1','8', '\3','1','1','9', + '\3','1','2','0', '\3','1','2','1', '\3','1','2','2', '\3','1','2','3', '\3','1','2','4', + '\3','1','2','5', '\3','1','2','6', '\3','1','2','7', '\3','1','2','8', '\3','1','2','9', + '\3','1','3','0', '\3','1','3','1', '\3','1','3','2', '\3','1','3','3', '\3','1','3','4', + '\3','1','3','5', '\3','1','3','6', '\3','1','3','7', '\3','1','3','8', '\3','1','3','9', + '\3','1','4','0', '\3','1','4','1', '\3','1','4','2', '\3','1','4','3', '\3','1','4','4', + '\3','1','4','5', '\3','1','4','6', '\3','1','4','7', '\3','1','4','8', '\3','1','4','9', + '\3','1','5','0', '\3','1','5','1', '\3','1','5','2', '\3','1','5','3', '\3','1','5','4', + '\3','1','5','5', '\3','1','5','6', '\3','1','5','7', '\3','1','5','8', '\3','1','5','9', + '\3','1','6','0', '\3','1','6','1', '\3','1','6','2', '\3','1','6','3', '\3','1','6','4', + '\3','1','6','5', '\3','1','6','6', '\3','1','6','7', '\3','1','6','8', '\3','1','6','9', + '\3','1','7','0', '\3','1','7','1', '\3','1','7','2', '\3','1','7','3', '\3','1','7','4', + '\3','1','7','5', '\3','1','7','6', '\3','1','7','7', '\3','1','7','8', '\3','1','7','9', + '\3','1','8','0', '\3','1','8','1', '\3','1','8','2', '\3','1','8','3', '\3','1','8','4', + '\3','1','8','5', '\3','1','8','6', '\3','1','8','7', '\3','1','8','8', '\3','1','8','9', + '\3','1','9','0', '\3','1','9','1', '\3','1','9','2', '\3','1','9','3', '\3','1','9','4', + '\3','1','9','5', '\3','1','9','6', '\3','1','9','7', '\3','1','9','8', '\3','1','9','9', + '\3','2','0','0', '\3','2','0','1', '\3','2','0','2', '\3','2','0','3', '\3','2','0','4', + '\3','2','0','5', '\3','2','0','6', '\3','2','0','7', '\3','2','0','8', '\3','2','0','9', + '\3','2','1','0', '\3','2','1','1', '\3','2','1','2', '\3','2','1','3', '\3','2','1','4', + '\3','2','1','5', '\3','2','1','6', '\3','2','1','7', '\3','2','1','8', '\3','2','1','9', + '\3','2','2','0', '\3','2','2','1', '\3','2','2','2', '\3','2','2','3', '\3','2','2','4', + '\3','2','2','5', '\3','2','2','6', '\3','2','2','7', '\3','2','2','8', '\3','2','2','9', + '\3','2','3','0', '\3','2','3','1', '\3','2','3','2', '\3','2','3','3', '\3','2','3','4', + '\3','2','3','5', '\3','2','3','6', '\3','2','3','7', '\3','2','3','8', '\3','2','3','9', + '\3','2','4','0', '\3','2','4','1', '\3','2','4','2', '\3','2','4','3', '\3','2','4','4', + '\3','2','4','5', '\3','2','4','6', '\3','2','4','7', '\3','2','4','8', '\3','2','4','9', + '\3','2','5','0', '\3','2','5','1', '\3','2','5','2', '\3','2','5','3', '\3','2','5','4', + '\3','2','5','5', '\3','2','5','6', '\3','2','5','7', '\3','2','5','8', '\3','2','5','9', + '\3','2','6','0', '\3','2','6','1', '\3','2','6','2', '\3','2','6','3', '\3','2','6','4', + '\3','2','6','5', '\3','2','6','6', '\3','2','6','7', '\3','2','6','8', '\3','2','6','9', + '\3','2','7','0', '\3','2','7','1', '\3','2','7','2', '\3','2','7','3', '\3','2','7','4', + '\3','2','7','5', '\3','2','7','6', '\3','2','7','7', '\3','2','7','8', '\3','2','7','9', + '\3','2','8','0', '\3','2','8','1', '\3','2','8','2', '\3','2','8','3', '\3','2','8','4', + '\3','2','8','5', '\3','2','8','6', '\3','2','8','7', '\3','2','8','8', '\3','2','8','9', + '\3','2','9','0', '\3','2','9','1', '\3','2','9','2', '\3','2','9','3', '\3','2','9','4', + '\3','2','9','5', '\3','2','9','6', '\3','2','9','7', '\3','2','9','8', '\3','2','9','9', + '\3','3','0','0', '\3','3','0','1', '\3','3','0','2', '\3','3','0','3', '\3','3','0','4', + '\3','3','0','5', '\3','3','0','6', '\3','3','0','7', '\3','3','0','8', '\3','3','0','9', + '\3','3','1','0', '\3','3','1','1', '\3','3','1','2', '\3','3','1','3', '\3','3','1','4', + '\3','3','1','5', '\3','3','1','6', '\3','3','1','7', '\3','3','1','8', '\3','3','1','9', + '\3','3','2','0', '\3','3','2','1', '\3','3','2','2', '\3','3','2','3', '\3','3','2','4', + '\3','3','2','5', '\3','3','2','6', '\3','3','2','7', '\3','3','2','8', '\3','3','2','9', + '\3','3','3','0', '\3','3','3','1', '\3','3','3','2', '\3','3','3','3', '\3','3','3','4', + '\3','3','3','5', '\3','3','3','6', '\3','3','3','7', '\3','3','3','8', '\3','3','3','9', + '\3','3','4','0', '\3','3','4','1', '\3','3','4','2', '\3','3','4','3', '\3','3','4','4', + '\3','3','4','5', '\3','3','4','6', '\3','3','4','7', '\3','3','4','8', '\3','3','4','9', + '\3','3','5','0', '\3','3','5','1', '\3','3','5','2', '\3','3','5','3', '\3','3','5','4', + '\3','3','5','5', '\3','3','5','6', '\3','3','5','7', '\3','3','5','8', '\3','3','5','9', + '\3','3','6','0', '\3','3','6','1', '\3','3','6','2', '\3','3','6','3', '\3','3','6','4', + '\3','3','6','5', '\3','3','6','6', '\3','3','6','7', '\3','3','6','8', '\3','3','6','9', + '\3','3','7','0', '\3','3','7','1', '\3','3','7','2', '\3','3','7','3', '\3','3','7','4', + '\3','3','7','5', '\3','3','7','6', '\3','3','7','7', '\3','3','7','8', '\3','3','7','9', + '\3','3','8','0', '\3','3','8','1', '\3','3','8','2', '\3','3','8','3', '\3','3','8','4', + '\3','3','8','5', '\3','3','8','6', '\3','3','8','7', '\3','3','8','8', '\3','3','8','9', + '\3','3','9','0', '\3','3','9','1', '\3','3','9','2', '\3','3','9','3', '\3','3','9','4', + '\3','3','9','5', '\3','3','9','6', '\3','3','9','7', '\3','3','9','8', '\3','3','9','9', + '\3','4','0','0', '\3','4','0','1', '\3','4','0','2', '\3','4','0','3', '\3','4','0','4', + '\3','4','0','5', '\3','4','0','6', '\3','4','0','7', '\3','4','0','8', '\3','4','0','9', + '\3','4','1','0', '\3','4','1','1', '\3','4','1','2', '\3','4','1','3', '\3','4','1','4', + '\3','4','1','5', '\3','4','1','6', '\3','4','1','7', '\3','4','1','8', '\3','4','1','9', + '\3','4','2','0', '\3','4','2','1', '\3','4','2','2', '\3','4','2','3', '\3','4','2','4', + '\3','4','2','5', '\3','4','2','6', '\3','4','2','7', '\3','4','2','8', '\3','4','2','9', + '\3','4','3','0', '\3','4','3','1', '\3','4','3','2', '\3','4','3','3', '\3','4','3','4', + '\3','4','3','5', '\3','4','3','6', '\3','4','3','7', '\3','4','3','8', '\3','4','3','9', + '\3','4','4','0', '\3','4','4','1', '\3','4','4','2', '\3','4','4','3', '\3','4','4','4', + '\3','4','4','5', '\3','4','4','6', '\3','4','4','7', '\3','4','4','8', '\3','4','4','9', + '\3','4','5','0', '\3','4','5','1', '\3','4','5','2', '\3','4','5','3', '\3','4','5','4', + '\3','4','5','5', '\3','4','5','6', '\3','4','5','7', '\3','4','5','8', '\3','4','5','9', + '\3','4','6','0', '\3','4','6','1', '\3','4','6','2', '\3','4','6','3', '\3','4','6','4', + '\3','4','6','5', '\3','4','6','6', '\3','4','6','7', '\3','4','6','8', '\3','4','6','9', + '\3','4','7','0', '\3','4','7','1', '\3','4','7','2', '\3','4','7','3', '\3','4','7','4', + '\3','4','7','5', '\3','4','7','6', '\3','4','7','7', '\3','4','7','8', '\3','4','7','9', + '\3','4','8','0', '\3','4','8','1', '\3','4','8','2', '\3','4','8','3', '\3','4','8','4', + '\3','4','8','5', '\3','4','8','6', '\3','4','8','7', '\3','4','8','8', '\3','4','8','9', + '\3','4','9','0', '\3','4','9','1', '\3','4','9','2', '\3','4','9','3', '\3','4','9','4', + '\3','4','9','5', '\3','4','9','6', '\3','4','9','7', '\3','4','9','8', '\3','4','9','9', + '\3','5','0','0', '\3','5','0','1', '\3','5','0','2', '\3','5','0','3', '\3','5','0','4', + '\3','5','0','5', '\3','5','0','6', '\3','5','0','7', '\3','5','0','8', '\3','5','0','9', + '\3','5','1','0', '\3','5','1','1', '\3','5','1','2', '\3','5','1','3', '\3','5','1','4', + '\3','5','1','5', '\3','5','1','6', '\3','5','1','7', '\3','5','1','8', '\3','5','1','9', + '\3','5','2','0', '\3','5','2','1', '\3','5','2','2', '\3','5','2','3', '\3','5','2','4', + '\3','5','2','5', '\3','5','2','6', '\3','5','2','7', '\3','5','2','8', '\3','5','2','9', + '\3','5','3','0', '\3','5','3','1', '\3','5','3','2', '\3','5','3','3', '\3','5','3','4', + '\3','5','3','5', '\3','5','3','6', '\3','5','3','7', '\3','5','3','8', '\3','5','3','9', + '\3','5','4','0', '\3','5','4','1', '\3','5','4','2', '\3','5','4','3', '\3','5','4','4', + '\3','5','4','5', '\3','5','4','6', '\3','5','4','7', '\3','5','4','8', '\3','5','4','9', + '\3','5','5','0', '\3','5','5','1', '\3','5','5','2', '\3','5','5','3', '\3','5','5','4', + '\3','5','5','5', '\3','5','5','6', '\3','5','5','7', '\3','5','5','8', '\3','5','5','9', + '\3','5','6','0', '\3','5','6','1', '\3','5','6','2', '\3','5','6','3', '\3','5','6','4', + '\3','5','6','5', '\3','5','6','6', '\3','5','6','7', '\3','5','6','8', '\3','5','6','9', + '\3','5','7','0', '\3','5','7','1', '\3','5','7','2', '\3','5','7','3', '\3','5','7','4', + '\3','5','7','5', '\3','5','7','6', '\3','5','7','7', '\3','5','7','8', '\3','5','7','9', + '\3','5','8','0', '\3','5','8','1', '\3','5','8','2', '\3','5','8','3', '\3','5','8','4', + '\3','5','8','5', '\3','5','8','6', '\3','5','8','7', '\3','5','8','8', '\3','5','8','9', + '\3','5','9','0', '\3','5','9','1', '\3','5','9','2', '\3','5','9','3', '\3','5','9','4', + '\3','5','9','5', '\3','5','9','6', '\3','5','9','7', '\3','5','9','8', '\3','5','9','9', + '\3','6','0','0', '\3','6','0','1', '\3','6','0','2', '\3','6','0','3', '\3','6','0','4', + '\3','6','0','5', '\3','6','0','6', '\3','6','0','7', '\3','6','0','8', '\3','6','0','9', + '\3','6','1','0', '\3','6','1','1', '\3','6','1','2', '\3','6','1','3', '\3','6','1','4', + '\3','6','1','5', '\3','6','1','6', '\3','6','1','7', '\3','6','1','8', '\3','6','1','9', + '\3','6','2','0', '\3','6','2','1', '\3','6','2','2', '\3','6','2','3', '\3','6','2','4', + '\3','6','2','5', '\3','6','2','6', '\3','6','2','7', '\3','6','2','8', '\3','6','2','9', + '\3','6','3','0', '\3','6','3','1', '\3','6','3','2', '\3','6','3','3', '\3','6','3','4', + '\3','6','3','5', '\3','6','3','6', '\3','6','3','7', '\3','6','3','8', '\3','6','3','9', + '\3','6','4','0', '\3','6','4','1', '\3','6','4','2', '\3','6','4','3', '\3','6','4','4', + '\3','6','4','5', '\3','6','4','6', '\3','6','4','7', '\3','6','4','8', '\3','6','4','9', + '\3','6','5','0', '\3','6','5','1', '\3','6','5','2', '\3','6','5','3', '\3','6','5','4', + '\3','6','5','5', '\3','6','5','6', '\3','6','5','7', '\3','6','5','8', '\3','6','5','9', + '\3','6','6','0', '\3','6','6','1', '\3','6','6','2', '\3','6','6','3', '\3','6','6','4', + '\3','6','6','5', '\3','6','6','6', '\3','6','6','7', '\3','6','6','8', '\3','6','6','9', + '\3','6','7','0', '\3','6','7','1', '\3','6','7','2', '\3','6','7','3', '\3','6','7','4', + '\3','6','7','5', '\3','6','7','6', '\3','6','7','7', '\3','6','7','8', '\3','6','7','9', + '\3','6','8','0', '\3','6','8','1', '\3','6','8','2', '\3','6','8','3', '\3','6','8','4', + '\3','6','8','5', '\3','6','8','6', '\3','6','8','7', '\3','6','8','8', '\3','6','8','9', + '\3','6','9','0', '\3','6','9','1', '\3','6','9','2', '\3','6','9','3', '\3','6','9','4', + '\3','6','9','5', '\3','6','9','6', '\3','6','9','7', '\3','6','9','8', '\3','6','9','9', + '\3','7','0','0', '\3','7','0','1', '\3','7','0','2', '\3','7','0','3', '\3','7','0','4', + '\3','7','0','5', '\3','7','0','6', '\3','7','0','7', '\3','7','0','8', '\3','7','0','9', + '\3','7','1','0', '\3','7','1','1', '\3','7','1','2', '\3','7','1','3', '\3','7','1','4', + '\3','7','1','5', '\3','7','1','6', '\3','7','1','7', '\3','7','1','8', '\3','7','1','9', + '\3','7','2','0', '\3','7','2','1', '\3','7','2','2', '\3','7','2','3', '\3','7','2','4', + '\3','7','2','5', '\3','7','2','6', '\3','7','2','7', '\3','7','2','8', '\3','7','2','9', + '\3','7','3','0', '\3','7','3','1', '\3','7','3','2', '\3','7','3','3', '\3','7','3','4', + '\3','7','3','5', '\3','7','3','6', '\3','7','3','7', '\3','7','3','8', '\3','7','3','9', + '\3','7','4','0', '\3','7','4','1', '\3','7','4','2', '\3','7','4','3', '\3','7','4','4', + '\3','7','4','5', '\3','7','4','6', '\3','7','4','7', '\3','7','4','8', '\3','7','4','9', + '\3','7','5','0', '\3','7','5','1', '\3','7','5','2', '\3','7','5','3', '\3','7','5','4', + '\3','7','5','5', '\3','7','5','6', '\3','7','5','7', '\3','7','5','8', '\3','7','5','9', + '\3','7','6','0', '\3','7','6','1', '\3','7','6','2', '\3','7','6','3', '\3','7','6','4', + '\3','7','6','5', '\3','7','6','6', '\3','7','6','7', '\3','7','6','8', '\3','7','6','9', + '\3','7','7','0', '\3','7','7','1', '\3','7','7','2', '\3','7','7','3', '\3','7','7','4', + '\3','7','7','5', '\3','7','7','6', '\3','7','7','7', '\3','7','7','8', '\3','7','7','9', + '\3','7','8','0', '\3','7','8','1', '\3','7','8','2', '\3','7','8','3', '\3','7','8','4', + '\3','7','8','5', '\3','7','8','6', '\3','7','8','7', '\3','7','8','8', '\3','7','8','9', + '\3','7','9','0', '\3','7','9','1', '\3','7','9','2', '\3','7','9','3', '\3','7','9','4', + '\3','7','9','5', '\3','7','9','6', '\3','7','9','7', '\3','7','9','8', '\3','7','9','9', + '\3','8','0','0', '\3','8','0','1', '\3','8','0','2', '\3','8','0','3', '\3','8','0','4', + '\3','8','0','5', '\3','8','0','6', '\3','8','0','7', '\3','8','0','8', '\3','8','0','9', + '\3','8','1','0', '\3','8','1','1', '\3','8','1','2', '\3','8','1','3', '\3','8','1','4', + '\3','8','1','5', '\3','8','1','6', '\3','8','1','7', '\3','8','1','8', '\3','8','1','9', + '\3','8','2','0', '\3','8','2','1', '\3','8','2','2', '\3','8','2','3', '\3','8','2','4', + '\3','8','2','5', '\3','8','2','6', '\3','8','2','7', '\3','8','2','8', '\3','8','2','9', + '\3','8','3','0', '\3','8','3','1', '\3','8','3','2', '\3','8','3','3', '\3','8','3','4', + '\3','8','3','5', '\3','8','3','6', '\3','8','3','7', '\3','8','3','8', '\3','8','3','9', + '\3','8','4','0', '\3','8','4','1', '\3','8','4','2', '\3','8','4','3', '\3','8','4','4', + '\3','8','4','5', '\3','8','4','6', '\3','8','4','7', '\3','8','4','8', '\3','8','4','9', + '\3','8','5','0', '\3','8','5','1', '\3','8','5','2', '\3','8','5','3', '\3','8','5','4', + '\3','8','5','5', '\3','8','5','6', '\3','8','5','7', '\3','8','5','8', '\3','8','5','9', + '\3','8','6','0', '\3','8','6','1', '\3','8','6','2', '\3','8','6','3', '\3','8','6','4', + '\3','8','6','5', '\3','8','6','6', '\3','8','6','7', '\3','8','6','8', '\3','8','6','9', + '\3','8','7','0', '\3','8','7','1', '\3','8','7','2', '\3','8','7','3', '\3','8','7','4', + '\3','8','7','5', '\3','8','7','6', '\3','8','7','7', '\3','8','7','8', '\3','8','7','9', + '\3','8','8','0', '\3','8','8','1', '\3','8','8','2', '\3','8','8','3', '\3','8','8','4', + '\3','8','8','5', '\3','8','8','6', '\3','8','8','7', '\3','8','8','8', '\3','8','8','9', + '\3','8','9','0', '\3','8','9','1', '\3','8','9','2', '\3','8','9','3', '\3','8','9','4', + '\3','8','9','5', '\3','8','9','6', '\3','8','9','7', '\3','8','9','8', '\3','8','9','9', + '\3','9','0','0', '\3','9','0','1', '\3','9','0','2', '\3','9','0','3', '\3','9','0','4', + '\3','9','0','5', '\3','9','0','6', '\3','9','0','7', '\3','9','0','8', '\3','9','0','9', + '\3','9','1','0', '\3','9','1','1', '\3','9','1','2', '\3','9','1','3', '\3','9','1','4', + '\3','9','1','5', '\3','9','1','6', '\3','9','1','7', '\3','9','1','8', '\3','9','1','9', + '\3','9','2','0', '\3','9','2','1', '\3','9','2','2', '\3','9','2','3', '\3','9','2','4', + '\3','9','2','5', '\3','9','2','6', '\3','9','2','7', '\3','9','2','8', '\3','9','2','9', + '\3','9','3','0', '\3','9','3','1', '\3','9','3','2', '\3','9','3','3', '\3','9','3','4', + '\3','9','3','5', '\3','9','3','6', '\3','9','3','7', '\3','9','3','8', '\3','9','3','9', + '\3','9','4','0', '\3','9','4','1', '\3','9','4','2', '\3','9','4','3', '\3','9','4','4', + '\3','9','4','5', '\3','9','4','6', '\3','9','4','7', '\3','9','4','8', '\3','9','4','9', + '\3','9','5','0', '\3','9','5','1', '\3','9','5','2', '\3','9','5','3', '\3','9','5','4', + '\3','9','5','5', '\3','9','5','6', '\3','9','5','7', '\3','9','5','8', '\3','9','5','9', + '\3','9','6','0', '\3','9','6','1', '\3','9','6','2', '\3','9','6','3', '\3','9','6','4', + '\3','9','6','5', '\3','9','6','6', '\3','9','6','7', '\3','9','6','8', '\3','9','6','9', + '\3','9','7','0', '\3','9','7','1', '\3','9','7','2', '\3','9','7','3', '\3','9','7','4', + '\3','9','7','5', '\3','9','7','6', '\3','9','7','7', '\3','9','7','8', '\3','9','7','9', + '\3','9','8','0', '\3','9','8','1', '\3','9','8','2', '\3','9','8','3', '\3','9','8','4', + '\3','9','8','5', '\3','9','8','6', '\3','9','8','7', '\3','9','8','8', '\3','9','8','9', + '\3','9','9','0', '\3','9','9','1', '\3','9','9','2', '\3','9','9','3', '\3','9','9','4', + '\3','9','9','5', '\3','9','9','6', '\3','9','9','7', '\3','9','9','8', '\3','9','9','9', '\0'}; +#endif + +#if defined(DEC_DPD2BCD8) && DEC_DPD2BCD8==1 && !defined(DECDPD2BCD8) +#define DECDPD2BCD8 + +const uint8_t DPD2BCD8[4096]={ + 0,0,0,0, 0,0,1,1, 0,0,2,1, 0,0,3,1, 0,0,4,1, 0,0,5,1, 0,0,6,1, 0,0,7,1, 0,0,8,1, + 0,0,9,1, 0,8,0,2, 0,8,1,2, 8,0,0,3, 8,0,1,3, 8,8,0,3, 8,8,1,3, 0,1,0,2, 0,1,1,2, + 0,1,2,2, 0,1,3,2, 0,1,4,2, 0,1,5,2, 0,1,6,2, 0,1,7,2, 0,1,8,2, 0,1,9,2, 0,9,0,2, + 0,9,1,2, 8,1,0,3, 8,1,1,3, 8,9,0,3, 8,9,1,3, 0,2,0,2, 0,2,1,2, 0,2,2,2, 0,2,3,2, + 0,2,4,2, 0,2,5,2, 0,2,6,2, 0,2,7,2, 0,2,8,2, 0,2,9,2, 0,8,2,2, 0,8,3,2, 8,2,0,3, + 8,2,1,3, 8,0,8,3, 8,0,9,3, 0,3,0,2, 0,3,1,2, 0,3,2,2, 0,3,3,2, 0,3,4,2, 0,3,5,2, + 0,3,6,2, 0,3,7,2, 0,3,8,2, 0,3,9,2, 0,9,2,2, 0,9,3,2, 8,3,0,3, 8,3,1,3, 8,1,8,3, + 8,1,9,3, 0,4,0,2, 0,4,1,2, 0,4,2,2, 0,4,3,2, 0,4,4,2, 0,4,5,2, 0,4,6,2, 0,4,7,2, + 0,4,8,2, 0,4,9,2, 0,8,4,2, 0,8,5,2, 8,4,0,3, 8,4,1,3, 0,8,8,2, 0,8,9,2, 0,5,0,2, + 0,5,1,2, 0,5,2,2, 0,5,3,2, 0,5,4,2, 0,5,5,2, 0,5,6,2, 0,5,7,2, 0,5,8,2, 0,5,9,2, + 0,9,4,2, 0,9,5,2, 8,5,0,3, 8,5,1,3, 0,9,8,2, 0,9,9,2, 0,6,0,2, 0,6,1,2, 0,6,2,2, + 0,6,3,2, 0,6,4,2, 0,6,5,2, 0,6,6,2, 0,6,7,2, 0,6,8,2, 0,6,9,2, 0,8,6,2, 0,8,7,2, + 8,6,0,3, 8,6,1,3, 8,8,8,3, 8,8,9,3, 0,7,0,2, 0,7,1,2, 0,7,2,2, 0,7,3,2, 0,7,4,2, + 0,7,5,2, 0,7,6,2, 0,7,7,2, 0,7,8,2, 0,7,9,2, 0,9,6,2, 0,9,7,2, 8,7,0,3, 8,7,1,3, + 8,9,8,3, 8,9,9,3, 1,0,0,3, 1,0,1,3, 1,0,2,3, 1,0,3,3, 1,0,4,3, 1,0,5,3, 1,0,6,3, + 1,0,7,3, 1,0,8,3, 1,0,9,3, 1,8,0,3, 1,8,1,3, 9,0,0,3, 9,0,1,3, 9,8,0,3, 9,8,1,3, + 1,1,0,3, 1,1,1,3, 1,1,2,3, 1,1,3,3, 1,1,4,3, 1,1,5,3, 1,1,6,3, 1,1,7,3, 1,1,8,3, + 1,1,9,3, 1,9,0,3, 1,9,1,3, 9,1,0,3, 9,1,1,3, 9,9,0,3, 9,9,1,3, 1,2,0,3, 1,2,1,3, + 1,2,2,3, 1,2,3,3, 1,2,4,3, 1,2,5,3, 1,2,6,3, 1,2,7,3, 1,2,8,3, 1,2,9,3, 1,8,2,3, + 1,8,3,3, 9,2,0,3, 9,2,1,3, 9,0,8,3, 9,0,9,3, 1,3,0,3, 1,3,1,3, 1,3,2,3, 1,3,3,3, + 1,3,4,3, 1,3,5,3, 1,3,6,3, 1,3,7,3, 1,3,8,3, 1,3,9,3, 1,9,2,3, 1,9,3,3, 9,3,0,3, + 9,3,1,3, 9,1,8,3, 9,1,9,3, 1,4,0,3, 1,4,1,3, 1,4,2,3, 1,4,3,3, 1,4,4,3, 1,4,5,3, + 1,4,6,3, 1,4,7,3, 1,4,8,3, 1,4,9,3, 1,8,4,3, 1,8,5,3, 9,4,0,3, 9,4,1,3, 1,8,8,3, + 1,8,9,3, 1,5,0,3, 1,5,1,3, 1,5,2,3, 1,5,3,3, 1,5,4,3, 1,5,5,3, 1,5,6,3, 1,5,7,3, + 1,5,8,3, 1,5,9,3, 1,9,4,3, 1,9,5,3, 9,5,0,3, 9,5,1,3, 1,9,8,3, 1,9,9,3, 1,6,0,3, + 1,6,1,3, 1,6,2,3, 1,6,3,3, 1,6,4,3, 1,6,5,3, 1,6,6,3, 1,6,7,3, 1,6,8,3, 1,6,9,3, + 1,8,6,3, 1,8,7,3, 9,6,0,3, 9,6,1,3, 9,8,8,3, 9,8,9,3, 1,7,0,3, 1,7,1,3, 1,7,2,3, + 1,7,3,3, 1,7,4,3, 1,7,5,3, 1,7,6,3, 1,7,7,3, 1,7,8,3, 1,7,9,3, 1,9,6,3, 1,9,7,3, + 9,7,0,3, 9,7,1,3, 9,9,8,3, 9,9,9,3, 2,0,0,3, 2,0,1,3, 2,0,2,3, 2,0,3,3, 2,0,4,3, + 2,0,5,3, 2,0,6,3, 2,0,7,3, 2,0,8,3, 2,0,9,3, 2,8,0,3, 2,8,1,3, 8,0,2,3, 8,0,3,3, + 8,8,2,3, 8,8,3,3, 2,1,0,3, 2,1,1,3, 2,1,2,3, 2,1,3,3, 2,1,4,3, 2,1,5,3, 2,1,6,3, + 2,1,7,3, 2,1,8,3, 2,1,9,3, 2,9,0,3, 2,9,1,3, 8,1,2,3, 8,1,3,3, 8,9,2,3, 8,9,3,3, + 2,2,0,3, 2,2,1,3, 2,2,2,3, 2,2,3,3, 2,2,4,3, 2,2,5,3, 2,2,6,3, 2,2,7,3, 2,2,8,3, + 2,2,9,3, 2,8,2,3, 2,8,3,3, 8,2,2,3, 8,2,3,3, 8,2,8,3, 8,2,9,3, 2,3,0,3, 2,3,1,3, + 2,3,2,3, 2,3,3,3, 2,3,4,3, 2,3,5,3, 2,3,6,3, 2,3,7,3, 2,3,8,3, 2,3,9,3, 2,9,2,3, + 2,9,3,3, 8,3,2,3, 8,3,3,3, 8,3,8,3, 8,3,9,3, 2,4,0,3, 2,4,1,3, 2,4,2,3, 2,4,3,3, + 2,4,4,3, 2,4,5,3, 2,4,6,3, 2,4,7,3, 2,4,8,3, 2,4,9,3, 2,8,4,3, 2,8,5,3, 8,4,2,3, + 8,4,3,3, 2,8,8,3, 2,8,9,3, 2,5,0,3, 2,5,1,3, 2,5,2,3, 2,5,3,3, 2,5,4,3, 2,5,5,3, + 2,5,6,3, 2,5,7,3, 2,5,8,3, 2,5,9,3, 2,9,4,3, 2,9,5,3, 8,5,2,3, 8,5,3,3, 2,9,8,3, + 2,9,9,3, 2,6,0,3, 2,6,1,3, 2,6,2,3, 2,6,3,3, 2,6,4,3, 2,6,5,3, 2,6,6,3, 2,6,7,3, + 2,6,8,3, 2,6,9,3, 2,8,6,3, 2,8,7,3, 8,6,2,3, 8,6,3,3, 8,8,8,3, 8,8,9,3, 2,7,0,3, + 2,7,1,3, 2,7,2,3, 2,7,3,3, 2,7,4,3, 2,7,5,3, 2,7,6,3, 2,7,7,3, 2,7,8,3, 2,7,9,3, + 2,9,6,3, 2,9,7,3, 8,7,2,3, 8,7,3,3, 8,9,8,3, 8,9,9,3, 3,0,0,3, 3,0,1,3, 3,0,2,3, + 3,0,3,3, 3,0,4,3, 3,0,5,3, 3,0,6,3, 3,0,7,3, 3,0,8,3, 3,0,9,3, 3,8,0,3, 3,8,1,3, + 9,0,2,3, 9,0,3,3, 9,8,2,3, 9,8,3,3, 3,1,0,3, 3,1,1,3, 3,1,2,3, 3,1,3,3, 3,1,4,3, + 3,1,5,3, 3,1,6,3, 3,1,7,3, 3,1,8,3, 3,1,9,3, 3,9,0,3, 3,9,1,3, 9,1,2,3, 9,1,3,3, + 9,9,2,3, 9,9,3,3, 3,2,0,3, 3,2,1,3, 3,2,2,3, 3,2,3,3, 3,2,4,3, 3,2,5,3, 3,2,6,3, + 3,2,7,3, 3,2,8,3, 3,2,9,3, 3,8,2,3, 3,8,3,3, 9,2,2,3, 9,2,3,3, 9,2,8,3, 9,2,9,3, + 3,3,0,3, 3,3,1,3, 3,3,2,3, 3,3,3,3, 3,3,4,3, 3,3,5,3, 3,3,6,3, 3,3,7,3, 3,3,8,3, + 3,3,9,3, 3,9,2,3, 3,9,3,3, 9,3,2,3, 9,3,3,3, 9,3,8,3, 9,3,9,3, 3,4,0,3, 3,4,1,3, + 3,4,2,3, 3,4,3,3, 3,4,4,3, 3,4,5,3, 3,4,6,3, 3,4,7,3, 3,4,8,3, 3,4,9,3, 3,8,4,3, + 3,8,5,3, 9,4,2,3, 9,4,3,3, 3,8,8,3, 3,8,9,3, 3,5,0,3, 3,5,1,3, 3,5,2,3, 3,5,3,3, + 3,5,4,3, 3,5,5,3, 3,5,6,3, 3,5,7,3, 3,5,8,3, 3,5,9,3, 3,9,4,3, 3,9,5,3, 9,5,2,3, + 9,5,3,3, 3,9,8,3, 3,9,9,3, 3,6,0,3, 3,6,1,3, 3,6,2,3, 3,6,3,3, 3,6,4,3, 3,6,5,3, + 3,6,6,3, 3,6,7,3, 3,6,8,3, 3,6,9,3, 3,8,6,3, 3,8,7,3, 9,6,2,3, 9,6,3,3, 9,8,8,3, + 9,8,9,3, 3,7,0,3, 3,7,1,3, 3,7,2,3, 3,7,3,3, 3,7,4,3, 3,7,5,3, 3,7,6,3, 3,7,7,3, + 3,7,8,3, 3,7,9,3, 3,9,6,3, 3,9,7,3, 9,7,2,3, 9,7,3,3, 9,9,8,3, 9,9,9,3, 4,0,0,3, + 4,0,1,3, 4,0,2,3, 4,0,3,3, 4,0,4,3, 4,0,5,3, 4,0,6,3, 4,0,7,3, 4,0,8,3, 4,0,9,3, + 4,8,0,3, 4,8,1,3, 8,0,4,3, 8,0,5,3, 8,8,4,3, 8,8,5,3, 4,1,0,3, 4,1,1,3, 4,1,2,3, + 4,1,3,3, 4,1,4,3, 4,1,5,3, 4,1,6,3, 4,1,7,3, 4,1,8,3, 4,1,9,3, 4,9,0,3, 4,9,1,3, + 8,1,4,3, 8,1,5,3, 8,9,4,3, 8,9,5,3, 4,2,0,3, 4,2,1,3, 4,2,2,3, 4,2,3,3, 4,2,4,3, + 4,2,5,3, 4,2,6,3, 4,2,7,3, 4,2,8,3, 4,2,9,3, 4,8,2,3, 4,8,3,3, 8,2,4,3, 8,2,5,3, + 8,4,8,3, 8,4,9,3, 4,3,0,3, 4,3,1,3, 4,3,2,3, 4,3,3,3, 4,3,4,3, 4,3,5,3, 4,3,6,3, + 4,3,7,3, 4,3,8,3, 4,3,9,3, 4,9,2,3, 4,9,3,3, 8,3,4,3, 8,3,5,3, 8,5,8,3, 8,5,9,3, + 4,4,0,3, 4,4,1,3, 4,4,2,3, 4,4,3,3, 4,4,4,3, 4,4,5,3, 4,4,6,3, 4,4,7,3, 4,4,8,3, + 4,4,9,3, 4,8,4,3, 4,8,5,3, 8,4,4,3, 8,4,5,3, 4,8,8,3, 4,8,9,3, 4,5,0,3, 4,5,1,3, + 4,5,2,3, 4,5,3,3, 4,5,4,3, 4,5,5,3, 4,5,6,3, 4,5,7,3, 4,5,8,3, 4,5,9,3, 4,9,4,3, + 4,9,5,3, 8,5,4,3, 8,5,5,3, 4,9,8,3, 4,9,9,3, 4,6,0,3, 4,6,1,3, 4,6,2,3, 4,6,3,3, + 4,6,4,3, 4,6,5,3, 4,6,6,3, 4,6,7,3, 4,6,8,3, 4,6,9,3, 4,8,6,3, 4,8,7,3, 8,6,4,3, + 8,6,5,3, 8,8,8,3, 8,8,9,3, 4,7,0,3, 4,7,1,3, 4,7,2,3, 4,7,3,3, 4,7,4,3, 4,7,5,3, + 4,7,6,3, 4,7,7,3, 4,7,8,3, 4,7,9,3, 4,9,6,3, 4,9,7,3, 8,7,4,3, 8,7,5,3, 8,9,8,3, + 8,9,9,3, 5,0,0,3, 5,0,1,3, 5,0,2,3, 5,0,3,3, 5,0,4,3, 5,0,5,3, 5,0,6,3, 5,0,7,3, + 5,0,8,3, 5,0,9,3, 5,8,0,3, 5,8,1,3, 9,0,4,3, 9,0,5,3, 9,8,4,3, 9,8,5,3, 5,1,0,3, + 5,1,1,3, 5,1,2,3, 5,1,3,3, 5,1,4,3, 5,1,5,3, 5,1,6,3, 5,1,7,3, 5,1,8,3, 5,1,9,3, + 5,9,0,3, 5,9,1,3, 9,1,4,3, 9,1,5,3, 9,9,4,3, 9,9,5,3, 5,2,0,3, 5,2,1,3, 5,2,2,3, + 5,2,3,3, 5,2,4,3, 5,2,5,3, 5,2,6,3, 5,2,7,3, 5,2,8,3, 5,2,9,3, 5,8,2,3, 5,8,3,3, + 9,2,4,3, 9,2,5,3, 9,4,8,3, 9,4,9,3, 5,3,0,3, 5,3,1,3, 5,3,2,3, 5,3,3,3, 5,3,4,3, + 5,3,5,3, 5,3,6,3, 5,3,7,3, 5,3,8,3, 5,3,9,3, 5,9,2,3, 5,9,3,3, 9,3,4,3, 9,3,5,3, + 9,5,8,3, 9,5,9,3, 5,4,0,3, 5,4,1,3, 5,4,2,3, 5,4,3,3, 5,4,4,3, 5,4,5,3, 5,4,6,3, + 5,4,7,3, 5,4,8,3, 5,4,9,3, 5,8,4,3, 5,8,5,3, 9,4,4,3, 9,4,5,3, 5,8,8,3, 5,8,9,3, + 5,5,0,3, 5,5,1,3, 5,5,2,3, 5,5,3,3, 5,5,4,3, 5,5,5,3, 5,5,6,3, 5,5,7,3, 5,5,8,3, + 5,5,9,3, 5,9,4,3, 5,9,5,3, 9,5,4,3, 9,5,5,3, 5,9,8,3, 5,9,9,3, 5,6,0,3, 5,6,1,3, + 5,6,2,3, 5,6,3,3, 5,6,4,3, 5,6,5,3, 5,6,6,3, 5,6,7,3, 5,6,8,3, 5,6,9,3, 5,8,6,3, + 5,8,7,3, 9,6,4,3, 9,6,5,3, 9,8,8,3, 9,8,9,3, 5,7,0,3, 5,7,1,3, 5,7,2,3, 5,7,3,3, + 5,7,4,3, 5,7,5,3, 5,7,6,3, 5,7,7,3, 5,7,8,3, 5,7,9,3, 5,9,6,3, 5,9,7,3, 9,7,4,3, + 9,7,5,3, 9,9,8,3, 9,9,9,3, 6,0,0,3, 6,0,1,3, 6,0,2,3, 6,0,3,3, 6,0,4,3, 6,0,5,3, + 6,0,6,3, 6,0,7,3, 6,0,8,3, 6,0,9,3, 6,8,0,3, 6,8,1,3, 8,0,6,3, 8,0,7,3, 8,8,6,3, + 8,8,7,3, 6,1,0,3, 6,1,1,3, 6,1,2,3, 6,1,3,3, 6,1,4,3, 6,1,5,3, 6,1,6,3, 6,1,7,3, + 6,1,8,3, 6,1,9,3, 6,9,0,3, 6,9,1,3, 8,1,6,3, 8,1,7,3, 8,9,6,3, 8,9,7,3, 6,2,0,3, + 6,2,1,3, 6,2,2,3, 6,2,3,3, 6,2,4,3, 6,2,5,3, 6,2,6,3, 6,2,7,3, 6,2,8,3, 6,2,9,3, + 6,8,2,3, 6,8,3,3, 8,2,6,3, 8,2,7,3, 8,6,8,3, 8,6,9,3, 6,3,0,3, 6,3,1,3, 6,3,2,3, + 6,3,3,3, 6,3,4,3, 6,3,5,3, 6,3,6,3, 6,3,7,3, 6,3,8,3, 6,3,9,3, 6,9,2,3, 6,9,3,3, + 8,3,6,3, 8,3,7,3, 8,7,8,3, 8,7,9,3, 6,4,0,3, 6,4,1,3, 6,4,2,3, 6,4,3,3, 6,4,4,3, + 6,4,5,3, 6,4,6,3, 6,4,7,3, 6,4,8,3, 6,4,9,3, 6,8,4,3, 6,8,5,3, 8,4,6,3, 8,4,7,3, + 6,8,8,3, 6,8,9,3, 6,5,0,3, 6,5,1,3, 6,5,2,3, 6,5,3,3, 6,5,4,3, 6,5,5,3, 6,5,6,3, + 6,5,7,3, 6,5,8,3, 6,5,9,3, 6,9,4,3, 6,9,5,3, 8,5,6,3, 8,5,7,3, 6,9,8,3, 6,9,9,3, + 6,6,0,3, 6,6,1,3, 6,6,2,3, 6,6,3,3, 6,6,4,3, 6,6,5,3, 6,6,6,3, 6,6,7,3, 6,6,8,3, + 6,6,9,3, 6,8,6,3, 6,8,7,3, 8,6,6,3, 8,6,7,3, 8,8,8,3, 8,8,9,3, 6,7,0,3, 6,7,1,3, + 6,7,2,3, 6,7,3,3, 6,7,4,3, 6,7,5,3, 6,7,6,3, 6,7,7,3, 6,7,8,3, 6,7,9,3, 6,9,6,3, + 6,9,7,3, 8,7,6,3, 8,7,7,3, 8,9,8,3, 8,9,9,3, 7,0,0,3, 7,0,1,3, 7,0,2,3, 7,0,3,3, + 7,0,4,3, 7,0,5,3, 7,0,6,3, 7,0,7,3, 7,0,8,3, 7,0,9,3, 7,8,0,3, 7,8,1,3, 9,0,6,3, + 9,0,7,3, 9,8,6,3, 9,8,7,3, 7,1,0,3, 7,1,1,3, 7,1,2,3, 7,1,3,3, 7,1,4,3, 7,1,5,3, + 7,1,6,3, 7,1,7,3, 7,1,8,3, 7,1,9,3, 7,9,0,3, 7,9,1,3, 9,1,6,3, 9,1,7,3, 9,9,6,3, + 9,9,7,3, 7,2,0,3, 7,2,1,3, 7,2,2,3, 7,2,3,3, 7,2,4,3, 7,2,5,3, 7,2,6,3, 7,2,7,3, + 7,2,8,3, 7,2,9,3, 7,8,2,3, 7,8,3,3, 9,2,6,3, 9,2,7,3, 9,6,8,3, 9,6,9,3, 7,3,0,3, + 7,3,1,3, 7,3,2,3, 7,3,3,3, 7,3,4,3, 7,3,5,3, 7,3,6,3, 7,3,7,3, 7,3,8,3, 7,3,9,3, + 7,9,2,3, 7,9,3,3, 9,3,6,3, 9,3,7,3, 9,7,8,3, 9,7,9,3, 7,4,0,3, 7,4,1,3, 7,4,2,3, + 7,4,3,3, 7,4,4,3, 7,4,5,3, 7,4,6,3, 7,4,7,3, 7,4,8,3, 7,4,9,3, 7,8,4,3, 7,8,5,3, + 9,4,6,3, 9,4,7,3, 7,8,8,3, 7,8,9,3, 7,5,0,3, 7,5,1,3, 7,5,2,3, 7,5,3,3, 7,5,4,3, + 7,5,5,3, 7,5,6,3, 7,5,7,3, 7,5,8,3, 7,5,9,3, 7,9,4,3, 7,9,5,3, 9,5,6,3, 9,5,7,3, + 7,9,8,3, 7,9,9,3, 7,6,0,3, 7,6,1,3, 7,6,2,3, 7,6,3,3, 7,6,4,3, 7,6,5,3, 7,6,6,3, + 7,6,7,3, 7,6,8,3, 7,6,9,3, 7,8,6,3, 7,8,7,3, 9,6,6,3, 9,6,7,3, 9,8,8,3, 9,8,9,3, + 7,7,0,3, 7,7,1,3, 7,7,2,3, 7,7,3,3, 7,7,4,3, 7,7,5,3, 7,7,6,3, 7,7,7,3, 7,7,8,3, + 7,7,9,3, 7,9,6,3, 7,9,7,3, 9,7,6,3, 9,7,7,3, 9,9,8,3, 9,9,9,3}; +#endif + +#if defined(DEC_BIN2BCD8) && DEC_BIN2BCD8==1 && !defined(DECBIN2BCD8) +#define DECBIN2BCD8 + +const uint8_t BIN2BCD8[4000]={ + 0,0,0,0, 0,0,1,1, 0,0,2,1, 0,0,3,1, 0,0,4,1, 0,0,5,1, 0,0,6,1, 0,0,7,1, 0,0,8,1, + 0,0,9,1, 0,1,0,2, 0,1,1,2, 0,1,2,2, 0,1,3,2, 0,1,4,2, 0,1,5,2, 0,1,6,2, 0,1,7,2, + 0,1,8,2, 0,1,9,2, 0,2,0,2, 0,2,1,2, 0,2,2,2, 0,2,3,2, 0,2,4,2, 0,2,5,2, 0,2,6,2, + 0,2,7,2, 0,2,8,2, 0,2,9,2, 0,3,0,2, 0,3,1,2, 0,3,2,2, 0,3,3,2, 0,3,4,2, 0,3,5,2, + 0,3,6,2, 0,3,7,2, 0,3,8,2, 0,3,9,2, 0,4,0,2, 0,4,1,2, 0,4,2,2, 0,4,3,2, 0,4,4,2, + 0,4,5,2, 0,4,6,2, 0,4,7,2, 0,4,8,2, 0,4,9,2, 0,5,0,2, 0,5,1,2, 0,5,2,2, 0,5,3,2, + 0,5,4,2, 0,5,5,2, 0,5,6,2, 0,5,7,2, 0,5,8,2, 0,5,9,2, 0,6,0,2, 0,6,1,2, 0,6,2,2, + 0,6,3,2, 0,6,4,2, 0,6,5,2, 0,6,6,2, 0,6,7,2, 0,6,8,2, 0,6,9,2, 0,7,0,2, 0,7,1,2, + 0,7,2,2, 0,7,3,2, 0,7,4,2, 0,7,5,2, 0,7,6,2, 0,7,7,2, 0,7,8,2, 0,7,9,2, 0,8,0,2, + 0,8,1,2, 0,8,2,2, 0,8,3,2, 0,8,4,2, 0,8,5,2, 0,8,6,2, 0,8,7,2, 0,8,8,2, 0,8,9,2, + 0,9,0,2, 0,9,1,2, 0,9,2,2, 0,9,3,2, 0,9,4,2, 0,9,5,2, 0,9,6,2, 0,9,7,2, 0,9,8,2, + 0,9,9,2, 1,0,0,3, 1,0,1,3, 1,0,2,3, 1,0,3,3, 1,0,4,3, 1,0,5,3, 1,0,6,3, 1,0,7,3, + 1,0,8,3, 1,0,9,3, 1,1,0,3, 1,1,1,3, 1,1,2,3, 1,1,3,3, 1,1,4,3, 1,1,5,3, 1,1,6,3, + 1,1,7,3, 1,1,8,3, 1,1,9,3, 1,2,0,3, 1,2,1,3, 1,2,2,3, 1,2,3,3, 1,2,4,3, 1,2,5,3, + 1,2,6,3, 1,2,7,3, 1,2,8,3, 1,2,9,3, 1,3,0,3, 1,3,1,3, 1,3,2,3, 1,3,3,3, 1,3,4,3, + 1,3,5,3, 1,3,6,3, 1,3,7,3, 1,3,8,3, 1,3,9,3, 1,4,0,3, 1,4,1,3, 1,4,2,3, 1,4,3,3, + 1,4,4,3, 1,4,5,3, 1,4,6,3, 1,4,7,3, 1,4,8,3, 1,4,9,3, 1,5,0,3, 1,5,1,3, 1,5,2,3, + 1,5,3,3, 1,5,4,3, 1,5,5,3, 1,5,6,3, 1,5,7,3, 1,5,8,3, 1,5,9,3, 1,6,0,3, 1,6,1,3, + 1,6,2,3, 1,6,3,3, 1,6,4,3, 1,6,5,3, 1,6,6,3, 1,6,7,3, 1,6,8,3, 1,6,9,3, 1,7,0,3, + 1,7,1,3, 1,7,2,3, 1,7,3,3, 1,7,4,3, 1,7,5,3, 1,7,6,3, 1,7,7,3, 1,7,8,3, 1,7,9,3, + 1,8,0,3, 1,8,1,3, 1,8,2,3, 1,8,3,3, 1,8,4,3, 1,8,5,3, 1,8,6,3, 1,8,7,3, 1,8,8,3, + 1,8,9,3, 1,9,0,3, 1,9,1,3, 1,9,2,3, 1,9,3,3, 1,9,4,3, 1,9,5,3, 1,9,6,3, 1,9,7,3, + 1,9,8,3, 1,9,9,3, 2,0,0,3, 2,0,1,3, 2,0,2,3, 2,0,3,3, 2,0,4,3, 2,0,5,3, 2,0,6,3, + 2,0,7,3, 2,0,8,3, 2,0,9,3, 2,1,0,3, 2,1,1,3, 2,1,2,3, 2,1,3,3, 2,1,4,3, 2,1,5,3, + 2,1,6,3, 2,1,7,3, 2,1,8,3, 2,1,9,3, 2,2,0,3, 2,2,1,3, 2,2,2,3, 2,2,3,3, 2,2,4,3, + 2,2,5,3, 2,2,6,3, 2,2,7,3, 2,2,8,3, 2,2,9,3, 2,3,0,3, 2,3,1,3, 2,3,2,3, 2,3,3,3, + 2,3,4,3, 2,3,5,3, 2,3,6,3, 2,3,7,3, 2,3,8,3, 2,3,9,3, 2,4,0,3, 2,4,1,3, 2,4,2,3, + 2,4,3,3, 2,4,4,3, 2,4,5,3, 2,4,6,3, 2,4,7,3, 2,4,8,3, 2,4,9,3, 2,5,0,3, 2,5,1,3, + 2,5,2,3, 2,5,3,3, 2,5,4,3, 2,5,5,3, 2,5,6,3, 2,5,7,3, 2,5,8,3, 2,5,9,3, 2,6,0,3, + 2,6,1,3, 2,6,2,3, 2,6,3,3, 2,6,4,3, 2,6,5,3, 2,6,6,3, 2,6,7,3, 2,6,8,3, 2,6,9,3, + 2,7,0,3, 2,7,1,3, 2,7,2,3, 2,7,3,3, 2,7,4,3, 2,7,5,3, 2,7,6,3, 2,7,7,3, 2,7,8,3, + 2,7,9,3, 2,8,0,3, 2,8,1,3, 2,8,2,3, 2,8,3,3, 2,8,4,3, 2,8,5,3, 2,8,6,3, 2,8,7,3, + 2,8,8,3, 2,8,9,3, 2,9,0,3, 2,9,1,3, 2,9,2,3, 2,9,3,3, 2,9,4,3, 2,9,5,3, 2,9,6,3, + 2,9,7,3, 2,9,8,3, 2,9,9,3, 3,0,0,3, 3,0,1,3, 3,0,2,3, 3,0,3,3, 3,0,4,3, 3,0,5,3, + 3,0,6,3, 3,0,7,3, 3,0,8,3, 3,0,9,3, 3,1,0,3, 3,1,1,3, 3,1,2,3, 3,1,3,3, 3,1,4,3, + 3,1,5,3, 3,1,6,3, 3,1,7,3, 3,1,8,3, 3,1,9,3, 3,2,0,3, 3,2,1,3, 3,2,2,3, 3,2,3,3, + 3,2,4,3, 3,2,5,3, 3,2,6,3, 3,2,7,3, 3,2,8,3, 3,2,9,3, 3,3,0,3, 3,3,1,3, 3,3,2,3, + 3,3,3,3, 3,3,4,3, 3,3,5,3, 3,3,6,3, 3,3,7,3, 3,3,8,3, 3,3,9,3, 3,4,0,3, 3,4,1,3, + 3,4,2,3, 3,4,3,3, 3,4,4,3, 3,4,5,3, 3,4,6,3, 3,4,7,3, 3,4,8,3, 3,4,9,3, 3,5,0,3, + 3,5,1,3, 3,5,2,3, 3,5,3,3, 3,5,4,3, 3,5,5,3, 3,5,6,3, 3,5,7,3, 3,5,8,3, 3,5,9,3, + 3,6,0,3, 3,6,1,3, 3,6,2,3, 3,6,3,3, 3,6,4,3, 3,6,5,3, 3,6,6,3, 3,6,7,3, 3,6,8,3, + 3,6,9,3, 3,7,0,3, 3,7,1,3, 3,7,2,3, 3,7,3,3, 3,7,4,3, 3,7,5,3, 3,7,6,3, 3,7,7,3, + 3,7,8,3, 3,7,9,3, 3,8,0,3, 3,8,1,3, 3,8,2,3, 3,8,3,3, 3,8,4,3, 3,8,5,3, 3,8,6,3, + 3,8,7,3, 3,8,8,3, 3,8,9,3, 3,9,0,3, 3,9,1,3, 3,9,2,3, 3,9,3,3, 3,9,4,3, 3,9,5,3, + 3,9,6,3, 3,9,7,3, 3,9,8,3, 3,9,9,3, 4,0,0,3, 4,0,1,3, 4,0,2,3, 4,0,3,3, 4,0,4,3, + 4,0,5,3, 4,0,6,3, 4,0,7,3, 4,0,8,3, 4,0,9,3, 4,1,0,3, 4,1,1,3, 4,1,2,3, 4,1,3,3, + 4,1,4,3, 4,1,5,3, 4,1,6,3, 4,1,7,3, 4,1,8,3, 4,1,9,3, 4,2,0,3, 4,2,1,3, 4,2,2,3, + 4,2,3,3, 4,2,4,3, 4,2,5,3, 4,2,6,3, 4,2,7,3, 4,2,8,3, 4,2,9,3, 4,3,0,3, 4,3,1,3, + 4,3,2,3, 4,3,3,3, 4,3,4,3, 4,3,5,3, 4,3,6,3, 4,3,7,3, 4,3,8,3, 4,3,9,3, 4,4,0,3, + 4,4,1,3, 4,4,2,3, 4,4,3,3, 4,4,4,3, 4,4,5,3, 4,4,6,3, 4,4,7,3, 4,4,8,3, 4,4,9,3, + 4,5,0,3, 4,5,1,3, 4,5,2,3, 4,5,3,3, 4,5,4,3, 4,5,5,3, 4,5,6,3, 4,5,7,3, 4,5,8,3, + 4,5,9,3, 4,6,0,3, 4,6,1,3, 4,6,2,3, 4,6,3,3, 4,6,4,3, 4,6,5,3, 4,6,6,3, 4,6,7,3, + 4,6,8,3, 4,6,9,3, 4,7,0,3, 4,7,1,3, 4,7,2,3, 4,7,3,3, 4,7,4,3, 4,7,5,3, 4,7,6,3, + 4,7,7,3, 4,7,8,3, 4,7,9,3, 4,8,0,3, 4,8,1,3, 4,8,2,3, 4,8,3,3, 4,8,4,3, 4,8,5,3, + 4,8,6,3, 4,8,7,3, 4,8,8,3, 4,8,9,3, 4,9,0,3, 4,9,1,3, 4,9,2,3, 4,9,3,3, 4,9,4,3, + 4,9,5,3, 4,9,6,3, 4,9,7,3, 4,9,8,3, 4,9,9,3, 5,0,0,3, 5,0,1,3, 5,0,2,3, 5,0,3,3, + 5,0,4,3, 5,0,5,3, 5,0,6,3, 5,0,7,3, 5,0,8,3, 5,0,9,3, 5,1,0,3, 5,1,1,3, 5,1,2,3, + 5,1,3,3, 5,1,4,3, 5,1,5,3, 5,1,6,3, 5,1,7,3, 5,1,8,3, 5,1,9,3, 5,2,0,3, 5,2,1,3, + 5,2,2,3, 5,2,3,3, 5,2,4,3, 5,2,5,3, 5,2,6,3, 5,2,7,3, 5,2,8,3, 5,2,9,3, 5,3,0,3, + 5,3,1,3, 5,3,2,3, 5,3,3,3, 5,3,4,3, 5,3,5,3, 5,3,6,3, 5,3,7,3, 5,3,8,3, 5,3,9,3, + 5,4,0,3, 5,4,1,3, 5,4,2,3, 5,4,3,3, 5,4,4,3, 5,4,5,3, 5,4,6,3, 5,4,7,3, 5,4,8,3, + 5,4,9,3, 5,5,0,3, 5,5,1,3, 5,5,2,3, 5,5,3,3, 5,5,4,3, 5,5,5,3, 5,5,6,3, 5,5,7,3, + 5,5,8,3, 5,5,9,3, 5,6,0,3, 5,6,1,3, 5,6,2,3, 5,6,3,3, 5,6,4,3, 5,6,5,3, 5,6,6,3, + 5,6,7,3, 5,6,8,3, 5,6,9,3, 5,7,0,3, 5,7,1,3, 5,7,2,3, 5,7,3,3, 5,7,4,3, 5,7,5,3, + 5,7,6,3, 5,7,7,3, 5,7,8,3, 5,7,9,3, 5,8,0,3, 5,8,1,3, 5,8,2,3, 5,8,3,3, 5,8,4,3, + 5,8,5,3, 5,8,6,3, 5,8,7,3, 5,8,8,3, 5,8,9,3, 5,9,0,3, 5,9,1,3, 5,9,2,3, 5,9,3,3, + 5,9,4,3, 5,9,5,3, 5,9,6,3, 5,9,7,3, 5,9,8,3, 5,9,9,3, 6,0,0,3, 6,0,1,3, 6,0,2,3, + 6,0,3,3, 6,0,4,3, 6,0,5,3, 6,0,6,3, 6,0,7,3, 6,0,8,3, 6,0,9,3, 6,1,0,3, 6,1,1,3, + 6,1,2,3, 6,1,3,3, 6,1,4,3, 6,1,5,3, 6,1,6,3, 6,1,7,3, 6,1,8,3, 6,1,9,3, 6,2,0,3, + 6,2,1,3, 6,2,2,3, 6,2,3,3, 6,2,4,3, 6,2,5,3, 6,2,6,3, 6,2,7,3, 6,2,8,3, 6,2,9,3, + 6,3,0,3, 6,3,1,3, 6,3,2,3, 6,3,3,3, 6,3,4,3, 6,3,5,3, 6,3,6,3, 6,3,7,3, 6,3,8,3, + 6,3,9,3, 6,4,0,3, 6,4,1,3, 6,4,2,3, 6,4,3,3, 6,4,4,3, 6,4,5,3, 6,4,6,3, 6,4,7,3, + 6,4,8,3, 6,4,9,3, 6,5,0,3, 6,5,1,3, 6,5,2,3, 6,5,3,3, 6,5,4,3, 6,5,5,3, 6,5,6,3, + 6,5,7,3, 6,5,8,3, 6,5,9,3, 6,6,0,3, 6,6,1,3, 6,6,2,3, 6,6,3,3, 6,6,4,3, 6,6,5,3, + 6,6,6,3, 6,6,7,3, 6,6,8,3, 6,6,9,3, 6,7,0,3, 6,7,1,3, 6,7,2,3, 6,7,3,3, 6,7,4,3, + 6,7,5,3, 6,7,6,3, 6,7,7,3, 6,7,8,3, 6,7,9,3, 6,8,0,3, 6,8,1,3, 6,8,2,3, 6,8,3,3, + 6,8,4,3, 6,8,5,3, 6,8,6,3, 6,8,7,3, 6,8,8,3, 6,8,9,3, 6,9,0,3, 6,9,1,3, 6,9,2,3, + 6,9,3,3, 6,9,4,3, 6,9,5,3, 6,9,6,3, 6,9,7,3, 6,9,8,3, 6,9,9,3, 7,0,0,3, 7,0,1,3, + 7,0,2,3, 7,0,3,3, 7,0,4,3, 7,0,5,3, 7,0,6,3, 7,0,7,3, 7,0,8,3, 7,0,9,3, 7,1,0,3, + 7,1,1,3, 7,1,2,3, 7,1,3,3, 7,1,4,3, 7,1,5,3, 7,1,6,3, 7,1,7,3, 7,1,8,3, 7,1,9,3, + 7,2,0,3, 7,2,1,3, 7,2,2,3, 7,2,3,3, 7,2,4,3, 7,2,5,3, 7,2,6,3, 7,2,7,3, 7,2,8,3, + 7,2,9,3, 7,3,0,3, 7,3,1,3, 7,3,2,3, 7,3,3,3, 7,3,4,3, 7,3,5,3, 7,3,6,3, 7,3,7,3, + 7,3,8,3, 7,3,9,3, 7,4,0,3, 7,4,1,3, 7,4,2,3, 7,4,3,3, 7,4,4,3, 7,4,5,3, 7,4,6,3, + 7,4,7,3, 7,4,8,3, 7,4,9,3, 7,5,0,3, 7,5,1,3, 7,5,2,3, 7,5,3,3, 7,5,4,3, 7,5,5,3, + 7,5,6,3, 7,5,7,3, 7,5,8,3, 7,5,9,3, 7,6,0,3, 7,6,1,3, 7,6,2,3, 7,6,3,3, 7,6,4,3, + 7,6,5,3, 7,6,6,3, 7,6,7,3, 7,6,8,3, 7,6,9,3, 7,7,0,3, 7,7,1,3, 7,7,2,3, 7,7,3,3, + 7,7,4,3, 7,7,5,3, 7,7,6,3, 7,7,7,3, 7,7,8,3, 7,7,9,3, 7,8,0,3, 7,8,1,3, 7,8,2,3, + 7,8,3,3, 7,8,4,3, 7,8,5,3, 7,8,6,3, 7,8,7,3, 7,8,8,3, 7,8,9,3, 7,9,0,3, 7,9,1,3, + 7,9,2,3, 7,9,3,3, 7,9,4,3, 7,9,5,3, 7,9,6,3, 7,9,7,3, 7,9,8,3, 7,9,9,3, 8,0,0,3, + 8,0,1,3, 8,0,2,3, 8,0,3,3, 8,0,4,3, 8,0,5,3, 8,0,6,3, 8,0,7,3, 8,0,8,3, 8,0,9,3, + 8,1,0,3, 8,1,1,3, 8,1,2,3, 8,1,3,3, 8,1,4,3, 8,1,5,3, 8,1,6,3, 8,1,7,3, 8,1,8,3, + 8,1,9,3, 8,2,0,3, 8,2,1,3, 8,2,2,3, 8,2,3,3, 8,2,4,3, 8,2,5,3, 8,2,6,3, 8,2,7,3, + 8,2,8,3, 8,2,9,3, 8,3,0,3, 8,3,1,3, 8,3,2,3, 8,3,3,3, 8,3,4,3, 8,3,5,3, 8,3,6,3, + 8,3,7,3, 8,3,8,3, 8,3,9,3, 8,4,0,3, 8,4,1,3, 8,4,2,3, 8,4,3,3, 8,4,4,3, 8,4,5,3, + 8,4,6,3, 8,4,7,3, 8,4,8,3, 8,4,9,3, 8,5,0,3, 8,5,1,3, 8,5,2,3, 8,5,3,3, 8,5,4,3, + 8,5,5,3, 8,5,6,3, 8,5,7,3, 8,5,8,3, 8,5,9,3, 8,6,0,3, 8,6,1,3, 8,6,2,3, 8,6,3,3, + 8,6,4,3, 8,6,5,3, 8,6,6,3, 8,6,7,3, 8,6,8,3, 8,6,9,3, 8,7,0,3, 8,7,1,3, 8,7,2,3, + 8,7,3,3, 8,7,4,3, 8,7,5,3, 8,7,6,3, 8,7,7,3, 8,7,8,3, 8,7,9,3, 8,8,0,3, 8,8,1,3, + 8,8,2,3, 8,8,3,3, 8,8,4,3, 8,8,5,3, 8,8,6,3, 8,8,7,3, 8,8,8,3, 8,8,9,3, 8,9,0,3, + 8,9,1,3, 8,9,2,3, 8,9,3,3, 8,9,4,3, 8,9,5,3, 8,9,6,3, 8,9,7,3, 8,9,8,3, 8,9,9,3, + 9,0,0,3, 9,0,1,3, 9,0,2,3, 9,0,3,3, 9,0,4,3, 9,0,5,3, 9,0,6,3, 9,0,7,3, 9,0,8,3, + 9,0,9,3, 9,1,0,3, 9,1,1,3, 9,1,2,3, 9,1,3,3, 9,1,4,3, 9,1,5,3, 9,1,6,3, 9,1,7,3, + 9,1,8,3, 9,1,9,3, 9,2,0,3, 9,2,1,3, 9,2,2,3, 9,2,3,3, 9,2,4,3, 9,2,5,3, 9,2,6,3, + 9,2,7,3, 9,2,8,3, 9,2,9,3, 9,3,0,3, 9,3,1,3, 9,3,2,3, 9,3,3,3, 9,3,4,3, 9,3,5,3, + 9,3,6,3, 9,3,7,3, 9,3,8,3, 9,3,9,3, 9,4,0,3, 9,4,1,3, 9,4,2,3, 9,4,3,3, 9,4,4,3, + 9,4,5,3, 9,4,6,3, 9,4,7,3, 9,4,8,3, 9,4,9,3, 9,5,0,3, 9,5,1,3, 9,5,2,3, 9,5,3,3, + 9,5,4,3, 9,5,5,3, 9,5,6,3, 9,5,7,3, 9,5,8,3, 9,5,9,3, 9,6,0,3, 9,6,1,3, 9,6,2,3, + 9,6,3,3, 9,6,4,3, 9,6,5,3, 9,6,6,3, 9,6,7,3, 9,6,8,3, 9,6,9,3, 9,7,0,3, 9,7,1,3, + 9,7,2,3, 9,7,3,3, 9,7,4,3, 9,7,5,3, 9,7,6,3, 9,7,7,3, 9,7,8,3, 9,7,9,3, 9,8,0,3, + 9,8,1,3, 9,8,2,3, 9,8,3,3, 9,8,4,3, 9,8,5,3, 9,8,6,3, 9,8,7,3, 9,8,8,3, 9,8,9,3, + 9,9,0,3, 9,9,1,3, 9,9,2,3, 9,9,3,3, 9,9,4,3, 9,9,5,3, 9,9,6,3, 9,9,7,3, 9,9,8,3, + 9,9,9,3}; +#endif diff --git a/include/libdecnumber/decNumber.h b/include/libdecnumber/decNumber.h new file mode 100644 index 0000000..0a9fdce --- /dev/null +++ b/include/libdecnumber/decNumber.h @@ -0,0 +1,200 @@ +/* Decimal number arithmetic module header for the decNumber C Library. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------ */ +/* Decimal Number arithmetic module header */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECNUMBER) + #define DECNUMBER + #define DECNAME "decNumber" /* Short name */ + #define DECFULLNAME "Decimal Number Module" /* Verbose name */ + #define DECAUTHOR "Mike Cowlishaw" /* Who to blame */ + + #if !defined(DECCONTEXT) + #include "decContext.h" + #endif + + /* Bit settings for decNumber.bits */ + #define DECNEG 0x80 /* Sign; 1=negative, 0=positive or zero */ + #define DECINF 0x40 /* 1=Infinity */ + #define DECNAN 0x20 /* 1=NaN */ + #define DECSNAN 0x10 /* 1=sNaN */ + /* The remaining bits are reserved; they must be 0 */ + #define DECSPECIAL (DECINF|DECNAN|DECSNAN) /* any special value */ + + /* Define the decNumber data structure. The size and shape of the */ + /* units array in the structure is determined by the following */ + /* constant. This must not be changed without recompiling the */ + /* decNumber library modules. */ + + #define DECDPUN 3 /* DECimal Digits Per UNit [must be >0 */ + /* and <10; 3 or powers of 2 are best]. */ + + /* DECNUMDIGITS is the default number of digits that can be held in */ + /* the structure. If undefined, 1 is assumed and it is assumed */ + /* that the structure will be immediately followed by extra space, */ + /* as required. DECNUMDIGITS is always >0. */ + #if !defined(DECNUMDIGITS) + #define DECNUMDIGITS 1 + #endif + + /* The size (integer data type) of each unit is determined by the */ + /* number of digits it will hold. */ + #if DECDPUN<=2 + #define decNumberUnit uint8_t + #elif DECDPUN<=4 + #define decNumberUnit uint16_t + #else + #define decNumberUnit uint32_t + #endif + /* The number of units needed is ceil(DECNUMDIGITS/DECDPUN) */ + #define DECNUMUNITS ((DECNUMDIGITS+DECDPUN-1)/DECDPUN) + + /* The data structure... */ + typedef struct { + int32_t digits; /* Count of digits in the coefficient; >0 */ + int32_t exponent; /* Unadjusted exponent, unbiased, in */ + /* range: -1999999997 through 999999999 */ + uint8_t bits; /* Indicator bits (see above) */ + /* Coefficient, from least significant unit */ + decNumberUnit lsu[DECNUMUNITS]; + } decNumber; + + /* Notes: */ + /* 1. If digits is > DECDPUN then there will one or more */ + /* decNumberUnits immediately following the first element of lsu.*/ + /* These contain the remaining (more significant) digits of the */ + /* number, and may be in the lsu array, or may be guaranteed by */ + /* some other mechanism (such as being contained in another */ + /* structure, or being overlaid on dynamically allocated */ + /* storage). */ + /* */ + /* Each integer of the coefficient (except potentially the last) */ + /* contains DECDPUN digits (e.g., a value in the range 0 through */ + /* 99999999 if DECDPUN is 8, or 0 through 999 if DECDPUN is 3). */ + /* */ + /* 2. A decNumber converted to a string may need up to digits+14 */ + /* characters. The worst cases (non-exponential and exponential */ + /* formats) are -0.00000{9...}# and -9.{9...}E+999999999# */ + /* (where # is '\0') */ + + + /* ---------------------------------------------------------------- */ + /* decNumber public functions and macros */ + /* ---------------------------------------------------------------- */ + + #include "decNumberSymbols.h" + + /* Conversions */ + decNumber * decNumberFromInt32(decNumber *, int32_t); + decNumber * decNumberFromUInt32(decNumber *, uint32_t); + decNumber * decNumberFromString(decNumber *, const char *, decContext *); + char * decNumberToString(const decNumber *, char *); + char * decNumberToEngString(const decNumber *, char *); + uint32_t decNumberToUInt32(const decNumber *, decContext *); + int32_t decNumberToInt32(const decNumber *, decContext *); + uint8_t * decNumberGetBCD(const decNumber *, uint8_t *); + decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t); + + /* Operators and elementary functions */ + decNumber * decNumberAbs(decNumber *, const decNumber *, decContext *); + decNumber * decNumberAdd(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberAnd(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberCompare(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberCompareSignal(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberCompareTotal(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberCompareTotalMag(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberDivide(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberDivideInteger(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberExp(decNumber *, const decNumber *, decContext *); + decNumber * decNumberFMA(decNumber *, const decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberInvert(decNumber *, const decNumber *, decContext *); + decNumber * decNumberLn(decNumber *, const decNumber *, decContext *); + decNumber * decNumberLogB(decNumber *, const decNumber *, decContext *); + decNumber * decNumberLog10(decNumber *, const decNumber *, decContext *); + decNumber * decNumberMax(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberMaxMag(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberMin(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberMinMag(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberMinus(decNumber *, const decNumber *, decContext *); + decNumber * decNumberMultiply(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberNormalize(decNumber *, const decNumber *, decContext *); + decNumber * decNumberOr(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberPlus(decNumber *, const decNumber *, decContext *); + decNumber * decNumberPower(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberQuantize(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberReduce(decNumber *, const decNumber *, decContext *); + decNumber * decNumberRemainder(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberRemainderNear(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberRescale(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberRotate(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberSameQuantum(decNumber *, const decNumber *, const decNumber *); + decNumber * decNumberScaleB(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberShift(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberSquareRoot(decNumber *, const decNumber *, decContext *); + decNumber * decNumberSubtract(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberToIntegralExact(decNumber *, const decNumber *, decContext *); + decNumber * decNumberToIntegralValue(decNumber *, const decNumber *, decContext *); + decNumber * decNumberXor(decNumber *, const decNumber *, const decNumber *, decContext *); + + /* Utilities */ + enum decClass decNumberClass(const decNumber *, decContext *); + const char * decNumberClassToString(enum decClass); + decNumber * decNumberCopy(decNumber *, const decNumber *); + decNumber * decNumberCopyAbs(decNumber *, const decNumber *); + decNumber * decNumberCopyNegate(decNumber *, const decNumber *); + decNumber * decNumberCopySign(decNumber *, const decNumber *, const decNumber *); + decNumber * decNumberNextMinus(decNumber *, const decNumber *, decContext *); + decNumber * decNumberNextPlus(decNumber *, const decNumber *, decContext *); + decNumber * decNumberNextToward(decNumber *, const decNumber *, const decNumber *, decContext *); + decNumber * decNumberTrim(decNumber *); + const char * decNumberVersion(void); + decNumber * decNumberZero(decNumber *); + + /* Functions for testing decNumbers (normality depends on context) */ + int32_t decNumberIsNormal(const decNumber *, decContext *); + int32_t decNumberIsSubnormal(const decNumber *, decContext *); + + /* Macros for testing decNumber *dn */ + #define decNumberIsCanonical(dn) (1) /* All decNumbers are saintly */ + #define decNumberIsFinite(dn) (((dn)->bits&DECSPECIAL)==0) + #define decNumberIsInfinite(dn) (((dn)->bits&DECINF)!=0) + #define decNumberIsNaN(dn) (((dn)->bits&(DECNAN|DECSNAN))!=0) + #define decNumberIsNegative(dn) (((dn)->bits&DECNEG)!=0) + #define decNumberIsQNaN(dn) (((dn)->bits&(DECNAN))!=0) + #define decNumberIsSNaN(dn) (((dn)->bits&(DECSNAN))!=0) + #define decNumberIsSpecial(dn) (((dn)->bits&DECSPECIAL)!=0) + #define decNumberIsZero(dn) (*(dn)->lsu==0 \ + && (dn)->digits==1 \ + && (((dn)->bits&DECSPECIAL)==0)) + #define decNumberRadix(dn) (10) + +#endif diff --git a/include/libdecnumber/decNumberLocal.h b/include/libdecnumber/decNumberLocal.h new file mode 100644 index 0000000..f1568f7 --- /dev/null +++ b/include/libdecnumber/decNumberLocal.h @@ -0,0 +1,667 @@ +/* Local definitions for the decNumber C Library. + Copyright (C) 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------ */ +/* decNumber package local type, tuning, and macro definitions */ +/* ------------------------------------------------------------------ */ +/* This header file is included by all modules in the decNumber */ +/* library, and contains local type definitions, tuning parameters, */ +/* etc. It should not need to be used by application programs. */ +/* decNumber.h or one of decDouble (etc.) must be included first. */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECNUMBERLOC) + #define DECNUMBERLOC + #define DECVERSION "decNumber 3.53" /* Package Version [16 max.] */ + #define DECNLAUTHOR "Mike Cowlishaw" /* Who to blame */ + + #include <stdlib.h> /* for abs */ + #include <string.h> /* for memset, strcpy */ + #include "dconfig.h" /* for WORDS_BIGENDIAN */ + + /* Conditional code flag -- set this to match hardware platform */ + /* 1=little-endian, 0=big-endian */ + #if WORDS_BIGENDIAN + #define DECLITEND 0 + #else + #define DECLITEND 1 + #endif + + /* Conditional code flag -- set this to 1 for best performance */ + #define DECUSE64 1 /* 1=use int64s, 0=int32 & smaller only */ + + /* Conditional check flags -- set these to 0 for best performance */ + #define DECCHECK 0 /* 1 to enable robust checking */ + #define DECALLOC 0 /* 1 to enable memory accounting */ + #define DECTRACE 0 /* 1 to trace certain internals, etc. */ + + /* Tuning parameter for decNumber (arbitrary precision) module */ + #define DECBUFFER 36 /* Size basis for local buffers. This */ + /* should be a common maximum precision */ + /* rounded up to a multiple of 4; must */ + /* be zero or positive. */ + + /* ---------------------------------------------------------------- */ + /* Definitions for all modules (general-purpose) */ + /* ---------------------------------------------------------------- */ + + /* Local names for common types -- for safety, decNumber modules do */ + /* not use int or long directly. */ + #define Flag uint8_t + #define Byte int8_t + #define uByte uint8_t + #define Short int16_t + #define uShort uint16_t + #define Int int32_t + #define uInt uint32_t + #define Unit decNumberUnit + #if DECUSE64 + #define Long int64_t + #define uLong uint64_t + #endif + + /* Development-use definitions */ + typedef long int LI; /* for printf arguments only */ + #define DECNOINT 0 /* 1 to check no internal use of 'int' */ + #if DECNOINT + /* if these interfere with your C includes, do not set DECNOINT */ + #define int ? /* enable to ensure that plain C 'int' */ + #define long ?? /* .. or 'long' types are not used */ + #endif + + /* Shared lookup tables */ + extern const uByte DECSTICKYTAB[10]; /* re-round digits if sticky */ + extern const uInt DECPOWERS[10]; /* powers of ten table */ + /* The following are included from decDPD.h */ +#include "decDPDSymbols.h" + extern const uShort DPD2BIN[1024]; /* DPD -> 0-999 */ + extern const uShort BIN2DPD[1000]; /* 0-999 -> DPD */ + extern const uInt DPD2BINK[1024]; /* DPD -> 0-999000 */ + extern const uInt DPD2BINM[1024]; /* DPD -> 0-999000000 */ + extern const uByte DPD2BCD8[4096]; /* DPD -> ddd + len */ + extern const uByte BIN2BCD8[4000]; /* 0-999 -> ddd + len */ + extern const uShort BCD2DPD[2458]; /* 0-0x999 -> DPD (0x999=2457)*/ + + /* LONGMUL32HI -- set w=(u*v)>>32, where w, u, and v are uInts */ + /* (that is, sets w to be the high-order word of the 64-bit result; */ + /* the low-order word is simply u*v.) */ + /* This version is derived from Knuth via Hacker's Delight; */ + /* it seems to optimize better than some others tried */ + #define LONGMUL32HI(w, u, v) { \ + uInt u0, u1, v0, v1, w0, w1, w2, t; \ + u0=u & 0xffff; u1=u>>16; \ + v0=v & 0xffff; v1=v>>16; \ + w0=u0*v0; \ + t=u1*v0 + (w0>>16); \ + w1=t & 0xffff; w2=t>>16; \ + w1=u0*v1 + w1; \ + (w)=u1*v1 + w2 + (w1>>16);} + + /* ROUNDUP -- round an integer up to a multiple of n */ + #define ROUNDUP(i, n) ((((i)+(n)-1)/n)*n) + + /* ROUNDDOWN -- round an integer down to a multiple of n */ + #define ROUNDDOWN(i, n) (((i)/n)*n) + #define ROUNDDOWN4(i) ((i)&~3) /* special for n=4 */ + + /* References to multi-byte sequences under different sizes */ + /* Refer to a uInt from four bytes starting at a char* or uByte*, */ + /* etc. */ + #define UINTAT(b) (*((uInt *)(b))) + #define USHORTAT(b) (*((uShort *)(b))) + #define UBYTEAT(b) (*((uByte *)(b))) + + /* X10 and X100 -- multiply integer i by 10 or 100 */ + /* [shifts are usually faster than multiply; could be conditional] */ + #define X10(i) (((i)<<1)+((i)<<3)) + #define X100(i) (((i)<<2)+((i)<<5)+((i)<<6)) + + /* MAXI and MINI -- general max & min (not in ANSI) for integers */ + #define MAXI(x,y) ((x)<(y)?(y):(x)) + #define MINI(x,y) ((x)>(y)?(y):(x)) + + /* Useful constants */ + #define BILLION 1000000000 /* 10**9 */ + /* CHARMASK: 0x30303030 for ASCII/UTF8; 0xF0F0F0F0 for EBCDIC */ + #define CHARMASK ((((((((uInt)'0')<<8)+'0')<<8)+'0')<<8)+'0') + + + /* ---------------------------------------------------------------- */ + /* Definitions for arbitary-precision modules (only valid after */ + /* decNumber.h has been included) */ + /* ---------------------------------------------------------------- */ + + /* Limits and constants */ + #define DECNUMMAXP 999999999 /* maximum precision code can handle */ + #define DECNUMMAXE 999999999 /* maximum adjusted exponent ditto */ + #define DECNUMMINE -999999999 /* minimum adjusted exponent ditto */ + #if (DECNUMMAXP != DEC_MAX_DIGITS) + #error Maximum digits mismatch + #endif + #if (DECNUMMAXE != DEC_MAX_EMAX) + #error Maximum exponent mismatch + #endif + #if (DECNUMMINE != DEC_MIN_EMIN) + #error Minimum exponent mismatch + #endif + + /* Set DECDPUNMAX -- the maximum integer that fits in DECDPUN */ + /* digits, and D2UTABLE -- the initializer for the D2U table */ + #if DECDPUN==1 + #define DECDPUNMAX 9 + #define D2UTABLE {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17, \ + 18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, \ + 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, \ + 48,49} + #elif DECDPUN==2 + #define DECDPUNMAX 99 + #define D2UTABLE {0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10, \ + 11,11,12,12,13,13,14,14,15,15,16,16,17,17,18, \ + 18,19,19,20,20,21,21,22,22,23,23,24,24,25} + #elif DECDPUN==3 + #define DECDPUNMAX 999 + #define D2UTABLE {0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7, \ + 8,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13, \ + 13,14,14,14,15,15,15,16,16,16,17} + #elif DECDPUN==4 + #define DECDPUNMAX 9999 + #define D2UTABLE {0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6, \ + 6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11, \ + 11,11,11,12,12,12,12,13} + #elif DECDPUN==5 + #define DECDPUNMAX 99999 + #define D2UTABLE {0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5, \ + 5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9, \ + 9,9,10,10,10,10} + #elif DECDPUN==6 + #define DECDPUNMAX 999999 + #define D2UTABLE {0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4, \ + 4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8, \ + 8,8,8,8,8,9} + #elif DECDPUN==7 + #define DECDPUNMAX 9999999 + #define D2UTABLE {0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3, \ + 4,4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,7, \ + 7,7,7,7,7,7} + #elif DECDPUN==8 + #define DECDPUNMAX 99999999 + #define D2UTABLE {0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3, \ + 3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6, \ + 6,6,6,6,6,7} + #elif DECDPUN==9 + #define DECDPUNMAX 999999999 + #define D2UTABLE {0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3, \ + 3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5, \ + 5,5,6,6,6,6} + #elif defined(DECDPUN) + #error DECDPUN must be in the range 1-9 + #endif + + /* ----- Shared data (in decNumber.c) ----- */ + /* Public lookup table used by the D2U macro (see below) */ + #define DECMAXD2U 49 + extern const uByte d2utable[DECMAXD2U+1]; + + /* ----- Macros ----- */ + /* ISZERO -- return true if decNumber dn is a zero */ + /* [performance-critical in some situations] */ + #define ISZERO(dn) decNumberIsZero(dn) /* now just a local name */ + + /* D2U -- return the number of Units needed to hold d digits */ + /* (runtime version, with table lookaside for small d) */ + #if DECDPUN==8 + #define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+7)>>3)) + #elif DECDPUN==4 + #define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+3)>>2)) + #else + #define D2U(d) ((d)<=DECMAXD2U?d2utable[d]:((d)+DECDPUN-1)/DECDPUN) + #endif + /* SD2U -- static D2U macro (for compile-time calculation) */ + #define SD2U(d) (((d)+DECDPUN-1)/DECDPUN) + + /* MSUDIGITS -- returns digits in msu, from digits, calculated */ + /* using D2U */ + #define MSUDIGITS(d) ((d)-(D2U(d)-1)*DECDPUN) + + /* D2N -- return the number of decNumber structs that would be */ + /* needed to contain that number of digits (and the initial */ + /* decNumber struct) safely. Note that one Unit is included in the */ + /* initial structure. Used for allocating space that is aligned on */ + /* a decNumber struct boundary. */ + #define D2N(d) \ + ((((SD2U(d)-1)*sizeof(Unit))+sizeof(decNumber)*2-1)/sizeof(decNumber)) + + /* TODIGIT -- macro to remove the leading digit from the unsigned */ + /* integer u at column cut (counting from the right, LSD=0) and */ + /* place it as an ASCII character into the character pointed to by */ + /* c. Note that cut must be <= 9, and the maximum value for u is */ + /* 2,000,000,000 (as is needed for negative exponents of */ + /* subnormals). The unsigned integer pow is used as a temporary */ + /* variable. */ + #define TODIGIT(u, cut, c, pow) { \ + *(c)='0'; \ + pow=DECPOWERS[cut]*2; \ + if ((u)>pow) { \ + pow*=4; \ + if ((u)>=pow) {(u)-=pow; *(c)+=8;} \ + pow/=2; \ + if ((u)>=pow) {(u)-=pow; *(c)+=4;} \ + pow/=2; \ + } \ + if ((u)>=pow) {(u)-=pow; *(c)+=2;} \ + pow/=2; \ + if ((u)>=pow) {(u)-=pow; *(c)+=1;} \ + } + + /* ---------------------------------------------------------------- */ + /* Definitions for fixed-precision modules (only valid after */ + /* decSingle.h, decDouble.h, or decQuad.h has been included) */ + /* ---------------------------------------------------------------- */ + + /* bcdnum -- a structure describing a format-independent finite */ + /* number, whose coefficient is a string of bcd8 uBytes */ + typedef struct { + uByte *msd; /* -> most significant digit */ + uByte *lsd; /* -> least ditto */ + uInt sign; /* 0=positive, DECFLOAT_Sign=negative */ + Int exponent; /* Unadjusted signed exponent (q), or */ + /* DECFLOAT_NaN etc. for a special */ + } bcdnum; + + /* Test if exponent or bcdnum exponent must be a special, etc. */ + #define EXPISSPECIAL(exp) ((exp)>=DECFLOAT_MinSp) + #define EXPISINF(exp) (exp==DECFLOAT_Inf) + #define EXPISNAN(exp) (exp==DECFLOAT_qNaN || exp==DECFLOAT_sNaN) + #define NUMISSPECIAL(num) (EXPISSPECIAL((num)->exponent)) + + /* Refer to a 32-bit word or byte in a decFloat (df) by big-endian */ + /* (array) notation (the 0 word or byte contains the sign bit), */ + /* automatically adjusting for endianness; similarly address a word */ + /* in the next-wider format (decFloatWider, or dfw) */ + #define DECWORDS (DECBYTES/4) + #define DECWWORDS (DECWBYTES/4) + #if DECLITEND + #define DFWORD(df, off) ((df)->words[DECWORDS-1-(off)]) + #define DFBYTE(df, off) ((df)->bytes[DECBYTES-1-(off)]) + #define DFWWORD(dfw, off) ((dfw)->words[DECWWORDS-1-(off)]) + #else + #define DFWORD(df, off) ((df)->words[off]) + #define DFBYTE(df, off) ((df)->bytes[off]) + #define DFWWORD(dfw, off) ((dfw)->words[off]) + #endif + + /* Tests for sign or specials, directly on DECFLOATs */ + #define DFISSIGNED(df) (DFWORD(df, 0)&0x80000000) + #define DFISSPECIAL(df) ((DFWORD(df, 0)&0x78000000)==0x78000000) + #define DFISINF(df) ((DFWORD(df, 0)&0x7c000000)==0x78000000) + #define DFISNAN(df) ((DFWORD(df, 0)&0x7c000000)==0x7c000000) + #define DFISQNAN(df) ((DFWORD(df, 0)&0x7e000000)==0x7c000000) + #define DFISSNAN(df) ((DFWORD(df, 0)&0x7e000000)==0x7e000000) + + /* Shared lookup tables */ +#include "decCommonSymbols.h" + extern const uInt DECCOMBMSD[64]; /* Combination field -> MSD */ + extern const uInt DECCOMBFROM[48]; /* exp+msd -> Combination */ + + /* Private generic (utility) routine */ + #if DECCHECK || DECTRACE + extern void decShowNum(const bcdnum *, const char *); + #endif + + /* Format-dependent macros and constants */ + #if defined(DECPMAX) + + /* Useful constants */ + #define DECPMAX9 (ROUNDUP(DECPMAX, 9)/9) /* 'Pmax' in 10**9s */ + /* Top words for a zero */ + #define SINGLEZERO 0x22500000 + #define DOUBLEZERO 0x22380000 + #define QUADZERO 0x22080000 + /* [ZEROWORD is defined to be one of these in the DFISZERO macro] */ + + /* Format-dependent common tests: */ + /* DFISZERO -- test for (any) zero */ + /* DFISCCZERO -- test for coefficient continuation being zero */ + /* DFISCC01 -- test for coefficient contains only 0s and 1s */ + /* DFISINT -- test for finite and exponent q=0 */ + /* DFISUINT01 -- test for sign=0, finite, exponent q=0, and */ + /* MSD=0 or 1 */ + /* ZEROWORD is also defined here. */ + /* In DFISZERO the first test checks the least-significant word */ + /* (most likely to be non-zero); the penultimate tests MSD and */ + /* DPDs in the signword, and the final test excludes specials and */ + /* MSD>7. DFISINT similarly has to allow for the two forms of */ + /* MSD codes. DFISUINT01 only has to allow for one form of MSD */ + /* code. */ + #if DECPMAX==7 + #define ZEROWORD SINGLEZERO + /* [test macros not needed except for Zero] */ + #define DFISZERO(df) ((DFWORD(df, 0)&0x1c0fffff)==0 \ + && (DFWORD(df, 0)&0x60000000)!=0x60000000) + #elif DECPMAX==16 + #define ZEROWORD DOUBLEZERO + #define DFISZERO(df) ((DFWORD(df, 1)==0 \ + && (DFWORD(df, 0)&0x1c03ffff)==0 \ + && (DFWORD(df, 0)&0x60000000)!=0x60000000)) + #define DFISINT(df) ((DFWORD(df, 0)&0x63fc0000)==0x22380000 \ + ||(DFWORD(df, 0)&0x7bfc0000)==0x6a380000) + #define DFISUINT01(df) ((DFWORD(df, 0)&0xfbfc0000)==0x22380000) + #define DFISCCZERO(df) (DFWORD(df, 1)==0 \ + && (DFWORD(df, 0)&0x0003ffff)==0) + #define DFISCC01(df) ((DFWORD(df, 0)&~0xfffc9124)==0 \ + && (DFWORD(df, 1)&~0x49124491)==0) + #elif DECPMAX==34 + #define ZEROWORD QUADZERO + #define DFISZERO(df) ((DFWORD(df, 3)==0 \ + && DFWORD(df, 2)==0 \ + && DFWORD(df, 1)==0 \ + && (DFWORD(df, 0)&0x1c003fff)==0 \ + && (DFWORD(df, 0)&0x60000000)!=0x60000000)) + #define DFISINT(df) ((DFWORD(df, 0)&0x63ffc000)==0x22080000 \ + ||(DFWORD(df, 0)&0x7bffc000)==0x6a080000) + #define DFISUINT01(df) ((DFWORD(df, 0)&0xfbffc000)==0x22080000) + #define DFISCCZERO(df) (DFWORD(df, 3)==0 \ + && DFWORD(df, 2)==0 \ + && DFWORD(df, 1)==0 \ + && (DFWORD(df, 0)&0x00003fff)==0) + + #define DFISCC01(df) ((DFWORD(df, 0)&~0xffffc912)==0 \ + && (DFWORD(df, 1)&~0x44912449)==0 \ + && (DFWORD(df, 2)&~0x12449124)==0 \ + && (DFWORD(df, 3)&~0x49124491)==0) + #endif + + /* Macros to test if a certain 10 bits of a uInt or pair of uInts */ + /* are a canonical declet [higher or lower bits are ignored]. */ + /* declet is at offset 0 (from the right) in a uInt: */ + #define CANONDPD(dpd) (((dpd)&0x300)==0 || ((dpd)&0x6e)!=0x6e) + /* declet is at offset k (a multiple of 2) in a uInt: */ + #define CANONDPDOFF(dpd, k) (((dpd)&(0x300<<(k)))==0 \ + || ((dpd)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k))) + /* declet is at offset k (a multiple of 2) in a pair of uInts: */ + /* [the top 2 bits will always be in the more-significant uInt] */ + #define CANONDPDTWO(hi, lo, k) (((hi)&(0x300>>(32-(k))))==0 \ + || ((hi)&(0x6e>>(32-(k))))!=(0x6e>>(32-(k))) \ + || ((lo)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k))) + + /* Macro to test whether a full-length (length DECPMAX) BCD8 */ + /* coefficient is zero */ + /* test just the LSWord first, then the remainder */ + #if DECPMAX==7 + #define ISCOEFFZERO(u) (UINTAT((u)+DECPMAX-4)==0 \ + && UINTAT((u)+DECPMAX-7)==0) + #elif DECPMAX==16 + #define ISCOEFFZERO(u) (UINTAT((u)+DECPMAX-4)==0 \ + && (UINTAT((u)+DECPMAX-8)+UINTAT((u)+DECPMAX-12) \ + +UINTAT((u)+DECPMAX-16))==0) + #elif DECPMAX==34 + #define ISCOEFFZERO(u) (UINTAT((u)+DECPMAX-4)==0 \ + && (UINTAT((u)+DECPMAX-8) +UINTAT((u)+DECPMAX-12) \ + +UINTAT((u)+DECPMAX-16)+UINTAT((u)+DECPMAX-20) \ + +UINTAT((u)+DECPMAX-24)+UINTAT((u)+DECPMAX-28) \ + +UINTAT((u)+DECPMAX-32)+USHORTAT((u)+DECPMAX-34))==0) + #endif + + /* Macros and masks for the exponent continuation field and MSD */ + /* Get the exponent continuation from a decFloat *df as an Int */ + #define GETECON(df) ((Int)((DFWORD((df), 0)&0x03ffffff)>>(32-6-DECECONL))) + /* Ditto, from the next-wider format */ + #define GETWECON(df) ((Int)((DFWWORD((df), 0)&0x03ffffff)>>(32-6-DECWECONL))) + /* Get the biased exponent similarly */ + #define GETEXP(df) ((Int)(DECCOMBEXP[DFWORD((df), 0)>>26]+GETECON(df))) + /* Get the unbiased exponent similarly */ + #define GETEXPUN(df) ((Int)GETEXP(df)-DECBIAS) + /* Get the MSD similarly (as uInt) */ + #define GETMSD(df) (DECCOMBMSD[DFWORD((df), 0)>>26]) + + /* Compile-time computes of the exponent continuation field masks */ + /* full exponent continuation field: */ + #define ECONMASK ((0x03ffffff>>(32-6-DECECONL))<<(32-6-DECECONL)) + /* same, not including its first digit (the qNaN/sNaN selector): */ + #define ECONNANMASK ((0x01ffffff>>(32-6-DECECONL))<<(32-6-DECECONL)) + + /* Macros to decode the coefficient in a finite decFloat *df into */ + /* a BCD string (uByte *bcdin) of length DECPMAX uBytes */ + + /* In-line sequence to convert 10 bits at right end of uInt dpd */ + /* to three BCD8 digits starting at uByte u. Note that an extra */ + /* byte is written to the right of the three digits because this */ + /* moves four at a time for speed; the alternative macro moves */ + /* exactly three bytes */ + #define dpd2bcd8(u, dpd) { \ + UINTAT(u)=UINTAT(&DPD2BCD8[((dpd)&0x3ff)*4]);} + + #define dpd2bcd83(u, dpd) { \ + *(u)=DPD2BCD8[((dpd)&0x3ff)*4]; \ + *(u+1)=DPD2BCD8[((dpd)&0x3ff)*4+1]; \ + *(u+2)=DPD2BCD8[((dpd)&0x3ff)*4+2];} + + /* Decode the declets. After extracting each one, it is decoded */ + /* to BCD8 using a table lookup (also used for variable-length */ + /* decode). Each DPD decode is 3 bytes BCD8 plus a one-byte */ + /* length which is not used, here). Fixed-length 4-byte moves */ + /* are fast, however, almost everywhere, and so are used except */ + /* for the final three bytes (to avoid overrun). The code below */ + /* is 36 instructions for Doubles and about 70 for Quads, even */ + /* on IA32. */ + + /* Two macros are defined for each format: */ + /* GETCOEFF extracts the coefficient of the current format */ + /* GETWCOEFF extracts the coefficient of the next-wider format. */ + /* The latter is a copy of the next-wider GETCOEFF using DFWWORD. */ + + #if DECPMAX==7 + #define GETCOEFF(df, bcd) { \ + uInt sourhi=DFWORD(df, 0); \ + *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ + dpd2bcd8(bcd+1, sourhi>>10); \ + dpd2bcd83(bcd+4, sourhi);} + #define GETWCOEFF(df, bcd) { \ + uInt sourhi=DFWWORD(df, 0); \ + uInt sourlo=DFWWORD(df, 1); \ + *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ + dpd2bcd8(bcd+1, sourhi>>8); \ + dpd2bcd8(bcd+4, (sourhi<<2) | (sourlo>>30)); \ + dpd2bcd8(bcd+7, sourlo>>20); \ + dpd2bcd8(bcd+10, sourlo>>10); \ + dpd2bcd83(bcd+13, sourlo);} + + #elif DECPMAX==16 + #define GETCOEFF(df, bcd) { \ + uInt sourhi=DFWORD(df, 0); \ + uInt sourlo=DFWORD(df, 1); \ + *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ + dpd2bcd8(bcd+1, sourhi>>8); \ + dpd2bcd8(bcd+4, (sourhi<<2) | (sourlo>>30)); \ + dpd2bcd8(bcd+7, sourlo>>20); \ + dpd2bcd8(bcd+10, sourlo>>10); \ + dpd2bcd83(bcd+13, sourlo);} + #define GETWCOEFF(df, bcd) { \ + uInt sourhi=DFWWORD(df, 0); \ + uInt sourmh=DFWWORD(df, 1); \ + uInt sourml=DFWWORD(df, 2); \ + uInt sourlo=DFWWORD(df, 3); \ + *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ + dpd2bcd8(bcd+1, sourhi>>4); \ + dpd2bcd8(bcd+4, ((sourhi)<<6) | (sourmh>>26)); \ + dpd2bcd8(bcd+7, sourmh>>16); \ + dpd2bcd8(bcd+10, sourmh>>6); \ + dpd2bcd8(bcd+13, ((sourmh)<<4) | (sourml>>28)); \ + dpd2bcd8(bcd+16, sourml>>18); \ + dpd2bcd8(bcd+19, sourml>>8); \ + dpd2bcd8(bcd+22, ((sourml)<<2) | (sourlo>>30)); \ + dpd2bcd8(bcd+25, sourlo>>20); \ + dpd2bcd8(bcd+28, sourlo>>10); \ + dpd2bcd83(bcd+31, sourlo);} + + #elif DECPMAX==34 + #define GETCOEFF(df, bcd) { \ + uInt sourhi=DFWORD(df, 0); \ + uInt sourmh=DFWORD(df, 1); \ + uInt sourml=DFWORD(df, 2); \ + uInt sourlo=DFWORD(df, 3); \ + *(bcd)=(uByte)DECCOMBMSD[sourhi>>26]; \ + dpd2bcd8(bcd+1, sourhi>>4); \ + dpd2bcd8(bcd+4, ((sourhi)<<6) | (sourmh>>26)); \ + dpd2bcd8(bcd+7, sourmh>>16); \ + dpd2bcd8(bcd+10, sourmh>>6); \ + dpd2bcd8(bcd+13, ((sourmh)<<4) | (sourml>>28)); \ + dpd2bcd8(bcd+16, sourml>>18); \ + dpd2bcd8(bcd+19, sourml>>8); \ + dpd2bcd8(bcd+22, ((sourml)<<2) | (sourlo>>30)); \ + dpd2bcd8(bcd+25, sourlo>>20); \ + dpd2bcd8(bcd+28, sourlo>>10); \ + dpd2bcd83(bcd+31, sourlo);} + + #define GETWCOEFF(df, bcd) {??} /* [should never be used] */ + #endif + + /* Macros to decode the coefficient in a finite decFloat *df into */ + /* a base-billion uInt array, with the least-significant */ + /* 0-999999999 'digit' at offset 0. */ + + /* Decode the declets. After extracting each one, it is decoded */ + /* to binary using a table lookup. Three tables are used; one */ + /* the usual DPD to binary, the other two pre-multiplied by 1000 */ + /* and 1000000 to avoid multiplication during decode. These */ + /* tables can also be used for multiplying up the MSD as the DPD */ + /* code for 0 through 9 is the identity. */ + #define DPD2BIN0 DPD2BIN /* for prettier code */ + + #if DECPMAX==7 + #define GETCOEFFBILL(df, buf) { \ + uInt sourhi=DFWORD(df, 0); \ + (buf)[0]=DPD2BIN0[sourhi&0x3ff] \ + +DPD2BINK[(sourhi>>10)&0x3ff] \ + +DPD2BINM[DECCOMBMSD[sourhi>>26]];} + + #elif DECPMAX==16 + #define GETCOEFFBILL(df, buf) { \ + uInt sourhi, sourlo; \ + sourlo=DFWORD(df, 1); \ + (buf)[0]=DPD2BIN0[sourlo&0x3ff] \ + +DPD2BINK[(sourlo>>10)&0x3ff] \ + +DPD2BINM[(sourlo>>20)&0x3ff]; \ + sourhi=DFWORD(df, 0); \ + (buf)[1]=DPD2BIN0[((sourhi<<2) | (sourlo>>30))&0x3ff] \ + +DPD2BINK[(sourhi>>8)&0x3ff] \ + +DPD2BINM[DECCOMBMSD[sourhi>>26]];} + + #elif DECPMAX==34 + #define GETCOEFFBILL(df, buf) { \ + uInt sourhi, sourmh, sourml, sourlo; \ + sourlo=DFWORD(df, 3); \ + (buf)[0]=DPD2BIN0[sourlo&0x3ff] \ + +DPD2BINK[(sourlo>>10)&0x3ff] \ + +DPD2BINM[(sourlo>>20)&0x3ff]; \ + sourml=DFWORD(df, 2); \ + (buf)[1]=DPD2BIN0[((sourml<<2) | (sourlo>>30))&0x3ff] \ + +DPD2BINK[(sourml>>8)&0x3ff] \ + +DPD2BINM[(sourml>>18)&0x3ff]; \ + sourmh=DFWORD(df, 1); \ + (buf)[2]=DPD2BIN0[((sourmh<<4) | (sourml>>28))&0x3ff] \ + +DPD2BINK[(sourmh>>6)&0x3ff] \ + +DPD2BINM[(sourmh>>16)&0x3ff]; \ + sourhi=DFWORD(df, 0); \ + (buf)[3]=DPD2BIN0[((sourhi<<6) | (sourmh>>26))&0x3ff] \ + +DPD2BINK[(sourhi>>4)&0x3ff] \ + +DPD2BINM[DECCOMBMSD[sourhi>>26]];} + + #endif + + /* Macros to decode the coefficient in a finite decFloat *df into */ + /* a base-thousand uInt array, with the least-significant 0-999 */ + /* 'digit' at offset 0. */ + + /* Decode the declets. After extracting each one, it is decoded */ + /* to binary using a table lookup. */ + #if DECPMAX==7 + #define GETCOEFFTHOU(df, buf) { \ + uInt sourhi=DFWORD(df, 0); \ + (buf)[0]=DPD2BIN[sourhi&0x3ff]; \ + (buf)[1]=DPD2BIN[(sourhi>>10)&0x3ff]; \ + (buf)[2]=DECCOMBMSD[sourhi>>26];} + + #elif DECPMAX==16 + #define GETCOEFFTHOU(df, buf) { \ + uInt sourhi, sourlo; \ + sourlo=DFWORD(df, 1); \ + (buf)[0]=DPD2BIN[sourlo&0x3ff]; \ + (buf)[1]=DPD2BIN[(sourlo>>10)&0x3ff]; \ + (buf)[2]=DPD2BIN[(sourlo>>20)&0x3ff]; \ + sourhi=DFWORD(df, 0); \ + (buf)[3]=DPD2BIN[((sourhi<<2) | (sourlo>>30))&0x3ff]; \ + (buf)[4]=DPD2BIN[(sourhi>>8)&0x3ff]; \ + (buf)[5]=DECCOMBMSD[sourhi>>26];} + + #elif DECPMAX==34 + #define GETCOEFFTHOU(df, buf) { \ + uInt sourhi, sourmh, sourml, sourlo; \ + sourlo=DFWORD(df, 3); \ + (buf)[0]=DPD2BIN[sourlo&0x3ff]; \ + (buf)[1]=DPD2BIN[(sourlo>>10)&0x3ff]; \ + (buf)[2]=DPD2BIN[(sourlo>>20)&0x3ff]; \ + sourml=DFWORD(df, 2); \ + (buf)[3]=DPD2BIN[((sourml<<2) | (sourlo>>30))&0x3ff]; \ + (buf)[4]=DPD2BIN[(sourml>>8)&0x3ff]; \ + (buf)[5]=DPD2BIN[(sourml>>18)&0x3ff]; \ + sourmh=DFWORD(df, 1); \ + (buf)[6]=DPD2BIN[((sourmh<<4) | (sourml>>28))&0x3ff]; \ + (buf)[7]=DPD2BIN[(sourmh>>6)&0x3ff]; \ + (buf)[8]=DPD2BIN[(sourmh>>16)&0x3ff]; \ + sourhi=DFWORD(df, 0); \ + (buf)[9]=DPD2BIN[((sourhi<<6) | (sourmh>>26))&0x3ff]; \ + (buf)[10]=DPD2BIN[(sourhi>>4)&0x3ff]; \ + (buf)[11]=DECCOMBMSD[sourhi>>26];} + + #endif + + /* Set a decFloat to the maximum positive finite number (Nmax) */ + #if DECPMAX==7 + #define DFSETNMAX(df) \ + {DFWORD(df, 0)=0x77f3fcff;} + #elif DECPMAX==16 + #define DFSETNMAX(df) \ + {DFWORD(df, 0)=0x77fcff3f; \ + DFWORD(df, 1)=0xcff3fcff;} + #elif DECPMAX==34 + #define DFSETNMAX(df) \ + {DFWORD(df, 0)=0x77ffcff3; \ + DFWORD(df, 1)=0xfcff3fcf; \ + DFWORD(df, 2)=0xf3fcff3f; \ + DFWORD(df, 3)=0xcff3fcff;} + #endif + + /* [end of format-dependent macros and constants] */ + #endif + +#else + #error decNumberLocal included more than once +#endif diff --git a/include/libdecnumber/dpd/decimal128.h b/include/libdecnumber/dpd/decimal128.h new file mode 100644 index 0000000..f8f5b5a --- /dev/null +++ b/include/libdecnumber/dpd/decimal128.h @@ -0,0 +1,101 @@ +/* Decimal 128-bit format module header for the decNumber C Library. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------ */ +/* Decimal 128-bit format module header */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECIMAL128) + #define DECIMAL128 + #define DEC128NAME "decimal128" /* Short name */ + #define DEC128FULLNAME "Decimal 128-bit Number" /* Verbose name */ + #define DEC128AUTHOR "Mike Cowlishaw" /* Who to blame */ + + /* parameters for decimal128s */ + #define DECIMAL128_Bytes 16 /* length */ + #define DECIMAL128_Pmax 34 /* maximum precision (digits) */ + #define DECIMAL128_Emax 6144 /* maximum adjusted exponent */ + #define DECIMAL128_Emin -6143 /* minimum adjusted exponent */ + #define DECIMAL128_Bias 6176 /* bias for the exponent */ + #define DECIMAL128_String 43 /* maximum string length, +1 */ + #define DECIMAL128_EconL 12 /* exp. continuation length */ + /* highest biased exponent (Elimit-1) */ + #define DECIMAL128_Ehigh (DECIMAL128_Emax+DECIMAL128_Bias-DECIMAL128_Pmax+1) + + /* check enough digits, if pre-defined */ + #if defined(DECNUMDIGITS) + #if (DECNUMDIGITS<DECIMAL128_Pmax) + #error decimal128.h needs pre-defined DECNUMDIGITS>=34 for safe use + #endif + #endif + + #ifndef DECNUMDIGITS + #define DECNUMDIGITS DECIMAL128_Pmax /* size if not already defined*/ + #endif + #ifndef DECNUMBER + #include "decNumber.h" /* context and number library */ + #endif + + /* Decimal 128-bit type, accessible by bytes */ + typedef struct { + uint8_t bytes[DECIMAL128_Bytes]; /* decimal128: 1, 5, 12, 110 bits*/ + } decimal128; + + /* special values [top byte excluding sign bit; last two bits are */ + /* don't-care for Infinity on input, last bit don't-care for NaN] */ + #if !defined(DECIMAL_NaN) + #define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */ + #define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */ + #define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */ + #endif + + #include "decimal128Local.h" + + /* ---------------------------------------------------------------- */ + /* Routines */ + /* ---------------------------------------------------------------- */ + + #include "decimal128Symbols.h" + + /* String conversions */ + decimal128 * decimal128FromString(decimal128 *, const char *, decContext *); + char * decimal128ToString(const decimal128 *, char *); + char * decimal128ToEngString(const decimal128 *, char *); + + /* decNumber conversions */ + decimal128 * decimal128FromNumber(decimal128 *, const decNumber *, + decContext *); + decNumber * decimal128ToNumber(const decimal128 *, decNumber *); + + /* Format-dependent utilities */ + uint32_t decimal128IsCanonical(const decimal128 *); + decimal128 * decimal128Canonical(decimal128 *, const decimal128 *); + +#endif diff --git a/include/libdecnumber/dpd/decimal128Local.h b/include/libdecnumber/dpd/decimal128Local.h new file mode 100644 index 0000000..9765427 --- /dev/null +++ b/include/libdecnumber/dpd/decimal128Local.h @@ -0,0 +1,47 @@ +/* Local definitions for use with the decNumber C Library. + Copyright (C) 2007 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#if !defined(DECIMAL128LOCAL) + +/* The compiler needs sign manipulation functions for decimal128 which + are not part of the decNumber package. */ + +/* Set sign; this assumes the sign was previously zero. */ +#define decimal128SetSign(d,b) \ + { (d)->bytes[WORDS_BIGENDIAN ? 0 : 15] |= ((unsigned) (b) << 7); } + +/* Clear sign. */ +#define decimal128ClearSign(d) \ + { (d)->bytes[WORDS_BIGENDIAN ? 0 : 15] &= ~0x80; } + +/* Flip sign. */ +#define decimal128FlipSign(d) \ + { (d)->bytes[WORDS_BIGENDIAN ? 0 : 15] ^= 0x80; } + +#endif diff --git a/include/libdecnumber/dpd/decimal32.h b/include/libdecnumber/dpd/decimal32.h new file mode 100644 index 0000000..0d53046 --- /dev/null +++ b/include/libdecnumber/dpd/decimal32.h @@ -0,0 +1,99 @@ +/* Decimal 32-bit format module header for the decNumber C Library. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------ */ +/* Decimal 32-bit format module header */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECIMAL32) + #define DECIMAL32 + #define DEC32NAME "decimal32" /* Short name */ + #define DEC32FULLNAME "Decimal 32-bit Number" /* Verbose name */ + #define DEC32AUTHOR "Mike Cowlishaw" /* Who to blame */ + + /* parameters for decimal32s */ + #define DECIMAL32_Bytes 4 /* length */ + #define DECIMAL32_Pmax 7 /* maximum precision (digits) */ + #define DECIMAL32_Emax 96 /* maximum adjusted exponent */ + #define DECIMAL32_Emin -95 /* minimum adjusted exponent */ + #define DECIMAL32_Bias 101 /* bias for the exponent */ + #define DECIMAL32_String 15 /* maximum string length, +1 */ + #define DECIMAL32_EconL 6 /* exp. continuation length */ + /* highest biased exponent (Elimit-1) */ + #define DECIMAL32_Ehigh (DECIMAL32_Emax+DECIMAL32_Bias-DECIMAL32_Pmax+1) + + /* check enough digits, if pre-defined */ + #if defined(DECNUMDIGITS) + #if (DECNUMDIGITS<DECIMAL32_Pmax) + #error decimal32.h needs pre-defined DECNUMDIGITS>=7 for safe use + #endif + #endif + + #ifndef DECNUMDIGITS + #define DECNUMDIGITS DECIMAL32_Pmax /* size if not already defined*/ + #endif + #ifndef DECNUMBER + #include "decNumber.h" /* context and number library */ + #endif + + /* Decimal 32-bit type, accessible by bytes */ + typedef struct { + uint8_t bytes[DECIMAL32_Bytes]; /* decimal32: 1, 5, 6, 20 bits*/ + } decimal32; + + /* special values [top byte excluding sign bit; last two bits are */ + /* don't-care for Infinity on input, last bit don't-care for NaN] */ + #if !defined(DECIMAL_NaN) + #define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */ + #define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */ + #define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */ + #endif + + /* ---------------------------------------------------------------- */ + /* Routines */ + /* ---------------------------------------------------------------- */ + + #include "decimal32Symbols.h" + + /* String conversions */ + decimal32 * decimal32FromString(decimal32 *, const char *, decContext *); + char * decimal32ToString(const decimal32 *, char *); + char * decimal32ToEngString(const decimal32 *, char *); + + /* decNumber conversions */ + decimal32 * decimal32FromNumber(decimal32 *, const decNumber *, + decContext *); + decNumber * decimal32ToNumber(const decimal32 *, decNumber *); + + /* Format-dependent utilities */ + uint32_t decimal32IsCanonical(const decimal32 *); + decimal32 * decimal32Canonical(decimal32 *, const decimal32 *); + +#endif diff --git a/include/libdecnumber/dpd/decimal64.h b/include/libdecnumber/dpd/decimal64.h new file mode 100644 index 0000000..549b626 --- /dev/null +++ b/include/libdecnumber/dpd/decimal64.h @@ -0,0 +1,101 @@ +/* Decimal 64-bit format module header for the decNumber C Library. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------ */ +/* Decimal 64-bit format module header */ +/* ------------------------------------------------------------------ */ + +#if !defined(DECIMAL64) + #define DECIMAL64 + #define DEC64NAME "decimal64" /* Short name */ + #define DEC64FULLNAME "Decimal 64-bit Number" /* Verbose name */ + #define DEC64AUTHOR "Mike Cowlishaw" /* Who to blame */ + + + /* parameters for decimal64s */ + #define DECIMAL64_Bytes 8 /* length */ + #define DECIMAL64_Pmax 16 /* maximum precision (digits) */ + #define DECIMAL64_Emax 384 /* maximum adjusted exponent */ + #define DECIMAL64_Emin -383 /* minimum adjusted exponent */ + #define DECIMAL64_Bias 398 /* bias for the exponent */ + #define DECIMAL64_String 24 /* maximum string length, +1 */ + #define DECIMAL64_EconL 8 /* exp. continuation length */ + /* highest biased exponent (Elimit-1) */ + #define DECIMAL64_Ehigh (DECIMAL64_Emax+DECIMAL64_Bias-DECIMAL64_Pmax+1) + + /* check enough digits, if pre-defined */ + #if defined(DECNUMDIGITS) + #if (DECNUMDIGITS<DECIMAL64_Pmax) + #error decimal64.h needs pre-defined DECNUMDIGITS>=16 for safe use + #endif + #endif + + + #ifndef DECNUMDIGITS + #define DECNUMDIGITS DECIMAL64_Pmax /* size if not already defined*/ + #endif + #ifndef DECNUMBER + #include "decNumber.h" /* context and number library */ + #endif + + /* Decimal 64-bit type, accessible by bytes */ + typedef struct { + uint8_t bytes[DECIMAL64_Bytes]; /* decimal64: 1, 5, 8, 50 bits*/ + } decimal64; + + /* special values [top byte excluding sign bit; last two bits are */ + /* don't-care for Infinity on input, last bit don't-care for NaN] */ + #if !defined(DECIMAL_NaN) + #define DECIMAL_NaN 0x7c /* 0 11111 00 NaN */ + #define DECIMAL_sNaN 0x7e /* 0 11111 10 sNaN */ + #define DECIMAL_Inf 0x78 /* 0 11110 00 Infinity */ + #endif + + /* ---------------------------------------------------------------- */ + /* Routines */ + /* ---------------------------------------------------------------- */ + + #include "decimal64Symbols.h" + + /* String conversions */ + decimal64 * decimal64FromString(decimal64 *, const char *, decContext *); + char * decimal64ToString(const decimal64 *, char *); + char * decimal64ToEngString(const decimal64 *, char *); + + /* decNumber conversions */ + decimal64 * decimal64FromNumber(decimal64 *, const decNumber *, + decContext *); + decNumber * decimal64ToNumber(const decimal64 *, decNumber *); + + /* Format-dependent utilities */ + uint32_t decimal64IsCanonical(const decimal64 *); + decimal64 * decimal64Canonical(decimal64 *, const decimal64 *); + +#endif diff --git a/libdecnumber/decContext.c b/libdecnumber/decContext.c new file mode 100644 index 0000000..8d577f4 --- /dev/null +++ b/libdecnumber/decContext.c @@ -0,0 +1,431 @@ +/* Decimal context module for the decNumber C Library. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------ */ +/* Decimal Context module */ +/* ------------------------------------------------------------------ */ +/* This module comprises the routines for handling arithmetic */ +/* context structures. */ +/* ------------------------------------------------------------------ */ + +#include <string.h> /* for strcmp */ +#include <stdio.h> /* for printf if DECCHECK */ +#include "dconfig.h" /* for GCC definitions */ +#include "decContext.h" /* context and base types */ +#include "decNumberLocal.h" /* decNumber local types, etc. */ + +#if DECCHECK +/* compile-time endian tester [assumes sizeof(Int)>1] */ +static const Int mfcone=1; /* constant 1 */ +static const Flag *mfctop=(Flag *)&mfcone; /* -> top byte */ +#define LITEND *mfctop /* named flag; 1=little-endian */ +#endif + +/* ------------------------------------------------------------------ */ +/* round-for-reround digits */ +/* ------------------------------------------------------------------ */ +const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */ + +/* ------------------------------------------------------------------ */ +/* Powers of ten (powers[n]==10**n, 0<=n<=9) */ +/* ------------------------------------------------------------------ */ +const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000, + 10000000, 100000000, 1000000000}; + +/* ------------------------------------------------------------------ */ +/* decContextClearStatus -- clear bits in current status */ +/* */ +/* context is the context structure to be queried */ +/* mask indicates the bits to be cleared (the status bit that */ +/* corresponds to each 1 bit in the mask is cleared) */ +/* returns context */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decContext *decContextClearStatus(decContext *context, uInt mask) { + context->status&=~mask; + return context; + } /* decContextClearStatus */ + +/* ------------------------------------------------------------------ */ +/* decContextDefault -- initialize a context structure */ +/* */ +/* context is the structure to be initialized */ +/* kind selects the required set of default values, one of: */ +/* DEC_INIT_BASE -- select ANSI X3-274 defaults */ +/* DEC_INIT_DECIMAL32 -- select IEEE 754r defaults, 32-bit */ +/* DEC_INIT_DECIMAL64 -- select IEEE 754r defaults, 64-bit */ +/* DEC_INIT_DECIMAL128 -- select IEEE 754r defaults, 128-bit */ +/* For any other value a valid context is returned, but with */ +/* Invalid_operation set in the status field. */ +/* returns a context structure with the appropriate initial values. */ +/* ------------------------------------------------------------------ */ +decContext * decContextDefault(decContext *context, Int kind) { + /* set defaults... */ + context->digits=9; /* 9 digits */ + context->emax=DEC_MAX_EMAX; /* 9-digit exponents */ + context->emin=DEC_MIN_EMIN; /* .. balanced */ + context->round=DEC_ROUND_HALF_UP; /* 0.5 rises */ + context->traps=DEC_Errors; /* all but informational */ + context->status=0; /* cleared */ + context->clamp=0; /* no clamping */ + #if DECSUBSET + context->extended=0; /* cleared */ + #endif + switch (kind) { + case DEC_INIT_BASE: + /* [use defaults] */ + break; + case DEC_INIT_DECIMAL32: + context->digits=7; /* digits */ + context->emax=96; /* Emax */ + context->emin=-95; /* Emin */ + context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ + context->traps=0; /* no traps set */ + context->clamp=1; /* clamp exponents */ + #if DECSUBSET + context->extended=1; /* set */ + #endif + break; + case DEC_INIT_DECIMAL64: + context->digits=16; /* digits */ + context->emax=384; /* Emax */ + context->emin=-383; /* Emin */ + context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ + context->traps=0; /* no traps set */ + context->clamp=1; /* clamp exponents */ + #if DECSUBSET + context->extended=1; /* set */ + #endif + break; + case DEC_INIT_DECIMAL128: + context->digits=34; /* digits */ + context->emax=6144; /* Emax */ + context->emin=-6143; /* Emin */ + context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ + context->traps=0; /* no traps set */ + context->clamp=1; /* clamp exponents */ + #if DECSUBSET + context->extended=1; /* set */ + #endif + break; + + default: /* invalid Kind */ + /* use defaults, and .. */ + decContextSetStatus(context, DEC_Invalid_operation); /* trap */ + } + + #if DECCHECK + if (LITEND!=DECLITEND) { + const char *adj; + if (LITEND) adj="little"; + else adj="big"; + printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n", + DECLITEND, adj); + } + #endif + return context;} /* decContextDefault */ + +/* ------------------------------------------------------------------ */ +/* decContextGetRounding -- return current rounding mode */ +/* */ +/* context is the context structure to be queried */ +/* returns the rounding mode */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +enum rounding decContextGetRounding(decContext *context) { + return context->round; + } /* decContextGetRounding */ + +/* ------------------------------------------------------------------ */ +/* decContextGetStatus -- return current status */ +/* */ +/* context is the context structure to be queried */ +/* returns status */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uInt decContextGetStatus(decContext *context) { + return context->status; + } /* decContextGetStatus */ + +/* ------------------------------------------------------------------ */ +/* decContextRestoreStatus -- restore bits in current status */ +/* */ +/* context is the context structure to be updated */ +/* newstatus is the source for the bits to be restored */ +/* mask indicates the bits to be restored (the status bit that */ +/* corresponds to each 1 bit in the mask is set to the value of */ +/* the correspnding bit in newstatus) */ +/* returns context */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decContext *decContextRestoreStatus(decContext *context, + uInt newstatus, uInt mask) { + context->status&=~mask; /* clear the selected bits */ + context->status|=(mask&newstatus); /* or in the new bits */ + return context; + } /* decContextRestoreStatus */ + +/* ------------------------------------------------------------------ */ +/* decContextSaveStatus -- save bits in current status */ +/* */ +/* context is the context structure to be queried */ +/* mask indicates the bits to be saved (the status bits that */ +/* correspond to each 1 bit in the mask are saved) */ +/* returns the AND of the mask and the current status */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uInt decContextSaveStatus(decContext *context, uInt mask) { + return context->status&mask; + } /* decContextSaveStatus */ + +/* ------------------------------------------------------------------ */ +/* decContextSetRounding -- set current rounding mode */ +/* */ +/* context is the context structure to be updated */ +/* newround is the value which will replace the current mode */ +/* returns context */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decContext *decContextSetRounding(decContext *context, + enum rounding newround) { + context->round=newround; + return context; + } /* decContextSetRounding */ + +/* ------------------------------------------------------------------ */ +/* decContextSetStatus -- set status and raise trap if appropriate */ +/* */ +/* context is the context structure to be updated */ +/* status is the DEC_ exception code */ +/* returns the context structure */ +/* */ +/* Control may never return from this routine, if there is a signal */ +/* handler and it takes a long jump. */ +/* ------------------------------------------------------------------ */ +decContext * decContextSetStatus(decContext *context, uInt status) { + context->status|=status; + if (status & context->traps) raise(SIGFPE); + return context;} /* decContextSetStatus */ + +/* ------------------------------------------------------------------ */ +/* decContextSetStatusFromString -- set status from a string + trap */ +/* */ +/* context is the context structure to be updated */ +/* string is a string exactly equal to one that might be returned */ +/* by decContextStatusToString */ +/* */ +/* The status bit corresponding to the string is set, and a trap */ +/* is raised if appropriate. */ +/* */ +/* returns the context structure, unless the string is equal to */ +/* DEC_Condition_MU or is not recognized. In these cases NULL is */ +/* returned. */ +/* ------------------------------------------------------------------ */ +decContext * decContextSetStatusFromString(decContext *context, + const char *string) { + if (strcmp(string, DEC_Condition_CS)==0) + return decContextSetStatus(context, DEC_Conversion_syntax); + if (strcmp(string, DEC_Condition_DZ)==0) + return decContextSetStatus(context, DEC_Division_by_zero); + if (strcmp(string, DEC_Condition_DI)==0) + return decContextSetStatus(context, DEC_Division_impossible); + if (strcmp(string, DEC_Condition_DU)==0) + return decContextSetStatus(context, DEC_Division_undefined); + if (strcmp(string, DEC_Condition_IE)==0) + return decContextSetStatus(context, DEC_Inexact); + if (strcmp(string, DEC_Condition_IS)==0) + return decContextSetStatus(context, DEC_Insufficient_storage); + if (strcmp(string, DEC_Condition_IC)==0) + return decContextSetStatus(context, DEC_Invalid_context); + if (strcmp(string, DEC_Condition_IO)==0) + return decContextSetStatus(context, DEC_Invalid_operation); + #if DECSUBSET + if (strcmp(string, DEC_Condition_LD)==0) + return decContextSetStatus(context, DEC_Lost_digits); + #endif + if (strcmp(string, DEC_Condition_OV)==0) + return decContextSetStatus(context, DEC_Overflow); + if (strcmp(string, DEC_Condition_PA)==0) + return decContextSetStatus(context, DEC_Clamped); + if (strcmp(string, DEC_Condition_RO)==0) + return decContextSetStatus(context, DEC_Rounded); + if (strcmp(string, DEC_Condition_SU)==0) + return decContextSetStatus(context, DEC_Subnormal); + if (strcmp(string, DEC_Condition_UN)==0) + return decContextSetStatus(context, DEC_Underflow); + if (strcmp(string, DEC_Condition_ZE)==0) + return context; + return NULL; /* Multiple status, or unknown */ + } /* decContextSetStatusFromString */ + +/* ------------------------------------------------------------------ */ +/* decContextSetStatusFromStringQuiet -- set status from a string */ +/* */ +/* context is the context structure to be updated */ +/* string is a string exactly equal to one that might be returned */ +/* by decContextStatusToString */ +/* */ +/* The status bit corresponding to the string is set; no trap is */ +/* raised. */ +/* */ +/* returns the context structure, unless the string is equal to */ +/* DEC_Condition_MU or is not recognized. In these cases NULL is */ +/* returned. */ +/* ------------------------------------------------------------------ */ +decContext * decContextSetStatusFromStringQuiet(decContext *context, + const char *string) { + if (strcmp(string, DEC_Condition_CS)==0) + return decContextSetStatusQuiet(context, DEC_Conversion_syntax); + if (strcmp(string, DEC_Condition_DZ)==0) + return decContextSetStatusQuiet(context, DEC_Division_by_zero); + if (strcmp(string, DEC_Condition_DI)==0) + return decContextSetStatusQuiet(context, DEC_Division_impossible); + if (strcmp(string, DEC_Condition_DU)==0) + return decContextSetStatusQuiet(context, DEC_Division_undefined); + if (strcmp(string, DEC_Condition_IE)==0) + return decContextSetStatusQuiet(context, DEC_Inexact); + if (strcmp(string, DEC_Condition_IS)==0) + return decContextSetStatusQuiet(context, DEC_Insufficient_storage); + if (strcmp(string, DEC_Condition_IC)==0) + return decContextSetStatusQuiet(context, DEC_Invalid_context); + if (strcmp(string, DEC_Condition_IO)==0) + return decContextSetStatusQuiet(context, DEC_Invalid_operation); + #if DECSUBSET + if (strcmp(string, DEC_Condition_LD)==0) + return decContextSetStatusQuiet(context, DEC_Lost_digits); + #endif + if (strcmp(string, DEC_Condition_OV)==0) + return decContextSetStatusQuiet(context, DEC_Overflow); + if (strcmp(string, DEC_Condition_PA)==0) + return decContextSetStatusQuiet(context, DEC_Clamped); + if (strcmp(string, DEC_Condition_RO)==0) + return decContextSetStatusQuiet(context, DEC_Rounded); + if (strcmp(string, DEC_Condition_SU)==0) + return decContextSetStatusQuiet(context, DEC_Subnormal); + if (strcmp(string, DEC_Condition_UN)==0) + return decContextSetStatusQuiet(context, DEC_Underflow); + if (strcmp(string, DEC_Condition_ZE)==0) + return context; + return NULL; /* Multiple status, or unknown */ + } /* decContextSetStatusFromStringQuiet */ + +/* ------------------------------------------------------------------ */ +/* decContextSetStatusQuiet -- set status without trap */ +/* */ +/* context is the context structure to be updated */ +/* status is the DEC_ exception code */ +/* returns the context structure */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decContext * decContextSetStatusQuiet(decContext *context, uInt status) { + context->status|=status; + return context;} /* decContextSetStatusQuiet */ + +/* ------------------------------------------------------------------ */ +/* decContextStatusToString -- convert status flags to a string */ +/* */ +/* context is a context with valid status field */ +/* */ +/* returns a constant string describing the condition. If multiple */ +/* (or no) flags are set, a generic constant message is returned. */ +/* ------------------------------------------------------------------ */ +const char *decContextStatusToString(const decContext *context) { + Int status=context->status; + + /* test the five IEEE first, as some of the others are ambiguous when */ + /* DECEXTFLAG=0 */ + if (status==DEC_Invalid_operation ) return DEC_Condition_IO; + if (status==DEC_Division_by_zero ) return DEC_Condition_DZ; + if (status==DEC_Overflow ) return DEC_Condition_OV; + if (status==DEC_Underflow ) return DEC_Condition_UN; + if (status==DEC_Inexact ) return DEC_Condition_IE; + + if (status==DEC_Division_impossible ) return DEC_Condition_DI; + if (status==DEC_Division_undefined ) return DEC_Condition_DU; + if (status==DEC_Rounded ) return DEC_Condition_RO; + if (status==DEC_Clamped ) return DEC_Condition_PA; + if (status==DEC_Subnormal ) return DEC_Condition_SU; + if (status==DEC_Conversion_syntax ) return DEC_Condition_CS; + if (status==DEC_Insufficient_storage ) return DEC_Condition_IS; + if (status==DEC_Invalid_context ) return DEC_Condition_IC; + #if DECSUBSET + if (status==DEC_Lost_digits ) return DEC_Condition_LD; + #endif + if (status==0 ) return DEC_Condition_ZE; + return DEC_Condition_MU; /* Multiple errors */ + } /* decContextStatusToString */ + +/* ------------------------------------------------------------------ */ +/* decContextTestSavedStatus -- test bits in saved status */ +/* */ +/* oldstatus is the status word to be tested */ +/* mask indicates the bits to be tested (the oldstatus bits that */ +/* correspond to each 1 bit in the mask are tested) */ +/* returns 1 if any of the tested bits are 1, or 0 otherwise */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uInt decContextTestSavedStatus(uInt oldstatus, uInt mask) { + return (oldstatus&mask)!=0; + } /* decContextTestSavedStatus */ + +/* ------------------------------------------------------------------ */ +/* decContextTestStatus -- test bits in current status */ +/* */ +/* context is the context structure to be updated */ +/* mask indicates the bits to be tested (the status bits that */ +/* correspond to each 1 bit in the mask are tested) */ +/* returns 1 if any of the tested bits are 1, or 0 otherwise */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uInt decContextTestStatus(decContext *context, uInt mask) { + return (context->status&mask)!=0; + } /* decContextTestStatus */ + +/* ------------------------------------------------------------------ */ +/* decContextZeroStatus -- clear all status bits */ +/* */ +/* context is the context structure to be updated */ +/* returns context */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decContext *decContextZeroStatus(decContext *context) { + context->status=0; + return context; + } /* decContextZeroStatus */ diff --git a/libdecnumber/decNumber.c b/libdecnumber/decNumber.c new file mode 100644 index 0000000..f9a624a --- /dev/null +++ b/libdecnumber/decNumber.c @@ -0,0 +1,8122 @@ +/* Decimal number arithmetic module for the decNumber C Library. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------ */ +/* Decimal Number arithmetic module */ +/* ------------------------------------------------------------------ */ +/* This module comprises the routines for General Decimal Arithmetic */ +/* as defined in the specification which may be found on the */ +/* http://www2.hursley.ibm.com/decimal web pages. It implements both */ +/* the full ('extended') arithmetic and the simpler ('subset') */ +/* arithmetic. */ +/* */ +/* Usage notes: */ +/* */ +/* 1. This code is ANSI C89 except: */ +/* */ +/* If DECDPUN>4 or DECUSE64=1, the C99 64-bit int64_t and */ +/* uint64_t types may be used. To avoid these, set DECUSE64=0 */ +/* and DECDPUN<=4 (see documentation). */ +/* */ +/* 2. The decNumber format which this library uses is optimized for */ +/* efficient processing of relatively short numbers; in particular */ +/* it allows the use of fixed sized structures and minimizes copy */ +/* and move operations. It does, however, support arbitrary */ +/* precision (up to 999,999,999 digits) and arbitrary exponent */ +/* range (Emax in the range 0 through 999,999,999 and Emin in the */ +/* range -999,999,999 through 0). Mathematical functions (for */ +/* example decNumberExp) as identified below are restricted more */ +/* tightly: digits, emax, and -emin in the context must be <= */ +/* DEC_MAX_MATH (999999), and their operand(s) must be within */ +/* these bounds. */ +/* */ +/* 3. Logical functions are further restricted; their operands must */ +/* be finite, positive, have an exponent of zero, and all digits */ +/* must be either 0 or 1. The result will only contain digits */ +/* which are 0 or 1 (and will have exponent=0 and a sign of 0). */ +/* */ +/* 4. Operands to operator functions are never modified unless they */ +/* are also specified to be the result number (which is always */ +/* permitted). Other than that case, operands must not overlap. */ +/* */ +/* 5. Error handling: the type of the error is ORed into the status */ +/* flags in the current context (decContext structure). The */ +/* SIGFPE signal is then raised if the corresponding trap-enabler */ +/* flag in the decContext is set (is 1). */ +/* */ +/* It is the responsibility of the caller to clear the status */ +/* flags as required. */ +/* */ +/* The result of any routine which returns a number will always */ +/* be a valid number (which may be a special value, such as an */ +/* Infinity or NaN). */ +/* */ +/* 6. The decNumber format is not an exchangeable concrete */ +/* representation as it comprises fields which may be machine- */ +/* dependent (packed or unpacked, or special length, for example). */ +/* Canonical conversions to and from strings are provided; other */ +/* conversions are available in separate modules. */ +/* */ +/* 7. Normally, input operands are assumed to be valid. Set DECCHECK */ +/* to 1 for extended operand checking (including NULL operands). */ +/* Results are undefined if a badly-formed structure (or a NULL */ +/* pointer to a structure) is provided, though with DECCHECK */ +/* enabled the operator routines are protected against exceptions. */ +/* (Except if the result pointer is NULL, which is unrecoverable.) */ +/* */ +/* However, the routines will never cause exceptions if they are */ +/* given well-formed operands, even if the value of the operands */ +/* is inappropriate for the operation and DECCHECK is not set. */ +/* (Except for SIGFPE, as and where documented.) */ +/* */ +/* 8. Subset arithmetic is available only if DECSUBSET is set to 1. */ +/* ------------------------------------------------------------------ */ +/* Implementation notes for maintenance of this module: */ +/* */ +/* 1. Storage leak protection: Routines which use malloc are not */ +/* permitted to use return for fastpath or error exits (i.e., */ +/* they follow strict structured programming conventions). */ +/* Instead they have a do{}while(0); construct surrounding the */ +/* code which is protected -- break may be used to exit this. */ +/* Other routines can safely use the return statement inline. */ +/* */ +/* Storage leak accounting can be enabled using DECALLOC. */ +/* */ +/* 2. All loops use the for(;;) construct. Any do construct does */ +/* not loop; it is for allocation protection as just described. */ +/* */ +/* 3. Setting status in the context must always be the very last */ +/* action in a routine, as non-0 status may raise a trap and hence */ +/* the call to set status may not return (if the handler uses long */ +/* jump). Therefore all cleanup must be done first. In general, */ +/* to achieve this status is accumulated and is only applied just */ +/* before return by calling decContextSetStatus (via decStatus). */ +/* */ +/* Routines which allocate storage cannot, in general, use the */ +/* 'top level' routines which could cause a non-returning */ +/* transfer of control. The decXxxxOp routines are safe (do not */ +/* call decStatus even if traps are set in the context) and should */ +/* be used instead (they are also a little faster). */ +/* */ +/* 4. Exponent checking is minimized by allowing the exponent to */ +/* grow outside its limits during calculations, provided that */ +/* the decFinalize function is called later. Multiplication and */ +/* division, and intermediate calculations in exponentiation, */ +/* require more careful checks because of the risk of 31-bit */ +/* overflow (the most negative valid exponent is -1999999997, for */ +/* a 999999999-digit number with adjusted exponent of -999999999). */ +/* */ +/* 5. Rounding is deferred until finalization of results, with any */ +/* 'off to the right' data being represented as a single digit */ +/* residue (in the range -1 through 9). This avoids any double- */ +/* rounding when more than one shortening takes place (for */ +/* example, when a result is subnormal). */ +/* */ +/* 6. The digits count is allowed to rise to a multiple of DECDPUN */ +/* during many operations, so whole Units are handled and exact */ +/* accounting of digits is not needed. The correct digits value */ +/* is found by decGetDigits, which accounts for leading zeros. */ +/* This must be called before any rounding if the number of digits */ +/* is not known exactly. */ +/* */ +/* 7. The multiply-by-reciprocal 'trick' is used for partitioning */ +/* numbers up to four digits, using appropriate constants. This */ +/* is not useful for longer numbers because overflow of 32 bits */ +/* would lead to 4 multiplies, which is almost as expensive as */ +/* a divide (unless a floating-point or 64-bit multiply is */ +/* assumed to be available). */ +/* */ +/* 8. Unusual abbreviations that may be used in the commentary: */ +/* lhs -- left hand side (operand, of an operation) */ +/* lsd -- least significant digit (of coefficient) */ +/* lsu -- least significant Unit (of coefficient) */ +/* msd -- most significant digit (of coefficient) */ +/* msi -- most significant item (in an array) */ +/* msu -- most significant Unit (of coefficient) */ +/* rhs -- right hand side (operand, of an operation) */ +/* +ve -- positive */ +/* -ve -- negative */ +/* ** -- raise to the power */ +/* ------------------------------------------------------------------ */ + +#include <stdlib.h> /* for malloc, free, etc. */ +#include <stdio.h> /* for printf [if needed] */ +#include <string.h> /* for strcpy */ +#include <ctype.h> /* for lower */ +#include "dconfig.h" /* for GCC definitions */ +#include "decNumber.h" /* base number library */ +#include "decNumberLocal.h" /* decNumber local types, etc. */ + +/* Constants */ +/* Public lookup table used by the D2U macro */ +const uByte d2utable[DECMAXD2U+1]=D2UTABLE; + +#define DECVERB 1 /* set to 1 for verbose DECCHECK */ +#define powers DECPOWERS /* old internal name */ + +/* Local constants */ +#define DIVIDE 0x80 /* Divide operators */ +#define REMAINDER 0x40 /* .. */ +#define DIVIDEINT 0x20 /* .. */ +#define REMNEAR 0x10 /* .. */ +#define COMPARE 0x01 /* Compare operators */ +#define COMPMAX 0x02 /* .. */ +#define COMPMIN 0x03 /* .. */ +#define COMPTOTAL 0x04 /* .. */ +#define COMPNAN 0x05 /* .. [NaN processing] */ +#define COMPSIG 0x06 /* .. [signaling COMPARE] */ +#define COMPMAXMAG 0x07 /* .. */ +#define COMPMINMAG 0x08 /* .. */ + +#define DEC_sNaN 0x40000000 /* local status: sNaN signal */ +#define BADINT (Int)0x80000000 /* most-negative Int; error indicator */ +/* Next two indicate an integer >= 10**6, and its parity (bottom bit) */ +#define BIGEVEN (Int)0x80000002 +#define BIGODD (Int)0x80000003 + +static Unit uarrone[1]={1}; /* Unit array of 1, used for incrementing */ + +/* Granularity-dependent code */ +#if DECDPUN<=4 + #define eInt Int /* extended integer */ + #define ueInt uInt /* unsigned extended integer */ + /* Constant multipliers for divide-by-power-of five using reciprocal */ + /* multiply, after removing powers of 2 by shifting, and final shift */ + /* of 17 [we only need up to **4] */ + static const uInt multies[]={131073, 26215, 5243, 1049, 210}; + /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */ + #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17) +#else + /* For DECDPUN>4 non-ANSI-89 64-bit types are needed. */ + #if !DECUSE64 + #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4 + #endif + #define eInt Long /* extended integer */ + #define ueInt uLong /* unsigned extended integer */ +#endif + +/* Local routines */ +static decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *, + decContext *, uByte, uInt *); +static Flag decBiStr(const char *, const char *, const char *); +static uInt decCheckMath(const decNumber *, decContext *, uInt *); +static void decApplyRound(decNumber *, decContext *, Int, uInt *); +static Int decCompare(const decNumber *lhs, const decNumber *rhs, Flag); +static decNumber * decCompareOp(decNumber *, const decNumber *, + const decNumber *, decContext *, + Flag, uInt *); +static void decCopyFit(decNumber *, const decNumber *, decContext *, + Int *, uInt *); +static decNumber * decDecap(decNumber *, Int); +static decNumber * decDivideOp(decNumber *, const decNumber *, + const decNumber *, decContext *, Flag, uInt *); +static decNumber * decExpOp(decNumber *, const decNumber *, + decContext *, uInt *); +static void decFinalize(decNumber *, decContext *, Int *, uInt *); +static Int decGetDigits(Unit *, Int); +static Int decGetInt(const decNumber *); +static decNumber * decLnOp(decNumber *, const decNumber *, + decContext *, uInt *); +static decNumber * decMultiplyOp(decNumber *, const decNumber *, + const decNumber *, decContext *, + uInt *); +static decNumber * decNaNs(decNumber *, const decNumber *, + const decNumber *, decContext *, uInt *); +static decNumber * decQuantizeOp(decNumber *, const decNumber *, + const decNumber *, decContext *, Flag, + uInt *); +static void decReverse(Unit *, Unit *); +static void decSetCoeff(decNumber *, decContext *, const Unit *, + Int, Int *, uInt *); +static void decSetMaxValue(decNumber *, decContext *); +static void decSetOverflow(decNumber *, decContext *, uInt *); +static void decSetSubnormal(decNumber *, decContext *, Int *, uInt *); +static Int decShiftToLeast(Unit *, Int, Int); +static Int decShiftToMost(Unit *, Int, Int); +static void decStatus(decNumber *, uInt, decContext *); +static void decToString(const decNumber *, char[], Flag); +static decNumber * decTrim(decNumber *, decContext *, Flag, Int *); +static Int decUnitAddSub(const Unit *, Int, const Unit *, Int, Int, + Unit *, Int); +static Int decUnitCompare(const Unit *, Int, const Unit *, Int, Int); + +#if !DECSUBSET +/* decFinish == decFinalize when no subset arithmetic needed */ +#define decFinish(a,b,c,d) decFinalize(a,b,c,d) +#else +static void decFinish(decNumber *, decContext *, Int *, uInt *); +static decNumber * decRoundOperand(const decNumber *, decContext *, uInt *); +#endif + +/* Local macros */ +/* masked special-values bits */ +#define SPECIALARG (rhs->bits & DECSPECIAL) +#define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL) + +/* Diagnostic macros, etc. */ +#if DECALLOC +/* Handle malloc/free accounting. If enabled, our accountable routines */ +/* are used; otherwise the code just goes straight to the system malloc */ +/* and free routines. */ +#define malloc(a) decMalloc(a) +#define free(a) decFree(a) +#define DECFENCE 0x5a /* corruption detector */ +/* 'Our' malloc and free: */ +static void *decMalloc(size_t); +static void decFree(void *); +uInt decAllocBytes=0; /* count of bytes allocated */ +/* Note that DECALLOC code only checks for storage buffer overflow. */ +/* To check for memory leaks, the decAllocBytes variable must be */ +/* checked to be 0 at appropriate times (e.g., after the test */ +/* harness completes a set of tests). This checking may be unreliable */ +/* if the testing is done in a multi-thread environment. */ +#endif + +#if DECCHECK +/* Optional checking routines. Enabling these means that decNumber */ +/* and decContext operands to operator routines are checked for */ +/* correctness. This roughly doubles the execution time of the */ +/* fastest routines (and adds 600+ bytes), so should not normally be */ +/* used in 'production'. */ +/* decCheckInexact is used to check that inexact results have a full */ +/* complement of digits (where appropriate -- this is not the case */ +/* for Quantize, for example) */ +#define DECUNRESU ((decNumber *)(void *)0xffffffff) +#define DECUNUSED ((const decNumber *)(void *)0xffffffff) +#define DECUNCONT ((decContext *)(void *)(0xffffffff)) +static Flag decCheckOperands(decNumber *, const decNumber *, + const decNumber *, decContext *); +static Flag decCheckNumber(const decNumber *); +static void decCheckInexact(const decNumber *, decContext *); +#endif + +#if DECTRACE || DECCHECK +/* Optional trace/debugging routines (may or may not be used) */ +void decNumberShow(const decNumber *); /* displays the components of a number */ +static void decDumpAr(char, const Unit *, Int); +#endif + +/* ================================================================== */ +/* Conversions */ +/* ================================================================== */ + +/* ------------------------------------------------------------------ */ +/* from-int32 -- conversion from Int or uInt */ +/* */ +/* dn is the decNumber to receive the integer */ +/* in or uin is the integer to be converted */ +/* returns dn */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberFromInt32(decNumber *dn, Int in) { + uInt unsig; + if (in>=0) unsig=in; + else { /* negative (possibly BADINT) */ + if (in==BADINT) unsig=(uInt)1073741824*2; /* special case */ + else unsig=-in; /* invert */ + } + /* in is now positive */ + decNumberFromUInt32(dn, unsig); + if (in<0) dn->bits=DECNEG; /* sign needed */ + return dn; + } /* decNumberFromInt32 */ + +decNumber * decNumberFromUInt32(decNumber *dn, uInt uin) { + Unit *up; /* work pointer */ + decNumberZero(dn); /* clean */ + if (uin==0) return dn; /* [or decGetDigits bad call] */ + for (up=dn->lsu; uin>0; up++) { + *up=(Unit)(uin%(DECDPUNMAX+1)); + uin=uin/(DECDPUNMAX+1); + } + dn->digits=decGetDigits(dn->lsu, up-dn->lsu); + return dn; + } /* decNumberFromUInt32 */ + +/* ------------------------------------------------------------------ */ +/* to-int32 -- conversion to Int or uInt */ +/* */ +/* dn is the decNumber to convert */ +/* set is the context for reporting errors */ +/* returns the converted decNumber, or 0 if Invalid is set */ +/* */ +/* Invalid is set if the decNumber does not have exponent==0 or if */ +/* it is a NaN, Infinite, or out-of-range. */ +/* ------------------------------------------------------------------ */ +Int decNumberToInt32(const decNumber *dn, decContext *set) { + #if DECCHECK + if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; + #endif + + /* special or too many digits, or bad exponent */ + if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0) ; /* bad */ + else { /* is a finite integer with 10 or fewer digits */ + Int d; /* work */ + const Unit *up; /* .. */ + uInt hi=0, lo; /* .. */ + up=dn->lsu; /* -> lsu */ + lo=*up; /* get 1 to 9 digits */ + #if DECDPUN>1 /* split to higher */ + hi=lo/10; + lo=lo%10; + #endif + up++; + /* collect remaining Units, if any, into hi */ + for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1]; + /* now low has the lsd, hi the remainder */ + if (hi>214748364 || (hi==214748364 && lo>7)) { /* out of range? */ + /* most-negative is a reprieve */ + if (dn->bits&DECNEG && hi==214748364 && lo==8) return 0x80000000; + /* bad -- drop through */ + } + else { /* in-range always */ + Int i=X10(hi)+lo; + if (dn->bits&DECNEG) return -i; + return i; + } + } /* integer */ + decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */ + return 0; + } /* decNumberToInt32 */ + +uInt decNumberToUInt32(const decNumber *dn, decContext *set) { + #if DECCHECK + if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; + #endif + /* special or too many digits, or bad exponent, or negative (<0) */ + if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0 + || (dn->bits&DECNEG && !ISZERO(dn))); /* bad */ + else { /* is a finite integer with 10 or fewer digits */ + Int d; /* work */ + const Unit *up; /* .. */ + uInt hi=0, lo; /* .. */ + up=dn->lsu; /* -> lsu */ + lo=*up; /* get 1 to 9 digits */ + #if DECDPUN>1 /* split to higher */ + hi=lo/10; + lo=lo%10; + #endif + up++; + /* collect remaining Units, if any, into hi */ + for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1]; + + /* now low has the lsd, hi the remainder */ + if (hi>429496729 || (hi==429496729 && lo>5)) ; /* no reprieve possible */ + else return X10(hi)+lo; + } /* integer */ + decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */ + return 0; + } /* decNumberToUInt32 */ + +/* ------------------------------------------------------------------ */ +/* to-scientific-string -- conversion to numeric string */ +/* to-engineering-string -- conversion to numeric string */ +/* */ +/* decNumberToString(dn, string); */ +/* decNumberToEngString(dn, string); */ +/* */ +/* dn is the decNumber to convert */ +/* string is the string where the result will be laid out */ +/* */ +/* string must be at least dn->digits+14 characters long */ +/* */ +/* No error is possible, and no status can be set. */ +/* ------------------------------------------------------------------ */ +char * decNumberToString(const decNumber *dn, char *string){ + decToString(dn, string, 0); + return string; + } /* DecNumberToString */ + +char * decNumberToEngString(const decNumber *dn, char *string){ + decToString(dn, string, 1); + return string; + } /* DecNumberToEngString */ + +/* ------------------------------------------------------------------ */ +/* to-number -- conversion from numeric string */ +/* */ +/* decNumberFromString -- convert string to decNumber */ +/* dn -- the number structure to fill */ +/* chars[] -- the string to convert ('\0' terminated) */ +/* set -- the context used for processing any error, */ +/* determining the maximum precision available */ +/* (set.digits), determining the maximum and minimum */ +/* exponent (set.emax and set.emin), determining if */ +/* extended values are allowed, and checking the */ +/* rounding mode if overflow occurs or rounding is */ +/* needed. */ +/* */ +/* The length of the coefficient and the size of the exponent are */ +/* checked by this routine, so the correct error (Underflow or */ +/* Overflow) can be reported or rounding applied, as necessary. */ +/* */ +/* If bad syntax is detected, the result will be a quiet NaN. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberFromString(decNumber *dn, const char chars[], + decContext *set) { + Int exponent=0; /* working exponent [assume 0] */ + uByte bits=0; /* working flags [assume +ve] */ + Unit *res; /* where result will be built */ + Unit resbuff[SD2U(DECBUFFER+9)];/* local buffer in case need temporary */ + /* [+9 allows for ln() constants] */ + Unit *allocres=NULL; /* -> allocated result, iff allocated */ + Int d=0; /* count of digits found in decimal part */ + const char *dotchar=NULL; /* where dot was found */ + const char *cfirst=chars; /* -> first character of decimal part */ + const char *last=NULL; /* -> last digit of decimal part */ + const char *c; /* work */ + Unit *up; /* .. */ + #if DECDPUN>1 + Int cut, out; /* .. */ + #endif + Int residue; /* rounding residue */ + uInt status=0; /* error code */ + + #if DECCHECK + if (decCheckOperands(DECUNRESU, DECUNUSED, DECUNUSED, set)) + return decNumberZero(dn); + #endif + + do { /* status & malloc protection */ + for (c=chars;; c++) { /* -> input character */ + if (*c>='0' && *c<='9') { /* test for Arabic digit */ + last=c; + d++; /* count of real digits */ + continue; /* still in decimal part */ + } + if (*c=='.' && dotchar==NULL) { /* first '.' */ + dotchar=c; /* record offset into decimal part */ + if (c==cfirst) cfirst++; /* first digit must follow */ + continue;} + if (c==chars) { /* first in string... */ + if (*c=='-') { /* valid - sign */ + cfirst++; + bits=DECNEG; + continue;} + if (*c=='+') { /* valid + sign */ + cfirst++; + continue;} + } + /* *c is not a digit, or a valid +, -, or '.' */ + break; + } /* c */ + + if (last==NULL) { /* no digits yet */ + status=DEC_Conversion_syntax;/* assume the worst */ + if (*c=='\0') break; /* and no more to come... */ + #if DECSUBSET + /* if subset then infinities and NaNs are not allowed */ + if (!set->extended) break; /* hopeless */ + #endif + /* Infinities and NaNs are possible, here */ + if (dotchar!=NULL) break; /* .. unless had a dot */ + decNumberZero(dn); /* be optimistic */ + if (decBiStr(c, "infinity", "INFINITY") + || decBiStr(c, "inf", "INF")) { + dn->bits=bits | DECINF; + status=0; /* is OK */ + break; /* all done */ + } + /* a NaN expected */ + /* 2003.09.10 NaNs are now permitted to have a sign */ + dn->bits=bits | DECNAN; /* assume simple NaN */ + if (*c=='s' || *c=='S') { /* looks like an sNaN */ + c++; + dn->bits=bits | DECSNAN; + } + if (*c!='n' && *c!='N') break; /* check caseless "NaN" */ + c++; + if (*c!='a' && *c!='A') break; /* .. */ + c++; + if (*c!='n' && *c!='N') break; /* .. */ + c++; + /* now either nothing, or nnnn payload, expected */ + /* -> start of integer and skip leading 0s [including plain 0] */ + for (cfirst=c; *cfirst=='0';) cfirst++; + if (*cfirst=='\0') { /* "NaN" or "sNaN", maybe with all 0s */ + status=0; /* it's good */ + break; /* .. */ + } + /* something other than 0s; setup last and d as usual [no dots] */ + for (c=cfirst;; c++, d++) { + if (*c<'0' || *c>'9') break; /* test for Arabic digit */ + last=c; + } + if (*c!='\0') break; /* not all digits */ + if (d>set->digits-1) { + /* [NB: payload in a decNumber can be full length unless */ + /* clamped, in which case can only be digits-1] */ + if (set->clamp) break; + if (d>set->digits) break; + } /* too many digits? */ + /* good; drop through to convert the integer to coefficient */ + status=0; /* syntax is OK */ + bits=dn->bits; /* for copy-back */ + } /* last==NULL */ + + else if (*c!='\0') { /* more to process... */ + /* had some digits; exponent is only valid sequence now */ + Flag nege; /* 1=negative exponent */ + const char *firstexp; /* -> first significant exponent digit */ + status=DEC_Conversion_syntax;/* assume the worst */ + if (*c!='e' && *c!='E') break; + /* Found 'e' or 'E' -- now process explicit exponent */ + /* 1998.07.11: sign no longer required */ + nege=0; + c++; /* to (possible) sign */ + if (*c=='-') {nege=1; c++;} + else if (*c=='+') c++; + if (*c=='\0') break; + + for (; *c=='0' && *(c+1)!='\0';) c++; /* strip insignificant zeros */ + firstexp=c; /* save exponent digit place */ + for (; ;c++) { + if (*c<'0' || *c>'9') break; /* not a digit */ + exponent=X10(exponent)+(Int)*c-(Int)'0'; + } /* c */ + /* if not now on a '\0', *c must not be a digit */ + if (*c!='\0') break; + + /* (this next test must be after the syntax checks) */ + /* if it was too long the exponent may have wrapped, so check */ + /* carefully and set it to a certain overflow if wrap possible */ + if (c>=firstexp+9+1) { + if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2; + /* [up to 1999999999 is OK, for example 1E-1000000998] */ + } + if (nege) exponent=-exponent; /* was negative */ + status=0; /* is OK */ + } /* stuff after digits */ + + /* Here when whole string has been inspected; syntax is good */ + /* cfirst->first digit (never dot), last->last digit (ditto) */ + + /* strip leading zeros/dot [leave final 0 if all 0's] */ + if (*cfirst=='0') { /* [cfirst has stepped over .] */ + for (c=cfirst; c<last; c++, cfirst++) { + if (*c=='.') continue; /* ignore dots */ + if (*c!='0') break; /* non-zero found */ + d--; /* 0 stripped */ + } /* c */ + #if DECSUBSET + /* make a rapid exit for easy zeros if !extended */ + if (*cfirst=='0' && !set->extended) { + decNumberZero(dn); /* clean result */ + break; /* [could be return] */ + } + #endif + } /* at least one leading 0 */ + + /* Handle decimal point... */ + if (dotchar!=NULL && dotchar<last) /* non-trailing '.' found? */ + exponent-=(last-dotchar); /* adjust exponent */ + /* [we can now ignore the .] */ + + /* OK, the digits string is good. Assemble in the decNumber, or in */ + /* a temporary units array if rounding is needed */ + if (d<=set->digits) res=dn->lsu; /* fits into supplied decNumber */ + else { /* rounding needed */ + Int needbytes=D2U(d)*sizeof(Unit);/* bytes needed */ + res=resbuff; /* assume use local buffer */ + if (needbytes>(Int)sizeof(resbuff)) { /* too big for local */ + allocres=(Unit *)malloc(needbytes); + if (allocres==NULL) {status|=DEC_Insufficient_storage; break;} + res=allocres; + } + } + /* res now -> number lsu, buffer, or allocated storage for Unit array */ + + /* Place the coefficient into the selected Unit array */ + /* [this is often 70% of the cost of this function when DECDPUN>1] */ + #if DECDPUN>1 + out=0; /* accumulator */ + up=res+D2U(d)-1; /* -> msu */ + cut=d-(up-res)*DECDPUN; /* digits in top unit */ + for (c=cfirst;; c++) { /* along the digits */ + if (*c=='.') continue; /* ignore '.' [don't decrement cut] */ + out=X10(out)+(Int)*c-(Int)'0'; + if (c==last) break; /* done [never get to trailing '.'] */ + cut--; + if (cut>0) continue; /* more for this unit */ + *up=(Unit)out; /* write unit */ + up--; /* prepare for unit below.. */ + cut=DECDPUN; /* .. */ + out=0; /* .. */ + } /* c */ + *up=(Unit)out; /* write lsu */ + + #else + /* DECDPUN==1 */ + up=res; /* -> lsu */ + for (c=last; c>=cfirst; c--) { /* over each character, from least */ + if (*c=='.') continue; /* ignore . [don't step up] */ + *up=(Unit)((Int)*c-(Int)'0'); + up++; + } /* c */ + #endif + + dn->bits=bits; + dn->exponent=exponent; + dn->digits=d; + + /* if not in number (too long) shorten into the number */ + if (d>set->digits) { + residue=0; + decSetCoeff(dn, set, res, d, &residue, &status); + /* always check for overflow or subnormal and round as needed */ + decFinalize(dn, set, &residue, &status); + } + else { /* no rounding, but may still have overflow or subnormal */ + /* [these tests are just for performance; finalize repeats them] */ + if ((dn->exponent-1<set->emin-dn->digits) + || (dn->exponent-1>set->emax-set->digits)) { + residue=0; + decFinalize(dn, set, &residue, &status); + } + } + /* decNumberShow(dn); */ + } while(0); /* [for break] */ + + if (allocres!=NULL) free(allocres); /* drop any storage used */ + if (status!=0) decStatus(dn, status, set); + return dn; + } /* decNumberFromString */ + +/* ================================================================== */ +/* Operators */ +/* ================================================================== */ + +/* ------------------------------------------------------------------ */ +/* decNumberAbs -- absolute value operator */ +/* */ +/* This computes C = abs(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* See also decNumberCopyAbs for a quiet bitwise version of this. */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +/* This has the same effect as decNumberPlus unless A is negative, */ +/* in which case it has the same effect as decNumberMinus. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberAbs(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dzero; /* for 0 */ + uInt status=0; /* accumulator */ + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + decNumberZero(&dzero); /* set 0 */ + dzero.exponent=rhs->exponent; /* [no coefficient expansion] */ + decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberAbs */ + +/* ------------------------------------------------------------------ */ +/* decNumberAdd -- add two Numbers */ +/* */ +/* This computes C = A + B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +/* This just calls the routine shared with Subtract */ +decNumber * decNumberAdd(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decAddOp(res, lhs, rhs, set, 0, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberAdd */ + +/* ------------------------------------------------------------------ */ +/* decNumberAnd -- AND two Numbers, digitwise */ +/* */ +/* This computes C = A & B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X&X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context (used for result length and error report) */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Logical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberAnd(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + const Unit *ua, *ub; /* -> operands */ + const Unit *msua, *msub; /* -> operand msus */ + Unit *uc, *msuc; /* -> result and its msu */ + Int msudigs; /* digits in res msu */ + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) + || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + + /* operands are valid */ + ua=lhs->lsu; /* bottom-up */ + ub=rhs->lsu; /* .. */ + uc=res->lsu; /* .. */ + msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */ + msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */ + msuc=uc+D2U(set->digits)-1; /* -> msu of result */ + msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ + for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */ + Unit a, b; /* extract units */ + if (ua>msua) a=0; + else a=*ua; + if (ub>msub) b=0; + else b=*ub; + *uc=0; /* can now write back */ + if (a|b) { /* maybe 1 bits to examine */ + Int i, j; + *uc=0; /* can now write back */ + /* This loop could be unrolled and/or use BIN2BCD tables */ + for (i=0; i<DECDPUN; i++) { + if (a&b&1) *uc=*uc+(Unit)powers[i]; /* effect AND */ + j=a%10; + a=a/10; + j|=b%10; + b=b/10; + if (j>1) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + if (uc==msuc && i==msudigs-1) break; /* just did final digit */ + } /* each digit */ + } /* both OK */ + } /* each unit */ + /* [here uc-1 is the msu of the result] */ + res->digits=decGetDigits(res->lsu, uc-res->lsu); + res->exponent=0; /* integer */ + res->bits=0; /* sign=0 */ + return res; /* [no status to set] */ + } /* decNumberAnd */ + +/* ------------------------------------------------------------------ */ +/* decNumberCompare -- compare two Numbers */ +/* */ +/* This computes C = A ? B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for one digit (or NaN). */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCompare(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decCompareOp(res, lhs, rhs, set, COMPARE, &status); + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberCompare */ + +/* ------------------------------------------------------------------ */ +/* decNumberCompareSignal -- compare, signalling on all NaNs */ +/* */ +/* This computes C = A ? B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for one digit (or NaN). */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCompareSignal(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decCompareOp(res, lhs, rhs, set, COMPSIG, &status); + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberCompareSignal */ + +/* ------------------------------------------------------------------ */ +/* decNumberCompareTotal -- compare two Numbers, using total ordering */ +/* */ +/* This computes C = A ? B, under total ordering */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for one digit; the result will always be one of */ +/* -1, 0, or 1. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCompareTotal(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status); + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberCompareTotal */ + +/* ------------------------------------------------------------------ */ +/* decNumberCompareTotalMag -- compare, total ordering of magnitudes */ +/* */ +/* This computes C = |A| ? |B|, under total ordering */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for one digit; the result will always be one of */ +/* -1, 0, or 1. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCompareTotalMag(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + uInt needbytes; /* for space calculations */ + decNumber bufa[D2N(DECBUFFER+1)];/* +1 in case DECBUFFER=0 */ + decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ + decNumber bufb[D2N(DECBUFFER+1)]; + decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */ + decNumber *a, *b; /* temporary pointers */ + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { /* protect allocated storage */ + /* if either is negative, take a copy and absolute */ + if (decNumberIsNegative(lhs)) { /* lhs<0 */ + a=bufa; + needbytes=sizeof(decNumber)+(D2U(lhs->digits)-1)*sizeof(Unit); + if (needbytes>sizeof(bufa)) { /* need malloc space */ + allocbufa=(decNumber *)malloc(needbytes); + if (allocbufa==NULL) { /* hopeless -- abandon */ + status|=DEC_Insufficient_storage; + break;} + a=allocbufa; /* use the allocated space */ + } + decNumberCopy(a, lhs); /* copy content */ + a->bits&=~DECNEG; /* .. and clear the sign */ + lhs=a; /* use copy from here on */ + } + if (decNumberIsNegative(rhs)) { /* rhs<0 */ + b=bufb; + needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); + if (needbytes>sizeof(bufb)) { /* need malloc space */ + allocbufb=(decNumber *)malloc(needbytes); + if (allocbufb==NULL) { /* hopeless -- abandon */ + status|=DEC_Insufficient_storage; + break;} + b=allocbufb; /* use the allocated space */ + } + decNumberCopy(b, rhs); /* copy content */ + b->bits&=~DECNEG; /* .. and clear the sign */ + rhs=b; /* use copy from here on */ + } + decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status); + } while(0); /* end protected */ + + if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ + if (allocbufb!=NULL) free(allocbufb); /* .. */ + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberCompareTotalMag */ + +/* ------------------------------------------------------------------ */ +/* decNumberDivide -- divide one number by another */ +/* */ +/* This computes C = A / B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X/X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberDivide(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decDivideOp(res, lhs, rhs, set, DIVIDE, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberDivide */ + +/* ------------------------------------------------------------------ */ +/* decNumberDivideInteger -- divide and return integer quotient */ +/* */ +/* This computes C = A # B, where # is the integer divide operator */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X#X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberDivideInteger(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status); + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberDivideInteger */ + +/* ------------------------------------------------------------------ */ +/* decNumberExp -- exponentiation */ +/* */ +/* This computes C = exp(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Mathematical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* */ +/* Finite results will always be full precision and Inexact, except */ +/* when A is a zero or -Infinity (giving 1 or 0 respectively). */ +/* */ +/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* ------------------------------------------------------------------ */ +/* This is a wrapper for decExpOp which can handle the slightly wider */ +/* (double) range needed by Ln (which has to be able to calculate */ +/* exp(-a) where a can be the tiniest number (Ntiny). */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberExp(decNumber *res, const decNumber *rhs, + decContext *set) { + uInt status=0; /* accumulator */ + #if DECSUBSET + decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ + #endif + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + /* Check restrictions; these restrictions ensure that if h=8 (see */ + /* decExpOp) then the result will either overflow or underflow to 0. */ + /* Other math functions restrict the input range, too, for inverses. */ + /* If not violated then carry out the operation. */ + if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */ + #if DECSUBSET + if (!set->extended) { + /* reduce operand and set lostDigits status, as needed */ + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + decExpOp(res, rhs, set, &status); + } while(0); /* end protected */ + + #if DECSUBSET + if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */ + #endif + /* apply significant status */ + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberExp */ + +/* ------------------------------------------------------------------ */ +/* decNumberFMA -- fused multiply add */ +/* */ +/* This computes D = (A * B) + C with only one rounding */ +/* */ +/* res is D, the result. D may be A or B or C (e.g., X=FMA(X,X,X)) */ +/* lhs is A */ +/* rhs is B */ +/* fhs is C [far hand side] */ +/* set is the context */ +/* */ +/* Mathematical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberFMA(decNumber *res, const decNumber *lhs, + const decNumber *rhs, const decNumber *fhs, + decContext *set) { + uInt status=0; /* accumulator */ + decContext dcmul; /* context for the multiplication */ + uInt needbytes; /* for space calculations */ + decNumber bufa[D2N(DECBUFFER*2+1)]; + decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ + decNumber *acc; /* accumulator pointer */ + decNumber dzero; /* work */ + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + if (decCheckOperands(res, fhs, DECUNUSED, set)) return res; + #endif + + do { /* protect allocated storage */ + #if DECSUBSET + if (!set->extended) { /* [undefined if subset] */ + status|=DEC_Invalid_operation; + break;} + #endif + /* Check math restrictions [these ensure no overflow or underflow] */ + if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status)) + || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status)) + || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break; + /* set up context for multiply */ + dcmul=*set; + dcmul.digits=lhs->digits+rhs->digits; /* just enough */ + /* [The above may be an over-estimate for subset arithmetic, but that's OK] */ + dcmul.emax=DEC_MAX_EMAX; /* effectively unbounded .. */ + dcmul.emin=DEC_MIN_EMIN; /* [thanks to Math restrictions] */ + /* set up decNumber space to receive the result of the multiply */ + acc=bufa; /* may fit */ + needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit); + if (needbytes>sizeof(bufa)) { /* need malloc space */ + allocbufa=(decNumber *)malloc(needbytes); + if (allocbufa==NULL) { /* hopeless -- abandon */ + status|=DEC_Insufficient_storage; + break;} + acc=allocbufa; /* use the allocated space */ + } + /* multiply with extended range and necessary precision */ + /*printf("emin=%ld\n", dcmul.emin); */ + decMultiplyOp(acc, lhs, rhs, &dcmul, &status); + /* Only Invalid operation (from sNaN or Inf * 0) is possible in */ + /* status; if either is seen than ignore fhs (in case it is */ + /* another sNaN) and set acc to NaN unless we had an sNaN */ + /* [decMultiplyOp leaves that to caller] */ + /* Note sNaN has to go through addOp to shorten payload if */ + /* necessary */ + if ((status&DEC_Invalid_operation)!=0) { + if (!(status&DEC_sNaN)) { /* but be true invalid */ + decNumberZero(res); /* acc not yet set */ + res->bits=DECNAN; + break; + } + decNumberZero(&dzero); /* make 0 (any non-NaN would do) */ + fhs=&dzero; /* use that */ + } + #if DECCHECK + else { /* multiply was OK */ + if (status!=0) printf("Status=%08lx after FMA multiply\n", status); + } + #endif + /* add the third operand and result -> res, and all is done */ + decAddOp(res, acc, fhs, set, 0, &status); + } while(0); /* end protected */ + + if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberFMA */ + +/* ------------------------------------------------------------------ */ +/* decNumberInvert -- invert a Number, digitwise */ +/* */ +/* This computes C = ~A */ +/* */ +/* res is C, the result. C may be A (e.g., X=~X) */ +/* rhs is A */ +/* set is the context (used for result length and error report) */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Logical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberInvert(decNumber *res, const decNumber *rhs, + decContext *set) { + const Unit *ua, *msua; /* -> operand and its msu */ + Unit *uc, *msuc; /* -> result and its msu */ + Int msudigs; /* digits in res msu */ + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + if (rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + /* operand is valid */ + ua=rhs->lsu; /* bottom-up */ + uc=res->lsu; /* .. */ + msua=ua+D2U(rhs->digits)-1; /* -> msu of rhs */ + msuc=uc+D2U(set->digits)-1; /* -> msu of result */ + msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ + for (; uc<=msuc; ua++, uc++) { /* Unit loop */ + Unit a; /* extract unit */ + Int i, j; /* work */ + if (ua>msua) a=0; + else a=*ua; + *uc=0; /* can now write back */ + /* always need to examine all bits in rhs */ + /* This loop could be unrolled and/or use BIN2BCD tables */ + for (i=0; i<DECDPUN; i++) { + if ((~a)&1) *uc=*uc+(Unit)powers[i]; /* effect INVERT */ + j=a%10; + a=a/10; + if (j>1) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + if (uc==msuc && i==msudigs-1) break; /* just did final digit */ + } /* each digit */ + } /* each unit */ + /* [here uc-1 is the msu of the result] */ + res->digits=decGetDigits(res->lsu, uc-res->lsu); + res->exponent=0; /* integer */ + res->bits=0; /* sign=0 */ + return res; /* [no status to set] */ + } /* decNumberInvert */ + +/* ------------------------------------------------------------------ */ +/* decNumberLn -- natural logarithm */ +/* */ +/* This computes C = ln(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Notable cases: */ +/* A<0 -> Invalid */ +/* A=0 -> -Infinity (Exact) */ +/* A=+Infinity -> +Infinity (Exact) */ +/* A=1 exactly -> 0 (Exact) */ +/* */ +/* Mathematical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* */ +/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* ------------------------------------------------------------------ */ +/* This is a wrapper for decLnOp which can handle the slightly wider */ +/* (+11) range needed by Ln, Log10, etc. (which may have to be able */ +/* to calculate at p+e+2). */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberLn(decNumber *res, const decNumber *rhs, + decContext *set) { + uInt status=0; /* accumulator */ + #if DECSUBSET + decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ + #endif + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + /* Check restrictions; this is a math function; if not violated */ + /* then carry out the operation. */ + if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */ + #if DECSUBSET + if (!set->extended) { + /* reduce operand and set lostDigits status, as needed */ + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + /* special check in subset for rhs=0 */ + if (ISZERO(rhs)) { /* +/- zeros -> error */ + status|=DEC_Invalid_operation; + break;} + } /* extended=0 */ + #endif + decLnOp(res, rhs, set, &status); + } while(0); /* end protected */ + + #if DECSUBSET + if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */ + #endif + /* apply significant status */ + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberLn */ + +/* ------------------------------------------------------------------ */ +/* decNumberLogB - get adjusted exponent, by 754r rules */ +/* */ +/* This computes C = adjustedexponent(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context, used only for digits and status */ +/* */ +/* C must have space for 10 digits (A might have 10**9 digits and */ +/* an exponent of +999999999, or one digit and an exponent of */ +/* -1999999999). */ +/* */ +/* This returns the adjusted exponent of A after (in theory) padding */ +/* with zeros on the right to set->digits digits while keeping the */ +/* same value. The exponent is not limited by emin/emax. */ +/* */ +/* Notable cases: */ +/* A<0 -> Use |A| */ +/* A=0 -> -Infinity (Division by zero) */ +/* A=Infinite -> +Infinity (Exact) */ +/* A=1 exactly -> 0 (Exact) */ +/* NaNs are propagated as usual */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberLogB(decNumber *res, const decNumber *rhs, + decContext *set) { + uInt status=0; /* accumulator */ + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + /* NaNs as usual; Infinities return +Infinity; 0->oops */ + if (decNumberIsNaN(rhs)) decNaNs(res, rhs, NULL, set, &status); + else if (decNumberIsInfinite(rhs)) decNumberCopyAbs(res, rhs); + else if (decNumberIsZero(rhs)) { + decNumberZero(res); /* prepare for Infinity */ + res->bits=DECNEG|DECINF; /* -Infinity */ + status|=DEC_Division_by_zero; /* as per 754r */ + } + else { /* finite non-zero */ + Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */ + decNumberFromInt32(res, ae); /* lay it out */ + } + + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberLogB */ + +/* ------------------------------------------------------------------ */ +/* decNumberLog10 -- logarithm in base 10 */ +/* */ +/* This computes C = log10(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Notable cases: */ +/* A<0 -> Invalid */ +/* A=0 -> -Infinity (Exact) */ +/* A=+Infinity -> +Infinity (Exact) */ +/* A=10**n (if n is an integer) -> n (Exact) */ +/* */ +/* Mathematical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* */ +/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* ------------------------------------------------------------------ */ +/* This calculates ln(A)/ln(10) using appropriate precision. For */ +/* ln(A) this is the max(p, rhs->digits + t) + 3, where p is the */ +/* requested digits and t is the number of digits in the exponent */ +/* (maximum 6). For ln(10) it is p + 3; this is often handled by the */ +/* fastpath in decLnOp. The final division is done to the requested */ +/* precision. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberLog10(decNumber *res, const decNumber *rhs, + decContext *set) { + uInt status=0, ignore=0; /* status accumulators */ + uInt needbytes; /* for space calculations */ + Int p; /* working precision */ + Int t; /* digits in exponent of A */ + + /* buffers for a and b working decimals */ + /* (adjustment calculator, same size) */ + decNumber bufa[D2N(DECBUFFER+2)]; + decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ + decNumber *a=bufa; /* temporary a */ + decNumber bufb[D2N(DECBUFFER+2)]; + decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */ + decNumber *b=bufb; /* temporary b */ + decNumber bufw[D2N(10)]; /* working 2-10 digit number */ + decNumber *w=bufw; /* .. */ + #if DECSUBSET + decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ + #endif + + decContext aset; /* working context */ + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + /* Check restrictions; this is a math function; if not violated */ + /* then carry out the operation. */ + if (!decCheckMath(rhs, set, &status)) do { /* protect malloc */ + #if DECSUBSET + if (!set->extended) { + /* reduce operand and set lostDigits status, as needed */ + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + /* special check in subset for rhs=0 */ + if (ISZERO(rhs)) { /* +/- zeros -> error */ + status|=DEC_Invalid_operation; + break;} + } /* extended=0 */ + #endif + + decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */ + + /* handle exact powers of 10; only check if +ve finite */ + if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) { + Int residue=0; /* (no residue) */ + uInt copystat=0; /* clean status */ + + /* round to a single digit... */ + aset.digits=1; + decCopyFit(w, rhs, &aset, &residue, ©stat); /* copy & shorten */ + /* if exact and the digit is 1, rhs is a power of 10 */ + if (!(copystat&DEC_Inexact) && w->lsu[0]==1) { + /* the exponent, conveniently, is the power of 10; making */ + /* this the result needs a little care as it might not fit, */ + /* so first convert it into the working number, and then move */ + /* to res */ + decNumberFromInt32(w, w->exponent); + residue=0; + decCopyFit(res, w, set, &residue, &status); /* copy & round */ + decFinish(res, set, &residue, &status); /* cleanup/set flags */ + break; + } /* not a power of 10 */ + } /* not a candidate for exact */ + + /* simplify the information-content calculation to use 'total */ + /* number of digits in a, including exponent' as compared to the */ + /* requested digits, as increasing this will only rarely cost an */ + /* iteration in ln(a) anyway */ + t=6; /* it can never be >6 */ + + /* allocate space when needed... */ + p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3; + needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit); + if (needbytes>sizeof(bufa)) { /* need malloc space */ + allocbufa=(decNumber *)malloc(needbytes); + if (allocbufa==NULL) { /* hopeless -- abandon */ + status|=DEC_Insufficient_storage; + break;} + a=allocbufa; /* use the allocated space */ + } + aset.digits=p; /* as calculated */ + aset.emax=DEC_MAX_MATH; /* usual bounds */ + aset.emin=-DEC_MAX_MATH; /* .. */ + aset.clamp=0; /* and no concrete format */ + decLnOp(a, rhs, &aset, &status); /* a=ln(rhs) */ + + /* skip the division if the result so far is infinite, NaN, or */ + /* zero, or there was an error; note NaN from sNaN needs copy */ + if (status&DEC_NaNs && !(status&DEC_sNaN)) break; + if (a->bits&DECSPECIAL || ISZERO(a)) { + decNumberCopy(res, a); /* [will fit] */ + break;} + + /* for ln(10) an extra 3 digits of precision are needed */ + p=set->digits+3; + needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit); + if (needbytes>sizeof(bufb)) { /* need malloc space */ + allocbufb=(decNumber *)malloc(needbytes); + if (allocbufb==NULL) { /* hopeless -- abandon */ + status|=DEC_Insufficient_storage; + break;} + b=allocbufb; /* use the allocated space */ + } + decNumberZero(w); /* set up 10... */ + #if DECDPUN==1 + w->lsu[1]=1; w->lsu[0]=0; /* .. */ + #else + w->lsu[0]=10; /* .. */ + #endif + w->digits=2; /* .. */ + + aset.digits=p; + decLnOp(b, w, &aset, &ignore); /* b=ln(10) */ + + aset.digits=set->digits; /* for final divide */ + decDivideOp(res, a, b, &aset, DIVIDE, &status); /* into result */ + } while(0); /* [for break] */ + + if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ + if (allocbufb!=NULL) free(allocbufb); /* .. */ + #if DECSUBSET + if (allocrhs !=NULL) free(allocrhs); /* .. */ + #endif + /* apply significant status */ + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberLog10 */ + +/* ------------------------------------------------------------------ */ +/* decNumberMax -- compare two Numbers and return the maximum */ +/* */ +/* This computes C = A ? B, returning the maximum by 754R rules */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMax(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decCompareOp(res, lhs, rhs, set, COMPMAX, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberMax */ + +/* ------------------------------------------------------------------ */ +/* decNumberMaxMag -- compare and return the maximum by magnitude */ +/* */ +/* This computes C = A ? B, returning the maximum by 754R rules */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMaxMag(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberMaxMag */ + +/* ------------------------------------------------------------------ */ +/* decNumberMin -- compare two Numbers and return the minimum */ +/* */ +/* This computes C = A ? B, returning the minimum by 754R rules */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMin(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decCompareOp(res, lhs, rhs, set, COMPMIN, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberMin */ + +/* ------------------------------------------------------------------ */ +/* decNumberMinMag -- compare and return the minimum by magnitude */ +/* */ +/* This computes C = A ? B, returning the minimum by 754R rules */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMinMag(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberMinMag */ + +/* ------------------------------------------------------------------ */ +/* decNumberMinus -- prefix minus operator */ +/* */ +/* This computes C = 0 - A */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* See also decNumberCopyNegate for a quiet bitwise version of this. */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +/* Simply use AddOp for the subtract, which will do the necessary. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMinus(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dzero; + uInt status=0; /* accumulator */ + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + decNumberZero(&dzero); /* make 0 */ + dzero.exponent=rhs->exponent; /* [no coefficient expansion] */ + decAddOp(res, &dzero, rhs, set, DECNEG, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberMinus */ + +/* ------------------------------------------------------------------ */ +/* decNumberNextMinus -- next towards -Infinity */ +/* */ +/* This computes C = A - infinitesimal, rounded towards -Infinity */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* This is a generalization of 754r NextDown. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberNextMinus(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dtiny; /* constant */ + decContext workset=*set; /* work */ + uInt status=0; /* accumulator */ + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + /* +Infinity is the special case */ + if ((rhs->bits&(DECINF|DECNEG))==DECINF) { + decSetMaxValue(res, set); /* is +ve */ + /* there is no status to set */ + return res; + } + decNumberZero(&dtiny); /* start with 0 */ + dtiny.lsu[0]=1; /* make number that is .. */ + dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */ + workset.round=DEC_ROUND_FLOOR; + decAddOp(res, rhs, &dtiny, &workset, DECNEG, &status); + status&=DEC_Invalid_operation|DEC_sNaN; /* only sNaN Invalid please */ + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberNextMinus */ + +/* ------------------------------------------------------------------ */ +/* decNumberNextPlus -- next towards +Infinity */ +/* */ +/* This computes C = A + infinitesimal, rounded towards +Infinity */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* This is a generalization of 754r NextUp. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberNextPlus(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dtiny; /* constant */ + decContext workset=*set; /* work */ + uInt status=0; /* accumulator */ + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + /* -Infinity is the special case */ + if ((rhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) { + decSetMaxValue(res, set); + res->bits=DECNEG; /* negative */ + /* there is no status to set */ + return res; + } + decNumberZero(&dtiny); /* start with 0 */ + dtiny.lsu[0]=1; /* make number that is .. */ + dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */ + workset.round=DEC_ROUND_CEILING; + decAddOp(res, rhs, &dtiny, &workset, 0, &status); + status&=DEC_Invalid_operation|DEC_sNaN; /* only sNaN Invalid please */ + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberNextPlus */ + +/* ------------------------------------------------------------------ */ +/* decNumberNextToward -- next towards rhs */ +/* */ +/* This computes C = A +/- infinitesimal, rounded towards */ +/* +/-Infinity in the direction of B, as per 754r nextafter rules */ +/* */ +/* res is C, the result. C may be A or B. */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* This is a generalization of 754r NextAfter. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberNextToward(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + decNumber dtiny; /* constant */ + decContext workset=*set; /* work */ + Int result; /* .. */ + uInt status=0; /* accumulator */ + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { + decNaNs(res, lhs, rhs, set, &status); + } + else { /* Is numeric, so no chance of sNaN Invalid, etc. */ + result=decCompare(lhs, rhs, 0); /* sign matters */ + if (result==BADINT) status|=DEC_Insufficient_storage; /* rare */ + else { /* valid compare */ + if (result==0) decNumberCopySign(res, lhs, rhs); /* easy */ + else { /* differ: need NextPlus or NextMinus */ + uByte sub; /* add or subtract */ + if (result<0) { /* lhs<rhs, do nextplus */ + /* -Infinity is the special case */ + if ((lhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) { + decSetMaxValue(res, set); + res->bits=DECNEG; /* negative */ + return res; /* there is no status to set */ + } + workset.round=DEC_ROUND_CEILING; + sub=0; /* add, please */ + } /* plus */ + else { /* lhs>rhs, do nextminus */ + /* +Infinity is the special case */ + if ((lhs->bits&(DECINF|DECNEG))==DECINF) { + decSetMaxValue(res, set); + return res; /* there is no status to set */ + } + workset.round=DEC_ROUND_FLOOR; + sub=DECNEG; /* subtract, please */ + } /* minus */ + decNumberZero(&dtiny); /* start with 0 */ + dtiny.lsu[0]=1; /* make number that is .. */ + dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */ + decAddOp(res, lhs, &dtiny, &workset, sub, &status); /* + or - */ + /* turn off exceptions if the result is a normal number */ + /* (including Nmin), otherwise let all status through */ + if (decNumberIsNormal(res, set)) status=0; + } /* unequal */ + } /* compare OK */ + } /* numeric */ + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberNextToward */ + +/* ------------------------------------------------------------------ */ +/* decNumberOr -- OR two Numbers, digitwise */ +/* */ +/* This computes C = A | B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X|X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context (used for result length and error report) */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Logical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberOr(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + const Unit *ua, *ub; /* -> operands */ + const Unit *msua, *msub; /* -> operand msus */ + Unit *uc, *msuc; /* -> result and its msu */ + Int msudigs; /* digits in res msu */ + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) + || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + /* operands are valid */ + ua=lhs->lsu; /* bottom-up */ + ub=rhs->lsu; /* .. */ + uc=res->lsu; /* .. */ + msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */ + msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */ + msuc=uc+D2U(set->digits)-1; /* -> msu of result */ + msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ + for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */ + Unit a, b; /* extract units */ + if (ua>msua) a=0; + else a=*ua; + if (ub>msub) b=0; + else b=*ub; + *uc=0; /* can now write back */ + if (a|b) { /* maybe 1 bits to examine */ + Int i, j; + /* This loop could be unrolled and/or use BIN2BCD tables */ + for (i=0; i<DECDPUN; i++) { + if ((a|b)&1) *uc=*uc+(Unit)powers[i]; /* effect OR */ + j=a%10; + a=a/10; + j|=b%10; + b=b/10; + if (j>1) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + if (uc==msuc && i==msudigs-1) break; /* just did final digit */ + } /* each digit */ + } /* non-zero */ + } /* each unit */ + /* [here uc-1 is the msu of the result] */ + res->digits=decGetDigits(res->lsu, uc-res->lsu); + res->exponent=0; /* integer */ + res->bits=0; /* sign=0 */ + return res; /* [no status to set] */ + } /* decNumberOr */ + +/* ------------------------------------------------------------------ */ +/* decNumberPlus -- prefix plus operator */ +/* */ +/* This computes C = 0 + A */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* See also decNumberCopy for a quiet bitwise version of this. */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +/* This simply uses AddOp; Add will take fast path after preparing A. */ +/* Performance is a concern here, as this routine is often used to */ +/* check operands and apply rounding and overflow/underflow testing. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberPlus(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dzero; + uInt status=0; /* accumulator */ + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + decNumberZero(&dzero); /* make 0 */ + dzero.exponent=rhs->exponent; /* [no coefficient expansion] */ + decAddOp(res, &dzero, rhs, set, 0, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberPlus */ + +/* ------------------------------------------------------------------ */ +/* decNumberMultiply -- multiply two Numbers */ +/* */ +/* This computes C = A x B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberMultiply(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decMultiplyOp(res, lhs, rhs, set, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberMultiply */ + +/* ------------------------------------------------------------------ */ +/* decNumberPower -- raise a number to a power */ +/* */ +/* This computes C = A ** B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X**X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Mathematical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* */ +/* However, if 1999999997<=B<=999999999 and B is an integer then the */ +/* restrictions on A and the context are relaxed to the usual bounds, */ +/* for compatibility with the earlier (integer power only) version */ +/* of this function. */ +/* */ +/* When B is an integer, the result may be exact, even if rounded. */ +/* */ +/* The final result is rounded according to the context; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberPower(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + #if DECSUBSET + decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ + decNumber *allocrhs=NULL; /* .., rhs */ + #endif + decNumber *allocdac=NULL; /* -> allocated acc buffer, iff used */ + decNumber *allocinv=NULL; /* -> allocated 1/x buffer, iff used */ + Int reqdigits=set->digits; /* requested DIGITS */ + Int n; /* rhs in binary */ + Flag rhsint=0; /* 1 if rhs is an integer */ + Flag useint=0; /* 1 if can use integer calculation */ + Flag isoddint=0; /* 1 if rhs is an integer and odd */ + Int i; /* work */ + #if DECSUBSET + Int dropped; /* .. */ + #endif + uInt needbytes; /* buffer size needed */ + Flag seenbit; /* seen a bit while powering */ + Int residue=0; /* rounding residue */ + uInt status=0; /* accumulators */ + uByte bits=0; /* result sign if errors */ + decContext aset; /* working context */ + decNumber dnOne; /* work value 1... */ + /* local accumulator buffer [a decNumber, with digits+elength+1 digits] */ + decNumber dacbuff[D2N(DECBUFFER+9)]; + decNumber *dac=dacbuff; /* -> result accumulator */ + /* same again for possible 1/lhs calculation */ + decNumber invbuff[D2N(DECBUFFER+9)]; + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { /* protect allocated storage */ + #if DECSUBSET + if (!set->extended) { /* reduce operands and set status, as needed */ + if (lhs->digits>reqdigits) { + alloclhs=decRoundOperand(lhs, set, &status); + if (alloclhs==NULL) break; + lhs=alloclhs; + } + if (rhs->digits>reqdigits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + /* [following code does not require input rounding] */ + + /* handle NaNs and rhs Infinity (lhs infinity is harder) */ + if (SPECIALARGS) { + if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { /* NaNs */ + decNaNs(res, lhs, rhs, set, &status); + break;} + if (decNumberIsInfinite(rhs)) { /* rhs Infinity */ + Flag rhsneg=rhs->bits&DECNEG; /* save rhs sign */ + if (decNumberIsNegative(lhs) /* lhs<0 */ + && !decNumberIsZero(lhs)) /* .. */ + status|=DEC_Invalid_operation; + else { /* lhs >=0 */ + decNumberZero(&dnOne); /* set up 1 */ + dnOne.lsu[0]=1; + decNumberCompare(dac, lhs, &dnOne, set); /* lhs ? 1 */ + decNumberZero(res); /* prepare for 0/1/Infinity */ + if (decNumberIsNegative(dac)) { /* lhs<1 */ + if (rhsneg) res->bits|=DECINF; /* +Infinity [else is +0] */ + } + else if (dac->lsu[0]==0) { /* lhs=1 */ + /* 1**Infinity is inexact, so return fully-padded 1.0000 */ + Int shift=set->digits-1; + *res->lsu=1; /* was 0, make int 1 */ + res->digits=decShiftToMost(res->lsu, 1, shift); + res->exponent=-shift; /* make 1.0000... */ + status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */ + } + else { /* lhs>1 */ + if (!rhsneg) res->bits|=DECINF; /* +Infinity [else is +0] */ + } + } /* lhs>=0 */ + break;} + /* [lhs infinity drops through] */ + } /* specials */ + + /* Original rhs may be an integer that fits and is in range */ + n=decGetInt(rhs); + if (n!=BADINT) { /* it is an integer */ + rhsint=1; /* record the fact for 1**n */ + isoddint=(Flag)n&1; /* [works even if big] */ + if (n!=BIGEVEN && n!=BIGODD) /* can use integer path? */ + useint=1; /* looks good */ + } + + if (decNumberIsNegative(lhs) /* -x .. */ + && isoddint) bits=DECNEG; /* .. to an odd power */ + + /* handle LHS infinity */ + if (decNumberIsInfinite(lhs)) { /* [NaNs already handled] */ + uByte rbits=rhs->bits; /* save */ + decNumberZero(res); /* prepare */ + if (n==0) *res->lsu=1; /* [-]Inf**0 => 1 */ + else { + /* -Inf**nonint -> error */ + if (!rhsint && decNumberIsNegative(lhs)) { + status|=DEC_Invalid_operation; /* -Inf**nonint is error */ + break;} + if (!(rbits & DECNEG)) bits|=DECINF; /* was not a **-n */ + /* [otherwise will be 0 or -0] */ + res->bits=bits; + } + break;} + + /* similarly handle LHS zero */ + if (decNumberIsZero(lhs)) { + if (n==0) { /* 0**0 => Error */ + #if DECSUBSET + if (!set->extended) { /* [unless subset] */ + decNumberZero(res); + *res->lsu=1; /* return 1 */ + break;} + #endif + status|=DEC_Invalid_operation; + } + else { /* 0**x */ + uByte rbits=rhs->bits; /* save */ + if (rbits & DECNEG) { /* was a 0**(-n) */ + #if DECSUBSET + if (!set->extended) { /* [bad if subset] */ + status|=DEC_Invalid_operation; + break;} + #endif + bits|=DECINF; + } + decNumberZero(res); /* prepare */ + /* [otherwise will be 0 or -0] */ + res->bits=bits; + } + break;} + + /* here both lhs and rhs are finite; rhs==0 is handled in the */ + /* integer path. Next handle the non-integer cases */ + if (!useint) { /* non-integral rhs */ + /* any -ve lhs is bad, as is either operand or context out of */ + /* bounds */ + if (decNumberIsNegative(lhs)) { + status|=DEC_Invalid_operation; + break;} + if (decCheckMath(lhs, set, &status) + || decCheckMath(rhs, set, &status)) break; /* variable status */ + + decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */ + aset.emax=DEC_MAX_MATH; /* usual bounds */ + aset.emin=-DEC_MAX_MATH; /* .. */ + aset.clamp=0; /* and no concrete format */ + + /* calculate the result using exp(ln(lhs)*rhs), which can */ + /* all be done into the accumulator, dac. The precision needed */ + /* is enough to contain the full information in the lhs (which */ + /* is the total digits, including exponent), or the requested */ + /* precision, if larger, + 4; 6 is used for the exponent */ + /* maximum length, and this is also used when it is shorter */ + /* than the requested digits as it greatly reduces the >0.5 ulp */ + /* cases at little cost (because Ln doubles digits each */ + /* iteration so a few extra digits rarely causes an extra */ + /* iteration) */ + aset.digits=MAXI(lhs->digits, set->digits)+6+4; + } /* non-integer rhs */ + + else { /* rhs is in-range integer */ + if (n==0) { /* x**0 = 1 */ + /* (0**0 was handled above) */ + decNumberZero(res); /* result=1 */ + *res->lsu=1; /* .. */ + break;} + /* rhs is a non-zero integer */ + if (n<0) n=-n; /* use abs(n) */ + + aset=*set; /* clone the context */ + aset.round=DEC_ROUND_HALF_EVEN; /* internally use balanced */ + /* calculate the working DIGITS */ + aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2; + #if DECSUBSET + if (!set->extended) aset.digits--; /* use classic precision */ + #endif + /* it's an error if this is more than can be handled */ + if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;} + } /* integer path */ + + /* aset.digits is the count of digits for the accumulator needed */ + /* if accumulator is too long for local storage, then allocate */ + needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit); + /* [needbytes also used below if 1/lhs needed] */ + if (needbytes>sizeof(dacbuff)) { + allocdac=(decNumber *)malloc(needbytes); + if (allocdac==NULL) { /* hopeless -- abandon */ + status|=DEC_Insufficient_storage; + break;} + dac=allocdac; /* use the allocated space */ + } + /* here, aset is set up and accumulator is ready for use */ + + if (!useint) { /* non-integral rhs */ + /* x ** y; special-case x=1 here as it will otherwise always */ + /* reduce to integer 1; decLnOp has a fastpath which detects */ + /* the case of x=1 */ + decLnOp(dac, lhs, &aset, &status); /* dac=ln(lhs) */ + /* [no error possible, as lhs 0 already handled] */ + if (ISZERO(dac)) { /* x==1, 1.0, etc. */ + /* need to return fully-padded 1.0000 etc., but rhsint->1 */ + *dac->lsu=1; /* was 0, make int 1 */ + if (!rhsint) { /* add padding */ + Int shift=set->digits-1; + dac->digits=decShiftToMost(dac->lsu, 1, shift); + dac->exponent=-shift; /* make 1.0000... */ + status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */ + } + } + else { + decMultiplyOp(dac, dac, rhs, &aset, &status); /* dac=dac*rhs */ + decExpOp(dac, dac, &aset, &status); /* dac=exp(dac) */ + } + /* and drop through for final rounding */ + } /* non-integer rhs */ + + else { /* carry on with integer */ + decNumberZero(dac); /* acc=1 */ + *dac->lsu=1; /* .. */ + + /* if a negative power the constant 1 is needed, and if not subset */ + /* invert the lhs now rather than inverting the result later */ + if (decNumberIsNegative(rhs)) { /* was a **-n [hence digits>0] */ + decNumber *inv=invbuff; /* asssume use fixed buffer */ + decNumberCopy(&dnOne, dac); /* dnOne=1; [needed now or later] */ + #if DECSUBSET + if (set->extended) { /* need to calculate 1/lhs */ + #endif + /* divide lhs into 1, putting result in dac [dac=1/dac] */ + decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status); + /* now locate or allocate space for the inverted lhs */ + if (needbytes>sizeof(invbuff)) { + allocinv=(decNumber *)malloc(needbytes); + if (allocinv==NULL) { /* hopeless -- abandon */ + status|=DEC_Insufficient_storage; + break;} + inv=allocinv; /* use the allocated space */ + } + /* [inv now points to big-enough buffer or allocated storage] */ + decNumberCopy(inv, dac); /* copy the 1/lhs */ + decNumberCopy(dac, &dnOne); /* restore acc=1 */ + lhs=inv; /* .. and go forward with new lhs */ + #if DECSUBSET + } + #endif + } + + /* Raise-to-the-power loop... */ + seenbit=0; /* set once a 1-bit is encountered */ + for (i=1;;i++){ /* for each bit [top bit ignored] */ + /* abandon if had overflow or terminal underflow */ + if (status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */ + if (status&DEC_Overflow || ISZERO(dac)) break; + } + /* [the following two lines revealed an optimizer bug in a C++ */ + /* compiler, with symptom: 5**3 -> 25, when n=n+n was used] */ + n=n<<1; /* move next bit to testable position */ + if (n<0) { /* top bit is set */ + seenbit=1; /* OK, significant bit seen */ + decMultiplyOp(dac, dac, lhs, &aset, &status); /* dac=dac*x */ + } + if (i==31) break; /* that was the last bit */ + if (!seenbit) continue; /* no need to square 1 */ + decMultiplyOp(dac, dac, dac, &aset, &status); /* dac=dac*dac [square] */ + } /*i*/ /* 32 bits */ + + /* complete internal overflow or underflow processing */ + if (status & (DEC_Overflow|DEC_Underflow)) { + #if DECSUBSET + /* If subset, and power was negative, reverse the kind of -erflow */ + /* [1/x not yet done] */ + if (!set->extended && decNumberIsNegative(rhs)) { + if (status & DEC_Overflow) + status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal; + else { /* trickier -- Underflow may or may not be set */ + status&=~(DEC_Underflow | DEC_Subnormal); /* [one or both] */ + status|=DEC_Overflow; + } + } + #endif + dac->bits=(dac->bits & ~DECNEG) | bits; /* force correct sign */ + /* round subnormals [to set.digits rather than aset.digits] */ + /* or set overflow result similarly as required */ + decFinalize(dac, set, &residue, &status); + decNumberCopy(res, dac); /* copy to result (is now OK length) */ + break; + } + + #if DECSUBSET + if (!set->extended && /* subset math */ + decNumberIsNegative(rhs)) { /* was a **-n [hence digits>0] */ + /* so divide result into 1 [dac=1/dac] */ + decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status); + } + #endif + } /* rhs integer path */ + + /* reduce result to the requested length and copy to result */ + decCopyFit(res, dac, set, &residue, &status); + decFinish(res, set, &residue, &status); /* final cleanup */ + #if DECSUBSET + if (!set->extended) decTrim(res, set, 0, &dropped); /* trailing zeros */ + #endif + } while(0); /* end protected */ + + if (allocdac!=NULL) free(allocdac); /* drop any storage used */ + if (allocinv!=NULL) free(allocinv); /* .. */ + #if DECSUBSET + if (alloclhs!=NULL) free(alloclhs); /* .. */ + if (allocrhs!=NULL) free(allocrhs); /* .. */ + #endif + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberPower */ + +/* ------------------------------------------------------------------ */ +/* decNumberQuantize -- force exponent to requested value */ +/* */ +/* This computes C = op(A, B), where op adjusts the coefficient */ +/* of C (by rounding or shifting) such that the exponent (-scale) */ +/* of C has exponent of B. The numerical value of C will equal A, */ +/* except for the effects of any rounding that occurred. */ +/* */ +/* res is C, the result. C may be A or B */ +/* lhs is A, the number to adjust */ +/* rhs is B, the number with exponent to match */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Unless there is an error or the result is infinite, the exponent */ +/* after the operation is guaranteed to be equal to that of B. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberQuantize(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decQuantizeOp(res, lhs, rhs, set, 1, &status); + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberQuantize */ + +/* ------------------------------------------------------------------ */ +/* decNumberReduce -- remove trailing zeros */ +/* */ +/* This computes C = 0 + A, and normalizes the result */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +/* Previously known as Normalize */ +decNumber * decNumberNormalize(decNumber *res, const decNumber *rhs, + decContext *set) { + return decNumberReduce(res, rhs, set); + } /* decNumberNormalize */ + +decNumber * decNumberReduce(decNumber *res, const decNumber *rhs, + decContext *set) { + #if DECSUBSET + decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ + #endif + uInt status=0; /* as usual */ + Int residue=0; /* as usual */ + Int dropped; /* work */ + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + do { /* protect allocated storage */ + #if DECSUBSET + if (!set->extended) { + /* reduce operand and set lostDigits status, as needed */ + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + /* [following code does not require input rounding] */ + + /* Infinities copy through; NaNs need usual treatment */ + if (decNumberIsNaN(rhs)) { + decNaNs(res, rhs, NULL, set, &status); + break; + } + + /* reduce result to the requested length and copy to result */ + decCopyFit(res, rhs, set, &residue, &status); /* copy & round */ + decFinish(res, set, &residue, &status); /* cleanup/set flags */ + decTrim(res, set, 1, &dropped); /* normalize in place */ + } while(0); /* end protected */ + + #if DECSUBSET + if (allocrhs !=NULL) free(allocrhs); /* .. */ + #endif + if (status!=0) decStatus(res, status, set);/* then report status */ + return res; + } /* decNumberReduce */ + +/* ------------------------------------------------------------------ */ +/* decNumberRescale -- force exponent to requested value */ +/* */ +/* This computes C = op(A, B), where op adjusts the coefficient */ +/* of C (by rounding or shifting) such that the exponent (-scale) */ +/* of C has the value B. The numerical value of C will equal A, */ +/* except for the effects of any rounding that occurred. */ +/* */ +/* res is C, the result. C may be A or B */ +/* lhs is A, the number to adjust */ +/* rhs is B, the requested exponent */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Unless there is an error or the result is infinite, the exponent */ +/* after the operation is guaranteed to be equal to B. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberRescale(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decQuantizeOp(res, lhs, rhs, set, 0, &status); + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberRescale */ + +/* ------------------------------------------------------------------ */ +/* decNumberRemainder -- divide and return remainder */ +/* */ +/* This computes C = A % B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X%X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberRemainder(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decDivideOp(res, lhs, rhs, set, REMAINDER, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberRemainder */ + +/* ------------------------------------------------------------------ */ +/* decNumberRemainderNear -- divide and return remainder from nearest */ +/* */ +/* This computes C = A % B, where % is the IEEE remainder operator */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X%X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberRemainderNear(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + decDivideOp(res, lhs, rhs, set, REMNEAR, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberRemainderNear */ + +/* ------------------------------------------------------------------ */ +/* decNumberRotate -- rotate the coefficient of a Number left/right */ +/* */ +/* This computes C = A rot B (in base ten and rotating set->digits */ +/* digits). */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=XrotX) */ +/* lhs is A */ +/* rhs is B, the number of digits to rotate (-ve to right) */ +/* set is the context */ +/* */ +/* The digits of the coefficient of A are rotated to the left (if B */ +/* is positive) or to the right (if B is negative) without adjusting */ +/* the exponent or the sign of A. If lhs->digits is less than */ +/* set->digits the coefficient is padded with zeros on the left */ +/* before the rotate. Any leading zeros in the result are removed */ +/* as usual. */ +/* */ +/* B must be an integer (q=0) and in the range -set->digits through */ +/* +set->digits. */ +/* C must have space for set->digits digits. */ +/* NaNs are propagated as usual. Infinities are unaffected (but */ +/* B must be valid). No status is set unless B is invalid or an */ +/* operand is an sNaN. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberRotate(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + Int rotate; /* rhs as an Int */ + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + /* NaNs propagate as normal */ + if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) + decNaNs(res, lhs, rhs, set, &status); + /* rhs must be an integer */ + else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) + status=DEC_Invalid_operation; + else { /* both numeric, rhs is an integer */ + rotate=decGetInt(rhs); /* [cannot fail] */ + if (rotate==BADINT /* something bad .. */ + || rotate==BIGODD || rotate==BIGEVEN /* .. very big .. */ + || abs(rotate)>set->digits) /* .. or out of range */ + status=DEC_Invalid_operation; + else { /* rhs is OK */ + decNumberCopy(res, lhs); + /* convert -ve rotate to equivalent positive rotation */ + if (rotate<0) rotate=set->digits+rotate; + if (rotate!=0 && rotate!=set->digits /* zero or full rotation */ + && !decNumberIsInfinite(res)) { /* lhs was infinite */ + /* left-rotate to do; 0 < rotate < set->digits */ + uInt units, shift; /* work */ + uInt msudigits; /* digits in result msu */ + Unit *msu=res->lsu+D2U(res->digits)-1; /* current msu */ + Unit *msumax=res->lsu+D2U(set->digits)-1; /* rotation msu */ + for (msu++; msu<=msumax; msu++) *msu=0; /* ensure high units=0 */ + res->digits=set->digits; /* now full-length */ + msudigits=MSUDIGITS(res->digits); /* actual digits in msu */ + + /* rotation here is done in-place, in three steps */ + /* 1. shift all to least up to one unit to unit-align final */ + /* lsd [any digits shifted out are rotated to the left, */ + /* abutted to the original msd (which may require split)] */ + /* */ + /* [if there are no whole units left to rotate, the */ + /* rotation is now complete] */ + /* */ + /* 2. shift to least, from below the split point only, so that */ + /* the final msd is in the right place in its Unit [any */ + /* digits shifted out will fit exactly in the current msu, */ + /* left aligned, no split required] */ + /* */ + /* 3. rotate all the units by reversing left part, right */ + /* part, and then whole */ + /* */ + /* example: rotate right 8 digits (2 units + 2), DECDPUN=3. */ + /* */ + /* start: 00a bcd efg hij klm npq */ + /* */ + /* 1a 000 0ab cde fgh|ijk lmn [pq saved] */ + /* 1b 00p qab cde fgh|ijk lmn */ + /* */ + /* 2a 00p qab cde fgh|00i jkl [mn saved] */ + /* 2b mnp qab cde fgh|00i jkl */ + /* */ + /* 3a fgh cde qab mnp|00i jkl */ + /* 3b fgh cde qab mnp|jkl 00i */ + /* 3c 00i jkl mnp qab cde fgh */ + + /* Step 1: amount to shift is the partial right-rotate count */ + rotate=set->digits-rotate; /* make it right-rotate */ + units=rotate/DECDPUN; /* whole units to rotate */ + shift=rotate%DECDPUN; /* left-over digits count */ + if (shift>0) { /* not an exact number of units */ + uInt save=res->lsu[0]%powers[shift]; /* save low digit(s) */ + decShiftToLeast(res->lsu, D2U(res->digits), shift); + if (shift>msudigits) { /* msumax-1 needs >0 digits */ + uInt rem=save%powers[shift-msudigits];/* split save */ + *msumax=(Unit)(save/powers[shift-msudigits]); /* and insert */ + *(msumax-1)=*(msumax-1) + +(Unit)(rem*powers[DECDPUN-(shift-msudigits)]); /* .. */ + } + else { /* all fits in msumax */ + *msumax=*msumax+(Unit)(save*powers[msudigits-shift]); /* [maybe *1] */ + } + } /* digits shift needed */ + + /* If whole units to rotate... */ + if (units>0) { /* some to do */ + /* Step 2: the units to touch are the whole ones in rotate, */ + /* if any, and the shift is DECDPUN-msudigits (which may be */ + /* 0, again) */ + shift=DECDPUN-msudigits; + if (shift>0) { /* not an exact number of units */ + uInt save=res->lsu[0]%powers[shift]; /* save low digit(s) */ + decShiftToLeast(res->lsu, units, shift); + *msumax=*msumax+(Unit)(save*powers[msudigits]); + } /* partial shift needed */ + + /* Step 3: rotate the units array using triple reverse */ + /* (reversing is easy and fast) */ + decReverse(res->lsu+units, msumax); /* left part */ + decReverse(res->lsu, res->lsu+units-1); /* right part */ + decReverse(res->lsu, msumax); /* whole */ + } /* whole units to rotate */ + /* the rotation may have left an undetermined number of zeros */ + /* on the left, so true length needs to be calculated */ + res->digits=decGetDigits(res->lsu, msumax-res->lsu+1); + } /* rotate needed */ + } /* rhs OK */ + } /* numerics */ + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberRotate */ + +/* ------------------------------------------------------------------ */ +/* decNumberSameQuantum -- test for equal exponents */ +/* */ +/* res is the result number, which will contain either 0 or 1 */ +/* lhs is a number to test */ +/* rhs is the second (usually a pattern) */ +/* */ +/* No errors are possible and no context is needed. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberSameQuantum(decNumber *res, const decNumber *lhs, + const decNumber *rhs) { + Unit ret=0; /* return value */ + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, DECUNCONT)) return res; + #endif + + if (SPECIALARGS) { + if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1; + else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1; + /* [anything else with a special gives 0] */ + } + else if (lhs->exponent==rhs->exponent) ret=1; + + decNumberZero(res); /* OK to overwrite an operand now */ + *res->lsu=ret; + return res; + } /* decNumberSameQuantum */ + +/* ------------------------------------------------------------------ */ +/* decNumberScaleB -- multiply by a power of 10 */ +/* */ +/* This computes C = A x 10**B where B is an integer (q=0) with */ +/* maximum magnitude 2*(emax+digits) */ +/* */ +/* res is C, the result. C may be A or B */ +/* lhs is A, the number to adjust */ +/* rhs is B, the requested power of ten to use */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* The result may underflow or overflow. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberScaleB(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + Int reqexp; /* requested exponent change [B] */ + uInt status=0; /* accumulator */ + Int residue; /* work */ + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + /* Handle special values except lhs infinite */ + if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) + decNaNs(res, lhs, rhs, set, &status); + /* rhs must be an integer */ + else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) + status=DEC_Invalid_operation; + else { + /* lhs is a number; rhs is a finite with q==0 */ + reqexp=decGetInt(rhs); /* [cannot fail] */ + if (reqexp==BADINT /* something bad .. */ + || reqexp==BIGODD || reqexp==BIGEVEN /* .. very big .. */ + || abs(reqexp)>(2*(set->digits+set->emax))) /* .. or out of range */ + status=DEC_Invalid_operation; + else { /* rhs is OK */ + decNumberCopy(res, lhs); /* all done if infinite lhs */ + if (!decNumberIsInfinite(res)) { /* prepare to scale */ + res->exponent+=reqexp; /* adjust the exponent */ + residue=0; + decFinalize(res, set, &residue, &status); /* .. and check */ + } /* finite LHS */ + } /* rhs OK */ + } /* rhs finite */ + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberScaleB */ + +/* ------------------------------------------------------------------ */ +/* decNumberShift -- shift the coefficient of a Number left or right */ +/* */ +/* This computes C = A << B or C = A >> -B (in base ten). */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X<<X) */ +/* lhs is A */ +/* rhs is B, the number of digits to shift (-ve to right) */ +/* set is the context */ +/* */ +/* The digits of the coefficient of A are shifted to the left (if B */ +/* is positive) or to the right (if B is negative) without adjusting */ +/* the exponent or the sign of A. */ +/* */ +/* B must be an integer (q=0) and in the range -set->digits through */ +/* +set->digits. */ +/* C must have space for set->digits digits. */ +/* NaNs are propagated as usual. Infinities are unaffected (but */ +/* B must be valid). No status is set unless B is invalid or an */ +/* operand is an sNaN. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberShift(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + Int shift; /* rhs as an Int */ + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + /* NaNs propagate as normal */ + if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) + decNaNs(res, lhs, rhs, set, &status); + /* rhs must be an integer */ + else if (decNumberIsInfinite(rhs) || rhs->exponent!=0) + status=DEC_Invalid_operation; + else { /* both numeric, rhs is an integer */ + shift=decGetInt(rhs); /* [cannot fail] */ + if (shift==BADINT /* something bad .. */ + || shift==BIGODD || shift==BIGEVEN /* .. very big .. */ + || abs(shift)>set->digits) /* .. or out of range */ + status=DEC_Invalid_operation; + else { /* rhs is OK */ + decNumberCopy(res, lhs); + if (shift!=0 && !decNumberIsInfinite(res)) { /* something to do */ + if (shift>0) { /* to left */ + if (shift==set->digits) { /* removing all */ + *res->lsu=0; /* so place 0 */ + res->digits=1; /* .. */ + } + else { /* */ + /* first remove leading digits if necessary */ + if (res->digits+shift>set->digits) { + decDecap(res, res->digits+shift-set->digits); + /* that updated res->digits; may have gone to 1 (for a */ + /* single digit or for zero */ + } + if (res->digits>1 || *res->lsu) /* if non-zero.. */ + res->digits=decShiftToMost(res->lsu, res->digits, shift); + } /* partial left */ + } /* left */ + else { /* to right */ + if (-shift>=res->digits) { /* discarding all */ + *res->lsu=0; /* so place 0 */ + res->digits=1; /* .. */ + } + else { + decShiftToLeast(res->lsu, D2U(res->digits), -shift); + res->digits-=(-shift); + } + } /* to right */ + } /* non-0 non-Inf shift */ + } /* rhs OK */ + } /* numerics */ + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberShift */ + +/* ------------------------------------------------------------------ */ +/* decNumberSquareRoot -- square root operator */ +/* */ +/* This computes C = squareroot(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +/* This uses the following varying-precision algorithm in: */ +/* */ +/* Properly Rounded Variable Precision Square Root, T. E. Hull and */ +/* A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, */ +/* pp229-237, ACM, September 1985. */ +/* */ +/* The square-root is calculated using Newton's method, after which */ +/* a check is made to ensure the result is correctly rounded. */ +/* */ +/* % [Reformatted original Numerical Turing source code follows.] */ +/* function sqrt(x : real) : real */ +/* % sqrt(x) returns the properly rounded approximation to the square */ +/* % root of x, in the precision of the calling environment, or it */ +/* % fails if x < 0. */ +/* % t e hull and a abrham, august, 1984 */ +/* if x <= 0 then */ +/* if x < 0 then */ +/* assert false */ +/* else */ +/* result 0 */ +/* end if */ +/* end if */ +/* var f := setexp(x, 0) % fraction part of x [0.1 <= x < 1] */ +/* var e := getexp(x) % exponent part of x */ +/* var approx : real */ +/* if e mod 2 = 0 then */ +/* approx := .259 + .819 * f % approx to root of f */ +/* else */ +/* f := f/l0 % adjustments */ +/* e := e + 1 % for odd */ +/* approx := .0819 + 2.59 * f % exponent */ +/* end if */ +/* */ +/* var p:= 3 */ +/* const maxp := currentprecision + 2 */ +/* loop */ +/* p := min(2*p - 2, maxp) % p = 4,6,10, . . . , maxp */ +/* precision p */ +/* approx := .5 * (approx + f/approx) */ +/* exit when p = maxp */ +/* end loop */ +/* */ +/* % approx is now within 1 ulp of the properly rounded square root */ +/* % of f; to ensure proper rounding, compare squares of (approx - */ +/* % l/2 ulp) and (approx + l/2 ulp) with f. */ +/* p := currentprecision */ +/* begin */ +/* precision p + 2 */ +/* const approxsubhalf := approx - setexp(.5, -p) */ +/* if mulru(approxsubhalf, approxsubhalf) > f then */ +/* approx := approx - setexp(.l, -p + 1) */ +/* else */ +/* const approxaddhalf := approx + setexp(.5, -p) */ +/* if mulrd(approxaddhalf, approxaddhalf) < f then */ +/* approx := approx + setexp(.l, -p + 1) */ +/* end if */ +/* end if */ +/* end */ +/* result setexp(approx, e div 2) % fix exponent */ +/* end sqrt */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberSquareRoot(decNumber *res, const decNumber *rhs, + decContext *set) { + decContext workset, approxset; /* work contexts */ + decNumber dzero; /* used for constant zero */ + Int maxp; /* largest working precision */ + Int workp; /* working precision */ + Int residue=0; /* rounding residue */ + uInt status=0, ignore=0; /* status accumulators */ + uInt rstatus; /* .. */ + Int exp; /* working exponent */ + Int ideal; /* ideal (preferred) exponent */ + Int needbytes; /* work */ + Int dropped; /* .. */ + + #if DECSUBSET + decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */ + #endif + /* buffer for f [needs +1 in case DECBUFFER 0] */ + decNumber buff[D2N(DECBUFFER+1)]; + /* buffer for a [needs +2 to match likely maxp] */ + decNumber bufa[D2N(DECBUFFER+2)]; + /* buffer for temporary, b [must be same size as a] */ + decNumber bufb[D2N(DECBUFFER+2)]; + decNumber *allocbuff=NULL; /* -> allocated buff, iff allocated */ + decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ + decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */ + decNumber *f=buff; /* reduced fraction */ + decNumber *a=bufa; /* approximation to result */ + decNumber *b=bufb; /* intermediate result */ + /* buffer for temporary variable, up to 3 digits */ + decNumber buft[D2N(3)]; + decNumber *t=buft; /* up-to-3-digit constant or work */ + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + do { /* protect allocated storage */ + #if DECSUBSET + if (!set->extended) { + /* reduce operand and set lostDigits status, as needed */ + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, &status); + if (allocrhs==NULL) break; + /* [Note: 'f' allocation below could reuse this buffer if */ + /* used, but as this is rare they are kept separate for clarity.] */ + rhs=allocrhs; + } + } + #endif + /* [following code does not require input rounding] */ + + /* handle infinities and NaNs */ + if (SPECIALARG) { + if (decNumberIsInfinite(rhs)) { /* an infinity */ + if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation; + else decNumberCopy(res, rhs); /* +Infinity */ + } + else decNaNs(res, rhs, NULL, set, &status); /* a NaN */ + break; + } + + /* calculate the ideal (preferred) exponent [floor(exp/2)] */ + /* [We would like to write: ideal=rhs->exponent>>1, but this */ + /* generates a compiler warning. Generated code is the same.] */ + ideal=(rhs->exponent&~1)/2; /* target */ + + /* handle zeros */ + if (ISZERO(rhs)) { + decNumberCopy(res, rhs); /* could be 0 or -0 */ + res->exponent=ideal; /* use the ideal [safe] */ + /* use decFinish to clamp any out-of-range exponent, etc. */ + decFinish(res, set, &residue, &status); + break; + } + + /* any other -x is an oops */ + if (decNumberIsNegative(rhs)) { + status|=DEC_Invalid_operation; + break; + } + + /* space is needed for three working variables */ + /* f -- the same precision as the RHS, reduced to 0.01->0.99... */ + /* a -- Hull's approximation -- precision, when assigned, is */ + /* currentprecision+1 or the input argument precision, */ + /* whichever is larger (+2 for use as temporary) */ + /* b -- intermediate temporary result (same size as a) */ + /* if any is too long for local storage, then allocate */ + workp=MAXI(set->digits+1, rhs->digits); /* actual rounding precision */ + maxp=workp+2; /* largest working precision */ + + needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); + if (needbytes>(Int)sizeof(buff)) { + allocbuff=(decNumber *)malloc(needbytes); + if (allocbuff==NULL) { /* hopeless -- abandon */ + status|=DEC_Insufficient_storage; + break;} + f=allocbuff; /* use the allocated space */ + } + /* a and b both need to be able to hold a maxp-length number */ + needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit); + if (needbytes>(Int)sizeof(bufa)) { /* [same applies to b] */ + allocbufa=(decNumber *)malloc(needbytes); + allocbufb=(decNumber *)malloc(needbytes); + if (allocbufa==NULL || allocbufb==NULL) { /* hopeless */ + status|=DEC_Insufficient_storage; + break;} + a=allocbufa; /* use the allocated spaces */ + b=allocbufb; /* .. */ + } + + /* copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 */ + decNumberCopy(f, rhs); + exp=f->exponent+f->digits; /* adjusted to Hull rules */ + f->exponent=-(f->digits); /* to range */ + + /* set up working context */ + decContextDefault(&workset, DEC_INIT_DECIMAL64); + + /* [Until further notice, no error is possible and status bits */ + /* (Rounded, etc.) should be ignored, not accumulated.] */ + + /* Calculate initial approximation, and allow for odd exponent */ + workset.digits=workp; /* p for initial calculation */ + t->bits=0; t->digits=3; + a->bits=0; a->digits=3; + if ((exp & 1)==0) { /* even exponent */ + /* Set t=0.259, a=0.819 */ + t->exponent=-3; + a->exponent=-3; + #if DECDPUN>=3 + t->lsu[0]=259; + a->lsu[0]=819; + #elif DECDPUN==2 + t->lsu[0]=59; t->lsu[1]=2; + a->lsu[0]=19; a->lsu[1]=8; + #else + t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2; + a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8; + #endif + } + else { /* odd exponent */ + /* Set t=0.0819, a=2.59 */ + f->exponent--; /* f=f/10 */ + exp++; /* e=e+1 */ + t->exponent=-4; + a->exponent=-2; + #if DECDPUN>=3 + t->lsu[0]=819; + a->lsu[0]=259; + #elif DECDPUN==2 + t->lsu[0]=19; t->lsu[1]=8; + a->lsu[0]=59; a->lsu[1]=2; + #else + t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8; + a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2; + #endif + } + decMultiplyOp(a, a, f, &workset, &ignore); /* a=a*f */ + decAddOp(a, a, t, &workset, 0, &ignore); /* ..+t */ + /* [a is now the initial approximation for sqrt(f), calculated with */ + /* currentprecision, which is also a's precision.] */ + + /* the main calculation loop */ + decNumberZero(&dzero); /* make 0 */ + decNumberZero(t); /* set t = 0.5 */ + t->lsu[0]=5; /* .. */ + t->exponent=-1; /* .. */ + workset.digits=3; /* initial p */ + for (;;) { + /* set p to min(2*p - 2, maxp) [hence 3; or: 4, 6, 10, ... , maxp] */ + workset.digits=workset.digits*2-2; + if (workset.digits>maxp) workset.digits=maxp; + /* a = 0.5 * (a + f/a) */ + /* [calculated at p then rounded to currentprecision] */ + decDivideOp(b, f, a, &workset, DIVIDE, &ignore); /* b=f/a */ + decAddOp(b, b, a, &workset, 0, &ignore); /* b=b+a */ + decMultiplyOp(a, b, t, &workset, &ignore); /* a=b*0.5 */ + if (a->digits==maxp) break; /* have required digits */ + } /* loop */ + + /* Here, 0.1 <= a < 1 [Hull], and a has maxp digits */ + /* now reduce to length, etc.; this needs to be done with a */ + /* having the correct exponent so as to handle subnormals */ + /* correctly */ + approxset=*set; /* get emin, emax, etc. */ + approxset.round=DEC_ROUND_HALF_EVEN; + a->exponent+=exp/2; /* set correct exponent */ + + rstatus=0; /* clear status */ + residue=0; /* .. and accumulator */ + decCopyFit(a, a, &approxset, &residue, &rstatus); /* reduce (if needed) */ + decFinish(a, &approxset, &residue, &rstatus); /* clean and finalize */ + + /* Overflow was possible if the input exponent was out-of-range, */ + /* in which case quit */ + if (rstatus&DEC_Overflow) { + status=rstatus; /* use the status as-is */ + decNumberCopy(res, a); /* copy to result */ + break; + } + + /* Preserve status except Inexact/Rounded */ + status|=(rstatus & ~(DEC_Rounded|DEC_Inexact)); + + /* Carry out the Hull correction */ + a->exponent-=exp/2; /* back to 0.1->1 */ + + /* a is now at final precision and within 1 ulp of the properly */ + /* rounded square root of f; to ensure proper rounding, compare */ + /* squares of (a - l/2 ulp) and (a + l/2 ulp) with f. */ + /* Here workset.digits=maxp and t=0.5, and a->digits determines */ + /* the ulp */ + workset.digits--; /* maxp-1 is OK now */ + t->exponent=-a->digits-1; /* make 0.5 ulp */ + decAddOp(b, a, t, &workset, DECNEG, &ignore); /* b = a - 0.5 ulp */ + workset.round=DEC_ROUND_UP; + decMultiplyOp(b, b, b, &workset, &ignore); /* b = mulru(b, b) */ + decCompareOp(b, f, b, &workset, COMPARE, &ignore); /* b ? f, reversed */ + if (decNumberIsNegative(b)) { /* f < b [i.e., b > f] */ + /* this is the more common adjustment, though both are rare */ + t->exponent++; /* make 1.0 ulp */ + t->lsu[0]=1; /* .. */ + decAddOp(a, a, t, &workset, DECNEG, &ignore); /* a = a - 1 ulp */ + /* assign to approx [round to length] */ + approxset.emin-=exp/2; /* adjust to match a */ + approxset.emax-=exp/2; + decAddOp(a, &dzero, a, &approxset, 0, &ignore); + } + else { + decAddOp(b, a, t, &workset, 0, &ignore); /* b = a + 0.5 ulp */ + workset.round=DEC_ROUND_DOWN; + decMultiplyOp(b, b, b, &workset, &ignore); /* b = mulrd(b, b) */ + decCompareOp(b, b, f, &workset, COMPARE, &ignore); /* b ? f */ + if (decNumberIsNegative(b)) { /* b < f */ + t->exponent++; /* make 1.0 ulp */ + t->lsu[0]=1; /* .. */ + decAddOp(a, a, t, &workset, 0, &ignore); /* a = a + 1 ulp */ + /* assign to approx [round to length] */ + approxset.emin-=exp/2; /* adjust to match a */ + approxset.emax-=exp/2; + decAddOp(a, &dzero, a, &approxset, 0, &ignore); + } + } + /* [no errors are possible in the above, and rounding/inexact during */ + /* estimation are irrelevant, so status was not accumulated] */ + + /* Here, 0.1 <= a < 1 (still), so adjust back */ + a->exponent+=exp/2; /* set correct exponent */ + + /* count droppable zeros [after any subnormal rounding] by */ + /* trimming a copy */ + decNumberCopy(b, a); + decTrim(b, set, 1, &dropped); /* [drops trailing zeros] */ + + /* Set Inexact and Rounded. The answer can only be exact if */ + /* it is short enough so that squaring it could fit in workp digits, */ + /* and it cannot have trailing zeros due to clamping, so these are */ + /* the only (relatively rare) conditions a careful check is needed */ + if (b->digits*2-1 > workp && !set->clamp) { /* cannot fit */ + status|=DEC_Inexact|DEC_Rounded; + } + else { /* could be exact/unrounded */ + uInt mstatus=0; /* local status */ + decMultiplyOp(b, b, b, &workset, &mstatus); /* try the multiply */ + if (mstatus&DEC_Overflow) { /* result just won't fit */ + status|=DEC_Inexact|DEC_Rounded; + } + else { /* plausible */ + decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); /* b ? rhs */ + if (!ISZERO(t)) status|=DEC_Inexact|DEC_Rounded; /* not equal */ + else { /* is Exact */ + /* here, dropped is the count of trailing zeros in 'a' */ + /* use closest exponent to ideal... */ + Int todrop=ideal-a->exponent; /* most that can be dropped */ + if (todrop<0) status|=DEC_Rounded; /* ideally would add 0s */ + else { /* unrounded */ + if (dropped<todrop) { /* clamp to those available */ + todrop=dropped; + status|=DEC_Clamped; + } + if (todrop>0) { /* have some to drop */ + decShiftToLeast(a->lsu, D2U(a->digits), todrop); + a->exponent+=todrop; /* maintain numerical value */ + a->digits-=todrop; /* new length */ + } + } + } + } + } + + /* double-check Underflow, as perhaps the result could not have */ + /* been subnormal (initial argument too big), or it is now Exact */ + if (status&DEC_Underflow) { + Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */ + /* check if truly subnormal */ + #if DECEXTFLAG /* DEC_Subnormal too */ + if (ae>=set->emin*2) status&=~(DEC_Subnormal|DEC_Underflow); + #else + if (ae>=set->emin*2) status&=~DEC_Underflow; + #endif + /* check if truly inexact */ + if (!(status&DEC_Inexact)) status&=~DEC_Underflow; + } + + decNumberCopy(res, a); /* a is now the result */ + } while(0); /* end protected */ + + if (allocbuff!=NULL) free(allocbuff); /* drop any storage used */ + if (allocbufa!=NULL) free(allocbufa); /* .. */ + if (allocbufb!=NULL) free(allocbufb); /* .. */ + #if DECSUBSET + if (allocrhs !=NULL) free(allocrhs); /* .. */ + #endif + if (status!=0) decStatus(res, status, set);/* then report status */ + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberSquareRoot */ + +/* ------------------------------------------------------------------ */ +/* decNumberSubtract -- subtract two Numbers */ +/* */ +/* This computes C = A - B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X-X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* */ +/* C must have space for set->digits digits. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberSubtract(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + uInt status=0; /* accumulator */ + + decAddOp(res, lhs, rhs, set, DECNEG, &status); + if (status!=0) decStatus(res, status, set); + #if DECCHECK + decCheckInexact(res, set); + #endif + return res; + } /* decNumberSubtract */ + +/* ------------------------------------------------------------------ */ +/* decNumberToIntegralExact -- round-to-integral-value with InExact */ +/* decNumberToIntegralValue -- round-to-integral-value */ +/* */ +/* res is the result */ +/* rhs is input number */ +/* set is the context */ +/* */ +/* res must have space for any value of rhs. */ +/* */ +/* This implements the IEEE special operators and therefore treats */ +/* special values as valid. For finite numbers it returns */ +/* rescale(rhs, 0) if rhs->exponent is <0. */ +/* Otherwise the result is rhs (so no error is possible, except for */ +/* sNaN). */ +/* */ +/* The context is used for rounding mode and status after sNaN, but */ +/* the digits setting is ignored. The Exact version will signal */ +/* Inexact if the result differs numerically from rhs; the other */ +/* never signals Inexact. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberToIntegralExact(decNumber *res, const decNumber *rhs, + decContext *set) { + decNumber dn; + decContext workset; /* working context */ + uInt status=0; /* accumulator */ + + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + /* handle infinities and NaNs */ + if (SPECIALARG) { + if (decNumberIsInfinite(rhs)) decNumberCopy(res, rhs); /* an Infinity */ + else decNaNs(res, rhs, NULL, set, &status); /* a NaN */ + } + else { /* finite */ + /* have a finite number; no error possible (res must be big enough) */ + if (rhs->exponent>=0) return decNumberCopy(res, rhs); + /* that was easy, but if negative exponent there is work to do... */ + workset=*set; /* clone rounding, etc. */ + workset.digits=rhs->digits; /* no length rounding */ + workset.traps=0; /* no traps */ + decNumberZero(&dn); /* make a number with exponent 0 */ + decNumberQuantize(res, rhs, &dn, &workset); + status|=workset.status; + } + if (status!=0) decStatus(res, status, set); + return res; + } /* decNumberToIntegralExact */ + +decNumber * decNumberToIntegralValue(decNumber *res, const decNumber *rhs, + decContext *set) { + decContext workset=*set; /* working context */ + workset.traps=0; /* no traps */ + decNumberToIntegralExact(res, rhs, &workset); + /* this never affects set, except for sNaNs; NaN will have been set */ + /* or propagated already, so no need to call decStatus */ + set->status|=workset.status&DEC_Invalid_operation; + return res; + } /* decNumberToIntegralValue */ + +/* ------------------------------------------------------------------ */ +/* decNumberXor -- XOR two Numbers, digitwise */ +/* */ +/* This computes C = A ^ B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X^X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context (used for result length and error report) */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Logical function restrictions apply (see above); a NaN is */ +/* returned with Invalid_operation if a restriction is violated. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberXor(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + const Unit *ua, *ub; /* -> operands */ + const Unit *msua, *msub; /* -> operand msus */ + Unit *uc, *msuc; /* -> result and its msu */ + Int msudigs; /* digits in res msu */ + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs) + || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + /* operands are valid */ + ua=lhs->lsu; /* bottom-up */ + ub=rhs->lsu; /* .. */ + uc=res->lsu; /* .. */ + msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */ + msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */ + msuc=uc+D2U(set->digits)-1; /* -> msu of result */ + msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */ + for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */ + Unit a, b; /* extract units */ + if (ua>msua) a=0; + else a=*ua; + if (ub>msub) b=0; + else b=*ub; + *uc=0; /* can now write back */ + if (a|b) { /* maybe 1 bits to examine */ + Int i, j; + /* This loop could be unrolled and/or use BIN2BCD tables */ + for (i=0; i<DECDPUN; i++) { + if ((a^b)&1) *uc=*uc+(Unit)powers[i]; /* effect XOR */ + j=a%10; + a=a/10; + j|=b%10; + b=b/10; + if (j>1) { + decStatus(res, DEC_Invalid_operation, set); + return res; + } + if (uc==msuc && i==msudigs-1) break; /* just did final digit */ + } /* each digit */ + } /* non-zero */ + } /* each unit */ + /* [here uc-1 is the msu of the result] */ + res->digits=decGetDigits(res->lsu, uc-res->lsu); + res->exponent=0; /* integer */ + res->bits=0; /* sign=0 */ + return res; /* [no status to set] */ + } /* decNumberXor */ + + +/* ================================================================== */ +/* Utility routines */ +/* ================================================================== */ + +/* ------------------------------------------------------------------ */ +/* decNumberClass -- return the decClass of a decNumber */ +/* dn -- the decNumber to test */ +/* set -- the context to use for Emin */ +/* returns the decClass enum */ +/* ------------------------------------------------------------------ */ +enum decClass decNumberClass(const decNumber *dn, decContext *set) { + if (decNumberIsSpecial(dn)) { + if (decNumberIsQNaN(dn)) return DEC_CLASS_QNAN; + if (decNumberIsSNaN(dn)) return DEC_CLASS_SNAN; + /* must be an infinity */ + if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_INF; + return DEC_CLASS_POS_INF; + } + /* is finite */ + if (decNumberIsNormal(dn, set)) { /* most common */ + if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_NORMAL; + return DEC_CLASS_POS_NORMAL; + } + /* is subnormal or zero */ + if (decNumberIsZero(dn)) { /* most common */ + if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_ZERO; + return DEC_CLASS_POS_ZERO; + } + if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_SUBNORMAL; + return DEC_CLASS_POS_SUBNORMAL; + } /* decNumberClass */ + +/* ------------------------------------------------------------------ */ +/* decNumberClassToString -- convert decClass to a string */ +/* */ +/* eclass is a valid decClass */ +/* returns a constant string describing the class (max 13+1 chars) */ +/* ------------------------------------------------------------------ */ +const char *decNumberClassToString(enum decClass eclass) { + if (eclass==DEC_CLASS_POS_NORMAL) return DEC_ClassString_PN; + if (eclass==DEC_CLASS_NEG_NORMAL) return DEC_ClassString_NN; + if (eclass==DEC_CLASS_POS_ZERO) return DEC_ClassString_PZ; + if (eclass==DEC_CLASS_NEG_ZERO) return DEC_ClassString_NZ; + if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS; + if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS; + if (eclass==DEC_CLASS_POS_INF) return DEC_ClassString_PI; + if (eclass==DEC_CLASS_NEG_INF) return DEC_ClassString_NI; + if (eclass==DEC_CLASS_QNAN) return DEC_ClassString_QN; + if (eclass==DEC_CLASS_SNAN) return DEC_ClassString_SN; + return DEC_ClassString_UN; /* Unknown */ + } /* decNumberClassToString */ + +/* ------------------------------------------------------------------ */ +/* decNumberCopy -- copy a number */ +/* */ +/* dest is the target decNumber */ +/* src is the source decNumber */ +/* returns dest */ +/* */ +/* (dest==src is allowed and is a no-op) */ +/* All fields are updated as required. This is a utility operation, */ +/* so special values are unchanged and no error is possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCopy(decNumber *dest, const decNumber *src) { + + #if DECCHECK + if (src==NULL) return decNumberZero(dest); + #endif + + if (dest==src) return dest; /* no copy required */ + + /* Use explicit assignments here as structure assignment could copy */ + /* more than just the lsu (for small DECDPUN). This would not affect */ + /* the value of the results, but could disturb test harness spill */ + /* checking. */ + dest->bits=src->bits; + dest->exponent=src->exponent; + dest->digits=src->digits; + dest->lsu[0]=src->lsu[0]; + if (src->digits>DECDPUN) { /* more Units to come */ + const Unit *smsup, *s; /* work */ + Unit *d; /* .. */ + /* memcpy for the remaining Units would be safe as they cannot */ + /* overlap. However, this explicit loop is faster in short cases. */ + d=dest->lsu+1; /* -> first destination */ + smsup=src->lsu+D2U(src->digits); /* -> source msu+1 */ + for (s=src->lsu+1; s<smsup; s++, d++) *d=*s; + } + return dest; + } /* decNumberCopy */ + +/* ------------------------------------------------------------------ */ +/* decNumberCopyAbs -- quiet absolute value operator */ +/* */ +/* This sets C = abs(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* */ +/* C must have space for set->digits digits. */ +/* No exception or error can occur; this is a quiet bitwise operation.*/ +/* See also decNumberAbs for a checking version of this. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCopyAbs(decNumber *res, const decNumber *rhs) { + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; + #endif + decNumberCopy(res, rhs); + res->bits&=~DECNEG; /* turn off sign */ + return res; + } /* decNumberCopyAbs */ + +/* ------------------------------------------------------------------ */ +/* decNumberCopyNegate -- quiet negate value operator */ +/* */ +/* This sets C = negate(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* */ +/* C must have space for set->digits digits. */ +/* No exception or error can occur; this is a quiet bitwise operation.*/ +/* See also decNumberMinus for a checking version of this. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCopyNegate(decNumber *res, const decNumber *rhs) { + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; + #endif + decNumberCopy(res, rhs); + res->bits^=DECNEG; /* invert the sign */ + return res; + } /* decNumberCopyNegate */ + +/* ------------------------------------------------------------------ */ +/* decNumberCopySign -- quiet copy and set sign operator */ +/* */ +/* This sets C = A with the sign of B */ +/* */ +/* res is C, the result. C may be A */ +/* lhs is A */ +/* rhs is B */ +/* */ +/* C must have space for set->digits digits. */ +/* No exception or error can occur; this is a quiet bitwise operation.*/ +/* ------------------------------------------------------------------ */ +decNumber * decNumberCopySign(decNumber *res, const decNumber *lhs, + const decNumber *rhs) { + uByte sign; /* rhs sign */ + #if DECCHECK + if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res; + #endif + sign=rhs->bits & DECNEG; /* save sign bit */ + decNumberCopy(res, lhs); + res->bits&=~DECNEG; /* clear the sign */ + res->bits|=sign; /* set from rhs */ + return res; + } /* decNumberCopySign */ + +/* ------------------------------------------------------------------ */ +/* decNumberGetBCD -- get the coefficient in BCD8 */ +/* dn is the source decNumber */ +/* bcd is the uInt array that will receive dn->digits BCD bytes, */ +/* most-significant at offset 0 */ +/* returns bcd */ +/* */ +/* bcd must have at least dn->digits bytes. No error is possible; if */ +/* dn is a NaN or Infinite, digits must be 1 and the coefficient 0. */ +/* ------------------------------------------------------------------ */ +uByte * decNumberGetBCD(const decNumber *dn, uint8_t *bcd) { + uByte *ub=bcd+dn->digits-1; /* -> lsd */ + const Unit *up=dn->lsu; /* Unit pointer, -> lsu */ + + #if DECDPUN==1 /* trivial simple copy */ + for (; ub>=bcd; ub--, up++) *ub=*up; + #else /* chopping needed */ + uInt u=*up; /* work */ + uInt cut=DECDPUN; /* downcounter through unit */ + for (; ub>=bcd; ub--) { + *ub=(uByte)(u%10); /* [*6554 trick inhibits, here] */ + u=u/10; + cut--; + if (cut>0) continue; /* more in this unit */ + up++; + u=*up; + cut=DECDPUN; + } + #endif + return bcd; + } /* decNumberGetBCD */ + +/* ------------------------------------------------------------------ */ +/* decNumberSetBCD -- set (replace) the coefficient from BCD8 */ +/* dn is the target decNumber */ +/* bcd is the uInt array that will source n BCD bytes, most- */ +/* significant at offset 0 */ +/* n is the number of digits in the source BCD array (bcd) */ +/* returns dn */ +/* */ +/* dn must have space for at least n digits. No error is possible; */ +/* if dn is a NaN, or Infinite, or is to become a zero, n must be 1 */ +/* and bcd[0] zero. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) { + Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [target pointer] */ + const uByte *ub=bcd; /* -> source msd */ + + #if DECDPUN==1 /* trivial simple copy */ + for (; ub<bcd+n; ub++, up--) *up=*ub; + #else /* some assembly needed */ + /* calculate how many digits in msu, and hence first cut */ + Int cut=MSUDIGITS(n); /* [faster than remainder] */ + for (;up>=dn->lsu; up--) { /* each Unit from msu */ + *up=0; /* will take <=DECDPUN digits */ + for (; cut>0; ub++, cut--) *up=X10(*up)+*ub; + cut=DECDPUN; /* next Unit has all digits */ + } + #endif + dn->digits=n; /* set digit count */ + return dn; + } /* decNumberSetBCD */ + +/* ------------------------------------------------------------------ */ +/* decNumberIsNormal -- test normality of a decNumber */ +/* dn is the decNumber to test */ +/* set is the context to use for Emin */ +/* returns 1 if |dn| is finite and >=Nmin, 0 otherwise */ +/* ------------------------------------------------------------------ */ +Int decNumberIsNormal(const decNumber *dn, decContext *set) { + Int ae; /* adjusted exponent */ + #if DECCHECK + if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; + #endif + + if (decNumberIsSpecial(dn)) return 0; /* not finite */ + if (decNumberIsZero(dn)) return 0; /* not non-zero */ + + ae=dn->exponent+dn->digits-1; /* adjusted exponent */ + if (ae<set->emin) return 0; /* is subnormal */ + return 1; + } /* decNumberIsNormal */ + +/* ------------------------------------------------------------------ */ +/* decNumberIsSubnormal -- test subnormality of a decNumber */ +/* dn is the decNumber to test */ +/* set is the context to use for Emin */ +/* returns 1 if |dn| is finite, non-zero, and <Nmin, 0 otherwise */ +/* ------------------------------------------------------------------ */ +Int decNumberIsSubnormal(const decNumber *dn, decContext *set) { + Int ae; /* adjusted exponent */ + #if DECCHECK + if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0; + #endif + + if (decNumberIsSpecial(dn)) return 0; /* not finite */ + if (decNumberIsZero(dn)) return 0; /* not non-zero */ + + ae=dn->exponent+dn->digits-1; /* adjusted exponent */ + if (ae<set->emin) return 1; /* is subnormal */ + return 0; + } /* decNumberIsSubnormal */ + +/* ------------------------------------------------------------------ */ +/* decNumberTrim -- remove insignificant zeros */ +/* */ +/* dn is the number to trim */ +/* returns dn */ +/* */ +/* All fields are updated as required. This is a utility operation, */ +/* so special values are unchanged and no error is possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decNumberTrim(decNumber *dn) { + Int dropped; /* work */ + decContext set; /* .. */ + #if DECCHECK + if (decCheckOperands(DECUNRESU, DECUNUSED, dn, DECUNCONT)) return dn; + #endif + decContextDefault(&set, DEC_INIT_BASE); /* clamp=0 */ + return decTrim(dn, &set, 0, &dropped); + } /* decNumberTrim */ + +/* ------------------------------------------------------------------ */ +/* decNumberVersion -- return the name and version of this module */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +const char * decNumberVersion(void) { + return DECVERSION; + } /* decNumberVersion */ + +/* ------------------------------------------------------------------ */ +/* decNumberZero -- set a number to 0 */ +/* */ +/* dn is the number to set, with space for one digit */ +/* returns dn */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +/* Memset is not used as it is much slower in some environments. */ +decNumber * decNumberZero(decNumber *dn) { + + #if DECCHECK + if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn; + #endif + + dn->bits=0; + dn->exponent=0; + dn->digits=1; + dn->lsu[0]=0; + return dn; + } /* decNumberZero */ + +/* ================================================================== */ +/* Local routines */ +/* ================================================================== */ + +/* ------------------------------------------------------------------ */ +/* decToString -- lay out a number into a string */ +/* */ +/* dn is the number to lay out */ +/* string is where to lay out the number */ +/* eng is 1 if Engineering, 0 if Scientific */ +/* */ +/* string must be at least dn->digits+14 characters long */ +/* No error is possible. */ +/* */ +/* Note that this routine can generate a -0 or 0.000. These are */ +/* never generated in subset to-number or arithmetic, but can occur */ +/* in non-subset arithmetic (e.g., -1*0 or 1.234-1.234). */ +/* ------------------------------------------------------------------ */ +/* If DECCHECK is enabled the string "?" is returned if a number is */ +/* invalid. */ +static void decToString(const decNumber *dn, char *string, Flag eng) { + Int exp=dn->exponent; /* local copy */ + Int e; /* E-part value */ + Int pre; /* digits before the '.' */ + Int cut; /* for counting digits in a Unit */ + char *c=string; /* work [output pointer] */ + const Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [input pointer] */ + uInt u, pow; /* work */ + + #if DECCHECK + if (decCheckOperands(DECUNRESU, dn, DECUNUSED, DECUNCONT)) { + strcpy(string, "?"); + return;} + #endif + + if (decNumberIsNegative(dn)) { /* Negatives get a minus */ + *c='-'; + c++; + } + if (dn->bits&DECSPECIAL) { /* Is a special value */ + if (decNumberIsInfinite(dn)) { + strcpy(c, "Inf"); + strcpy(c+3, "inity"); + return;} + /* a NaN */ + if (dn->bits&DECSNAN) { /* signalling NaN */ + *c='s'; + c++; + } + strcpy(c, "NaN"); + c+=3; /* step past */ + /* if not a clean non-zero coefficient, that's all there is in a */ + /* NaN string */ + if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return; + /* [drop through to add integer] */ + } + + /* calculate how many digits in msu, and hence first cut */ + cut=MSUDIGITS(dn->digits); /* [faster than remainder] */ + cut--; /* power of ten for digit */ + + if (exp==0) { /* simple integer [common fastpath] */ + for (;up>=dn->lsu; up--) { /* each Unit from msu */ + u=*up; /* contains DECDPUN digits to lay out */ + for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow); + cut=DECDPUN-1; /* next Unit has all digits */ + } + *c='\0'; /* terminate the string */ + return;} + + /* non-0 exponent -- assume plain form */ + pre=dn->digits+exp; /* digits before '.' */ + e=0; /* no E */ + if ((exp>0) || (pre<-5)) { /* need exponential form */ + e=exp+dn->digits-1; /* calculate E value */ + pre=1; /* assume one digit before '.' */ + if (eng && (e!=0)) { /* engineering: may need to adjust */ + Int adj; /* adjustment */ + /* The C remainder operator is undefined for negative numbers, so */ + /* a positive remainder calculation must be used here */ + if (e<0) { + adj=(-e)%3; + if (adj!=0) adj=3-adj; + } + else { /* e>0 */ + adj=e%3; + } + e=e-adj; + /* if dealing with zero still produce an exponent which is a */ + /* multiple of three, as expected, but there will only be the */ + /* one zero before the E, still. Otherwise note the padding. */ + if (!ISZERO(dn)) pre+=adj; + else { /* is zero */ + if (adj!=0) { /* 0.00Esnn needed */ + e=e+3; + pre=-(2-adj); + } + } /* zero */ + } /* eng */ + } /* need exponent */ + + /* lay out the digits of the coefficient, adding 0s and . as needed */ + u=*up; + if (pre>0) { /* xxx.xxx or xx00 (engineering) form */ + Int n=pre; + for (; pre>0; pre--, c++, cut--) { + if (cut<0) { /* need new Unit */ + if (up==dn->lsu) break; /* out of input digits (pre>digits) */ + up--; + cut=DECDPUN-1; + u=*up; + } + TODIGIT(u, cut, c, pow); + } + if (n<dn->digits) { /* more to come, after '.' */ + *c='.'; c++; + for (;; c++, cut--) { + if (cut<0) { /* need new Unit */ + if (up==dn->lsu) break; /* out of input digits */ + up--; + cut=DECDPUN-1; + u=*up; + } + TODIGIT(u, cut, c, pow); + } + } + else for (; pre>0; pre--, c++) *c='0'; /* 0 padding (for engineering) needed */ + } + else { /* 0.xxx or 0.000xxx form */ + *c='0'; c++; + *c='.'; c++; + for (; pre<0; pre++, c++) *c='0'; /* add any 0's after '.' */ + for (; ; c++, cut--) { + if (cut<0) { /* need new Unit */ + if (up==dn->lsu) break; /* out of input digits */ + up--; + cut=DECDPUN-1; + u=*up; + } + TODIGIT(u, cut, c, pow); + } + } + + /* Finally add the E-part, if needed. It will never be 0, has a + base maximum and minimum of +999999999 through -999999999, but + could range down to -1999999998 for anormal numbers */ + if (e!=0) { + Flag had=0; /* 1=had non-zero */ + *c='E'; c++; + *c='+'; c++; /* assume positive */ + u=e; /* .. */ + if (e<0) { + *(c-1)='-'; /* oops, need - */ + u=-e; /* uInt, please */ + } + /* lay out the exponent [_itoa or equivalent is not ANSI C] */ + for (cut=9; cut>=0; cut--) { + TODIGIT(u, cut, c, pow); + if (*c=='0' && !had) continue; /* skip leading zeros */ + had=1; /* had non-0 */ + c++; /* step for next */ + } /* cut */ + } + *c='\0'; /* terminate the string (all paths) */ + return; + } /* decToString */ + +/* ------------------------------------------------------------------ */ +/* decAddOp -- add/subtract operation */ +/* */ +/* This computes C = A + B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X+X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* negate is DECNEG if rhs should be negated, or 0 otherwise */ +/* status accumulates status for the caller */ +/* */ +/* C must have space for set->digits digits. */ +/* Inexact in status must be 0 for correct Exact zero sign in result */ +/* ------------------------------------------------------------------ */ +/* If possible, the coefficient is calculated directly into C. */ +/* However, if: */ +/* -- a digits+1 calculation is needed because the numbers are */ +/* unaligned and span more than set->digits digits */ +/* -- a carry to digits+1 digits looks possible */ +/* -- C is the same as A or B, and the result would destructively */ +/* overlap the A or B coefficient */ +/* then the result must be calculated into a temporary buffer. In */ +/* this case a local (stack) buffer is used if possible, and only if */ +/* too long for that does malloc become the final resort. */ +/* */ +/* Misalignment is handled as follows: */ +/* Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp. */ +/* BPad: Apply the padding by a combination of shifting (whole */ +/* units) and multiplication (part units). */ +/* */ +/* Addition, especially x=x+1, is speed-critical. */ +/* The static buffer is larger than might be expected to allow for */ +/* calls from higher-level funtions (notable exp). */ +/* ------------------------------------------------------------------ */ +static decNumber * decAddOp(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set, + uByte negate, uInt *status) { + #if DECSUBSET + decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ + decNumber *allocrhs=NULL; /* .., rhs */ + #endif + Int rhsshift; /* working shift (in Units) */ + Int maxdigits; /* longest logical length */ + Int mult; /* multiplier */ + Int residue; /* rounding accumulator */ + uByte bits; /* result bits */ + Flag diffsign; /* non-0 if arguments have different sign */ + Unit *acc; /* accumulator for result */ + Unit accbuff[SD2U(DECBUFFER*2+20)]; /* local buffer [*2+20 reduces many */ + /* allocations when called from */ + /* other operations, notable exp] */ + Unit *allocacc=NULL; /* -> allocated acc buffer, iff allocated */ + Int reqdigits=set->digits; /* local copy; requested DIGITS */ + Int padding; /* work */ + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { /* protect allocated storage */ + #if DECSUBSET + if (!set->extended) { + /* reduce operands and set lostDigits status, as needed */ + if (lhs->digits>reqdigits) { + alloclhs=decRoundOperand(lhs, set, status); + if (alloclhs==NULL) break; + lhs=alloclhs; + } + if (rhs->digits>reqdigits) { + allocrhs=decRoundOperand(rhs, set, status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + /* [following code does not require input rounding] */ + + /* note whether signs differ [used all paths] */ + diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG); + + /* handle infinities and NaNs */ + if (SPECIALARGS) { /* a special bit set */ + if (SPECIALARGS & (DECSNAN | DECNAN)) /* a NaN */ + decNaNs(res, lhs, rhs, set, status); + else { /* one or two infinities */ + if (decNumberIsInfinite(lhs)) { /* LHS is infinity */ + /* two infinities with different signs is invalid */ + if (decNumberIsInfinite(rhs) && diffsign) { + *status|=DEC_Invalid_operation; + break; + } + bits=lhs->bits & DECNEG; /* get sign from LHS */ + } + else bits=(rhs->bits^negate) & DECNEG;/* RHS must be Infinity */ + bits|=DECINF; + decNumberZero(res); + res->bits=bits; /* set +/- infinity */ + } /* an infinity */ + break; + } + + /* Quick exit for add 0s; return the non-0, modified as need be */ + if (ISZERO(lhs)) { + Int adjust; /* work */ + Int lexp=lhs->exponent; /* save in case LHS==RES */ + bits=lhs->bits; /* .. */ + residue=0; /* clear accumulator */ + decCopyFit(res, rhs, set, &residue, status); /* copy (as needed) */ + res->bits^=negate; /* flip if rhs was negated */ + #if DECSUBSET + if (set->extended) { /* exponents on zeros count */ + #endif + /* exponent will be the lower of the two */ + adjust=lexp-res->exponent; /* adjustment needed [if -ve] */ + if (ISZERO(res)) { /* both 0: special IEEE 854 rules */ + if (adjust<0) res->exponent=lexp; /* set exponent */ + /* 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 */ + if (diffsign) { + if (set->round!=DEC_ROUND_FLOOR) res->bits=0; + else res->bits=DECNEG; /* preserve 0 sign */ + } + } + else { /* non-0 res */ + if (adjust<0) { /* 0-padding needed */ + if ((res->digits-adjust)>set->digits) { + adjust=res->digits-set->digits; /* to fit exactly */ + *status|=DEC_Rounded; /* [but exact] */ + } + res->digits=decShiftToMost(res->lsu, res->digits, -adjust); + res->exponent+=adjust; /* set the exponent. */ + } + } /* non-0 res */ + #if DECSUBSET + } /* extended */ + #endif + decFinish(res, set, &residue, status); /* clean and finalize */ + break;} + + if (ISZERO(rhs)) { /* [lhs is non-zero] */ + Int adjust; /* work */ + Int rexp=rhs->exponent; /* save in case RHS==RES */ + bits=rhs->bits; /* be clean */ + residue=0; /* clear accumulator */ + decCopyFit(res, lhs, set, &residue, status); /* copy (as needed) */ + #if DECSUBSET + if (set->extended) { /* exponents on zeros count */ + #endif + /* exponent will be the lower of the two */ + /* [0-0 case handled above] */ + adjust=rexp-res->exponent; /* adjustment needed [if -ve] */ + if (adjust<0) { /* 0-padding needed */ + if ((res->digits-adjust)>set->digits) { + adjust=res->digits-set->digits; /* to fit exactly */ + *status|=DEC_Rounded; /* [but exact] */ + } + res->digits=decShiftToMost(res->lsu, res->digits, -adjust); + res->exponent+=adjust; /* set the exponent. */ + } + #if DECSUBSET + } /* extended */ + #endif + decFinish(res, set, &residue, status); /* clean and finalize */ + break;} + + /* [NB: both fastpath and mainpath code below assume these cases */ + /* (notably 0-0) have already been handled] */ + + /* calculate the padding needed to align the operands */ + padding=rhs->exponent-lhs->exponent; + + /* Fastpath cases where the numbers are aligned and normal, the RHS */ + /* is all in one unit, no operand rounding is needed, and no carry, */ + /* lengthening, or borrow is needed */ + if (padding==0 + && rhs->digits<=DECDPUN + && rhs->exponent>=set->emin /* [some normals drop through] */ + && rhs->exponent<=set->emax-set->digits+1 /* [could clamp] */ + && rhs->digits<=reqdigits + && lhs->digits<=reqdigits) { + Int partial=*lhs->lsu; + if (!diffsign) { /* adding */ + partial+=*rhs->lsu; + if ((partial<=DECDPUNMAX) /* result fits in unit */ + && (lhs->digits>=DECDPUN || /* .. and no digits-count change */ + partial<(Int)powers[lhs->digits])) { /* .. */ + if (res!=lhs) decNumberCopy(res, lhs); /* not in place */ + *res->lsu=(Unit)partial; /* [copy could have overwritten RHS] */ + break; + } + /* else drop out for careful add */ + } + else { /* signs differ */ + partial-=*rhs->lsu; + if (partial>0) { /* no borrow needed, and non-0 result */ + if (res!=lhs) decNumberCopy(res, lhs); /* not in place */ + *res->lsu=(Unit)partial; + /* this could have reduced digits [but result>0] */ + res->digits=decGetDigits(res->lsu, D2U(res->digits)); + break; + } + /* else drop out for careful subtract */ + } + } + + /* Now align (pad) the lhs or rhs so they can be added or */ + /* subtracted, as necessary. If one number is much larger than */ + /* the other (that is, if in plain form there is a least one */ + /* digit between the lowest digit of one and the highest of the */ + /* other) padding with up to DIGITS-1 trailing zeros may be */ + /* needed; then apply rounding (as exotic rounding modes may be */ + /* affected by the residue). */ + rhsshift=0; /* rhs shift to left (padding) in Units */ + bits=lhs->bits; /* assume sign is that of LHS */ + mult=1; /* likely multiplier */ + + /* [if padding==0 the operands are aligned; no padding is needed] */ + if (padding!=0) { + /* some padding needed; always pad the RHS, as any required */ + /* padding can then be effected by a simple combination of */ + /* shifts and a multiply */ + Flag swapped=0; + if (padding<0) { /* LHS needs the padding */ + const decNumber *t; + padding=-padding; /* will be +ve */ + bits=(uByte)(rhs->bits^negate); /* assumed sign is now that of RHS */ + t=lhs; lhs=rhs; rhs=t; + swapped=1; + } + + /* If, after pad, rhs would be longer than lhs by digits+1 or */ + /* more then lhs cannot affect the answer, except as a residue, */ + /* so only need to pad up to a length of DIGITS+1. */ + if (rhs->digits+padding > lhs->digits+reqdigits+1) { + /* The RHS is sufficient */ + /* for residue use the relative sign indication... */ + Int shift=reqdigits-rhs->digits; /* left shift needed */ + residue=1; /* residue for rounding */ + if (diffsign) residue=-residue; /* signs differ */ + /* copy, shortening if necessary */ + decCopyFit(res, rhs, set, &residue, status); + /* if it was already shorter, then need to pad with zeros */ + if (shift>0) { + res->digits=decShiftToMost(res->lsu, res->digits, shift); + res->exponent-=shift; /* adjust the exponent. */ + } + /* flip the result sign if unswapped and rhs was negated */ + if (!swapped) res->bits^=negate; + decFinish(res, set, &residue, status); /* done */ + break;} + + /* LHS digits may affect result */ + rhsshift=D2U(padding+1)-1; /* this much by Unit shift .. */ + mult=powers[padding-(rhsshift*DECDPUN)]; /* .. this by multiplication */ + } /* padding needed */ + + if (diffsign) mult=-mult; /* signs differ */ + + /* determine the longer operand */ + maxdigits=rhs->digits+padding; /* virtual length of RHS */ + if (lhs->digits>maxdigits) maxdigits=lhs->digits; + + /* Decide on the result buffer to use; if possible place directly */ + /* into result. */ + acc=res->lsu; /* assume add direct to result */ + /* If destructive overlap, or the number is too long, or a carry or */ + /* borrow to DIGITS+1 might be possible, a buffer must be used. */ + /* [Might be worth more sophisticated tests when maxdigits==reqdigits] */ + if ((maxdigits>=reqdigits) /* is, or could be, too large */ + || (res==rhs && rhsshift>0)) { /* destructive overlap */ + /* buffer needed, choose it; units for maxdigits digits will be */ + /* needed, +1 Unit for carry or borrow */ + Int need=D2U(maxdigits)+1; + acc=accbuff; /* assume use local buffer */ + if (need*sizeof(Unit)>sizeof(accbuff)) { + /* printf("malloc add %ld %ld\n", need, sizeof(accbuff)); */ + allocacc=(Unit *)malloc(need*sizeof(Unit)); + if (allocacc==NULL) { /* hopeless -- abandon */ + *status|=DEC_Insufficient_storage; + break;} + acc=allocacc; + } + } + + res->bits=(uByte)(bits&DECNEG); /* it's now safe to overwrite.. */ + res->exponent=lhs->exponent; /* .. operands (even if aliased) */ + + #if DECTRACE + decDumpAr('A', lhs->lsu, D2U(lhs->digits)); + decDumpAr('B', rhs->lsu, D2U(rhs->digits)); + printf(" :h: %ld %ld\n", rhsshift, mult); + #endif + + /* add [A+B*m] or subtract [A+B*(-m)] */ + res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits), + rhs->lsu, D2U(rhs->digits), + rhsshift, acc, mult) + *DECDPUN; /* [units -> digits] */ + if (res->digits<0) { /* borrowed... */ + res->digits=-res->digits; + res->bits^=DECNEG; /* flip the sign */ + } + #if DECTRACE + decDumpAr('+', acc, D2U(res->digits)); + #endif + + /* If a buffer was used the result must be copied back, possibly */ + /* shortening. (If no buffer was used then the result must have */ + /* fit, so can't need rounding and residue must be 0.) */ + residue=0; /* clear accumulator */ + if (acc!=res->lsu) { + #if DECSUBSET + if (set->extended) { /* round from first significant digit */ + #endif + /* remove leading zeros that were added due to rounding up to */ + /* integral Units -- before the test for rounding. */ + if (res->digits>reqdigits) + res->digits=decGetDigits(acc, D2U(res->digits)); + decSetCoeff(res, set, acc, res->digits, &residue, status); + #if DECSUBSET + } + else { /* subset arithmetic rounds from original significant digit */ + /* May have an underestimate. This only occurs when both */ + /* numbers fit in DECDPUN digits and are padding with a */ + /* negative multiple (-10, -100...) and the top digit(s) become */ + /* 0. (This only matters when using X3.274 rules where the */ + /* leading zero could be included in the rounding.) */ + if (res->digits<maxdigits) { + *(acc+D2U(res->digits))=0; /* ensure leading 0 is there */ + res->digits=maxdigits; + } + else { + /* remove leading zeros that added due to rounding up to */ + /* integral Units (but only those in excess of the original */ + /* maxdigits length, unless extended) before test for rounding. */ + if (res->digits>reqdigits) { + res->digits=decGetDigits(acc, D2U(res->digits)); + if (res->digits<maxdigits) res->digits=maxdigits; + } + } + decSetCoeff(res, set, acc, res->digits, &residue, status); + /* Now apply rounding if needed before removing leading zeros. */ + /* This is safe because subnormals are not a possibility */ + if (residue!=0) { + decApplyRound(res, set, residue, status); + residue=0; /* did what needed to be done */ + } + } /* subset */ + #endif + } /* used buffer */ + + /* strip leading zeros [these were left on in case of subset subtract] */ + res->digits=decGetDigits(res->lsu, D2U(res->digits)); + + /* apply checks and rounding */ + decFinish(res, set, &residue, status); + + /* "When the sum of two operands with opposite signs is exactly */ + /* zero, the sign of that sum shall be '+' in all rounding modes */ + /* except round toward -Infinity, in which mode that sign shall be */ + /* '-'." [Subset zeros also never have '-', set by decFinish.] */ + if (ISZERO(res) && diffsign + #if DECSUBSET + && set->extended + #endif + && (*status&DEC_Inexact)==0) { + if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG; /* sign - */ + else res->bits&=~DECNEG; /* sign + */ + } + } while(0); /* end protected */ + + if (allocacc!=NULL) free(allocacc); /* drop any storage used */ + #if DECSUBSET + if (allocrhs!=NULL) free(allocrhs); /* .. */ + if (alloclhs!=NULL) free(alloclhs); /* .. */ + #endif + return res; + } /* decAddOp */ + +/* ------------------------------------------------------------------ */ +/* decDivideOp -- division operation */ +/* */ +/* This routine performs the calculations for all four division */ +/* operators (divide, divideInteger, remainder, remainderNear). */ +/* */ +/* C=A op B */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X/X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* op is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively. */ +/* status is the usual accumulator */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* ------------------------------------------------------------------ */ +/* The underlying algorithm of this routine is the same as in the */ +/* 1981 S/370 implementation, that is, non-restoring long division */ +/* with bi-unit (rather than bi-digit) estimation for each unit */ +/* multiplier. In this pseudocode overview, complications for the */ +/* Remainder operators and division residues for exact rounding are */ +/* omitted for clarity. */ +/* */ +/* Prepare operands and handle special values */ +/* Test for x/0 and then 0/x */ +/* Exp =Exp1 - Exp2 */ +/* Exp =Exp +len(var1) -len(var2) */ +/* Sign=Sign1 * Sign2 */ +/* Pad accumulator (Var1) to double-length with 0's (pad1) */ +/* Pad Var2 to same length as Var1 */ +/* msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round */ +/* have=0 */ +/* Do until (have=digits+1 OR residue=0) */ +/* if exp<0 then if integer divide/residue then leave */ +/* this_unit=0 */ +/* Do forever */ +/* compare numbers */ +/* if <0 then leave inner_loop */ +/* if =0 then (* quick exit without subtract *) do */ +/* this_unit=this_unit+1; output this_unit */ +/* leave outer_loop; end */ +/* Compare lengths of numbers (mantissae): */ +/* If same then tops2=msu2pair -- {units 1&2 of var2} */ +/* else tops2=msu2plus -- {0, unit 1 of var2} */ +/* tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */ +/* mult=tops1/tops2 -- Good and safe guess at divisor */ +/* if mult=0 then mult=1 */ +/* this_unit=this_unit+mult */ +/* subtract */ +/* end inner_loop */ +/* if have\=0 | this_unit\=0 then do */ +/* output this_unit */ +/* have=have+1; end */ +/* var2=var2/10 */ +/* exp=exp-1 */ +/* end outer_loop */ +/* exp=exp+1 -- set the proper exponent */ +/* if have=0 then generate answer=0 */ +/* Return (Result is defined by Var1) */ +/* */ +/* ------------------------------------------------------------------ */ +/* Two working buffers are needed during the division; one (digits+ */ +/* 1) to accumulate the result, and the other (up to 2*digits+1) for */ +/* long subtractions. These are acc and var1 respectively. */ +/* var1 is a copy of the lhs coefficient, var2 is the rhs coefficient.*/ +/* The static buffers may be larger than might be expected to allow */ +/* for calls from higher-level funtions (notable exp). */ +/* ------------------------------------------------------------------ */ +static decNumber * decDivideOp(decNumber *res, + const decNumber *lhs, const decNumber *rhs, + decContext *set, Flag op, uInt *status) { + #if DECSUBSET + decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ + decNumber *allocrhs=NULL; /* .., rhs */ + #endif + Unit accbuff[SD2U(DECBUFFER+DECDPUN+10)]; /* local buffer */ + Unit *acc=accbuff; /* -> accumulator array for result */ + Unit *allocacc=NULL; /* -> allocated buffer, iff allocated */ + Unit *accnext; /* -> where next digit will go */ + Int acclength; /* length of acc needed [Units] */ + Int accunits; /* count of units accumulated */ + Int accdigits; /* count of digits accumulated */ + + Unit varbuff[SD2U(DECBUFFER*2+DECDPUN)*sizeof(Unit)]; /* buffer for var1 */ + Unit *var1=varbuff; /* -> var1 array for long subtraction */ + Unit *varalloc=NULL; /* -> allocated buffer, iff used */ + Unit *msu1; /* -> msu of var1 */ + + const Unit *var2; /* -> var2 array */ + const Unit *msu2; /* -> msu of var2 */ + Int msu2plus; /* msu2 plus one [does not vary] */ + eInt msu2pair; /* msu2 pair plus one [does not vary] */ + + Int var1units, var2units; /* actual lengths */ + Int var2ulen; /* logical length (units) */ + Int var1initpad=0; /* var1 initial padding (digits) */ + Int maxdigits; /* longest LHS or required acc length */ + Int mult; /* multiplier for subtraction */ + Unit thisunit; /* current unit being accumulated */ + Int residue; /* for rounding */ + Int reqdigits=set->digits; /* requested DIGITS */ + Int exponent; /* working exponent */ + Int maxexponent=0; /* DIVIDE maximum exponent if unrounded */ + uByte bits; /* working sign */ + Unit *target; /* work */ + const Unit *source; /* .. */ + uInt const *pow; /* .. */ + Int shift, cut; /* .. */ + #if DECSUBSET + Int dropped; /* work */ + #endif + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { /* protect allocated storage */ + #if DECSUBSET + if (!set->extended) { + /* reduce operands and set lostDigits status, as needed */ + if (lhs->digits>reqdigits) { + alloclhs=decRoundOperand(lhs, set, status); + if (alloclhs==NULL) break; + lhs=alloclhs; + } + if (rhs->digits>reqdigits) { + allocrhs=decRoundOperand(rhs, set, status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + /* [following code does not require input rounding] */ + + bits=(lhs->bits^rhs->bits)&DECNEG; /* assumed sign for divisions */ + + /* handle infinities and NaNs */ + if (SPECIALARGS) { /* a special bit set */ + if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */ + decNaNs(res, lhs, rhs, set, status); + break; + } + /* one or two infinities */ + if (decNumberIsInfinite(lhs)) { /* LHS (dividend) is infinite */ + if (decNumberIsInfinite(rhs) || /* two infinities are invalid .. */ + op & (REMAINDER | REMNEAR)) { /* as is remainder of infinity */ + *status|=DEC_Invalid_operation; + break; + } + /* [Note that infinity/0 raises no exceptions] */ + decNumberZero(res); + res->bits=bits|DECINF; /* set +/- infinity */ + break; + } + else { /* RHS (divisor) is infinite */ + residue=0; + if (op&(REMAINDER|REMNEAR)) { + /* result is [finished clone of] lhs */ + decCopyFit(res, lhs, set, &residue, status); + } + else { /* a division */ + decNumberZero(res); + res->bits=bits; /* set +/- zero */ + /* for DIVIDEINT the exponent is always 0. For DIVIDE, result */ + /* is a 0 with infinitely negative exponent, clamped to minimum */ + if (op&DIVIDE) { + res->exponent=set->emin-set->digits+1; + *status|=DEC_Clamped; + } + } + decFinish(res, set, &residue, status); + break; + } + } + + /* handle 0 rhs (x/0) */ + if (ISZERO(rhs)) { /* x/0 is always exceptional */ + if (ISZERO(lhs)) { + decNumberZero(res); /* [after lhs test] */ + *status|=DEC_Division_undefined;/* 0/0 will become NaN */ + } + else { + decNumberZero(res); + if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation; + else { + *status|=DEC_Division_by_zero; /* x/0 */ + res->bits=bits|DECINF; /* .. is +/- Infinity */ + } + } + break;} + + /* handle 0 lhs (0/x) */ + if (ISZERO(lhs)) { /* 0/x [x!=0] */ + #if DECSUBSET + if (!set->extended) decNumberZero(res); + else { + #endif + if (op&DIVIDE) { + residue=0; + exponent=lhs->exponent-rhs->exponent; /* ideal exponent */ + decNumberCopy(res, lhs); /* [zeros always fit] */ + res->bits=bits; /* sign as computed */ + res->exponent=exponent; /* exponent, too */ + decFinalize(res, set, &residue, status); /* check exponent */ + } + else if (op&DIVIDEINT) { + decNumberZero(res); /* integer 0 */ + res->bits=bits; /* sign as computed */ + } + else { /* a remainder */ + exponent=rhs->exponent; /* [save in case overwrite] */ + decNumberCopy(res, lhs); /* [zeros always fit] */ + if (exponent<res->exponent) res->exponent=exponent; /* use lower */ + } + #if DECSUBSET + } + #endif + break;} + + /* Precalculate exponent. This starts off adjusted (and hence fits */ + /* in 31 bits) and becomes the usual unadjusted exponent as the */ + /* division proceeds. The order of evaluation is important, here, */ + /* to avoid wrap. */ + exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits); + + /* If the working exponent is -ve, then some quick exits are */ + /* possible because the quotient is known to be <1 */ + /* [for REMNEAR, it needs to be < -1, as -0.5 could need work] */ + if (exponent<0 && !(op==DIVIDE)) { + if (op&DIVIDEINT) { + decNumberZero(res); /* integer part is 0 */ + #if DECSUBSET + if (set->extended) + #endif + res->bits=bits; /* set +/- zero */ + break;} + /* fastpath remainders so long as the lhs has the smaller */ + /* (or equal) exponent */ + if (lhs->exponent<=rhs->exponent) { + if (op&REMAINDER || exponent<-1) { + /* It is REMAINDER or safe REMNEAR; result is [finished */ + /* clone of] lhs (r = x - 0*y) */ + residue=0; + decCopyFit(res, lhs, set, &residue, status); + decFinish(res, set, &residue, status); + break; + } + /* [unsafe REMNEAR drops through] */ + } + } /* fastpaths */ + + /* Long (slow) division is needed; roll up the sleeves... */ + + /* The accumulator will hold the quotient of the division. */ + /* If it needs to be too long for stack storage, then allocate. */ + acclength=D2U(reqdigits+DECDPUN); /* in Units */ + if (acclength*sizeof(Unit)>sizeof(accbuff)) { + /* printf("malloc dvacc %ld units\n", acclength); */ + allocacc=(Unit *)malloc(acclength*sizeof(Unit)); + if (allocacc==NULL) { /* hopeless -- abandon */ + *status|=DEC_Insufficient_storage; + break;} + acc=allocacc; /* use the allocated space */ + } + + /* var1 is the padded LHS ready for subtractions. */ + /* If it needs to be too long for stack storage, then allocate. */ + /* The maximum units needed for var1 (long subtraction) is: */ + /* Enough for */ + /* (rhs->digits+reqdigits-1) -- to allow full slide to right */ + /* or (lhs->digits) -- to allow for long lhs */ + /* whichever is larger */ + /* +1 -- for rounding of slide to right */ + /* +1 -- for leading 0s */ + /* +1 -- for pre-adjust if a remainder or DIVIDEINT */ + /* [Note: unused units do not participate in decUnitAddSub data] */ + maxdigits=rhs->digits+reqdigits-1; + if (lhs->digits>maxdigits) maxdigits=lhs->digits; + var1units=D2U(maxdigits)+2; + /* allocate a guard unit above msu1 for REMAINDERNEAR */ + if (!(op&DIVIDE)) var1units++; + if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) { + /* printf("malloc dvvar %ld units\n", var1units+1); */ + varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit)); + if (varalloc==NULL) { /* hopeless -- abandon */ + *status|=DEC_Insufficient_storage; + break;} + var1=varalloc; /* use the allocated space */ + } + + /* Extend the lhs and rhs to full long subtraction length. The lhs */ + /* is truly extended into the var1 buffer, with 0 padding, so a */ + /* subtract in place is always possible. The rhs (var2) has */ + /* virtual padding (implemented by decUnitAddSub). */ + /* One guard unit was allocated above msu1 for rem=rem+rem in */ + /* REMAINDERNEAR. */ + msu1=var1+var1units-1; /* msu of var1 */ + source=lhs->lsu+D2U(lhs->digits)-1; /* msu of input array */ + for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source; + for (; target>=var1; target--) *target=0; + + /* rhs (var2) is left-aligned with var1 at the start */ + var2ulen=var1units; /* rhs logical length (units) */ + var2units=D2U(rhs->digits); /* rhs actual length (units) */ + var2=rhs->lsu; /* -> rhs array */ + msu2=var2+var2units-1; /* -> msu of var2 [never changes] */ + /* now set up the variables which will be used for estimating the */ + /* multiplication factor. If these variables are not exact, add */ + /* 1 to make sure that the multiplier is never overestimated. */ + msu2plus=*msu2; /* it's value .. */ + if (var2units>1) msu2plus++; /* .. +1 if any more */ + msu2pair=(eInt)*msu2*(DECDPUNMAX+1);/* top two pair .. */ + if (var2units>1) { /* .. [else treat 2nd as 0] */ + msu2pair+=*(msu2-1); /* .. */ + if (var2units>2) msu2pair++; /* .. +1 if any more */ + } + + /* The calculation is working in units, which may have leading zeros, */ + /* but the exponent was calculated on the assumption that they are */ + /* both left-aligned. Adjust the exponent to compensate: add the */ + /* number of leading zeros in var1 msu and subtract those in var2 msu. */ + /* [This is actually done by counting the digits and negating, as */ + /* lead1=DECDPUN-digits1, and similarly for lead2.] */ + for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--; + for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++; + + /* Now, if doing an integer divide or remainder, ensure that */ + /* the result will be Unit-aligned. To do this, shift the var1 */ + /* accumulator towards least if need be. (It's much easier to */ + /* do this now than to reassemble the residue afterwards, if */ + /* doing a remainder.) Also ensure the exponent is not negative. */ + if (!(op&DIVIDE)) { + Unit *u; /* work */ + /* save the initial 'false' padding of var1, in digits */ + var1initpad=(var1units-D2U(lhs->digits))*DECDPUN; + /* Determine the shift to do. */ + if (exponent<0) cut=-exponent; + else cut=DECDPUN-exponent%DECDPUN; + decShiftToLeast(var1, var1units, cut); + exponent+=cut; /* maintain numerical value */ + var1initpad-=cut; /* .. and reduce padding */ + /* clean any most-significant units which were just emptied */ + for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0; + } /* align */ + else { /* is DIVIDE */ + maxexponent=lhs->exponent-rhs->exponent; /* save */ + /* optimization: if the first iteration will just produce 0, */ + /* preadjust to skip it [valid for DIVIDE only] */ + if (*msu1<*msu2) { + var2ulen--; /* shift down */ + exponent-=DECDPUN; /* update the exponent */ + } + } + + /* ---- start the long-division loops ------------------------------ */ + accunits=0; /* no units accumulated yet */ + accdigits=0; /* .. or digits */ + accnext=acc+acclength-1; /* -> msu of acc [NB: allows digits+1] */ + for (;;) { /* outer forever loop */ + thisunit=0; /* current unit assumed 0 */ + /* find the next unit */ + for (;;) { /* inner forever loop */ + /* strip leading zero units [from either pre-adjust or from */ + /* subtract last time around]. Leave at least one unit. */ + for (; *msu1==0 && msu1>var1; msu1--) var1units--; + + if (var1units<var2ulen) break; /* var1 too low for subtract */ + if (var1units==var2ulen) { /* unit-by-unit compare needed */ + /* compare the two numbers, from msu */ + const Unit *pv1, *pv2; + Unit v2; /* units to compare */ + pv2=msu2; /* -> msu */ + for (pv1=msu1; ; pv1--, pv2--) { + /* v1=*pv1 -- always OK */ + v2=0; /* assume in padding */ + if (pv2>=var2) v2=*pv2; /* in range */ + if (*pv1!=v2) break; /* no longer the same */ + if (pv1==var1) break; /* done; leave pv1 as is */ + } + /* here when all inspected or a difference seen */ + if (*pv1<v2) break; /* var1 too low to subtract */ + if (*pv1==v2) { /* var1 == var2 */ + /* reach here if var1 and var2 are identical; subtraction */ + /* would increase digit by one, and the residue will be 0 so */ + /* the calculation is done; leave the loop with residue=0. */ + thisunit++; /* as though subtracted */ + *var1=0; /* set var1 to 0 */ + var1units=1; /* .. */ + break; /* from inner */ + } /* var1 == var2 */ + /* *pv1>v2. Prepare for real subtraction; the lengths are equal */ + /* Estimate the multiplier (there's always a msu1-1)... */ + /* Bring in two units of var2 to provide a good estimate. */ + mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair); + } /* lengths the same */ + else { /* var1units > var2ulen, so subtraction is safe */ + /* The var2 msu is one unit towards the lsu of the var1 msu, */ + /* so only one unit for var2 can be used. */ + mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus); + } + if (mult==0) mult=1; /* must always be at least 1 */ + /* subtraction needed; var1 is > var2 */ + thisunit=(Unit)(thisunit+mult); /* accumulate */ + /* subtract var1-var2, into var1; only the overlap needs */ + /* processing, as this is an in-place calculation */ + shift=var2ulen-var2units; + #if DECTRACE + decDumpAr('1', &var1[shift], var1units-shift); + decDumpAr('2', var2, var2units); + printf("m=%ld\n", -mult); + #endif + decUnitAddSub(&var1[shift], var1units-shift, + var2, var2units, 0, + &var1[shift], -mult); + #if DECTRACE + decDumpAr('#', &var1[shift], var1units-shift); + #endif + /* var1 now probably has leading zeros; these are removed at the */ + /* top of the inner loop. */ + } /* inner loop */ + + /* The next unit has been calculated in full; unless it's a */ + /* leading zero, add to acc */ + if (accunits!=0 || thisunit!=0) { /* is first or non-zero */ + *accnext=thisunit; /* store in accumulator */ + /* account exactly for the new digits */ + if (accunits==0) { + accdigits++; /* at least one */ + for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++; + } + else accdigits+=DECDPUN; + accunits++; /* update count */ + accnext--; /* ready for next */ + if (accdigits>reqdigits) break; /* have enough digits */ + } + + /* if the residue is zero, the operation is done (unless divide */ + /* or divideInteger and still not enough digits yet) */ + if (*var1==0 && var1units==1) { /* residue is 0 */ + if (op&(REMAINDER|REMNEAR)) break; + if ((op&DIVIDE) && (exponent<=maxexponent)) break; + /* [drop through if divideInteger] */ + } + /* also done enough if calculating remainder or integer */ + /* divide and just did the last ('units') unit */ + if (exponent==0 && !(op&DIVIDE)) break; + + /* to get here, var1 is less than var2, so divide var2 by the per- */ + /* Unit power of ten and go for the next digit */ + var2ulen--; /* shift down */ + exponent-=DECDPUN; /* update the exponent */ + } /* outer loop */ + + /* ---- division is complete --------------------------------------- */ + /* here: acc has at least reqdigits+1 of good results (or fewer */ + /* if early stop), starting at accnext+1 (its lsu) */ + /* var1 has any residue at the stopping point */ + /* accunits is the number of digits collected in acc */ + if (accunits==0) { /* acc is 0 */ + accunits=1; /* show have a unit .. */ + accdigits=1; /* .. */ + *accnext=0; /* .. whose value is 0 */ + } + else accnext++; /* back to last placed */ + /* accnext now -> lowest unit of result */ + + residue=0; /* assume no residue */ + if (op&DIVIDE) { + /* record the presence of any residue, for rounding */ + if (*var1!=0 || var1units>1) residue=1; + else { /* no residue */ + /* Had an exact division; clean up spurious trailing 0s. */ + /* There will be at most DECDPUN-1, from the final multiply, */ + /* and then only if the result is non-0 (and even) and the */ + /* exponent is 'loose'. */ + #if DECDPUN>1 + Unit lsu=*accnext; + if (!(lsu&0x01) && (lsu!=0)) { + /* count the trailing zeros */ + Int drop=0; + for (;; drop++) { /* [will terminate because lsu!=0] */ + if (exponent>=maxexponent) break; /* don't chop real 0s */ + #if DECDPUN<=4 + if ((lsu-QUOT10(lsu, drop+1) + *powers[drop+1])!=0) break; /* found non-0 digit */ + #else + if (lsu%powers[drop+1]!=0) break; /* found non-0 digit */ + #endif + exponent++; + } + if (drop>0) { + accunits=decShiftToLeast(accnext, accunits, drop); + accdigits=decGetDigits(accnext, accunits); + accunits=D2U(accdigits); + /* [exponent was adjusted in the loop] */ + } + } /* neither odd nor 0 */ + #endif + } /* exact divide */ + } /* divide */ + else /* op!=DIVIDE */ { + /* check for coefficient overflow */ + if (accdigits+exponent>reqdigits) { + *status|=DEC_Division_impossible; + break; + } + if (op & (REMAINDER|REMNEAR)) { + /* [Here, the exponent will be 0, because var1 was adjusted */ + /* appropriately.] */ + Int postshift; /* work */ + Flag wasodd=0; /* integer was odd */ + Unit *quotlsu; /* for save */ + Int quotdigits; /* .. */ + + bits=lhs->bits; /* remainder sign is always as lhs */ + + /* Fastpath when residue is truly 0 is worthwhile [and */ + /* simplifies the code below] */ + if (*var1==0 && var1units==1) { /* residue is 0 */ + Int exp=lhs->exponent; /* save min(exponents) */ + if (rhs->exponent<exp) exp=rhs->exponent; + decNumberZero(res); /* 0 coefficient */ + #if DECSUBSET + if (set->extended) + #endif + res->exponent=exp; /* .. with proper exponent */ + res->bits=(uByte)(bits&DECNEG); /* [cleaned] */ + decFinish(res, set, &residue, status); /* might clamp */ + break; + } + /* note if the quotient was odd */ + if (*accnext & 0x01) wasodd=1; /* acc is odd */ + quotlsu=accnext; /* save in case need to reinspect */ + quotdigits=accdigits; /* .. */ + + /* treat the residue, in var1, as the value to return, via acc */ + /* calculate the unused zero digits. This is the smaller of: */ + /* var1 initial padding (saved above) */ + /* var2 residual padding, which happens to be given by: */ + postshift=var1initpad+exponent-lhs->exponent+rhs->exponent; + /* [the 'exponent' term accounts for the shifts during divide] */ + if (var1initpad<postshift) postshift=var1initpad; + + /* shift var1 the requested amount, and adjust its digits */ + var1units=decShiftToLeast(var1, var1units, postshift); + accnext=var1; + accdigits=decGetDigits(var1, var1units); + accunits=D2U(accdigits); + + exponent=lhs->exponent; /* exponent is smaller of lhs & rhs */ + if (rhs->exponent<exponent) exponent=rhs->exponent; + + /* Now correct the result if doing remainderNear; if it */ + /* (looking just at coefficients) is > rhs/2, or == rhs/2 and */ + /* the integer was odd then the result should be rem-rhs. */ + if (op&REMNEAR) { + Int compare, tarunits; /* work */ + Unit *up; /* .. */ + /* calculate remainder*2 into the var1 buffer (which has */ + /* 'headroom' of an extra unit and hence enough space) */ + /* [a dedicated 'double' loop would be faster, here] */ + tarunits=decUnitAddSub(accnext, accunits, accnext, accunits, + 0, accnext, 1); + /* decDumpAr('r', accnext, tarunits); */ + + /* Here, accnext (var1) holds tarunits Units with twice the */ + /* remainder's coefficient, which must now be compared to the */ + /* RHS. The remainder's exponent may be smaller than the RHS's. */ + compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits), + rhs->exponent-exponent); + if (compare==BADINT) { /* deep trouble */ + *status|=DEC_Insufficient_storage; + break;} + + /* now restore the remainder by dividing by two; the lsu */ + /* is known to be even. */ + for (up=accnext; up<accnext+tarunits; up++) { + Int half; /* half to add to lower unit */ + half=*up & 0x01; + *up/=2; /* [shift] */ + if (!half) continue; + *(up-1)+=(DECDPUNMAX+1)/2; + } + /* [accunits still describes the original remainder length] */ + + if (compare>0 || (compare==0 && wasodd)) { /* adjustment needed */ + Int exp, expunits, exprem; /* work */ + /* This is effectively causing round-up of the quotient, */ + /* so if it was the rare case where it was full and all */ + /* nines, it would overflow and hence division-impossible */ + /* should be raised */ + Flag allnines=0; /* 1 if quotient all nines */ + if (quotdigits==reqdigits) { /* could be borderline */ + for (up=quotlsu; ; up++) { + if (quotdigits>DECDPUN) { + if (*up!=DECDPUNMAX) break;/* non-nines */ + } + else { /* this is the last Unit */ + if (*up==powers[quotdigits]-1) allnines=1; + break; + } + quotdigits-=DECDPUN; /* checked those digits */ + } /* up */ + } /* borderline check */ + if (allnines) { + *status|=DEC_Division_impossible; + break;} + + /* rem-rhs is needed; the sign will invert. Again, var1 */ + /* can safely be used for the working Units array. */ + exp=rhs->exponent-exponent; /* RHS padding needed */ + /* Calculate units and remainder from exponent. */ + expunits=exp/DECDPUN; + exprem=exp%DECDPUN; + /* subtract [A+B*(-m)]; the result will always be negative */ + accunits=-decUnitAddSub(accnext, accunits, + rhs->lsu, D2U(rhs->digits), + expunits, accnext, -(Int)powers[exprem]); + accdigits=decGetDigits(accnext, accunits); /* count digits exactly */ + accunits=D2U(accdigits); /* and recalculate the units for copy */ + /* [exponent is as for original remainder] */ + bits^=DECNEG; /* flip the sign */ + } + } /* REMNEAR */ + } /* REMAINDER or REMNEAR */ + } /* not DIVIDE */ + + /* Set exponent and bits */ + res->exponent=exponent; + res->bits=(uByte)(bits&DECNEG); /* [cleaned] */ + + /* Now the coefficient. */ + decSetCoeff(res, set, accnext, accdigits, &residue, status); + + decFinish(res, set, &residue, status); /* final cleanup */ + + #if DECSUBSET + /* If a divide then strip trailing zeros if subset [after round] */ + if (!set->extended && (op==DIVIDE)) decTrim(res, set, 0, &dropped); + #endif + } while(0); /* end protected */ + + if (varalloc!=NULL) free(varalloc); /* drop any storage used */ + if (allocacc!=NULL) free(allocacc); /* .. */ + #if DECSUBSET + if (allocrhs!=NULL) free(allocrhs); /* .. */ + if (alloclhs!=NULL) free(alloclhs); /* .. */ + #endif + return res; + } /* decDivideOp */ + +/* ------------------------------------------------------------------ */ +/* decMultiplyOp -- multiplication operation */ +/* */ +/* This routine performs the multiplication C=A x B. */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X*X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* status is the usual accumulator */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* ------------------------------------------------------------------ */ +/* 'Classic' multiplication is used rather than Karatsuba, as the */ +/* latter would give only a minor improvement for the short numbers */ +/* expected to be handled most (and uses much more memory). */ +/* */ +/* There are two major paths here: the general-purpose ('old code') */ +/* path which handles all DECDPUN values, and a fastpath version */ +/* which is used if 64-bit ints are available, DECDPUN<=4, and more */ +/* than two calls to decUnitAddSub would be made. */ +/* */ +/* The fastpath version lumps units together into 8-digit or 9-digit */ +/* chunks, and also uses a lazy carry strategy to minimise expensive */ +/* 64-bit divisions. The chunks are then broken apart again into */ +/* units for continuing processing. Despite this overhead, the */ +/* fastpath can speed up some 16-digit operations by 10x (and much */ +/* more for higher-precision calculations). */ +/* */ +/* A buffer always has to be used for the accumulator; in the */ +/* fastpath, buffers are also always needed for the chunked copies of */ +/* of the operand coefficients. */ +/* Static buffers are larger than needed just for multiply, to allow */ +/* for calls from other operations (notably exp). */ +/* ------------------------------------------------------------------ */ +#define FASTMUL (DECUSE64 && DECDPUN<5) +static decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set, + uInt *status) { + Int accunits; /* Units of accumulator in use */ + Int exponent; /* work */ + Int residue=0; /* rounding residue */ + uByte bits; /* result sign */ + Unit *acc; /* -> accumulator Unit array */ + Int needbytes; /* size calculator */ + void *allocacc=NULL; /* -> allocated accumulator, iff allocated */ + Unit accbuff[SD2U(DECBUFFER*4+1)]; /* buffer (+1 for DECBUFFER==0, */ + /* *4 for calls from other operations) */ + const Unit *mer, *mermsup; /* work */ + Int madlength; /* Units in multiplicand */ + Int shift; /* Units to shift multiplicand by */ + + #if FASTMUL + /* if DECDPUN is 1 or 3 work in base 10**9, otherwise */ + /* (DECDPUN is 2 or 4) then work in base 10**8 */ + #if DECDPUN & 1 /* odd */ + #define FASTBASE 1000000000 /* base */ + #define FASTDIGS 9 /* digits in base */ + #define FASTLAZY 18 /* carry resolution point [1->18] */ + #else + #define FASTBASE 100000000 + #define FASTDIGS 8 + #define FASTLAZY 1844 /* carry resolution point [1->1844] */ + #endif + /* three buffers are used, two for chunked copies of the operands */ + /* (base 10**8 or base 10**9) and one base 2**64 accumulator with */ + /* lazy carry evaluation */ + uInt zlhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */ + uInt *zlhi=zlhibuff; /* -> lhs array */ + uInt *alloclhi=NULL; /* -> allocated buffer, iff allocated */ + uInt zrhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */ + uInt *zrhi=zrhibuff; /* -> rhs array */ + uInt *allocrhi=NULL; /* -> allocated buffer, iff allocated */ + uLong zaccbuff[(DECBUFFER*2+1)/4+2]; /* buffer (+1 for DECBUFFER==0) */ + /* [allocacc is shared for both paths, as only one will run] */ + uLong *zacc=zaccbuff; /* -> accumulator array for exact result */ + #if DECDPUN==1 + Int zoff; /* accumulator offset */ + #endif + uInt *lip, *rip; /* item pointers */ + uInt *lmsi, *rmsi; /* most significant items */ + Int ilhs, irhs, iacc; /* item counts in the arrays */ + Int lazy; /* lazy carry counter */ + uLong lcarry; /* uLong carry */ + uInt carry; /* carry (NB not uLong) */ + Int count; /* work */ + const Unit *cup; /* .. */ + Unit *up; /* .. */ + uLong *lp; /* .. */ + Int p; /* .. */ + #endif + + #if DECSUBSET + decNumber *alloclhs=NULL; /* -> allocated buffer, iff allocated */ + decNumber *allocrhs=NULL; /* -> allocated buffer, iff allocated */ + #endif + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + /* precalculate result sign */ + bits=(uByte)((lhs->bits^rhs->bits)&DECNEG); + + /* handle infinities and NaNs */ + if (SPECIALARGS) { /* a special bit set */ + if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */ + decNaNs(res, lhs, rhs, set, status); + return res;} + /* one or two infinities; Infinity * 0 is invalid */ + if (((lhs->bits & DECINF)==0 && ISZERO(lhs)) + ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) { + *status|=DEC_Invalid_operation; + return res;} + decNumberZero(res); + res->bits=bits|DECINF; /* infinity */ + return res;} + + /* For best speed, as in DMSRCN [the original Rexx numerics */ + /* module], use the shorter number as the multiplier (rhs) and */ + /* the longer as the multiplicand (lhs) to minimise the number of */ + /* adds (partial products) */ + if (lhs->digits<rhs->digits) { /* swap... */ + const decNumber *hold=lhs; + lhs=rhs; + rhs=hold; + } + + do { /* protect allocated storage */ + #if DECSUBSET + if (!set->extended) { + /* reduce operands and set lostDigits status, as needed */ + if (lhs->digits>set->digits) { + alloclhs=decRoundOperand(lhs, set, status); + if (alloclhs==NULL) break; + lhs=alloclhs; + } + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + /* [following code does not require input rounding] */ + + #if FASTMUL /* fastpath can be used */ + /* use the fast path if there are enough digits in the shorter */ + /* operand to make the setup and takedown worthwhile */ + #define NEEDTWO (DECDPUN*2) /* within two decUnitAddSub calls */ + if (rhs->digits>NEEDTWO) { /* use fastpath... */ + /* calculate the number of elements in each array */ + ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; /* [ceiling] */ + irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; /* .. */ + iacc=ilhs+irhs; + + /* allocate buffers if required, as usual */ + needbytes=ilhs*sizeof(uInt); + if (needbytes>(Int)sizeof(zlhibuff)) { + alloclhi=(uInt *)malloc(needbytes); + zlhi=alloclhi;} + needbytes=irhs*sizeof(uInt); + if (needbytes>(Int)sizeof(zrhibuff)) { + allocrhi=(uInt *)malloc(needbytes); + zrhi=allocrhi;} + + /* Allocating the accumulator space needs a special case when */ + /* DECDPUN=1 because when converting the accumulator to Units */ + /* after the multiplication each 8-byte item becomes 9 1-byte */ + /* units. Therefore iacc extra bytes are needed at the front */ + /* (rounded up to a multiple of 8 bytes), and the uLong */ + /* accumulator starts offset the appropriate number of units */ + /* to the right to avoid overwrite during the unchunking. */ + needbytes=iacc*sizeof(uLong); + #if DECDPUN==1 + zoff=(iacc+7)/8; /* items to offset by */ + needbytes+=zoff*8; + #endif + if (needbytes>(Int)sizeof(zaccbuff)) { + allocacc=(uLong *)malloc(needbytes); + zacc=(uLong *)allocacc;} + if (zlhi==NULL||zrhi==NULL||zacc==NULL) { + *status|=DEC_Insufficient_storage; + break;} + + acc=(Unit *)zacc; /* -> target Unit array */ + #if DECDPUN==1 + zacc+=zoff; /* start uLong accumulator to right */ + #endif + + /* assemble the chunked copies of the left and right sides */ + for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++) + for (p=0, *lip=0; p<FASTDIGS && count>0; + p+=DECDPUN, cup++, count-=DECDPUN) + *lip+=*cup*powers[p]; + lmsi=lip-1; /* save -> msi */ + for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++) + for (p=0, *rip=0; p<FASTDIGS && count>0; + p+=DECDPUN, cup++, count-=DECDPUN) + *rip+=*cup*powers[p]; + rmsi=rip-1; /* save -> msi */ + + /* zero the accumulator */ + for (lp=zacc; lp<zacc+iacc; lp++) *lp=0; + + /* Start the multiplication */ + /* Resolving carries can dominate the cost of accumulating the */ + /* partial products, so this is only done when necessary. */ + /* Each uLong item in the accumulator can hold values up to */ + /* 2**64-1, and each partial product can be as large as */ + /* (10**FASTDIGS-1)**2. When FASTDIGS=9, this can be added to */ + /* itself 18.4 times in a uLong without overflowing, so during */ + /* the main calculation resolution is carried out every 18th */ + /* add -- every 162 digits. Similarly, when FASTDIGS=8, the */ + /* partial products can be added to themselves 1844.6 times in */ + /* a uLong without overflowing, so intermediate carry */ + /* resolution occurs only every 14752 digits. Hence for common */ + /* short numbers usually only the one final carry resolution */ + /* occurs. */ + /* (The count is set via FASTLAZY to simplify experiments to */ + /* measure the value of this approach: a 35% improvement on a */ + /* [34x34] multiply.) */ + lazy=FASTLAZY; /* carry delay count */ + for (rip=zrhi; rip<=rmsi; rip++) { /* over each item in rhs */ + lp=zacc+(rip-zrhi); /* where to add the lhs */ + for (lip=zlhi; lip<=lmsi; lip++, lp++) { /* over each item in lhs */ + *lp+=(uLong)(*lip)*(*rip); /* [this should in-line] */ + } /* lip loop */ + lazy--; + if (lazy>0 && rip!=rmsi) continue; + lazy=FASTLAZY; /* reset delay count */ + /* spin up the accumulator resolving overflows */ + for (lp=zacc; lp<zacc+iacc; lp++) { + if (*lp<FASTBASE) continue; /* it fits */ + lcarry=*lp/FASTBASE; /* top part [slow divide] */ + /* lcarry can exceed 2**32-1, so check again; this check */ + /* and occasional extra divide (slow) is well worth it, as */ + /* it allows FASTLAZY to be increased to 18 rather than 4 */ + /* in the FASTDIGS=9 case */ + if (lcarry<FASTBASE) carry=(uInt)lcarry; /* [usual] */ + else { /* two-place carry [fairly rare] */ + uInt carry2=(uInt)(lcarry/FASTBASE); /* top top part */ + *(lp+2)+=carry2; /* add to item+2 */ + *lp-=((uLong)FASTBASE*FASTBASE*carry2); /* [slow] */ + carry=(uInt)(lcarry-((uLong)FASTBASE*carry2)); /* [inline] */ + } + *(lp+1)+=carry; /* add to item above [inline] */ + *lp-=((uLong)FASTBASE*carry); /* [inline] */ + } /* carry resolution */ + } /* rip loop */ + + /* The multiplication is complete; time to convert back into */ + /* units. This can be done in-place in the accumulator and in */ + /* 32-bit operations, because carries were resolved after the */ + /* final add. This needs N-1 divides and multiplies for */ + /* each item in the accumulator (which will become up to N */ + /* units, where 2<=N<=9). */ + for (lp=zacc, up=acc; lp<zacc+iacc; lp++) { + uInt item=(uInt)*lp; /* decapitate to uInt */ + for (p=0; p<FASTDIGS-DECDPUN; p+=DECDPUN, up++) { + uInt part=item/(DECDPUNMAX+1); + *up=(Unit)(item-(part*(DECDPUNMAX+1))); + item=part; + } /* p */ + *up=(Unit)item; up++; /* [final needs no division] */ + } /* lp */ + accunits=up-acc; /* count of units */ + } + else { /* here to use units directly, without chunking ['old code'] */ + #endif + + /* if accumulator will be too long for local storage, then allocate */ + acc=accbuff; /* -> assume buffer for accumulator */ + needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit); + if (needbytes>(Int)sizeof(accbuff)) { + allocacc=(Unit *)malloc(needbytes); + if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;} + acc=(Unit *)allocacc; /* use the allocated space */ + } + + /* Now the main long multiplication loop */ + /* Unlike the equivalent in the IBM Java implementation, there */ + /* is no advantage in calculating from msu to lsu. So, do it */ + /* by the book, as it were. */ + /* Each iteration calculates ACC=ACC+MULTAND*MULT */ + accunits=1; /* accumulator starts at '0' */ + *acc=0; /* .. (lsu=0) */ + shift=0; /* no multiplicand shift at first */ + madlength=D2U(lhs->digits); /* this won't change */ + mermsup=rhs->lsu+D2U(rhs->digits); /* -> msu+1 of multiplier */ + + for (mer=rhs->lsu; mer<mermsup; mer++) { + /* Here, *mer is the next Unit in the multiplier to use */ + /* If non-zero [optimization] add it... */ + if (*mer!=0) accunits=decUnitAddSub(&acc[shift], accunits-shift, + lhs->lsu, madlength, 0, + &acc[shift], *mer) + + shift; + else { /* extend acc with a 0; it will be used shortly */ + *(acc+accunits)=0; /* [this avoids length of <=0 later] */ + accunits++; + } + /* multiply multiplicand by 10**DECDPUN for next Unit to left */ + shift++; /* add this for 'logical length' */ + } /* n */ + #if FASTMUL + } /* unchunked units */ + #endif + /* common end-path */ + #if DECTRACE + decDumpAr('*', acc, accunits); /* Show exact result */ + #endif + + /* acc now contains the exact result of the multiplication, */ + /* possibly with a leading zero unit; build the decNumber from */ + /* it, noting if any residue */ + res->bits=bits; /* set sign */ + res->digits=decGetDigits(acc, accunits); /* count digits exactly */ + + /* There can be a 31-bit wrap in calculating the exponent. */ + /* This can only happen if both input exponents are negative and */ + /* both their magnitudes are large. If there was a wrap, set a */ + /* safe very negative exponent, from which decFinalize() will */ + /* raise a hard underflow shortly. */ + exponent=lhs->exponent+rhs->exponent; /* calculate exponent */ + if (lhs->exponent<0 && rhs->exponent<0 && exponent>0) + exponent=-2*DECNUMMAXE; /* force underflow */ + res->exponent=exponent; /* OK to overwrite now */ + + + /* Set the coefficient. If any rounding, residue records */ + decSetCoeff(res, set, acc, res->digits, &residue, status); + decFinish(res, set, &residue, status); /* final cleanup */ + } while(0); /* end protected */ + + if (allocacc!=NULL) free(allocacc); /* drop any storage used */ + #if DECSUBSET + if (allocrhs!=NULL) free(allocrhs); /* .. */ + if (alloclhs!=NULL) free(alloclhs); /* .. */ + #endif + #if FASTMUL + if (allocrhi!=NULL) free(allocrhi); /* .. */ + if (alloclhi!=NULL) free(alloclhi); /* .. */ + #endif + return res; + } /* decMultiplyOp */ + +/* ------------------------------------------------------------------ */ +/* decExpOp -- effect exponentiation */ +/* */ +/* This computes C = exp(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. status is updated but */ +/* not set. */ +/* */ +/* Restrictions: */ +/* */ +/* digits, emax, and -emin in the context must be less than */ +/* 2*DEC_MAX_MATH (1999998), and the rhs must be within these */ +/* bounds or a zero. This is an internal routine, so these */ +/* restrictions are contractual and not enforced. */ +/* */ +/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* */ +/* Finite results will always be full precision and Inexact, except */ +/* when A is a zero or -Infinity (giving 1 or 0 respectively). */ +/* ------------------------------------------------------------------ */ +/* This approach used here is similar to the algorithm described in */ +/* */ +/* Variable Precision Exponential Function, T. E. Hull and */ +/* A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */ +/* pp79-91, ACM, June 1986. */ +/* */ +/* with the main difference being that the iterations in the series */ +/* evaluation are terminated dynamically (which does not require the */ +/* extra variable-precision variables which are expensive in this */ +/* context). */ +/* */ +/* The error analysis in Hull & Abrham's paper applies except for the */ +/* round-off error accumulation during the series evaluation. This */ +/* code does not precalculate the number of iterations and so cannot */ +/* use Horner's scheme. Instead, the accumulation is done at double- */ +/* precision, which ensures that the additions of the terms are exact */ +/* and do not accumulate round-off (and any round-off errors in the */ +/* terms themselves move 'to the right' faster than they can */ +/* accumulate). This code also extends the calculation by allowing, */ +/* in the spirit of other decNumber operators, the input to be more */ +/* precise than the result (the precision used is based on the more */ +/* precise of the input or requested result). */ +/* */ +/* Implementation notes: */ +/* */ +/* 1. This is separated out as decExpOp so it can be called from */ +/* other Mathematical functions (notably Ln) with a wider range */ +/* than normal. In particular, it can handle the slightly wider */ +/* (double) range needed by Ln (which has to be able to calculate */ +/* exp(-x) where x can be the tiniest number (Ntiny). */ +/* */ +/* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop */ +/* iterations by appoximately a third with additional (although */ +/* diminishing) returns as the range is reduced to even smaller */ +/* fractions. However, h (the power of 10 used to correct the */ +/* result at the end, see below) must be kept <=8 as otherwise */ +/* the final result cannot be computed. Hence the leverage is a */ +/* sliding value (8-h), where potentially the range is reduced */ +/* more for smaller values. */ +/* */ +/* The leverage that can be applied in this way is severely */ +/* limited by the cost of the raise-to-the power at the end, */ +/* which dominates when the number of iterations is small (less */ +/* than ten) or when rhs is short. As an example, the adjustment */ +/* x**10,000,000 needs 31 multiplications, all but one full-width. */ +/* */ +/* 3. The restrictions (especially precision) could be raised with */ +/* care, but the full decNumber range seems very hard within the */ +/* 32-bit limits. */ +/* */ +/* 4. The working precisions for the static buffers are twice the */ +/* obvious size to allow for calls from decNumberPower. */ +/* ------------------------------------------------------------------ */ +decNumber * decExpOp(decNumber *res, const decNumber *rhs, + decContext *set, uInt *status) { + uInt ignore=0; /* working status */ + Int h; /* adjusted exponent for 0.xxxx */ + Int p; /* working precision */ + Int residue; /* rounding residue */ + uInt needbytes; /* for space calculations */ + const decNumber *x=rhs; /* (may point to safe copy later) */ + decContext aset, tset, dset; /* working contexts */ + Int comp; /* work */ + + /* the argument is often copied to normalize it, so (unusually) it */ + /* is treated like other buffers, using DECBUFFER, +1 in case */ + /* DECBUFFER is 0 */ + decNumber bufr[D2N(DECBUFFER*2+1)]; + decNumber *allocrhs=NULL; /* non-NULL if rhs buffer allocated */ + + /* the working precision will be no more than set->digits+8+1 */ + /* so for on-stack buffers DECBUFFER+9 is used, +1 in case DECBUFFER */ + /* is 0 (and twice that for the accumulator) */ + + /* buffer for t, term (working precision plus) */ + decNumber buft[D2N(DECBUFFER*2+9+1)]; + decNumber *allocbuft=NULL; /* -> allocated buft, iff allocated */ + decNumber *t=buft; /* term */ + /* buffer for a, accumulator (working precision * 2), at least 9 */ + decNumber bufa[D2N(DECBUFFER*4+18+1)]; + decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ + decNumber *a=bufa; /* accumulator */ + /* decNumber for the divisor term; this needs at most 9 digits */ + /* and so can be fixed size [16 so can use standard context] */ + decNumber bufd[D2N(16)]; + decNumber *d=bufd; /* divisor */ + decNumber numone; /* constant 1 */ + + #if DECCHECK + Int iterations=0; /* for later sanity check */ + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + do { /* protect allocated storage */ + if (SPECIALARG) { /* handle infinities and NaNs */ + if (decNumberIsInfinite(rhs)) { /* an infinity */ + if (decNumberIsNegative(rhs)) /* -Infinity -> +0 */ + decNumberZero(res); + else decNumberCopy(res, rhs); /* +Infinity -> self */ + } + else decNaNs(res, rhs, NULL, set, status); /* a NaN */ + break;} + + if (ISZERO(rhs)) { /* zeros -> exact 1 */ + decNumberZero(res); /* make clean 1 */ + *res->lsu=1; /* .. */ + break;} /* [no status to set] */ + + /* e**x when 0 < x < 0.66 is < 1+3x/2, hence can fast-path */ + /* positive and negative tiny cases which will result in inexact */ + /* 1. This also allows the later add-accumulate to always be */ + /* exact (because its length will never be more than twice the */ + /* working precision). */ + /* The comparator (tiny) needs just one digit, so use the */ + /* decNumber d for it (reused as the divisor, etc., below); its */ + /* exponent is such that if x is positive it will have */ + /* set->digits-1 zeros between the decimal point and the digit, */ + /* which is 4, and if x is negative one more zero there as the */ + /* more precise result will be of the form 0.9999999 rather than */ + /* 1.0000001. Hence, tiny will be 0.0000004 if digits=7 and x>0 */ + /* or 0.00000004 if digits=7 and x<0. If RHS not larger than */ + /* this then the result will be 1.000000 */ + decNumberZero(d); /* clean */ + *d->lsu=4; /* set 4 .. */ + d->exponent=-set->digits; /* * 10**(-d) */ + if (decNumberIsNegative(rhs)) d->exponent--; /* negative case */ + comp=decCompare(d, rhs, 1); /* signless compare */ + if (comp==BADINT) { + *status|=DEC_Insufficient_storage; + break;} + if (comp>=0) { /* rhs < d */ + Int shift=set->digits-1; + decNumberZero(res); /* set 1 */ + *res->lsu=1; /* .. */ + res->digits=decShiftToMost(res->lsu, 1, shift); + res->exponent=-shift; /* make 1.0000... */ + *status|=DEC_Inexact | DEC_Rounded; /* .. inexactly */ + break;} /* tiny */ + + /* set up the context to be used for calculating a, as this is */ + /* used on both paths below */ + decContextDefault(&aset, DEC_INIT_DECIMAL64); + /* accumulator bounds are as requested (could underflow) */ + aset.emax=set->emax; /* usual bounds */ + aset.emin=set->emin; /* .. */ + aset.clamp=0; /* and no concrete format */ + + /* calculate the adjusted (Hull & Abrham) exponent (where the */ + /* decimal point is just to the left of the coefficient msd) */ + h=rhs->exponent+rhs->digits; + /* if h>8 then 10**h cannot be calculated safely; however, when */ + /* h=8 then exp(|rhs|) will be at least exp(1E+7) which is at */ + /* least 6.59E+4342944, so (due to the restriction on Emax/Emin) */ + /* overflow (or underflow to 0) is guaranteed -- so this case can */ + /* be handled by simply forcing the appropriate excess */ + if (h>8) { /* overflow/underflow */ + /* set up here so Power call below will over or underflow to */ + /* zero; set accumulator to either 2 or 0.02 */ + /* [stack buffer for a is always big enough for this] */ + decNumberZero(a); + *a->lsu=2; /* not 1 but < exp(1) */ + if (decNumberIsNegative(rhs)) a->exponent=-2; /* make 0.02 */ + h=8; /* clamp so 10**h computable */ + p=9; /* set a working precision */ + } + else { /* h<=8 */ + Int maxlever=(rhs->digits>8?1:0); + /* [could/should increase this for precisions >40 or so, too] */ + + /* if h is 8, cannot normalize to a lower upper limit because */ + /* the final result will not be computable (see notes above), */ + /* but leverage can be applied whenever h is less than 8. */ + /* Apply as much as possible, up to a MAXLEVER digits, which */ + /* sets the tradeoff against the cost of the later a**(10**h). */ + /* As h is increased, the working precision below also */ + /* increases to compensate for the "constant digits at the */ + /* front" effect. */ + Int lever=MINI(8-h, maxlever); /* leverage attainable */ + Int use=-rhs->digits-lever; /* exponent to use for RHS */ + h+=lever; /* apply leverage selected */ + if (h<0) { /* clamp */ + use+=h; /* [may end up subnormal] */ + h=0; + } + /* Take a copy of RHS if it needs normalization (true whenever x>=1) */ + if (rhs->exponent!=use) { + decNumber *newrhs=bufr; /* assume will fit on stack */ + needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit); + if (needbytes>sizeof(bufr)) { /* need malloc space */ + allocrhs=(decNumber *)malloc(needbytes); + if (allocrhs==NULL) { /* hopeless -- abandon */ + *status|=DEC_Insufficient_storage; + break;} + newrhs=allocrhs; /* use the allocated space */ + } + decNumberCopy(newrhs, rhs); /* copy to safe space */ + newrhs->exponent=use; /* normalize; now <1 */ + x=newrhs; /* ready for use */ + /* decNumberShow(x); */ + } + + /* Now use the usual power series to evaluate exp(x). The */ + /* series starts as 1 + x + x^2/2 ... so prime ready for the */ + /* third term by setting the term variable t=x, the accumulator */ + /* a=1, and the divisor d=2. */ + + /* First determine the working precision. From Hull & Abrham */ + /* this is set->digits+h+2. However, if x is 'over-precise' we */ + /* need to allow for all its digits to potentially participate */ + /* (consider an x where all the excess digits are 9s) so in */ + /* this case use x->digits+h+2 */ + p=MAXI(x->digits, set->digits)+h+2; /* [h<=8] */ + + /* a and t are variable precision, and depend on p, so space */ + /* must be allocated for them if necessary */ + + /* the accumulator needs to be able to hold 2p digits so that */ + /* the additions on the second and subsequent iterations are */ + /* sufficiently exact. */ + needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit); + if (needbytes>sizeof(bufa)) { /* need malloc space */ + allocbufa=(decNumber *)malloc(needbytes); + if (allocbufa==NULL) { /* hopeless -- abandon */ + *status|=DEC_Insufficient_storage; + break;} + a=allocbufa; /* use the allocated space */ + } + /* the term needs to be able to hold p digits (which is */ + /* guaranteed to be larger than x->digits, so the initial copy */ + /* is safe); it may also be used for the raise-to-power */ + /* calculation below, which needs an extra two digits */ + needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit); + if (needbytes>sizeof(buft)) { /* need malloc space */ + allocbuft=(decNumber *)malloc(needbytes); + if (allocbuft==NULL) { /* hopeless -- abandon */ + *status|=DEC_Insufficient_storage; + break;} + t=allocbuft; /* use the allocated space */ + } + + decNumberCopy(t, x); /* term=x */ + decNumberZero(a); *a->lsu=1; /* accumulator=1 */ + decNumberZero(d); *d->lsu=2; /* divisor=2 */ + decNumberZero(&numone); *numone.lsu=1; /* constant 1 for increment */ + + /* set up the contexts for calculating a, t, and d */ + decContextDefault(&tset, DEC_INIT_DECIMAL64); + dset=tset; + /* accumulator bounds are set above, set precision now */ + aset.digits=p*2; /* double */ + /* term bounds avoid any underflow or overflow */ + tset.digits=p; + tset.emin=DEC_MIN_EMIN; /* [emax is plenty] */ + /* [dset.digits=16, etc., are sufficient] */ + + /* finally ready to roll */ + for (;;) { + #if DECCHECK + iterations++; + #endif + /* only the status from the accumulation is interesting */ + /* [but it should remain unchanged after first add] */ + decAddOp(a, a, t, &aset, 0, status); /* a=a+t */ + decMultiplyOp(t, t, x, &tset, &ignore); /* t=t*x */ + decDivideOp(t, t, d, &tset, DIVIDE, &ignore); /* t=t/d */ + /* the iteration ends when the term cannot affect the result, */ + /* if rounded to p digits, which is when its value is smaller */ + /* than the accumulator by p+1 digits. There must also be */ + /* full precision in a. */ + if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1)) + && (a->digits>=p)) break; + decAddOp(d, d, &numone, &dset, 0, &ignore); /* d=d+1 */ + } /* iterate */ + + #if DECCHECK + /* just a sanity check; comment out test to show always */ + if (iterations>p+3) + printf("Exp iterations=%ld, status=%08lx, p=%ld, d=%ld\n", + iterations, *status, p, x->digits); + #endif + } /* h<=8 */ + + /* apply postconditioning: a=a**(10**h) -- this is calculated */ + /* at a slightly higher precision than Hull & Abrham suggest */ + if (h>0) { + Int seenbit=0; /* set once a 1-bit is seen */ + Int i; /* counter */ + Int n=powers[h]; /* always positive */ + aset.digits=p+2; /* sufficient precision */ + /* avoid the overhead and many extra digits of decNumberPower */ + /* as all that is needed is the short 'multipliers' loop; here */ + /* accumulate the answer into t */ + decNumberZero(t); *t->lsu=1; /* acc=1 */ + for (i=1;;i++){ /* for each bit [top bit ignored] */ + /* abandon if have had overflow or terminal underflow */ + if (*status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */ + if (*status&DEC_Overflow || ISZERO(t)) break;} + n=n<<1; /* move next bit to testable position */ + if (n<0) { /* top bit is set */ + seenbit=1; /* OK, have a significant bit */ + decMultiplyOp(t, t, a, &aset, status); /* acc=acc*x */ + } + if (i==31) break; /* that was the last bit */ + if (!seenbit) continue; /* no need to square 1 */ + decMultiplyOp(t, t, t, &aset, status); /* acc=acc*acc [square] */ + } /*i*/ /* 32 bits */ + /* decNumberShow(t); */ + a=t; /* and carry on using t instead of a */ + } + + /* Copy and round the result to res */ + residue=1; /* indicate dirt to right .. */ + if (ISZERO(a)) residue=0; /* .. unless underflowed to 0 */ + aset.digits=set->digits; /* [use default rounding] */ + decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */ + decFinish(res, set, &residue, status); /* cleanup/set flags */ + } while(0); /* end protected */ + + if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */ + if (allocbufa!=NULL) free(allocbufa); /* .. */ + if (allocbuft!=NULL) free(allocbuft); /* .. */ + /* [status is handled by caller] */ + return res; + } /* decExpOp */ + +/* ------------------------------------------------------------------ */ +/* Initial-estimate natural logarithm table */ +/* */ +/* LNnn -- 90-entry 16-bit table for values from .10 through .99. */ +/* The result is a 4-digit encode of the coefficient (c=the */ +/* top 14 bits encoding 0-9999) and a 2-digit encode of the */ +/* exponent (e=the bottom 2 bits encoding 0-3) */ +/* */ +/* The resulting value is given by: */ +/* */ +/* v = -c * 10**(-e-3) */ +/* */ +/* where e and c are extracted from entry k = LNnn[x-10] */ +/* where x is truncated (NB) into the range 10 through 99, */ +/* and then c = k>>2 and e = k&3. */ +/* ------------------------------------------------------------------ */ +const uShort LNnn[90]={9016, 8652, 8316, 8008, 7724, 7456, 7208, + 6972, 6748, 6540, 6340, 6148, 5968, 5792, 5628, 5464, 5312, + 5164, 5020, 4884, 4748, 4620, 4496, 4376, 4256, 4144, 4032, + 39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629, + 29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837, + 22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321, + 15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717, + 10197, 9685, 9177, 8677, 8185, 7697, 7213, 6737, 6269, 5801, + 5341, 4889, 4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254, + 10130, 6046, 20055}; + +/* ------------------------------------------------------------------ */ +/* decLnOp -- effect natural logarithm */ +/* */ +/* This computes C = ln(A) */ +/* */ +/* res is C, the result. C may be A */ +/* rhs is A */ +/* set is the context; note that rounding mode has no effect */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Notable cases: */ +/* A<0 -> Invalid */ +/* A=0 -> -Infinity (Exact) */ +/* A=+Infinity -> +Infinity (Exact) */ +/* A=1 exactly -> 0 (Exact) */ +/* */ +/* Restrictions (as for Exp): */ +/* */ +/* digits, emax, and -emin in the context must be less than */ +/* DEC_MAX_MATH+11 (1000010), and the rhs must be within these */ +/* bounds or a zero. This is an internal routine, so these */ +/* restrictions are contractual and not enforced. */ +/* */ +/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */ +/* almost always be correctly rounded, but may be up to 1 ulp in */ +/* error in rare cases. */ +/* ------------------------------------------------------------------ */ +/* The result is calculated using Newton's method, with each */ +/* iteration calculating a' = a + x * exp(-a) - 1. See, for example, */ +/* Epperson 1989. */ +/* */ +/* The iteration ends when the adjustment x*exp(-a)-1 is tiny enough. */ +/* This has to be calculated at the sum of the precision of x and the */ +/* working precision. */ +/* */ +/* Implementation notes: */ +/* */ +/* 1. This is separated out as decLnOp so it can be called from */ +/* other Mathematical functions (e.g., Log 10) with a wider range */ +/* than normal. In particular, it can handle the slightly wider */ +/* (+9+2) range needed by a power function. */ +/* */ +/* 2. The speed of this function is about 10x slower than exp, as */ +/* it typically needs 4-6 iterations for short numbers, and the */ +/* extra precision needed adds a squaring effect, twice. */ +/* */ +/* 3. Fastpaths are included for ln(10) and ln(2), up to length 40, */ +/* as these are common requests. ln(10) is used by log10(x). */ +/* */ +/* 4. An iteration might be saved by widening the LNnn table, and */ +/* would certainly save at least one if it were made ten times */ +/* bigger, too (for truncated fractions 0.100 through 0.999). */ +/* However, for most practical evaluations, at least four or five */ +/* iterations will be neede -- so this would only speed up by */ +/* 20-25% and that probably does not justify increasing the table */ +/* size. */ +/* */ +/* 5. The static buffers are larger than might be expected to allow */ +/* for calls from decNumberPower. */ +/* ------------------------------------------------------------------ */ +decNumber * decLnOp(decNumber *res, const decNumber *rhs, + decContext *set, uInt *status) { + uInt ignore=0; /* working status accumulator */ + uInt needbytes; /* for space calculations */ + Int residue; /* rounding residue */ + Int r; /* rhs=f*10**r [see below] */ + Int p; /* working precision */ + Int pp; /* precision for iteration */ + Int t; /* work */ + + /* buffers for a (accumulator, typically precision+2) and b */ + /* (adjustment calculator, same size) */ + decNumber bufa[D2N(DECBUFFER+12)]; + decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */ + decNumber *a=bufa; /* accumulator/work */ + decNumber bufb[D2N(DECBUFFER*2+2)]; + decNumber *allocbufb=NULL; /* -> allocated bufa, iff allocated */ + decNumber *b=bufb; /* adjustment/work */ + + decNumber numone; /* constant 1 */ + decNumber cmp; /* work */ + decContext aset, bset; /* working contexts */ + + #if DECCHECK + Int iterations=0; /* for later sanity check */ + if (decCheckOperands(res, DECUNUSED, rhs, set)) return res; + #endif + + do { /* protect allocated storage */ + if (SPECIALARG) { /* handle infinities and NaNs */ + if (decNumberIsInfinite(rhs)) { /* an infinity */ + if (decNumberIsNegative(rhs)) /* -Infinity -> error */ + *status|=DEC_Invalid_operation; + else decNumberCopy(res, rhs); /* +Infinity -> self */ + } + else decNaNs(res, rhs, NULL, set, status); /* a NaN */ + break;} + + if (ISZERO(rhs)) { /* +/- zeros -> -Infinity */ + decNumberZero(res); /* make clean */ + res->bits=DECINF|DECNEG; /* set - infinity */ + break;} /* [no status to set] */ + + /* Non-zero negatives are bad... */ + if (decNumberIsNegative(rhs)) { /* -x -> error */ + *status|=DEC_Invalid_operation; + break;} + + /* Here, rhs is positive, finite, and in range */ + + /* lookaside fastpath code for ln(2) and ln(10) at common lengths */ + if (rhs->exponent==0 && set->digits<=40) { + #if DECDPUN==1 + if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { /* ln(10) */ + #else + if (rhs->lsu[0]==10 && rhs->digits==2) { /* ln(10) */ + #endif + aset=*set; aset.round=DEC_ROUND_HALF_EVEN; + #define LN10 "2.302585092994045684017991454684364207601" + decNumberFromString(res, LN10, &aset); + *status|=(DEC_Inexact | DEC_Rounded); /* is inexact */ + break;} + if (rhs->lsu[0]==2 && rhs->digits==1) { /* ln(2) */ + aset=*set; aset.round=DEC_ROUND_HALF_EVEN; + #define LN2 "0.6931471805599453094172321214581765680755" + decNumberFromString(res, LN2, &aset); + *status|=(DEC_Inexact | DEC_Rounded); + break;} + } /* integer and short */ + + /* Determine the working precision. This is normally the */ + /* requested precision + 2, with a minimum of 9. However, if */ + /* the rhs is 'over-precise' then allow for all its digits to */ + /* potentially participate (consider an rhs where all the excess */ + /* digits are 9s) so in this case use rhs->digits+2. */ + p=MAXI(rhs->digits, MAXI(set->digits, 7))+2; + + /* Allocate space for the accumulator and the high-precision */ + /* adjustment calculator, if necessary. The accumulator must */ + /* be able to hold p digits, and the adjustment up to */ + /* rhs->digits+p digits. They are also made big enough for 16 */ + /* digits so that they can be used for calculating the initial */ + /* estimate. */ + needbytes=sizeof(decNumber)+(D2U(MAXI(p,16))-1)*sizeof(Unit); + if (needbytes>sizeof(bufa)) { /* need malloc space */ + allocbufa=(decNumber *)malloc(needbytes); + if (allocbufa==NULL) { /* hopeless -- abandon */ + *status|=DEC_Insufficient_storage; + break;} + a=allocbufa; /* use the allocated space */ + } + pp=p+rhs->digits; + needbytes=sizeof(decNumber)+(D2U(MAXI(pp,16))-1)*sizeof(Unit); + if (needbytes>sizeof(bufb)) { /* need malloc space */ + allocbufb=(decNumber *)malloc(needbytes); + if (allocbufb==NULL) { /* hopeless -- abandon */ + *status|=DEC_Insufficient_storage; + break;} + b=allocbufb; /* use the allocated space */ + } + + /* Prepare an initial estimate in acc. Calculate this by */ + /* considering the coefficient of x to be a normalized fraction, */ + /* f, with the decimal point at far left and multiplied by */ + /* 10**r. Then, rhs=f*10**r and 0.1<=f<1, and */ + /* ln(x) = ln(f) + ln(10)*r */ + /* Get the initial estimate for ln(f) from a small lookup */ + /* table (see above) indexed by the first two digits of f, */ + /* truncated. */ + + decContextDefault(&aset, DEC_INIT_DECIMAL64); /* 16-digit extended */ + r=rhs->exponent+rhs->digits; /* 'normalised' exponent */ + decNumberFromInt32(a, r); /* a=r */ + decNumberFromInt32(b, 2302585); /* b=ln(10) (2.302585) */ + b->exponent=-6; /* .. */ + decMultiplyOp(a, a, b, &aset, &ignore); /* a=a*b */ + /* now get top two digits of rhs into b by simple truncate and */ + /* force to integer */ + residue=0; /* (no residue) */ + aset.digits=2; aset.round=DEC_ROUND_DOWN; + decCopyFit(b, rhs, &aset, &residue, &ignore); /* copy & shorten */ + b->exponent=0; /* make integer */ + t=decGetInt(b); /* [cannot fail] */ + if (t<10) t=X10(t); /* adjust single-digit b */ + t=LNnn[t-10]; /* look up ln(b) */ + decNumberFromInt32(b, t>>2); /* b=ln(b) coefficient */ + b->exponent=-(t&3)-3; /* set exponent */ + b->bits=DECNEG; /* ln(0.10)->ln(0.99) always -ve */ + aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; /* restore */ + decAddOp(a, a, b, &aset, 0, &ignore); /* acc=a+b */ + /* the initial estimate is now in a, with up to 4 digits correct. */ + /* When rhs is at or near Nmax the estimate will be low, so we */ + /* will approach it from below, avoiding overflow when calling exp. */ + + decNumberZero(&numone); *numone.lsu=1; /* constant 1 for adjustment */ + + /* accumulator bounds are as requested (could underflow, but */ + /* cannot overflow) */ + aset.emax=set->emax; + aset.emin=set->emin; + aset.clamp=0; /* no concrete format */ + /* set up a context to be used for the multiply and subtract */ + bset=aset; + bset.emax=DEC_MAX_MATH*2; /* use double bounds for the */ + bset.emin=-DEC_MAX_MATH*2; /* adjustment calculation */ + /* [see decExpOp call below] */ + /* for each iteration double the number of digits to calculate, */ + /* up to a maximum of p */ + pp=9; /* initial precision */ + /* [initially 9 as then the sequence starts 7+2, 16+2, and */ + /* 34+2, which is ideal for standard-sized numbers] */ + aset.digits=pp; /* working context */ + bset.digits=pp+rhs->digits; /* wider context */ + for (;;) { /* iterate */ + #if DECCHECK + iterations++; + if (iterations>24) break; /* consider 9 * 2**24 */ + #endif + /* calculate the adjustment (exp(-a)*x-1) into b. This is a */ + /* catastrophic subtraction but it really is the difference */ + /* from 1 that is of interest. */ + /* Use the internal entry point to Exp as it allows the double */ + /* range for calculating exp(-a) when a is the tiniest subnormal. */ + a->bits^=DECNEG; /* make -a */ + decExpOp(b, a, &bset, &ignore); /* b=exp(-a) */ + a->bits^=DECNEG; /* restore sign of a */ + /* now multiply by rhs and subtract 1, at the wider precision */ + decMultiplyOp(b, b, rhs, &bset, &ignore); /* b=b*rhs */ + decAddOp(b, b, &numone, &bset, DECNEG, &ignore); /* b=b-1 */ + + /* the iteration ends when the adjustment cannot affect the */ + /* result by >=0.5 ulp (at the requested digits), which */ + /* is when its value is smaller than the accumulator by */ + /* set->digits+1 digits (or it is zero) -- this is a looser */ + /* requirement than for Exp because all that happens to the */ + /* accumulator after this is the final rounding (but note that */ + /* there must also be full precision in a, or a=0). */ + + if (decNumberIsZero(b) || + (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) { + if (a->digits==p) break; + if (decNumberIsZero(a)) { + decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); /* rhs=1 ? */ + if (cmp.lsu[0]==0) a->exponent=0; /* yes, exact 0 */ + else *status|=(DEC_Inexact | DEC_Rounded); /* no, inexact */ + break; + } + /* force padding if adjustment has gone to 0 before full length */ + if (decNumberIsZero(b)) b->exponent=a->exponent-p; + } + + /* not done yet ... */ + decAddOp(a, a, b, &aset, 0, &ignore); /* a=a+b for next estimate */ + if (pp==p) continue; /* precision is at maximum */ + /* lengthen the next calculation */ + pp=pp*2; /* double precision */ + if (pp>p) pp=p; /* clamp to maximum */ + aset.digits=pp; /* working context */ + bset.digits=pp+rhs->digits; /* wider context */ + } /* Newton's iteration */ + + #if DECCHECK + /* just a sanity check; remove the test to show always */ + if (iterations>24) + printf("Ln iterations=%ld, status=%08lx, p=%ld, d=%ld\n", + iterations, *status, p, rhs->digits); + #endif + + /* Copy and round the result to res */ + residue=1; /* indicate dirt to right */ + if (ISZERO(a)) residue=0; /* .. unless underflowed to 0 */ + aset.digits=set->digits; /* [use default rounding] */ + decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */ + decFinish(res, set, &residue, status); /* cleanup/set flags */ + } while(0); /* end protected */ + + if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */ + if (allocbufb!=NULL) free(allocbufb); /* .. */ + /* [status is handled by caller] */ + return res; + } /* decLnOp */ + +/* ------------------------------------------------------------------ */ +/* decQuantizeOp -- force exponent to requested value */ +/* */ +/* This computes C = op(A, B), where op adjusts the coefficient */ +/* of C (by rounding or shifting) such that the exponent (-scale) */ +/* of C has the value B or matches the exponent of B. */ +/* The numerical value of C will equal A, except for the effects of */ +/* any rounding that occurred. */ +/* */ +/* res is C, the result. C may be A or B */ +/* lhs is A, the number to adjust */ +/* rhs is B, the requested exponent */ +/* set is the context */ +/* quant is 1 for quantize or 0 for rescale */ +/* status is the status accumulator (this can be called without */ +/* risk of control loss) */ +/* */ +/* C must have space for set->digits digits. */ +/* */ +/* Unless there is an error or the result is infinite, the exponent */ +/* after the operation is guaranteed to be that requested. */ +/* ------------------------------------------------------------------ */ +static decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set, + Flag quant, uInt *status) { + #if DECSUBSET + decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ + decNumber *allocrhs=NULL; /* .., rhs */ + #endif + const decNumber *inrhs=rhs; /* save original rhs */ + Int reqdigits=set->digits; /* requested DIGITS */ + Int reqexp; /* requested exponent [-scale] */ + Int residue=0; /* rounding residue */ + Int etiny=set->emin-(reqdigits-1); + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { /* protect allocated storage */ + #if DECSUBSET + if (!set->extended) { + /* reduce operands and set lostDigits status, as needed */ + if (lhs->digits>reqdigits) { + alloclhs=decRoundOperand(lhs, set, status); + if (alloclhs==NULL) break; + lhs=alloclhs; + } + if (rhs->digits>reqdigits) { /* [this only checks lostDigits] */ + allocrhs=decRoundOperand(rhs, set, status); + if (allocrhs==NULL) break; + rhs=allocrhs; + } + } + #endif + /* [following code does not require input rounding] */ + + /* Handle special values */ + if (SPECIALARGS) { + /* NaNs get usual processing */ + if (SPECIALARGS & (DECSNAN | DECNAN)) + decNaNs(res, lhs, rhs, set, status); + /* one infinity but not both is bad */ + else if ((lhs->bits ^ rhs->bits) & DECINF) + *status|=DEC_Invalid_operation; + /* both infinity: return lhs */ + else decNumberCopy(res, lhs); /* [nop if in place] */ + break; + } + + /* set requested exponent */ + if (quant) reqexp=inrhs->exponent; /* quantize -- match exponents */ + else { /* rescale -- use value of rhs */ + /* Original rhs must be an integer that fits and is in range, */ + /* which could be from -1999999997 to +999999999, thanks to */ + /* subnormals */ + reqexp=decGetInt(inrhs); /* [cannot fail] */ + } + + #if DECSUBSET + if (!set->extended) etiny=set->emin; /* no subnormals */ + #endif + + if (reqexp==BADINT /* bad (rescale only) or .. */ + || reqexp==BIGODD || reqexp==BIGEVEN /* very big (ditto) or .. */ + || (reqexp<etiny) /* < lowest */ + || (reqexp>set->emax)) { /* > emax */ + *status|=DEC_Invalid_operation; + break;} + + /* the RHS has been processed, so it can be overwritten now if necessary */ + if (ISZERO(lhs)) { /* zero coefficient unchanged */ + decNumberCopy(res, lhs); /* [nop if in place] */ + res->exponent=reqexp; /* .. just set exponent */ + #if DECSUBSET + if (!set->extended) res->bits=0; /* subset specification; no -0 */ + #endif + } + else { /* non-zero lhs */ + Int adjust=reqexp-lhs->exponent; /* digit adjustment needed */ + /* if adjusted coefficient will definitely not fit, give up now */ + if ((lhs->digits-adjust)>reqdigits) { + *status|=DEC_Invalid_operation; + break; + } + + if (adjust>0) { /* increasing exponent */ + /* this will decrease the length of the coefficient by adjust */ + /* digits, and must round as it does so */ + decContext workset; /* work */ + workset=*set; /* clone rounding, etc. */ + workset.digits=lhs->digits-adjust; /* set requested length */ + /* [note that the latter can be <1, here] */ + decCopyFit(res, lhs, &workset, &residue, status); /* fit to result */ + decApplyRound(res, &workset, residue, status); /* .. and round */ + residue=0; /* [used] */ + /* If just rounded a 999s case, exponent will be off by one; */ + /* adjust back (after checking space), if so. */ + if (res->exponent>reqexp) { + /* re-check needed, e.g., for quantize(0.9999, 0.001) under */ + /* set->digits==3 */ + if (res->digits==reqdigits) { /* cannot shift by 1 */ + *status&=~(DEC_Inexact | DEC_Rounded); /* [clean these] */ + *status|=DEC_Invalid_operation; + break; + } + res->digits=decShiftToMost(res->lsu, res->digits, 1); /* shift */ + res->exponent--; /* (re)adjust the exponent. */ + } + #if DECSUBSET + if (ISZERO(res) && !set->extended) res->bits=0; /* subset; no -0 */ + #endif + } /* increase */ + else /* adjust<=0 */ { /* decreasing or = exponent */ + /* this will increase the length of the coefficient by -adjust */ + /* digits, by adding zero or more trailing zeros; this is */ + /* already checked for fit, above */ + decNumberCopy(res, lhs); /* [it will fit] */ + /* if padding needed (adjust<0), add it now... */ + if (adjust<0) { + res->digits=decShiftToMost(res->lsu, res->digits, -adjust); + res->exponent+=adjust; /* adjust the exponent */ + } + } /* decrease */ + } /* non-zero */ + + /* Check for overflow [do not use Finalize in this case, as an */ + /* overflow here is a "don't fit" situation] */ + if (res->exponent>set->emax-res->digits+1) { /* too big */ + *status|=DEC_Invalid_operation; + break; + } + else { + decFinalize(res, set, &residue, status); /* set subnormal flags */ + *status&=~DEC_Underflow; /* suppress Underflow [754r] */ + } + } while(0); /* end protected */ + + #if DECSUBSET + if (allocrhs!=NULL) free(allocrhs); /* drop any storage used */ + if (alloclhs!=NULL) free(alloclhs); /* .. */ + #endif + return res; + } /* decQuantizeOp */ + +/* ------------------------------------------------------------------ */ +/* decCompareOp -- compare, min, or max two Numbers */ +/* */ +/* This computes C = A ? B and carries out one of four operations: */ +/* COMPARE -- returns the signum (as a number) giving the */ +/* result of a comparison unless one or both */ +/* operands is a NaN (in which case a NaN results) */ +/* COMPSIG -- as COMPARE except that a quiet NaN raises */ +/* Invalid operation. */ +/* COMPMAX -- returns the larger of the operands, using the */ +/* 754r maxnum operation */ +/* COMPMAXMAG -- ditto, comparing absolute values */ +/* COMPMIN -- the 754r minnum operation */ +/* COMPMINMAG -- ditto, comparing absolute values */ +/* COMTOTAL -- returns the signum (as a number) giving the */ +/* result of a comparison using 754r total ordering */ +/* */ +/* res is C, the result. C may be A and/or B (e.g., X=X?X) */ +/* lhs is A */ +/* rhs is B */ +/* set is the context */ +/* op is the operation flag */ +/* status is the usual accumulator */ +/* */ +/* C must have space for one digit for COMPARE or set->digits for */ +/* COMPMAX, COMPMIN, COMPMAXMAG, or COMPMINMAG. */ +/* ------------------------------------------------------------------ */ +/* The emphasis here is on speed for common cases, and avoiding */ +/* coefficient comparison if possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decCompareOp(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set, + Flag op, uInt *status) { + #if DECSUBSET + decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */ + decNumber *allocrhs=NULL; /* .., rhs */ + #endif + Int result=0; /* default result value */ + uByte merged; /* work */ + + #if DECCHECK + if (decCheckOperands(res, lhs, rhs, set)) return res; + #endif + + do { /* protect allocated storage */ + #if DECSUBSET + if (!set->extended) { + /* reduce operands and set lostDigits status, as needed */ + if (lhs->digits>set->digits) { + alloclhs=decRoundOperand(lhs, set, status); + if (alloclhs==NULL) {result=BADINT; break;} + lhs=alloclhs; + } + if (rhs->digits>set->digits) { + allocrhs=decRoundOperand(rhs, set, status); + if (allocrhs==NULL) {result=BADINT; break;} + rhs=allocrhs; + } + } + #endif + /* [following code does not require input rounding] */ + + /* If total ordering then handle differing signs 'up front' */ + if (op==COMPTOTAL) { /* total ordering */ + if (decNumberIsNegative(lhs) & !decNumberIsNegative(rhs)) { + result=-1; + break; + } + if (!decNumberIsNegative(lhs) & decNumberIsNegative(rhs)) { + result=+1; + break; + } + } + + /* handle NaNs specially; let infinities drop through */ + /* This assumes sNaN (even just one) leads to NaN. */ + merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN); + if (merged) { /* a NaN bit set */ + if (op==COMPARE); /* result will be NaN */ + else if (op==COMPSIG) /* treat qNaN as sNaN */ + *status|=DEC_Invalid_operation | DEC_sNaN; + else if (op==COMPTOTAL) { /* total ordering, always finite */ + /* signs are known to be the same; compute the ordering here */ + /* as if the signs are both positive, then invert for negatives */ + if (!decNumberIsNaN(lhs)) result=-1; + else if (!decNumberIsNaN(rhs)) result=+1; + /* here if both NaNs */ + else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1; + else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1; + else { /* both NaN or both sNaN */ + /* now it just depends on the payload */ + result=decUnitCompare(lhs->lsu, D2U(lhs->digits), + rhs->lsu, D2U(rhs->digits), 0); + /* [Error not possible, as these are 'aligned'] */ + } /* both same NaNs */ + if (decNumberIsNegative(lhs)) result=-result; + break; + } /* total order */ + + else if (merged & DECSNAN); /* sNaN -> qNaN */ + else { /* here if MIN or MAX and one or two quiet NaNs */ + /* min or max -- 754r rules ignore single NaN */ + if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) { + /* just one NaN; force choice to be the non-NaN operand */ + op=COMPMAX; + if (lhs->bits & DECNAN) result=-1; /* pick rhs */ + else result=+1; /* pick lhs */ + break; + } + } /* max or min */ + op=COMPNAN; /* use special path */ + decNaNs(res, lhs, rhs, set, status); /* propagate NaN */ + break; + } + /* have numbers */ + if (op==COMPMAXMAG || op==COMPMINMAG) result=decCompare(lhs, rhs, 1); + else result=decCompare(lhs, rhs, 0); /* sign matters */ + } while(0); /* end protected */ + + if (result==BADINT) *status|=DEC_Insufficient_storage; /* rare */ + else { + if (op==COMPARE || op==COMPSIG ||op==COMPTOTAL) { /* returning signum */ + if (op==COMPTOTAL && result==0) { + /* operands are numerically equal or same NaN (and same sign, */ + /* tested first); if identical, leave result 0 */ + if (lhs->exponent!=rhs->exponent) { + if (lhs->exponent<rhs->exponent) result=-1; + else result=+1; + if (decNumberIsNegative(lhs)) result=-result; + } /* lexp!=rexp */ + } /* total-order by exponent */ + decNumberZero(res); /* [always a valid result] */ + if (result!=0) { /* must be -1 or +1 */ + *res->lsu=1; + if (result<0) res->bits=DECNEG; + } + } + else if (op==COMPNAN); /* special, drop through */ + else { /* MAX or MIN, non-NaN result */ + Int residue=0; /* rounding accumulator */ + /* choose the operand for the result */ + const decNumber *choice; + if (result==0) { /* operands are numerically equal */ + /* choose according to sign then exponent (see 754r) */ + uByte slhs=(lhs->bits & DECNEG); + uByte srhs=(rhs->bits & DECNEG); + #if DECSUBSET + if (!set->extended) { /* subset: force left-hand */ + op=COMPMAX; + result=+1; + } + else + #endif + if (slhs!=srhs) { /* signs differ */ + if (slhs) result=-1; /* rhs is max */ + else result=+1; /* lhs is max */ + } + else if (slhs && srhs) { /* both negative */ + if (lhs->exponent<rhs->exponent) result=+1; + else result=-1; + /* [if equal, use lhs, technically identical] */ + } + else { /* both positive */ + if (lhs->exponent>rhs->exponent) result=+1; + else result=-1; + /* [ditto] */ + } + } /* numerically equal */ + /* here result will be non-0; reverse if looking for MIN */ + if (op==COMPMIN || op==COMPMINMAG) result=-result; + choice=(result>0 ? lhs : rhs); /* choose */ + /* copy chosen to result, rounding if need be */ + decCopyFit(res, choice, set, &residue, status); + decFinish(res, set, &residue, status); + } + } + #if DECSUBSET + if (allocrhs!=NULL) free(allocrhs); /* free any storage used */ + if (alloclhs!=NULL) free(alloclhs); /* .. */ + #endif + return res; + } /* decCompareOp */ + +/* ------------------------------------------------------------------ */ +/* decCompare -- compare two decNumbers by numerical value */ +/* */ +/* This routine compares A ? B without altering them. */ +/* */ +/* Arg1 is A, a decNumber which is not a NaN */ +/* Arg2 is B, a decNumber which is not a NaN */ +/* Arg3 is 1 for a sign-independent compare, 0 otherwise */ +/* */ +/* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */ +/* (the only possible failure is an allocation error) */ +/* ------------------------------------------------------------------ */ +static Int decCompare(const decNumber *lhs, const decNumber *rhs, + Flag abs) { + Int result; /* result value */ + Int sigr; /* rhs signum */ + Int compare; /* work */ + + result=1; /* assume signum(lhs) */ + if (ISZERO(lhs)) result=0; + if (abs) { + if (ISZERO(rhs)) return result; /* LHS wins or both 0 */ + /* RHS is non-zero */ + if (result==0) return -1; /* LHS is 0; RHS wins */ + /* [here, both non-zero, result=1] */ + } + else { /* signs matter */ + if (result && decNumberIsNegative(lhs)) result=-1; + sigr=1; /* compute signum(rhs) */ + if (ISZERO(rhs)) sigr=0; + else if (decNumberIsNegative(rhs)) sigr=-1; + if (result > sigr) return +1; /* L > R, return 1 */ + if (result < sigr) return -1; /* L < R, return -1 */ + if (result==0) return 0; /* both 0 */ + } + + /* signums are the same; both are non-zero */ + if ((lhs->bits | rhs->bits) & DECINF) { /* one or more infinities */ + if (decNumberIsInfinite(rhs)) { + if (decNumberIsInfinite(lhs)) result=0;/* both infinite */ + else result=-result; /* only rhs infinite */ + } + return result; + } + /* must compare the coefficients, allowing for exponents */ + if (lhs->exponent>rhs->exponent) { /* LHS exponent larger */ + /* swap sides, and sign */ + const decNumber *temp=lhs; + lhs=rhs; + rhs=temp; + result=-result; + } + compare=decUnitCompare(lhs->lsu, D2U(lhs->digits), + rhs->lsu, D2U(rhs->digits), + rhs->exponent-lhs->exponent); + if (compare!=BADINT) compare*=result; /* comparison succeeded */ + return compare; + } /* decCompare */ + +/* ------------------------------------------------------------------ */ +/* decUnitCompare -- compare two >=0 integers in Unit arrays */ +/* */ +/* This routine compares A ? B*10**E where A and B are unit arrays */ +/* A is a plain integer */ +/* B has an exponent of E (which must be non-negative) */ +/* */ +/* Arg1 is A first Unit (lsu) */ +/* Arg2 is A length in Units */ +/* Arg3 is B first Unit (lsu) */ +/* Arg4 is B length in Units */ +/* Arg5 is E (0 if the units are aligned) */ +/* */ +/* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */ +/* (the only possible failure is an allocation error, which can */ +/* only occur if E!=0) */ +/* ------------------------------------------------------------------ */ +static Int decUnitCompare(const Unit *a, Int alength, + const Unit *b, Int blength, Int exp) { + Unit *acc; /* accumulator for result */ + Unit accbuff[SD2U(DECBUFFER*2+1)]; /* local buffer */ + Unit *allocacc=NULL; /* -> allocated acc buffer, iff allocated */ + Int accunits, need; /* units in use or needed for acc */ + const Unit *l, *r, *u; /* work */ + Int expunits, exprem, result; /* .. */ + + if (exp==0) { /* aligned; fastpath */ + if (alength>blength) return 1; + if (alength<blength) return -1; + /* same number of units in both -- need unit-by-unit compare */ + l=a+alength-1; + r=b+alength-1; + for (;l>=a; l--, r--) { + if (*l>*r) return 1; + if (*l<*r) return -1; + } + return 0; /* all units match */ + } /* aligned */ + + /* Unaligned. If one is >1 unit longer than the other, padded */ + /* approximately, then can return easily */ + if (alength>blength+(Int)D2U(exp)) return 1; + if (alength+1<blength+(Int)D2U(exp)) return -1; + + /* Need to do a real subtract. For this, a result buffer is needed */ + /* even though only the sign is of interest. Its length needs */ + /* to be the larger of alength and padded blength, +2 */ + need=blength+D2U(exp); /* maximum real length of B */ + if (need<alength) need=alength; + need+=2; + acc=accbuff; /* assume use local buffer */ + if (need*sizeof(Unit)>sizeof(accbuff)) { + allocacc=(Unit *)malloc(need*sizeof(Unit)); + if (allocacc==NULL) return BADINT; /* hopeless -- abandon */ + acc=allocacc; + } + /* Calculate units and remainder from exponent. */ + expunits=exp/DECDPUN; + exprem=exp%DECDPUN; + /* subtract [A+B*(-m)] */ + accunits=decUnitAddSub(a, alength, b, blength, expunits, acc, + -(Int)powers[exprem]); + /* [UnitAddSub result may have leading zeros, even on zero] */ + if (accunits<0) result=-1; /* negative result */ + else { /* non-negative result */ + /* check units of the result before freeing any storage */ + for (u=acc; u<acc+accunits-1 && *u==0;) u++; + result=(*u==0 ? 0 : +1); + } + /* clean up and return the result */ + if (allocacc!=NULL) free(allocacc); /* drop any storage used */ + return result; + } /* decUnitCompare */ + +/* ------------------------------------------------------------------ */ +/* decUnitAddSub -- add or subtract two >=0 integers in Unit arrays */ +/* */ +/* This routine performs the calculation: */ +/* */ +/* C=A+(B*M) */ +/* */ +/* Where M is in the range -DECDPUNMAX through +DECDPUNMAX. */ +/* */ +/* A may be shorter or longer than B. */ +/* */ +/* Leading zeros are not removed after a calculation. The result is */ +/* either the same length as the longer of A and B (adding any */ +/* shift), or one Unit longer than that (if a Unit carry occurred). */ +/* */ +/* A and B content are not altered unless C is also A or B. */ +/* C may be the same array as A or B, but only if no zero padding is */ +/* requested (that is, C may be B only if bshift==0). */ +/* C is filled from the lsu; only those units necessary to complete */ +/* the calculation are referenced. */ +/* */ +/* Arg1 is A first Unit (lsu) */ +/* Arg2 is A length in Units */ +/* Arg3 is B first Unit (lsu) */ +/* Arg4 is B length in Units */ +/* Arg5 is B shift in Units (>=0; pads with 0 units if positive) */ +/* Arg6 is C first Unit (lsu) */ +/* Arg7 is M, the multiplier */ +/* */ +/* returns the count of Units written to C, which will be non-zero */ +/* and negated if the result is negative. That is, the sign of the */ +/* returned Int is the sign of the result (positive for zero) and */ +/* the absolute value of the Int is the count of Units. */ +/* */ +/* It is the caller's responsibility to make sure that C size is */ +/* safe, allowing space if necessary for a one-Unit carry. */ +/* */ +/* This routine is severely performance-critical; *any* change here */ +/* must be measured (timed) to assure no performance degradation. */ +/* In particular, trickery here tends to be counter-productive, as */ +/* increased complexity of code hurts register optimizations on */ +/* register-poor architectures. Avoiding divisions is nearly */ +/* always a Good Idea, however. */ +/* */ +/* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark */ +/* (IBM Warwick, UK) for some of the ideas used in this routine. */ +/* ------------------------------------------------------------------ */ +static Int decUnitAddSub(const Unit *a, Int alength, + const Unit *b, Int blength, Int bshift, + Unit *c, Int m) { + const Unit *alsu=a; /* A lsu [need to remember it] */ + Unit *clsu=c; /* C ditto */ + Unit *minC; /* low water mark for C */ + Unit *maxC; /* high water mark for C */ + eInt carry=0; /* carry integer (could be Long) */ + Int add; /* work */ + #if DECDPUN<=4 /* myriadal, millenary, etc. */ + Int est; /* estimated quotient */ + #endif + + #if DECTRACE + if (alength<1 || blength<1) + printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m); + #endif + + maxC=c+alength; /* A is usually the longer */ + minC=c+blength; /* .. and B the shorter */ + if (bshift!=0) { /* B is shifted; low As copy across */ + minC+=bshift; + /* if in place [common], skip copy unless there's a gap [rare] */ + if (a==c && bshift<=alength) { + c+=bshift; + a+=bshift; + } + else for (; c<clsu+bshift; a++, c++) { /* copy needed */ + if (a<alsu+alength) *c=*a; + else *c=0; + } + } + if (minC>maxC) { /* swap */ + Unit *hold=minC; + minC=maxC; + maxC=hold; + } + + /* For speed, do the addition as two loops; the first where both A */ + /* and B contribute, and the second (if necessary) where only one or */ + /* other of the numbers contribute. */ + /* Carry handling is the same (i.e., duplicated) in each case. */ + for (; c<minC; c++) { + carry+=*a; + a++; + carry+=((eInt)*b)*m; /* [special-casing m=1/-1 */ + b++; /* here is not a win] */ + /* here carry is new Unit of digits; it could be +ve or -ve */ + if ((ueInt)carry<=DECDPUNMAX) { /* fastpath 0-DECDPUNMAX */ + *c=(Unit)carry; + carry=0; + continue; + } + #if DECDPUN==4 /* use divide-by-multiply */ + if (carry>=0) { + est=(((ueInt)carry>>11)*53687)>>18; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ + carry=est; /* likely quotient [89%] */ + if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ + carry++; + *c-=DECDPUNMAX+1; + continue; + } + /* negative case */ + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ + est=(((ueInt)carry>>11)*53687)>>18; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); /* correctly negative */ + if (*c<DECDPUNMAX+1) continue; /* was OK */ + carry++; + *c-=DECDPUNMAX+1; + #elif DECDPUN==3 + if (carry>=0) { + est=(((ueInt)carry>>3)*16777)>>21; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ + carry=est; /* likely quotient [99%] */ + if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ + carry++; + *c-=DECDPUNMAX+1; + continue; + } + /* negative case */ + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ + est=(((ueInt)carry>>3)*16777)>>21; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); /* correctly negative */ + if (*c<DECDPUNMAX+1) continue; /* was OK */ + carry++; + *c-=DECDPUNMAX+1; + #elif DECDPUN<=2 + /* Can use QUOT10 as carry <= 4 digits */ + if (carry>=0) { + est=QUOT10(carry, DECDPUN); + *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ + carry=est; /* quotient */ + continue; + } + /* negative case */ + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ + est=QUOT10(carry, DECDPUN); + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); /* correctly negative */ + #else + /* remainder operator is undefined if negative, so must test */ + if ((ueInt)carry<(DECDPUNMAX+1)*2) { /* fastpath carry +1 */ + *c=(Unit)(carry-(DECDPUNMAX+1)); /* [helps additions] */ + carry=1; + continue; + } + if (carry>=0) { + *c=(Unit)(carry%(DECDPUNMAX+1)); + carry=carry/(DECDPUNMAX+1); + continue; + } + /* negative case */ + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ + *c=(Unit)(carry%(DECDPUNMAX+1)); + carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1); + #endif + } /* c */ + + /* now may have one or other to complete */ + /* [pretest to avoid loop setup/shutdown] */ + if (c<maxC) for (; c<maxC; c++) { + if (a<alsu+alength) { /* still in A */ + carry+=*a; + a++; + } + else { /* inside B */ + carry+=((eInt)*b)*m; + b++; + } + /* here carry is new Unit of digits; it could be +ve or -ve and */ + /* magnitude up to DECDPUNMAX squared */ + if ((ueInt)carry<=DECDPUNMAX) { /* fastpath 0-DECDPUNMAX */ + *c=(Unit)carry; + carry=0; + continue; + } + /* result for this unit is negative or >DECDPUNMAX */ + #if DECDPUN==4 /* use divide-by-multiply */ + if (carry>=0) { + est=(((ueInt)carry>>11)*53687)>>18; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ + carry=est; /* likely quotient [79.7%] */ + if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ + carry++; + *c-=DECDPUNMAX+1; + continue; + } + /* negative case */ + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ + est=(((ueInt)carry>>11)*53687)>>18; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); /* correctly negative */ + if (*c<DECDPUNMAX+1) continue; /* was OK */ + carry++; + *c-=DECDPUNMAX+1; + #elif DECDPUN==3 + if (carry>=0) { + est=(((ueInt)carry>>3)*16777)>>21; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ + carry=est; /* likely quotient [99%] */ + if (*c<DECDPUNMAX+1) continue; /* estimate was correct */ + carry++; + *c-=DECDPUNMAX+1; + continue; + } + /* negative case */ + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ + est=(((ueInt)carry>>3)*16777)>>21; + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); /* correctly negative */ + if (*c<DECDPUNMAX+1) continue; /* was OK */ + carry++; + *c-=DECDPUNMAX+1; + #elif DECDPUN<=2 + if (carry>=0) { + est=QUOT10(carry, DECDPUN); + *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */ + carry=est; /* quotient */ + continue; + } + /* negative case */ + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ + est=QUOT10(carry, DECDPUN); + *c=(Unit)(carry-est*(DECDPUNMAX+1)); + carry=est-(DECDPUNMAX+1); /* correctly negative */ + #else + if ((ueInt)carry<(DECDPUNMAX+1)*2){ /* fastpath carry 1 */ + *c=(Unit)(carry-(DECDPUNMAX+1)); + carry=1; + continue; + } + /* remainder operator is undefined if negative, so must test */ + if (carry>=0) { + *c=(Unit)(carry%(DECDPUNMAX+1)); + carry=carry/(DECDPUNMAX+1); + continue; + } + /* negative case */ + carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */ + *c=(Unit)(carry%(DECDPUNMAX+1)); + carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1); + #endif + } /* c */ + + /* OK, all A and B processed; might still have carry or borrow */ + /* return number of Units in the result, negated if a borrow */ + if (carry==0) return c-clsu; /* no carry, so no more to do */ + if (carry>0) { /* positive carry */ + *c=(Unit)carry; /* place as new unit */ + c++; /* .. */ + return c-clsu; + } + /* -ve carry: it's a borrow; complement needed */ + add=1; /* temporary carry... */ + for (c=clsu; c<maxC; c++) { + add=DECDPUNMAX+add-*c; + if (add<=DECDPUNMAX) { + *c=(Unit)add; + add=0; + } + else { + *c=0; + add=1; + } + } + /* add an extra unit iff it would be non-zero */ + #if DECTRACE + printf("UAS borrow: add %ld, carry %ld\n", add, carry); + #endif + if ((add-carry-1)!=0) { + *c=(Unit)(add-carry-1); + c++; /* interesting, include it */ + } + return clsu-c; /* -ve result indicates borrowed */ + } /* decUnitAddSub */ + +/* ------------------------------------------------------------------ */ +/* decTrim -- trim trailing zeros or normalize */ +/* */ +/* dn is the number to trim or normalize */ +/* set is the context to use to check for clamp */ +/* all is 1 to remove all trailing zeros, 0 for just fraction ones */ +/* dropped returns the number of discarded trailing zeros */ +/* returns dn */ +/* */ +/* If clamp is set in the context then the number of zeros trimmed */ +/* may be limited if the exponent is high. */ +/* All fields are updated as required. This is a utility operation, */ +/* so special values are unchanged and no error is possible. */ +/* ------------------------------------------------------------------ */ +static decNumber * decTrim(decNumber *dn, decContext *set, Flag all, + Int *dropped) { + Int d, exp; /* work */ + uInt cut; /* .. */ + Unit *up; /* -> current Unit */ + + #if DECCHECK + if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn; + #endif + + *dropped=0; /* assume no zeros dropped */ + if ((dn->bits & DECSPECIAL) /* fast exit if special .. */ + || (*dn->lsu & 0x01)) return dn; /* .. or odd */ + if (ISZERO(dn)) { /* .. or 0 */ + dn->exponent=0; /* (sign is preserved) */ + return dn; + } + + /* have a finite number which is even */ + exp=dn->exponent; + cut=1; /* digit (1-DECDPUN) in Unit */ + up=dn->lsu; /* -> current Unit */ + for (d=0; d<dn->digits-1; d++) { /* [don't strip the final digit] */ + /* slice by powers */ + #if DECDPUN<=4 + uInt quot=QUOT10(*up, cut); + if ((*up-quot*powers[cut])!=0) break; /* found non-0 digit */ + #else + if (*up%powers[cut]!=0) break; /* found non-0 digit */ + #endif + /* have a trailing 0 */ + if (!all) { /* trimming */ + /* [if exp>0 then all trailing 0s are significant for trim] */ + if (exp<=0) { /* if digit might be significant */ + if (exp==0) break; /* then quit */ + exp++; /* next digit might be significant */ + } + } + cut++; /* next power */ + if (cut>DECDPUN) { /* need new Unit */ + up++; + cut=1; + } + } /* d */ + if (d==0) return dn; /* none to drop */ + + /* may need to limit drop if clamping */ + if (set->clamp) { + Int maxd=set->emax-set->digits+1-dn->exponent; + if (maxd<=0) return dn; /* nothing possible */ + if (d>maxd) d=maxd; + } + + /* effect the drop */ + decShiftToLeast(dn->lsu, D2U(dn->digits), d); + dn->exponent+=d; /* maintain numerical value */ + dn->digits-=d; /* new length */ + *dropped=d; /* report the count */ + return dn; + } /* decTrim */ + +/* ------------------------------------------------------------------ */ +/* decReverse -- reverse a Unit array in place */ +/* */ +/* ulo is the start of the array */ +/* uhi is the end of the array (highest Unit to include) */ +/* */ +/* The units ulo through uhi are reversed in place (if the number */ +/* of units is odd, the middle one is untouched). Note that the */ +/* digit(s) in each unit are unaffected. */ +/* ------------------------------------------------------------------ */ +static void decReverse(Unit *ulo, Unit *uhi) { + Unit temp; + for (; ulo<uhi; ulo++, uhi--) { + temp=*ulo; + *ulo=*uhi; + *uhi=temp; + } + return; + } /* decReverse */ + +/* ------------------------------------------------------------------ */ +/* decShiftToMost -- shift digits in array towards most significant */ +/* */ +/* uar is the array */ +/* digits is the count of digits in use in the array */ +/* shift is the number of zeros to pad with (least significant); */ +/* it must be zero or positive */ +/* */ +/* returns the new length of the integer in the array, in digits */ +/* */ +/* No overflow is permitted (that is, the uar array must be known to */ +/* be large enough to hold the result, after shifting). */ +/* ------------------------------------------------------------------ */ +static Int decShiftToMost(Unit *uar, Int digits, Int shift) { + Unit *target, *source, *first; /* work */ + Int cut; /* odd 0's to add */ + uInt next; /* work */ + + if (shift==0) return digits; /* [fastpath] nothing to do */ + if ((digits+shift)<=DECDPUN) { /* [fastpath] single-unit case */ + *uar=(Unit)(*uar*powers[shift]); + return digits+shift; + } + + next=0; /* all paths */ + source=uar+D2U(digits)-1; /* where msu comes from */ + target=source+D2U(shift); /* where upper part of first cut goes */ + cut=DECDPUN-MSUDIGITS(shift); /* where to slice */ + if (cut==0) { /* unit-boundary case */ + for (; source>=uar; source--, target--) *target=*source; + } + else { + first=uar+D2U(digits+shift)-1; /* where msu of source will end up */ + for (; source>=uar; source--, target--) { + /* split the source Unit and accumulate remainder for next */ + #if DECDPUN<=4 + uInt quot=QUOT10(*source, cut); + uInt rem=*source-quot*powers[cut]; + next+=quot; + #else + uInt rem=*source%powers[cut]; + next+=*source/powers[cut]; + #endif + if (target<=first) *target=(Unit)next; /* write to target iff valid */ + next=rem*powers[DECDPUN-cut]; /* save remainder for next Unit */ + } + } /* shift-move */ + + /* propagate any partial unit to one below and clear the rest */ + for (; target>=uar; target--) { + *target=(Unit)next; + next=0; + } + return digits+shift; + } /* decShiftToMost */ + +/* ------------------------------------------------------------------ */ +/* decShiftToLeast -- shift digits in array towards least significant */ +/* */ +/* uar is the array */ +/* units is length of the array, in units */ +/* shift is the number of digits to remove from the lsu end; it */ +/* must be zero or positive and <= than units*DECDPUN. */ +/* */ +/* returns the new length of the integer in the array, in units */ +/* */ +/* Removed digits are discarded (lost). Units not required to hold */ +/* the final result are unchanged. */ +/* ------------------------------------------------------------------ */ +static Int decShiftToLeast(Unit *uar, Int units, Int shift) { + Unit *target, *up; /* work */ + Int cut, count; /* work */ + Int quot, rem; /* for division */ + + if (shift==0) return units; /* [fastpath] nothing to do */ + if (shift==units*DECDPUN) { /* [fastpath] little to do */ + *uar=0; /* all digits cleared gives zero */ + return 1; /* leaves just the one */ + } + + target=uar; /* both paths */ + cut=MSUDIGITS(shift); + if (cut==DECDPUN) { /* unit-boundary case; easy */ + up=uar+D2U(shift); + for (; up<uar+units; target++, up++) *target=*up; + return target-uar; + } + + /* messier */ + up=uar+D2U(shift-cut); /* source; correct to whole Units */ + count=units*DECDPUN-shift; /* the maximum new length */ + #if DECDPUN<=4 + quot=QUOT10(*up, cut); + #else + quot=*up/powers[cut]; + #endif + for (; ; target++) { + *target=(Unit)quot; + count-=(DECDPUN-cut); + if (count<=0) break; + up++; + quot=*up; + #if DECDPUN<=4 + quot=QUOT10(quot, cut); + rem=*up-quot*powers[cut]; + #else + rem=quot%powers[cut]; + quot=quot/powers[cut]; + #endif + *target=(Unit)(*target+rem*powers[DECDPUN-cut]); + count-=cut; + if (count<=0) break; + } + return target-uar+1; + } /* decShiftToLeast */ + +#if DECSUBSET +/* ------------------------------------------------------------------ */ +/* decRoundOperand -- round an operand [used for subset only] */ +/* */ +/* dn is the number to round (dn->digits is > set->digits) */ +/* set is the relevant context */ +/* status is the status accumulator */ +/* */ +/* returns an allocated decNumber with the rounded result. */ +/* */ +/* lostDigits and other status may be set by this. */ +/* */ +/* Since the input is an operand, it must not be modified. */ +/* Instead, return an allocated decNumber, rounded as required. */ +/* It is the caller's responsibility to free the allocated storage. */ +/* */ +/* If no storage is available then the result cannot be used, so NULL */ +/* is returned. */ +/* ------------------------------------------------------------------ */ +static decNumber *decRoundOperand(const decNumber *dn, decContext *set, + uInt *status) { + decNumber *res; /* result structure */ + uInt newstatus=0; /* status from round */ + Int residue=0; /* rounding accumulator */ + + /* Allocate storage for the returned decNumber, big enough for the */ + /* length specified by the context */ + res=(decNumber *)malloc(sizeof(decNumber) + +(D2U(set->digits)-1)*sizeof(Unit)); + if (res==NULL) { + *status|=DEC_Insufficient_storage; + return NULL; + } + decCopyFit(res, dn, set, &residue, &newstatus); + decApplyRound(res, set, residue, &newstatus); + + /* If that set Inexact then "lost digits" is raised... */ + if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits; + *status|=newstatus; + return res; + } /* decRoundOperand */ +#endif + +/* ------------------------------------------------------------------ */ +/* decCopyFit -- copy a number, truncating the coefficient if needed */ +/* */ +/* dest is the target decNumber */ +/* src is the source decNumber */ +/* set is the context [used for length (digits) and rounding mode] */ +/* residue is the residue accumulator */ +/* status contains the current status to be updated */ +/* */ +/* (dest==src is allowed and will be a no-op if fits) */ +/* All fields are updated as required. */ +/* ------------------------------------------------------------------ */ +static void decCopyFit(decNumber *dest, const decNumber *src, + decContext *set, Int *residue, uInt *status) { + dest->bits=src->bits; + dest->exponent=src->exponent; + decSetCoeff(dest, set, src->lsu, src->digits, residue, status); + } /* decCopyFit */ + +/* ------------------------------------------------------------------ */ +/* decSetCoeff -- set the coefficient of a number */ +/* */ +/* dn is the number whose coefficient array is to be set. */ +/* It must have space for set->digits digits */ +/* set is the context [for size] */ +/* lsu -> lsu of the source coefficient [may be dn->lsu] */ +/* len is digits in the source coefficient [may be dn->digits] */ +/* residue is the residue accumulator. This has values as in */ +/* decApplyRound, and will be unchanged unless the */ +/* target size is less than len. In this case, the */ +/* coefficient is truncated and the residue is updated to */ +/* reflect the previous residue and the dropped digits. */ +/* status is the status accumulator, as usual */ +/* */ +/* The coefficient may already be in the number, or it can be an */ +/* external intermediate array. If it is in the number, lsu must == */ +/* dn->lsu and len must == dn->digits. */ +/* */ +/* Note that the coefficient length (len) may be < set->digits, and */ +/* in this case this merely copies the coefficient (or is a no-op */ +/* if dn->lsu==lsu). */ +/* */ +/* Note also that (only internally, from decQuantizeOp and */ +/* decSetSubnormal) the value of set->digits may be less than one, */ +/* indicating a round to left. This routine handles that case */ +/* correctly; caller ensures space. */ +/* */ +/* dn->digits, dn->lsu (and as required), and dn->exponent are */ +/* updated as necessary. dn->bits (sign) is unchanged. */ +/* */ +/* DEC_Rounded status is set if any digits are discarded. */ +/* DEC_Inexact status is set if any non-zero digits are discarded, or */ +/* incoming residue was non-0 (implies rounded) */ +/* ------------------------------------------------------------------ */ +/* mapping array: maps 0-9 to canonical residues, so that a residue */ +/* can be adjusted in the range [-1, +1] and achieve correct rounding */ +/* 0 1 2 3 4 5 6 7 8 9 */ +static const uByte resmap[10]={0, 3, 3, 3, 3, 5, 7, 7, 7, 7}; +static void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu, + Int len, Int *residue, uInt *status) { + Int discard; /* number of digits to discard */ + uInt cut; /* cut point in Unit */ + const Unit *up; /* work */ + Unit *target; /* .. */ + Int count; /* .. */ + #if DECDPUN<=4 + uInt temp; /* .. */ + #endif + + discard=len-set->digits; /* digits to discard */ + if (discard<=0) { /* no digits are being discarded */ + if (dn->lsu!=lsu) { /* copy needed */ + /* copy the coefficient array to the result number; no shift needed */ + count=len; /* avoids D2U */ + up=lsu; + for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN) + *target=*up; + dn->digits=len; /* set the new length */ + } + /* dn->exponent and residue are unchanged, record any inexactitude */ + if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded); + return; + } + + /* some digits must be discarded ... */ + dn->exponent+=discard; /* maintain numerical value */ + *status|=DEC_Rounded; /* accumulate Rounded status */ + if (*residue>1) *residue=1; /* previous residue now to right, so reduce */ + + if (discard>len) { /* everything, +1, is being discarded */ + /* guard digit is 0 */ + /* residue is all the number [NB could be all 0s] */ + if (*residue<=0) { /* not already positive */ + count=len; /* avoids D2U */ + for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { /* found non-0 */ + *residue=1; + break; /* no need to check any others */ + } + } + if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */ + *dn->lsu=0; /* coefficient will now be 0 */ + dn->digits=1; /* .. */ + return; + } /* total discard */ + + /* partial discard [most common case] */ + /* here, at least the first (most significant) discarded digit exists */ + + /* spin up the number, noting residue during the spin, until get to */ + /* the Unit with the first discarded digit. When reach it, extract */ + /* it and remember its position */ + count=0; + for (up=lsu;; up++) { + count+=DECDPUN; + if (count>=discard) break; /* full ones all checked */ + if (*up!=0) *residue=1; + } /* up */ + + /* here up -> Unit with first discarded digit */ + cut=discard-(count-DECDPUN)-1; + if (cut==DECDPUN-1) { /* unit-boundary case (fast) */ + Unit half=(Unit)powers[DECDPUN]>>1; + /* set residue directly */ + if (*up>=half) { + if (*up>half) *residue=7; + else *residue+=5; /* add sticky bit */ + } + else { /* <half */ + if (*up!=0) *residue=3; /* [else is 0, leave as sticky bit] */ + } + if (set->digits<=0) { /* special for Quantize/Subnormal :-( */ + *dn->lsu=0; /* .. result is 0 */ + dn->digits=1; /* .. */ + } + else { /* shift to least */ + count=set->digits; /* now digits to end up with */ + dn->digits=count; /* set the new length */ + up++; /* move to next */ + /* on unit boundary, so shift-down copy loop is simple */ + for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN) + *target=*up; + } + } /* unit-boundary case */ + + else { /* discard digit is in low digit(s), and not top digit */ + uInt discard1; /* first discarded digit */ + uInt quot, rem; /* for divisions */ + if (cut==0) quot=*up; /* is at bottom of unit */ + else /* cut>0 */ { /* it's not at bottom of unit */ + #if DECDPUN<=4 + quot=QUOT10(*up, cut); + rem=*up-quot*powers[cut]; + #else + rem=*up%powers[cut]; + quot=*up/powers[cut]; + #endif + if (rem!=0) *residue=1; + } + /* discard digit is now at bottom of quot */ + #if DECDPUN<=4 + temp=(quot*6554)>>16; /* fast /10 */ + /* Vowels algorithm here not a win (9 instructions) */ + discard1=quot-X10(temp); + quot=temp; + #else + discard1=quot%10; + quot=quot/10; + #endif + /* here, discard1 is the guard digit, and residue is everything */ + /* else [use mapping array to accumulate residue safely] */ + *residue+=resmap[discard1]; + cut++; /* update cut */ + /* here: up -> Unit of the array with bottom digit */ + /* cut is the division point for each Unit */ + /* quot holds the uncut high-order digits for the current unit */ + if (set->digits<=0) { /* special for Quantize/Subnormal :-( */ + *dn->lsu=0; /* .. result is 0 */ + dn->digits=1; /* .. */ + } + else { /* shift to least needed */ + count=set->digits; /* now digits to end up with */ + dn->digits=count; /* set the new length */ + /* shift-copy the coefficient array to the result number */ + for (target=dn->lsu; ; target++) { + *target=(Unit)quot; + count-=(DECDPUN-cut); + if (count<=0) break; + up++; + quot=*up; + #if DECDPUN<=4 + quot=QUOT10(quot, cut); + rem=*up-quot*powers[cut]; + #else + rem=quot%powers[cut]; + quot=quot/powers[cut]; + #endif + *target=(Unit)(*target+rem*powers[DECDPUN-cut]); + count-=cut; + if (count<=0) break; + } /* shift-copy loop */ + } /* shift to least */ + } /* not unit boundary */ + + if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */ + return; + } /* decSetCoeff */ + +/* ------------------------------------------------------------------ */ +/* decApplyRound -- apply pending rounding to a number */ +/* */ +/* dn is the number, with space for set->digits digits */ +/* set is the context [for size and rounding mode] */ +/* residue indicates pending rounding, being any accumulated */ +/* guard and sticky information. It may be: */ +/* 6-9: rounding digit is >5 */ +/* 5: rounding digit is exactly half-way */ +/* 1-4: rounding digit is <5 and >0 */ +/* 0: the coefficient is exact */ +/* -1: as 1, but the hidden digits are subtractive, that */ +/* is, of the opposite sign to dn. In this case the */ +/* coefficient must be non-0. This case occurs when */ +/* subtracting a small number (which can be reduced to */ +/* a sticky bit); see decAddOp. */ +/* status is the status accumulator, as usual */ +/* */ +/* This routine applies rounding while keeping the length of the */ +/* coefficient constant. The exponent and status are unchanged */ +/* except if: */ +/* */ +/* -- the coefficient was increased and is all nines (in which */ +/* case Overflow could occur, and is handled directly here so */ +/* the caller does not need to re-test for overflow) */ +/* */ +/* -- the coefficient was decreased and becomes all nines (in which */ +/* case Underflow could occur, and is also handled directly). */ +/* */ +/* All fields in dn are updated as required. */ +/* */ +/* ------------------------------------------------------------------ */ +static void decApplyRound(decNumber *dn, decContext *set, Int residue, + uInt *status) { + Int bump; /* 1 if coefficient needs to be incremented */ + /* -1 if coefficient needs to be decremented */ + + if (residue==0) return; /* nothing to apply */ + + bump=0; /* assume a smooth ride */ + + /* now decide whether, and how, to round, depending on mode */ + switch (set->round) { + case DEC_ROUND_05UP: { /* round zero or five up (for reround) */ + /* This is the same as DEC_ROUND_DOWN unless there is a */ + /* positive residue and the lsd of dn is 0 or 5, in which case */ + /* it is bumped; when residue is <0, the number is therefore */ + /* bumped down unless the final digit was 1 or 6 (in which */ + /* case it is bumped down and then up -- a no-op) */ + Int lsd5=*dn->lsu%5; /* get lsd and quintate */ + if (residue<0 && lsd5!=1) bump=-1; + else if (residue>0 && lsd5==0) bump=1; + /* [bump==1 could be applied directly; use common path for clarity] */ + break;} /* r-05 */ + + case DEC_ROUND_DOWN: { + /* no change, except if negative residue */ + if (residue<0) bump=-1; + break;} /* r-d */ + + case DEC_ROUND_HALF_DOWN: { + if (residue>5) bump=1; + break;} /* r-h-d */ + + case DEC_ROUND_HALF_EVEN: { + if (residue>5) bump=1; /* >0.5 goes up */ + else if (residue==5) { /* exactly 0.5000... */ + /* 0.5 goes up iff [new] lsd is odd */ + if (*dn->lsu & 0x01) bump=1; + } + break;} /* r-h-e */ + + case DEC_ROUND_HALF_UP: { + if (residue>=5) bump=1; + break;} /* r-h-u */ + + case DEC_ROUND_UP: { + if (residue>0) bump=1; + break;} /* r-u */ + + case DEC_ROUND_CEILING: { + /* same as _UP for positive numbers, and as _DOWN for negatives */ + /* [negative residue cannot occur on 0] */ + if (decNumberIsNegative(dn)) { + if (residue<0) bump=-1; + } + else { + if (residue>0) bump=1; + } + break;} /* r-c */ + + case DEC_ROUND_FLOOR: { + /* same as _UP for negative numbers, and as _DOWN for positive */ + /* [negative residue cannot occur on 0] */ + if (!decNumberIsNegative(dn)) { + if (residue<0) bump=-1; + } + else { + if (residue>0) bump=1; + } + break;} /* r-f */ + + default: { /* e.g., DEC_ROUND_MAX */ + *status|=DEC_Invalid_context; + #if DECTRACE || (DECCHECK && DECVERB) + printf("Unknown rounding mode: %d\n", set->round); + #endif + break;} + } /* switch */ + + /* now bump the number, up or down, if need be */ + if (bump==0) return; /* no action required */ + + /* Simply use decUnitAddSub unless bumping up and the number is */ + /* all nines. In this special case set to 100... explicitly */ + /* and adjust the exponent by one (as otherwise could overflow */ + /* the array) */ + /* Similarly handle all-nines result if bumping down. */ + if (bump>0) { + Unit *up; /* work */ + uInt count=dn->digits; /* digits to be checked */ + for (up=dn->lsu; ; up++) { + if (count<=DECDPUN) { + /* this is the last Unit (the msu) */ + if (*up!=powers[count]-1) break; /* not still 9s */ + /* here if it, too, is all nines */ + *up=(Unit)powers[count-1]; /* here 999 -> 100 etc. */ + for (up=up-1; up>=dn->lsu; up--) *up=0; /* others all to 0 */ + dn->exponent++; /* and bump exponent */ + /* [which, very rarely, could cause Overflow...] */ + if ((dn->exponent+dn->digits)>set->emax+1) { + decSetOverflow(dn, set, status); + } + return; /* done */ + } + /* a full unit to check, with more to come */ + if (*up!=DECDPUNMAX) break; /* not still 9s */ + count-=DECDPUN; + } /* up */ + } /* bump>0 */ + else { /* -1 */ + /* here checking for a pre-bump of 1000... (leading 1, all */ + /* other digits zero) */ + Unit *up, *sup; /* work */ + uInt count=dn->digits; /* digits to be checked */ + for (up=dn->lsu; ; up++) { + if (count<=DECDPUN) { + /* this is the last Unit (the msu) */ + if (*up!=powers[count-1]) break; /* not 100.. */ + /* here if have the 1000... case */ + sup=up; /* save msu pointer */ + *up=(Unit)powers[count]-1; /* here 100 in msu -> 999 */ + /* others all to all-nines, too */ + for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1; + dn->exponent--; /* and bump exponent */ + + /* iff the number was at the subnormal boundary (exponent=etiny) */ + /* then the exponent is now out of range, so it will in fact get */ + /* clamped to etiny and the final 9 dropped. */ + /* printf(">> emin=%d exp=%d sdig=%d\n", set->emin, */ + /* dn->exponent, set->digits); */ + if (dn->exponent+1==set->emin-set->digits+1) { + if (count==1 && dn->digits==1) *sup=0; /* here 9 -> 0[.9] */ + else { + *sup=(Unit)powers[count-1]-1; /* here 999.. in msu -> 99.. */ + dn->digits--; + } + dn->exponent++; + *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded; + } + return; /* done */ + } + + /* a full unit to check, with more to come */ + if (*up!=0) break; /* not still 0s */ + count-=DECDPUN; + } /* up */ + + } /* bump<0 */ + + /* Actual bump needed. Do it. */ + decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump); + } /* decApplyRound */ + +#if DECSUBSET +/* ------------------------------------------------------------------ */ +/* decFinish -- finish processing a number */ +/* */ +/* dn is the number */ +/* set is the context */ +/* residue is the rounding accumulator (as in decApplyRound) */ +/* status is the accumulator */ +/* */ +/* This finishes off the current number by: */ +/* 1. If not extended: */ +/* a. Converting a zero result to clean '0' */ +/* b. Reducing positive exponents to 0, if would fit in digits */ +/* 2. Checking for overflow and subnormals (always) */ +/* Note this is just Finalize when no subset arithmetic. */ +/* All fields are updated as required. */ +/* ------------------------------------------------------------------ */ +static void decFinish(decNumber *dn, decContext *set, Int *residue, + uInt *status) { + if (!set->extended) { + if ISZERO(dn) { /* value is zero */ + dn->exponent=0; /* clean exponent .. */ + dn->bits=0; /* .. and sign */ + return; /* no error possible */ + } + if (dn->exponent>=0) { /* non-negative exponent */ + /* >0; reduce to integer if possible */ + if (set->digits >= (dn->exponent+dn->digits)) { + dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent); + dn->exponent=0; + } + } + } /* !extended */ + + decFinalize(dn, set, residue, status); + } /* decFinish */ +#endif + +/* ------------------------------------------------------------------ */ +/* decFinalize -- final check, clamp, and round of a number */ +/* */ +/* dn is the number */ +/* set is the context */ +/* residue is the rounding accumulator (as in decApplyRound) */ +/* status is the status accumulator */ +/* */ +/* This finishes off the current number by checking for subnormal */ +/* results, applying any pending rounding, checking for overflow, */ +/* and applying any clamping. */ +/* Underflow and overflow conditions are raised as appropriate. */ +/* All fields are updated as required. */ +/* ------------------------------------------------------------------ */ +static void decFinalize(decNumber *dn, decContext *set, Int *residue, + uInt *status) { + Int shift; /* shift needed if clamping */ + Int tinyexp=set->emin-dn->digits+1; /* precalculate subnormal boundary */ + + /* Must be careful, here, when checking the exponent as the */ + /* adjusted exponent could overflow 31 bits [because it may already */ + /* be up to twice the expected]. */ + + /* First test for subnormal. This must be done before any final */ + /* round as the result could be rounded to Nmin or 0. */ + if (dn->exponent<=tinyexp) { /* prefilter */ + Int comp; + decNumber nmin; + /* A very nasty case here is dn == Nmin and residue<0 */ + if (dn->exponent<tinyexp) { + /* Go handle subnormals; this will apply round if needed. */ + decSetSubnormal(dn, set, residue, status); + return; + } + /* Equals case: only subnormal if dn=Nmin and negative residue */ + decNumberZero(&nmin); + nmin.lsu[0]=1; + nmin.exponent=set->emin; + comp=decCompare(dn, &nmin, 1); /* (signless compare) */ + if (comp==BADINT) { /* oops */ + *status|=DEC_Insufficient_storage; /* abandon... */ + return; + } + if (*residue<0 && comp==0) { /* neg residue and dn==Nmin */ + decApplyRound(dn, set, *residue, status); /* might force down */ + decSetSubnormal(dn, set, residue, status); + return; + } + } + + /* now apply any pending round (this could raise overflow). */ + if (*residue!=0) decApplyRound(dn, set, *residue, status); + + /* Check for overflow [redundant in the 'rare' case] or clamp */ + if (dn->exponent<=set->emax-set->digits+1) return; /* neither needed */ + + + /* here when might have an overflow or clamp to do */ + if (dn->exponent>set->emax-dn->digits+1) { /* too big */ + decSetOverflow(dn, set, status); + return; + } + /* here when the result is normal but in clamp range */ + if (!set->clamp) return; + + /* here when need to apply the IEEE exponent clamp (fold-down) */ + shift=dn->exponent-(set->emax-set->digits+1); + + /* shift coefficient (if non-zero) */ + if (!ISZERO(dn)) { + dn->digits=decShiftToMost(dn->lsu, dn->digits, shift); + } + dn->exponent-=shift; /* adjust the exponent to match */ + *status|=DEC_Clamped; /* and record the dirty deed */ + return; + } /* decFinalize */ + +/* ------------------------------------------------------------------ */ +/* decSetOverflow -- set number to proper overflow value */ +/* */ +/* dn is the number (used for sign [only] and result) */ +/* set is the context [used for the rounding mode, etc.] */ +/* status contains the current status to be updated */ +/* */ +/* This sets the sign of a number and sets its value to either */ +/* Infinity or the maximum finite value, depending on the sign of */ +/* dn and the rounding mode, following IEEE 854 rules. */ +/* ------------------------------------------------------------------ */ +static void decSetOverflow(decNumber *dn, decContext *set, uInt *status) { + Flag needmax=0; /* result is maximum finite value */ + uByte sign=dn->bits&DECNEG; /* clean and save sign bit */ + + if (ISZERO(dn)) { /* zero does not overflow magnitude */ + Int emax=set->emax; /* limit value */ + if (set->clamp) emax-=set->digits-1; /* lower if clamping */ + if (dn->exponent>emax) { /* clamp required */ + dn->exponent=emax; + *status|=DEC_Clamped; + } + return; + } + + decNumberZero(dn); + switch (set->round) { + case DEC_ROUND_DOWN: { + needmax=1; /* never Infinity */ + break;} /* r-d */ + case DEC_ROUND_05UP: { + needmax=1; /* never Infinity */ + break;} /* r-05 */ + case DEC_ROUND_CEILING: { + if (sign) needmax=1; /* Infinity if non-negative */ + break;} /* r-c */ + case DEC_ROUND_FLOOR: { + if (!sign) needmax=1; /* Infinity if negative */ + break;} /* r-f */ + default: break; /* Infinity in all other cases */ + } + if (needmax) { + decSetMaxValue(dn, set); + dn->bits=sign; /* set sign */ + } + else dn->bits=sign|DECINF; /* Value is +/-Infinity */ + *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded; + } /* decSetOverflow */ + +/* ------------------------------------------------------------------ */ +/* decSetMaxValue -- set number to +Nmax (maximum normal value) */ +/* */ +/* dn is the number to set */ +/* set is the context [used for digits and emax] */ +/* */ +/* This sets the number to the maximum positive value. */ +/* ------------------------------------------------------------------ */ +static void decSetMaxValue(decNumber *dn, decContext *set) { + Unit *up; /* work */ + Int count=set->digits; /* nines to add */ + dn->digits=count; + /* fill in all nines to set maximum value */ + for (up=dn->lsu; ; up++) { + if (count>DECDPUN) *up=DECDPUNMAX; /* unit full o'nines */ + else { /* this is the msu */ + *up=(Unit)(powers[count]-1); + break; + } + count-=DECDPUN; /* filled those digits */ + } /* up */ + dn->bits=0; /* + sign */ + dn->exponent=set->emax-set->digits+1; + } /* decSetMaxValue */ + +/* ------------------------------------------------------------------ */ +/* decSetSubnormal -- process value whose exponent is <Emin */ +/* */ +/* dn is the number (used as input as well as output; it may have */ +/* an allowed subnormal value, which may need to be rounded) */ +/* set is the context [used for the rounding mode] */ +/* residue is any pending residue */ +/* status contains the current status to be updated */ +/* */ +/* If subset mode, set result to zero and set Underflow flags. */ +/* */ +/* Value may be zero with a low exponent; this does not set Subnormal */ +/* but the exponent will be clamped to Etiny. */ +/* */ +/* Otherwise ensure exponent is not out of range, and round as */ +/* necessary. Underflow is set if the result is Inexact. */ +/* ------------------------------------------------------------------ */ +static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue, + uInt *status) { + Int dnexp; /* saves original exponent */ + decContext workset; /* work */ + Int etiny, adjust; /* .. */ + + #if DECSUBSET + /* simple set to zero and 'hard underflow' for subset */ + if (!set->extended) { + decNumberZero(dn); + /* always full overflow */ + *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded; + return; + } + #endif + + /* Full arithmetic -- allow subnormals, rounded to minimum exponent */ + /* (Etiny) if needed */ + etiny=set->emin-(set->digits-1); /* smallest allowed exponent */ + + if ISZERO(dn) { /* value is zero */ + /* residue can never be non-zero here */ + #if DECCHECK + if (*residue!=0) { + printf("++ Subnormal 0 residue %ld\n", (LI)*residue); + *status|=DEC_Invalid_operation; + } + #endif + if (dn->exponent<etiny) { /* clamp required */ + dn->exponent=etiny; + *status|=DEC_Clamped; + } + return; + } + + *status|=DEC_Subnormal; /* have a non-zero subnormal */ + adjust=etiny-dn->exponent; /* calculate digits to remove */ + if (adjust<=0) { /* not out of range; unrounded */ + /* residue can never be non-zero here, except in the Nmin-residue */ + /* case (which is a subnormal result), so can take fast-path here */ + /* it may already be inexact (from setting the coefficient) */ + if (*status&DEC_Inexact) *status|=DEC_Underflow; + return; + } + + /* adjust>0, so need to rescale the result so exponent becomes Etiny */ + /* [this code is similar to that in rescale] */ + dnexp=dn->exponent; /* save exponent */ + workset=*set; /* clone rounding, etc. */ + workset.digits=dn->digits-adjust; /* set requested length */ + workset.emin-=adjust; /* and adjust emin to match */ + /* [note that the latter can be <1, here, similar to Rescale case] */ + decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status); + decApplyRound(dn, &workset, *residue, status); + + /* Use 754R/854 default rule: Underflow is set iff Inexact */ + /* [independent of whether trapped] */ + if (*status&DEC_Inexact) *status|=DEC_Underflow; + + /* if rounded up a 999s case, exponent will be off by one; adjust */ + /* back if so [it will fit, because it was shortened earlier] */ + if (dn->exponent>etiny) { + dn->digits=decShiftToMost(dn->lsu, dn->digits, 1); + dn->exponent--; /* (re)adjust the exponent. */ + } + + /* if rounded to zero, it is by definition clamped... */ + if (ISZERO(dn)) *status|=DEC_Clamped; + } /* decSetSubnormal */ + +/* ------------------------------------------------------------------ */ +/* decCheckMath - check entry conditions for a math function */ +/* */ +/* This checks the context and the operand */ +/* */ +/* rhs is the operand to check */ +/* set is the context to check */ +/* status is unchanged if both are good */ +/* */ +/* returns non-zero if status is changed, 0 otherwise */ +/* */ +/* Restrictions enforced: */ +/* */ +/* digits, emax, and -emin in the context must be less than */ +/* DEC_MAX_MATH (999999), and A must be within these bounds if */ +/* non-zero. Invalid_operation is set in the status if a */ +/* restriction is violated. */ +/* ------------------------------------------------------------------ */ +static uInt decCheckMath(const decNumber *rhs, decContext *set, + uInt *status) { + uInt save=*status; /* record */ + if (set->digits>DEC_MAX_MATH + || set->emax>DEC_MAX_MATH + || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context; + else if ((rhs->digits>DEC_MAX_MATH + || rhs->exponent+rhs->digits>DEC_MAX_MATH+1 + || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH)) + && !ISZERO(rhs)) *status|=DEC_Invalid_operation; + return (*status!=save); + } /* decCheckMath */ + +/* ------------------------------------------------------------------ */ +/* decGetInt -- get integer from a number */ +/* */ +/* dn is the number [which will not be altered] */ +/* */ +/* returns one of: */ +/* BADINT if there is a non-zero fraction */ +/* the converted integer */ +/* BIGEVEN if the integer is even and magnitude > 2*10**9 */ +/* BIGODD if the integer is odd and magnitude > 2*10**9 */ +/* */ +/* This checks and gets a whole number from the input decNumber. */ +/* The sign can be determined from dn by the caller when BIGEVEN or */ +/* BIGODD is returned. */ +/* ------------------------------------------------------------------ */ +static Int decGetInt(const decNumber *dn) { + Int theInt; /* result accumulator */ + const Unit *up; /* work */ + Int got; /* digits (real or not) processed */ + Int ilength=dn->digits+dn->exponent; /* integral length */ + Flag neg=decNumberIsNegative(dn); /* 1 if -ve */ + + /* The number must be an integer that fits in 10 digits */ + /* Assert, here, that 10 is enough for any rescale Etiny */ + #if DEC_MAX_EMAX > 999999999 + #error GetInt may need updating [for Emax] + #endif + #if DEC_MIN_EMIN < -999999999 + #error GetInt may need updating [for Emin] + #endif + if (ISZERO(dn)) return 0; /* zeros are OK, with any exponent */ + + up=dn->lsu; /* ready for lsu */ + theInt=0; /* ready to accumulate */ + if (dn->exponent>=0) { /* relatively easy */ + /* no fractional part [usual]; allow for positive exponent */ + got=dn->exponent; + } + else { /* -ve exponent; some fractional part to check and discard */ + Int count=-dn->exponent; /* digits to discard */ + /* spin up whole units until reach the Unit with the unit digit */ + for (; count>=DECDPUN; up++) { + if (*up!=0) return BADINT; /* non-zero Unit to discard */ + count-=DECDPUN; + } + if (count==0) got=0; /* [a multiple of DECDPUN] */ + else { /* [not multiple of DECDPUN] */ + Int rem; /* work */ + /* slice off fraction digits and check for non-zero */ + #if DECDPUN<=4 + theInt=QUOT10(*up, count); + rem=*up-theInt*powers[count]; + #else + rem=*up%powers[count]; /* slice off discards */ + theInt=*up/powers[count]; + #endif + if (rem!=0) return BADINT; /* non-zero fraction */ + /* it looks good */ + got=DECDPUN-count; /* number of digits so far */ + up++; /* ready for next */ + } + } + /* now it's known there's no fractional part */ + + /* tricky code now, to accumulate up to 9.3 digits */ + if (got==0) {theInt=*up; got+=DECDPUN; up++;} /* ensure lsu is there */ + + if (ilength<11) { + Int save=theInt; + /* collect any remaining unit(s) */ + for (; got<ilength; up++) { + theInt+=*up*powers[got]; + got+=DECDPUN; + } + if (ilength==10) { /* need to check for wrap */ + if (theInt/(Int)powers[got-DECDPUN]!=(Int)*(up-1)) ilength=11; + /* [that test also disallows the BADINT result case] */ + else if (neg && theInt>1999999997) ilength=11; + else if (!neg && theInt>999999999) ilength=11; + if (ilength==11) theInt=save; /* restore correct low bit */ + } + } + + if (ilength>10) { /* too big */ + if (theInt&1) return BIGODD; /* bottom bit 1 */ + return BIGEVEN; /* bottom bit 0 */ + } + + if (neg) theInt=-theInt; /* apply sign */ + return theInt; + } /* decGetInt */ + +/* ------------------------------------------------------------------ */ +/* decDecap -- decapitate the coefficient of a number */ +/* */ +/* dn is the number to be decapitated */ +/* drop is the number of digits to be removed from the left of dn; */ +/* this must be <= dn->digits (if equal, the coefficient is */ +/* set to 0) */ +/* */ +/* Returns dn; dn->digits will be <= the initial digits less drop */ +/* (after removing drop digits there may be leading zero digits */ +/* which will also be removed). Only dn->lsu and dn->digits change. */ +/* ------------------------------------------------------------------ */ +static decNumber *decDecap(decNumber *dn, Int drop) { + Unit *msu; /* -> target cut point */ + Int cut; /* work */ + if (drop>=dn->digits) { /* losing the whole thing */ + #if DECCHECK + if (drop>dn->digits) + printf("decDecap called with drop>digits [%ld>%ld]\n", + (LI)drop, (LI)dn->digits); + #endif + dn->lsu[0]=0; + dn->digits=1; + return dn; + } + msu=dn->lsu+D2U(dn->digits-drop)-1; /* -> likely msu */ + cut=MSUDIGITS(dn->digits-drop); /* digits to be in use in msu */ + if (cut!=DECDPUN) *msu%=powers[cut]; /* clear left digits */ + /* that may have left leading zero digits, so do a proper count... */ + dn->digits=decGetDigits(dn->lsu, msu-dn->lsu+1); + return dn; + } /* decDecap */ + +/* ------------------------------------------------------------------ */ +/* decBiStr -- compare string with pairwise options */ +/* */ +/* targ is the string to compare */ +/* str1 is one of the strings to compare against (length may be 0) */ +/* str2 is the other; it must be the same length as str1 */ +/* */ +/* returns 1 if strings compare equal, (that is, it is the same */ +/* length as str1 and str2, and each character of targ is in either */ +/* str1 or str2 in the corresponding position), or 0 otherwise */ +/* */ +/* This is used for generic caseless compare, including the awkward */ +/* case of the Turkish dotted and dotless Is. Use as (for example): */ +/* if (decBiStr(test, "mike", "MIKE")) ... */ +/* ------------------------------------------------------------------ */ +static Flag decBiStr(const char *targ, const char *str1, const char *str2) { + for (;;targ++, str1++, str2++) { + if (*targ!=*str1 && *targ!=*str2) return 0; + /* *targ has a match in one (or both, if terminator) */ + if (*targ=='\0') break; + } /* forever */ + return 1; + } /* decBiStr */ + +/* ------------------------------------------------------------------ */ +/* decNaNs -- handle NaN operand or operands */ +/* */ +/* res is the result number */ +/* lhs is the first operand */ +/* rhs is the second operand, or NULL if none */ +/* context is used to limit payload length */ +/* status contains the current status */ +/* returns res in case convenient */ +/* */ +/* Called when one or both operands is a NaN, and propagates the */ +/* appropriate result to res. When an sNaN is found, it is changed */ +/* to a qNaN and Invalid operation is set. */ +/* ------------------------------------------------------------------ */ +static decNumber * decNaNs(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set, + uInt *status) { + /* This decision tree ends up with LHS being the source pointer, */ + /* and status updated if need be */ + if (lhs->bits & DECSNAN) + *status|=DEC_Invalid_operation | DEC_sNaN; + else if (rhs==NULL); + else if (rhs->bits & DECSNAN) { + lhs=rhs; + *status|=DEC_Invalid_operation | DEC_sNaN; + } + else if (lhs->bits & DECNAN); + else lhs=rhs; + + /* propagate the payload */ + if (lhs->digits<=set->digits) decNumberCopy(res, lhs); /* easy */ + else { /* too long */ + const Unit *ul; + Unit *ur, *uresp1; + /* copy safe number of units, then decapitate */ + res->bits=lhs->bits; /* need sign etc. */ + uresp1=res->lsu+D2U(set->digits); + for (ur=res->lsu, ul=lhs->lsu; ur<uresp1; ur++, ul++) *ur=*ul; + res->digits=D2U(set->digits)*DECDPUN; + /* maybe still too long */ + if (res->digits>set->digits) decDecap(res, res->digits-set->digits); + } + + res->bits&=~DECSNAN; /* convert any sNaN to NaN, while */ + res->bits|=DECNAN; /* .. preserving sign */ + res->exponent=0; /* clean exponent */ + /* [coefficient was copied/decapitated] */ + return res; + } /* decNaNs */ + +/* ------------------------------------------------------------------ */ +/* decStatus -- apply non-zero status */ +/* */ +/* dn is the number to set if error */ +/* status contains the current status (not yet in context) */ +/* set is the context */ +/* */ +/* If the status is an error status, the number is set to a NaN, */ +/* unless the error was an overflow, divide-by-zero, or underflow, */ +/* in which case the number will have already been set. */ +/* */ +/* The context status is then updated with the new status. Note that */ +/* this may raise a signal, so control may never return from this */ +/* routine (hence resources must be recovered before it is called). */ +/* ------------------------------------------------------------------ */ +static void decStatus(decNumber *dn, uInt status, decContext *set) { + if (status & DEC_NaNs) { /* error status -> NaN */ + /* if cause was an sNaN, clear and propagate [NaN is already set up] */ + if (status & DEC_sNaN) status&=~DEC_sNaN; + else { + decNumberZero(dn); /* other error: clean throughout */ + dn->bits=DECNAN; /* and make a quiet NaN */ + } + } + decContextSetStatus(set, status); /* [may not return] */ + return; + } /* decStatus */ + +/* ------------------------------------------------------------------ */ +/* decGetDigits -- count digits in a Units array */ +/* */ +/* uar is the Unit array holding the number (this is often an */ +/* accumulator of some sort) */ +/* len is the length of the array in units [>=1] */ +/* */ +/* returns the number of (significant) digits in the array */ +/* */ +/* All leading zeros are excluded, except the last if the array has */ +/* only zero Units. */ +/* ------------------------------------------------------------------ */ +/* This may be called twice during some operations. */ +static Int decGetDigits(Unit *uar, Int len) { + Unit *up=uar+(len-1); /* -> msu */ + Int digits=(len-1)*DECDPUN+1; /* possible digits excluding msu */ + #if DECDPUN>4 + uInt const *pow; /* work */ + #endif + /* (at least 1 in final msu) */ + #if DECCHECK + if (len<1) printf("decGetDigits called with len<1 [%ld]\n", (LI)len); + #endif + + for (; up>=uar; up--) { + if (*up==0) { /* unit is all 0s */ + if (digits==1) break; /* a zero has one digit */ + digits-=DECDPUN; /* adjust for 0 unit */ + continue;} + /* found the first (most significant) non-zero Unit */ + #if DECDPUN>1 /* not done yet */ + if (*up<10) break; /* is 1-9 */ + digits++; + #if DECDPUN>2 /* not done yet */ + if (*up<100) break; /* is 10-99 */ + digits++; + #if DECDPUN>3 /* not done yet */ + if (*up<1000) break; /* is 100-999 */ + digits++; + #if DECDPUN>4 /* count the rest ... */ + for (pow=&powers[4]; *up>=*pow; pow++) digits++; + #endif + #endif + #endif + #endif + break; + } /* up */ + return digits; + } /* decGetDigits */ + +#if DECTRACE | DECCHECK +/* ------------------------------------------------------------------ */ +/* decNumberShow -- display a number [debug aid] */ +/* dn is the number to show */ +/* */ +/* Shows: sign, exponent, coefficient (msu first), digits */ +/* or: sign, special-value */ +/* ------------------------------------------------------------------ */ +/* this is public so other modules can use it */ +void decNumberShow(const decNumber *dn) { + const Unit *up; /* work */ + uInt u, d; /* .. */ + Int cut; /* .. */ + char isign='+'; /* main sign */ + if (dn==NULL) { + printf("NULL\n"); + return;} + if (decNumberIsNegative(dn)) isign='-'; + printf(" >> %c ", isign); + if (dn->bits&DECSPECIAL) { /* Is a special value */ + if (decNumberIsInfinite(dn)) printf("Infinity"); + else { /* a NaN */ + if (dn->bits&DECSNAN) printf("sNaN"); /* signalling NaN */ + else printf("NaN"); + } + /* if coefficient and exponent are 0, no more to do */ + if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) { + printf("\n"); + return;} + /* drop through to report other information */ + printf(" "); + } + + /* now carefully display the coefficient */ + up=dn->lsu+D2U(dn->digits)-1; /* msu */ + printf("%ld", (LI)*up); + for (up=up-1; up>=dn->lsu; up--) { + u=*up; + printf(":"); + for (cut=DECDPUN-1; cut>=0; cut--) { + d=u/powers[cut]; + u-=d*powers[cut]; + printf("%ld", (LI)d); + } /* cut */ + } /* up */ + if (dn->exponent!=0) { + char esign='+'; + if (dn->exponent<0) esign='-'; + printf(" E%c%ld", esign, (LI)abs(dn->exponent)); + } + printf(" [%ld]\n", (LI)dn->digits); + } /* decNumberShow */ +#endif + +#if DECTRACE || DECCHECK +/* ------------------------------------------------------------------ */ +/* decDumpAr -- display a unit array [debug/check aid] */ +/* name is a single-character tag name */ +/* ar is the array to display */ +/* len is the length of the array in Units */ +/* ------------------------------------------------------------------ */ +static void decDumpAr(char name, const Unit *ar, Int len) { + Int i; + const char *spec; + #if DECDPUN==9 + spec="%09d "; + #elif DECDPUN==8 + spec="%08d "; + #elif DECDPUN==7 + spec="%07d "; + #elif DECDPUN==6 + spec="%06d "; + #elif DECDPUN==5 + spec="%05d "; + #elif DECDPUN==4 + spec="%04d "; + #elif DECDPUN==3 + spec="%03d "; + #elif DECDPUN==2 + spec="%02d "; + #else + spec="%d "; + #endif + printf(" :%c: ", name); + for (i=len-1; i>=0; i--) { + if (i==len-1) printf("%ld ", (LI)ar[i]); + else printf(spec, ar[i]); + } + printf("\n"); + return;} +#endif + +#if DECCHECK +/* ------------------------------------------------------------------ */ +/* decCheckOperands -- check operand(s) to a routine */ +/* res is the result structure (not checked; it will be set to */ +/* quiet NaN if error found (and it is not NULL)) */ +/* lhs is the first operand (may be DECUNRESU) */ +/* rhs is the second (may be DECUNUSED) */ +/* set is the context (may be DECUNCONT) */ +/* returns 0 if both operands, and the context are clean, or 1 */ +/* otherwise (in which case the context will show an error, */ +/* unless NULL). Note that res is not cleaned; caller should */ +/* handle this so res=NULL case is safe. */ +/* The caller is expected to abandon immediately if 1 is returned. */ +/* ------------------------------------------------------------------ */ +static Flag decCheckOperands(decNumber *res, const decNumber *lhs, + const decNumber *rhs, decContext *set) { + Flag bad=0; + if (set==NULL) { /* oops; hopeless */ + #if DECTRACE || DECVERB + printf("Reference to context is NULL.\n"); + #endif + bad=1; + return 1;} + else if (set!=DECUNCONT + && (set->digits<1 || set->round>=DEC_ROUND_MAX)) { + bad=1; + #if DECTRACE || DECVERB + printf("Bad context [digits=%ld round=%ld].\n", + (LI)set->digits, (LI)set->round); + #endif + } + else { + if (res==NULL) { + bad=1; + #if DECTRACE + /* this one not DECVERB as standard tests include NULL */ + printf("Reference to result is NULL.\n"); + #endif + } + if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs)); + if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs)); + } + if (bad) { + if (set!=DECUNCONT) decContextSetStatus(set, DEC_Invalid_operation); + if (res!=DECUNRESU && res!=NULL) { + decNumberZero(res); + res->bits=DECNAN; /* qNaN */ + } + } + return bad; + } /* decCheckOperands */ + +/* ------------------------------------------------------------------ */ +/* decCheckNumber -- check a number */ +/* dn is the number to check */ +/* returns 0 if the number is clean, or 1 otherwise */ +/* */ +/* The number is considered valid if it could be a result from some */ +/* operation in some valid context. */ +/* ------------------------------------------------------------------ */ +static Flag decCheckNumber(const decNumber *dn) { + const Unit *up; /* work */ + uInt maxuint; /* .. */ + Int ae, d, digits; /* .. */ + Int emin, emax; /* .. */ + + if (dn==NULL) { /* hopeless */ + #if DECTRACE + /* this one not DECVERB as standard tests include NULL */ + printf("Reference to decNumber is NULL.\n"); + #endif + return 1;} + + /* check special values */ + if (dn->bits & DECSPECIAL) { + if (dn->exponent!=0) { + #if DECTRACE || DECVERB + printf("Exponent %ld (not 0) for a special value [%02x].\n", + (LI)dn->exponent, dn->bits); + #endif + return 1;} + + /* 2003.09.08: NaNs may now have coefficients, so next tests Inf only */ + if (decNumberIsInfinite(dn)) { + if (dn->digits!=1) { + #if DECTRACE || DECVERB + printf("Digits %ld (not 1) for an infinity.\n", (LI)dn->digits); + #endif + return 1;} + if (*dn->lsu!=0) { + #if DECTRACE || DECVERB + printf("LSU %ld (not 0) for an infinity.\n", (LI)*dn->lsu); + #endif + decDumpAr('I', dn->lsu, D2U(dn->digits)); + return 1;} + } /* Inf */ + /* 2002.12.26: negative NaNs can now appear through proposed IEEE */ + /* concrete formats (decimal64, etc.). */ + return 0; + } + + /* check the coefficient */ + if (dn->digits<1 || dn->digits>DECNUMMAXP) { + #if DECTRACE || DECVERB + printf("Digits %ld in number.\n", (LI)dn->digits); + #endif + return 1;} + + d=dn->digits; + + for (up=dn->lsu; d>0; up++) { + if (d>DECDPUN) maxuint=DECDPUNMAX; + else { /* reached the msu */ + maxuint=powers[d]-1; + if (dn->digits>1 && *up<powers[d-1]) { + #if DECTRACE || DECVERB + printf("Leading 0 in number.\n"); + decNumberShow(dn); + #endif + return 1;} + } + if (*up>maxuint) { + #if DECTRACE || DECVERB + printf("Bad Unit [%08lx] in %ld-digit number at offset %ld [maxuint %ld].\n", + (LI)*up, (LI)dn->digits, (LI)(up-dn->lsu), (LI)maxuint); + #endif + return 1;} + d-=DECDPUN; + } + + /* check the exponent. Note that input operands can have exponents */ + /* which are out of the set->emin/set->emax and set->digits range */ + /* (just as they can have more digits than set->digits). */ + ae=dn->exponent+dn->digits-1; /* adjusted exponent */ + emax=DECNUMMAXE; + emin=DECNUMMINE; + digits=DECNUMMAXP; + if (ae<emin-(digits-1)) { + #if DECTRACE || DECVERB + printf("Adjusted exponent underflow [%ld].\n", (LI)ae); + decNumberShow(dn); + #endif + return 1;} + if (ae>+emax) { + #if DECTRACE || DECVERB + printf("Adjusted exponent overflow [%ld].\n", (LI)ae); + decNumberShow(dn); + #endif + return 1;} + + return 0; /* it's OK */ + } /* decCheckNumber */ + +/* ------------------------------------------------------------------ */ +/* decCheckInexact -- check a normal finite inexact result has digits */ +/* dn is the number to check */ +/* set is the context (for status and precision) */ +/* sets Invalid operation, etc., if some digits are missing */ +/* [this check is not made for DECSUBSET compilation or when */ +/* subnormal is not set] */ +/* ------------------------------------------------------------------ */ +static void decCheckInexact(const decNumber *dn, decContext *set) { + #if !DECSUBSET && DECEXTFLAG + if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact + && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) { + #if DECTRACE || DECVERB + printf("Insufficient digits [%ld] on normal Inexact result.\n", + (LI)dn->digits); + decNumberShow(dn); + #endif + decContextSetStatus(set, DEC_Invalid_operation); + } + #else + /* next is a noop for quiet compiler */ + if (dn!=NULL && dn->digits==0) set->status|=DEC_Invalid_operation; + #endif + return; + } /* decCheckInexact */ +#endif + +#if DECALLOC +#undef malloc +#undef free +/* ------------------------------------------------------------------ */ +/* decMalloc -- accountable allocation routine */ +/* n is the number of bytes to allocate */ +/* */ +/* Semantics is the same as the stdlib malloc routine, but bytes */ +/* allocated are accounted for globally, and corruption fences are */ +/* added before and after the 'actual' storage. */ +/* ------------------------------------------------------------------ */ +/* This routine allocates storage with an extra twelve bytes; 8 are */ +/* at the start and hold: */ +/* 0-3 the original length requested */ +/* 4-7 buffer corruption detection fence (DECFENCE, x4) */ +/* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */ +/* ------------------------------------------------------------------ */ +static void *decMalloc(size_t n) { + uInt size=n+12; /* true size */ + void *alloc; /* -> allocated storage */ + uInt *j; /* work */ + uByte *b, *b0; /* .. */ + + alloc=malloc(size); /* -> allocated storage */ + if (alloc==NULL) return NULL; /* out of strorage */ + b0=(uByte *)alloc; /* as bytes */ + decAllocBytes+=n; /* account for storage */ + j=(uInt *)alloc; /* -> first four bytes */ + *j=n; /* save n */ + /* printf(" alloc ++ dAB: %ld (%d)\n", decAllocBytes, n); */ + for (b=b0+4; b<b0+8; b++) *b=DECFENCE; + for (b=b0+n+8; b<b0+n+12; b++) *b=DECFENCE; + return b0+8; /* -> play area */ + } /* decMalloc */ + +/* ------------------------------------------------------------------ */ +/* decFree -- accountable free routine */ +/* alloc is the storage to free */ +/* */ +/* Semantics is the same as the stdlib malloc routine, except that */ +/* the global storage accounting is updated and the fences are */ +/* checked to ensure that no routine has written 'out of bounds'. */ +/* ------------------------------------------------------------------ */ +/* This routine first checks that the fences have not been corrupted. */ +/* It then frees the storage using the 'truw' storage address (that */ +/* is, offset by 8). */ +/* ------------------------------------------------------------------ */ +static void decFree(void *alloc) { + uInt *j, n; /* pointer, original length */ + uByte *b, *b0; /* work */ + + if (alloc==NULL) return; /* allowed; it's a nop */ + b0=(uByte *)alloc; /* as bytes */ + b0-=8; /* -> true start of storage */ + j=(uInt *)b0; /* -> first four bytes */ + n=*j; /* lift */ + for (b=b0+4; b<b0+8; b++) if (*b!=DECFENCE) + printf("=== Corrupt byte [%02x] at offset %d from %ld ===\n", *b, + b-b0-8, (Int)b0); + for (b=b0+n+8; b<b0+n+12; b++) if (*b!=DECFENCE) + printf("=== Corrupt byte [%02x] at offset +%d from %ld, n=%ld ===\n", *b, + b-b0-8, (Int)b0, n); + free(b0); /* drop the storage */ + decAllocBytes-=n; /* account for storage */ + /* printf(" free -- dAB: %d (%d)\n", decAllocBytes, -n); */ + } /* decFree */ +#define malloc(a) decMalloc(a) +#define free(a) decFree(a) +#endif diff --git a/libdecnumber/dpd/decimal128.c b/libdecnumber/dpd/decimal128.c new file mode 100644 index 0000000..54191aa --- /dev/null +++ b/libdecnumber/dpd/decimal128.c @@ -0,0 +1,566 @@ +/* Decimal 128-bit format module for the decNumber C Library. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------ */ +/* Decimal 128-bit format module */ +/* ------------------------------------------------------------------ */ +/* This module comprises the routines for decimal128 format numbers. */ +/* Conversions are supplied to and from decNumber and String. */ +/* */ +/* This is used when decNumber provides operations, either for all */ +/* operations or as a proxy between decNumber and decSingle. */ +/* */ +/* Error handling is the same as decNumber (qv.). */ +/* ------------------------------------------------------------------ */ +#include <string.h> /* [for memset/memcpy] */ +#include <stdio.h> /* [for printf] */ + +#include "dconfig.h" /* GCC definitions */ +#define DECNUMDIGITS 34 /* make decNumbers with space for 34 */ +#include "decNumber.h" /* base number library */ +#include "decNumberLocal.h" /* decNumber local types, etc. */ +#include "decimal128.h" /* our primary include */ + +/* Utility routines and tables [in decimal64.c] */ +extern const uInt COMBEXP[32], COMBMSD[32]; +extern const uShort DPD2BIN[1024]; +extern const uShort BIN2DPD[1000]; /* [not used] */ +extern const uByte BIN2CHAR[4001]; + +extern void decDigitsFromDPD(decNumber *, const uInt *, Int); +extern void decDigitsToDPD(const decNumber *, uInt *, Int); + +#if DECTRACE || DECCHECK +void decimal128Show(const decimal128 *); /* for debug */ +extern void decNumberShow(const decNumber *); /* .. */ +#endif + +/* Useful macro */ +/* Clear a structure (e.g., a decNumber) */ +#define DEC_clear(d) memset(d, 0, sizeof(*d)) + +/* ------------------------------------------------------------------ */ +/* decimal128FromNumber -- convert decNumber to decimal128 */ +/* */ +/* ds is the target decimal128 */ +/* dn is the source number (assumed valid) */ +/* set is the context, used only for reporting errors */ +/* */ +/* The set argument is used only for status reporting and for the */ +/* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/ +/* digits or an overflow is detected). If the exponent is out of the */ +/* valid range then Overflow or Underflow will be raised. */ +/* After Underflow a subnormal result is possible. */ +/* */ +/* DEC_Clamped is set if the number has to be 'folded down' to fit, */ +/* by reducing its exponent and multiplying the coefficient by a */ +/* power of ten, or if the exponent on a zero had to be clamped. */ +/* ------------------------------------------------------------------ */ +decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn, + decContext *set) { + uInt status=0; /* status accumulator */ + Int ae; /* adjusted exponent */ + decNumber dw; /* work */ + decContext dc; /* .. */ + uInt *pu; /* .. */ + uInt comb, exp; /* .. */ + uInt targar[4]={0,0,0,0}; /* target 128-bit */ + #define targhi targar[3] /* name the word with the sign */ + #define targmh targar[2] /* name the words */ + #define targml targar[1] /* .. */ + #define targlo targar[0] /* .. */ + + /* If the number has too many digits, or the exponent could be */ + /* out of range then reduce the number under the appropriate */ + /* constraints. This could push the number to Infinity or zero, */ + /* so this check and rounding must be done before generating the */ + /* decimal128] */ + ae=dn->exponent+dn->digits-1; /* [0 if special] */ + if (dn->digits>DECIMAL128_Pmax /* too many digits */ + || ae>DECIMAL128_Emax /* likely overflow */ + || ae<DECIMAL128_Emin) { /* likely underflow */ + decContextDefault(&dc, DEC_INIT_DECIMAL128); /* [no traps] */ + dc.round=set->round; /* use supplied rounding */ + decNumberPlus(&dw, dn, &dc); /* (round and check) */ + /* [this changes -0 to 0, so enforce the sign...] */ + dw.bits|=dn->bits&DECNEG; + status=dc.status; /* save status */ + dn=&dw; /* use the work number */ + } /* maybe out of range */ + + if (dn->bits&DECSPECIAL) { /* a special value */ + if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24; + else { /* sNaN or qNaN */ + if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */ + && (dn->digits<DECIMAL128_Pmax)) { /* coefficient fits */ + decDigitsToDPD(dn, targar, 0); + } + if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24; + else targhi|=DECIMAL_sNaN<<24; + } /* a NaN */ + } /* special */ + + else { /* is finite */ + if (decNumberIsZero(dn)) { /* is a zero */ + /* set and clamp exponent */ + if (dn->exponent<-DECIMAL128_Bias) { + exp=0; /* low clamp */ + status|=DEC_Clamped; + } + else { + exp=dn->exponent+DECIMAL128_Bias; /* bias exponent */ + if (exp>DECIMAL128_Ehigh) { /* top clamp */ + exp=DECIMAL128_Ehigh; + status|=DEC_Clamped; + } + } + comb=(exp>>9) & 0x18; /* msd=0, exp top 2 bits .. */ + } + else { /* non-zero finite number */ + uInt msd; /* work */ + Int pad=0; /* coefficient pad digits */ + + /* the dn is known to fit, but it may need to be padded */ + exp=(uInt)(dn->exponent+DECIMAL128_Bias); /* bias exponent */ + if (exp>DECIMAL128_Ehigh) { /* fold-down case */ + pad=exp-DECIMAL128_Ehigh; + exp=DECIMAL128_Ehigh; /* [to maximum] */ + status|=DEC_Clamped; + } + + /* [fastpath for common case is not a win, here] */ + decDigitsToDPD(dn, targar, pad); + /* save and clear the top digit */ + msd=targhi>>14; + targhi&=0x00003fff; + + /* create the combination field */ + if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01); + else comb=((exp>>9) & 0x18) | msd; + } + targhi|=comb<<26; /* add combination field .. */ + targhi|=(exp&0xfff)<<14; /* .. and exponent continuation */ + } /* finite */ + + if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */ + + /* now write to storage; this is endian */ + pu=(uInt *)d128->bytes; /* overlay */ + if (DECLITEND) { + pu[0]=targlo; /* directly store the low int */ + pu[1]=targml; /* then the mid-low */ + pu[2]=targmh; /* then the mid-high */ + pu[3]=targhi; /* then the high int */ + } + else { + pu[0]=targhi; /* directly store the high int */ + pu[1]=targmh; /* then the mid-high */ + pu[2]=targml; /* then the mid-low */ + pu[3]=targlo; /* then the low int */ + } + + if (status!=0) decContextSetStatus(set, status); /* pass on status */ + /* decimal128Show(d128); */ + return d128; + } /* decimal128FromNumber */ + +/* ------------------------------------------------------------------ */ +/* decimal128ToNumber -- convert decimal128 to decNumber */ +/* d128 is the source decimal128 */ +/* dn is the target number, with appropriate space */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) { + uInt msd; /* coefficient MSD */ + uInt exp; /* exponent top two bits */ + uInt comb; /* combination field */ + const uInt *pu; /* work */ + Int need; /* .. */ + uInt sourar[4]; /* source 128-bit */ + #define sourhi sourar[3] /* name the word with the sign */ + #define sourmh sourar[2] /* and the mid-high word */ + #define sourml sourar[1] /* and the mod-low word */ + #define sourlo sourar[0] /* and the lowest word */ + + /* load source from storage; this is endian */ + pu=(const uInt *)d128->bytes; /* overlay */ + if (DECLITEND) { + sourlo=pu[0]; /* directly load the low int */ + sourml=pu[1]; /* then the mid-low */ + sourmh=pu[2]; /* then the mid-high */ + sourhi=pu[3]; /* then the high int */ + } + else { + sourhi=pu[0]; /* directly load the high int */ + sourmh=pu[1]; /* then the mid-high */ + sourml=pu[2]; /* then the mid-low */ + sourlo=pu[3]; /* then the low int */ + } + + comb=(sourhi>>26)&0x1f; /* combination field */ + + decNumberZero(dn); /* clean number */ + if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */ + + msd=COMBMSD[comb]; /* decode the combination field */ + exp=COMBEXP[comb]; /* .. */ + + if (exp==3) { /* is a special */ + if (msd==0) { + dn->bits|=DECINF; + return dn; /* no coefficient needed */ + } + else if (sourhi&0x02000000) dn->bits|=DECSNAN; + else dn->bits|=DECNAN; + msd=0; /* no top digit */ + } + else { /* is a finite number */ + dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */ + } + + /* get the coefficient */ + sourhi&=0x00003fff; /* clean coefficient continuation */ + if (msd) { /* non-zero msd */ + sourhi|=msd<<14; /* prefix to coefficient */ + need=12; /* process 12 declets */ + } + else { /* msd=0 */ + if (sourhi) need=11; /* declets to process */ + else if (sourmh) need=10; + else if (sourml) need=7; + else if (sourlo) need=4; + else return dn; /* easy: coefficient is 0 */ + } /*msd=0 */ + + decDigitsFromDPD(dn, sourar, need); /* process declets */ + /* decNumberShow(dn); */ + return dn; + } /* decimal128ToNumber */ + +/* ------------------------------------------------------------------ */ +/* to-scientific-string -- conversion to numeric string */ +/* to-engineering-string -- conversion to numeric string */ +/* */ +/* decimal128ToString(d128, string); */ +/* decimal128ToEngString(d128, string); */ +/* */ +/* d128 is the decimal128 format number to convert */ +/* string is the string where the result will be laid out */ +/* */ +/* string must be at least 24 characters */ +/* */ +/* No error is possible, and no status can be set. */ +/* ------------------------------------------------------------------ */ +char * decimal128ToEngString(const decimal128 *d128, char *string){ + decNumber dn; /* work */ + decimal128ToNumber(d128, &dn); + decNumberToEngString(&dn, string); + return string; + } /* decimal128ToEngString */ + +char * decimal128ToString(const decimal128 *d128, char *string){ + uInt msd; /* coefficient MSD */ + Int exp; /* exponent top two bits or full */ + uInt comb; /* combination field */ + char *cstart; /* coefficient start */ + char *c; /* output pointer in string */ + const uInt *pu; /* work */ + char *s, *t; /* .. (source, target) */ + Int dpd; /* .. */ + Int pre, e; /* .. */ + const uByte *u; /* .. */ + + uInt sourar[4]; /* source 128-bit */ + #define sourhi sourar[3] /* name the word with the sign */ + #define sourmh sourar[2] /* and the mid-high word */ + #define sourml sourar[1] /* and the mod-low word */ + #define sourlo sourar[0] /* and the lowest word */ + + /* load source from storage; this is endian */ + pu=(const uInt *)d128->bytes; /* overlay */ + if (DECLITEND) { + sourlo=pu[0]; /* directly load the low int */ + sourml=pu[1]; /* then the mid-low */ + sourmh=pu[2]; /* then the mid-high */ + sourhi=pu[3]; /* then the high int */ + } + else { + sourhi=pu[0]; /* directly load the high int */ + sourmh=pu[1]; /* then the mid-high */ + sourml=pu[2]; /* then the mid-low */ + sourlo=pu[3]; /* then the low int */ + } + + c=string; /* where result will go */ + if (((Int)sourhi)<0) *c++='-'; /* handle sign */ + + comb=(sourhi>>26)&0x1f; /* combination field */ + msd=COMBMSD[comb]; /* decode the combination field */ + exp=COMBEXP[comb]; /* .. */ + + if (exp==3) { + if (msd==0) { /* infinity */ + strcpy(c, "Inf"); + strcpy(c+3, "inity"); + return string; /* easy */ + } + if (sourhi&0x02000000) *c++='s'; /* sNaN */ + strcpy(c, "NaN"); /* complete word */ + c+=3; /* step past */ + if (sourlo==0 && sourml==0 && sourmh==0 + && (sourhi&0x0003ffff)==0) return string; /* zero payload */ + /* otherwise drop through to add integer; set correct exp */ + exp=0; msd=0; /* setup for following code */ + } + else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */ + + /* convert 34 digits of significand to characters */ + cstart=c; /* save start of coefficient */ + if (msd) *c++='0'+(char)msd; /* non-zero most significant digit */ + + /* Now decode the declets. After extracting each one, it is */ + /* decoded to binary and then to a 4-char sequence by table lookup; */ + /* the 4-chars are a 1-char length (significant digits, except 000 */ + /* has length 0). This allows us to left-align the first declet */ + /* with non-zero content, then remaining ones are full 3-char */ + /* length. We use fixed-length memcpys because variable-length */ + /* causes a subroutine call in GCC. (These are length 4 for speed */ + /* and are safe because the array has an extra terminator byte.) */ + #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ + if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ + else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} + dpd=(sourhi>>4)&0x3ff; /* declet 1 */ + dpd2char; + dpd=((sourhi&0xf)<<6) | (sourmh>>26); /* declet 2 */ + dpd2char; + dpd=(sourmh>>16)&0x3ff; /* declet 3 */ + dpd2char; + dpd=(sourmh>>6)&0x3ff; /* declet 4 */ + dpd2char; + dpd=((sourmh&0x3f)<<4) | (sourml>>28); /* declet 5 */ + dpd2char; + dpd=(sourml>>18)&0x3ff; /* declet 6 */ + dpd2char; + dpd=(sourml>>8)&0x3ff; /* declet 7 */ + dpd2char; + dpd=((sourml&0xff)<<2) | (sourlo>>30); /* declet 8 */ + dpd2char; + dpd=(sourlo>>20)&0x3ff; /* declet 9 */ + dpd2char; + dpd=(sourlo>>10)&0x3ff; /* declet 10 */ + dpd2char; + dpd=(sourlo)&0x3ff; /* declet 11 */ + dpd2char; + + if (c==cstart) *c++='0'; /* all zeros -- make 0 */ + + if (exp==0) { /* integer or NaN case -- easy */ + *c='\0'; /* terminate */ + return string; + } + + /* non-0 exponent */ + e=0; /* assume no E */ + pre=c-cstart+exp; + /* [here, pre-exp is the digits count (==1 for zero)] */ + if (exp>0 || pre<-5) { /* need exponential form */ + e=pre-1; /* calculate E value */ + pre=1; /* assume one digit before '.' */ + } /* exponential form */ + + /* modify the coefficient, adding 0s, '.', and E+nn as needed */ + s=c-1; /* source (LSD) */ + if (pre>0) { /* ddd.ddd (plain), perhaps with E */ + char *dotat=cstart+pre; + if (dotat<c) { /* if embedded dot needed... */ + t=c; /* target */ + for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */ + *t='.'; /* insert the dot */ + c++; /* length increased by one */ + } + + /* finally add the E-part, if needed; it will never be 0, and has */ + /* a maximum length of 4 digits */ + if (e!=0) { + *c++='E'; /* starts with E */ + *c++='+'; /* assume positive */ + if (e<0) { + *(c-1)='-'; /* oops, need '-' */ + e=-e; /* uInt, please */ + } + if (e<1000) { /* 3 (or fewer) digits case */ + u=&BIN2CHAR[e*4]; /* -> length byte */ + memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */ + c+=*u; /* bump pointer appropriately */ + } + else { /* 4-digits */ + Int thou=((e>>3)*1049)>>17; /* e/1000 */ + Int rem=e-(1000*thou); /* e%1000 */ + *c++='0'+(char)thou; + u=&BIN2CHAR[rem*4]; /* -> length byte */ + memcpy(c, u+1, 4); /* copy fixed 3+1 characters [is safe] */ + c+=3; /* bump pointer, always 3 digits */ + } + } + *c='\0'; /* add terminator */ + /*printf("res %s\n", string); */ + return string; + } /* pre>0 */ + + /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ + t=c+1-pre; + *(t+1)='\0'; /* can add terminator now */ + for (; s>=cstart; s--, t--) *t=*s; /* shift whole coefficient right */ + c=cstart; + *c++='0'; /* always starts with 0. */ + *c++='.'; + for (; pre<0; pre++) *c++='0'; /* add any 0's after '.' */ + /*printf("res %s\n", string); */ + return string; + } /* decimal128ToString */ + +/* ------------------------------------------------------------------ */ +/* to-number -- conversion from numeric string */ +/* */ +/* decimal128FromString(result, string, set); */ +/* */ +/* result is the decimal128 format number which gets the result of */ +/* the conversion */ +/* *string is the character string which should contain a valid */ +/* number (which may be a special value) */ +/* set is the context */ +/* */ +/* The context is supplied to this routine is used for error handling */ +/* (setting of status and traps) and for the rounding mode, only. */ +/* If an error occurs, the result will be a valid decimal128 NaN. */ +/* ------------------------------------------------------------------ */ +decimal128 * decimal128FromString(decimal128 *result, const char *string, + decContext *set) { + decContext dc; /* work */ + decNumber dn; /* .. */ + + decContextDefault(&dc, DEC_INIT_DECIMAL128); /* no traps, please */ + dc.round=set->round; /* use supplied rounding */ + + decNumberFromString(&dn, string, &dc); /* will round if needed */ + decimal128FromNumber(result, &dn, &dc); + if (dc.status!=0) { /* something happened */ + decContextSetStatus(set, dc.status); /* .. pass it on */ + } + return result; + } /* decimal128FromString */ + +/* ------------------------------------------------------------------ */ +/* decimal128IsCanonical -- test whether encoding is canonical */ +/* d128 is the source decimal128 */ +/* returns 1 if the encoding of d128 is canonical, 0 otherwise */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uint32_t decimal128IsCanonical(const decimal128 *d128) { + decNumber dn; /* work */ + decimal128 canon; /* .. */ + decContext dc; /* .. */ + decContextDefault(&dc, DEC_INIT_DECIMAL128); + decimal128ToNumber(d128, &dn); + decimal128FromNumber(&canon, &dn, &dc);/* canon will now be canonical */ + return memcmp(d128, &canon, DECIMAL128_Bytes)==0; + } /* decimal128IsCanonical */ + +/* ------------------------------------------------------------------ */ +/* decimal128Canonical -- copy an encoding, ensuring it is canonical */ +/* d128 is the source decimal128 */ +/* result is the target (may be the same decimal128) */ +/* returns result */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) { + decNumber dn; /* work */ + decContext dc; /* .. */ + decContextDefault(&dc, DEC_INIT_DECIMAL128); + decimal128ToNumber(d128, &dn); + decimal128FromNumber(result, &dn, &dc);/* result will now be canonical */ + return result; + } /* decimal128Canonical */ + +#if DECTRACE || DECCHECK +/* Macros for accessing decimal128 fields. These assume the argument + is a reference (pointer) to the decimal128 structure, and the + decimal128 is in network byte order (big-endian) */ +/* Get sign */ +#define decimal128Sign(d) ((unsigned)(d)->bytes[0]>>7) + +/* Get combination field */ +#define decimal128Comb(d) (((d)->bytes[0] & 0x7c)>>2) + +/* Get exponent continuation [does not remove bias] */ +#define decimal128ExpCon(d) ((((d)->bytes[0] & 0x03)<<10) \ + | ((unsigned)(d)->bytes[1]<<2) \ + | ((unsigned)(d)->bytes[2]>>6)) + +/* Set sign [this assumes sign previously 0] */ +#define decimal128SetSign(d, b) { \ + (d)->bytes[0]|=((unsigned)(b)<<7);} + +/* Set exponent continuation [does not apply bias] */ +/* This assumes range has been checked and exponent previously 0; */ +/* type of exponent must be unsigned */ +#define decimal128SetExpCon(d, e) { \ + (d)->bytes[0]|=(uint8_t)((e)>>10); \ + (d)->bytes[1] =(uint8_t)(((e)&0x3fc)>>2); \ + (d)->bytes[2]|=(uint8_t)(((e)&0x03)<<6);} + +/* ------------------------------------------------------------------ */ +/* decimal128Show -- display a decimal128 in hexadecimal [debug aid] */ +/* d128 -- the number to show */ +/* ------------------------------------------------------------------ */ +/* Also shows sign/cob/expconfields extracted */ +void decimal128Show(const decimal128 *d128) { + char buf[DECIMAL128_Bytes*2+1]; + Int i, j=0; + + if (DECLITEND) { + for (i=0; i<DECIMAL128_Bytes; i++, j+=2) { + sprintf(&buf[j], "%02x", d128->bytes[15-i]); + } + printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, + d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f, + ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)| + (d128->bytes[13]>>6)); + } + else { + for (i=0; i<DECIMAL128_Bytes; i++, j+=2) { + sprintf(&buf[j], "%02x", d128->bytes[i]); + } + printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, + decimal128Sign(d128), decimal128Comb(d128), + decimal128ExpCon(d128)); + } + } /* decimal128Show */ +#endif diff --git a/libdecnumber/dpd/decimal128Local.h b/libdecnumber/dpd/decimal128Local.h new file mode 100644 index 0000000..1963678 --- /dev/null +++ b/libdecnumber/dpd/decimal128Local.h @@ -0,0 +1,42 @@ +/* Local definitions for use with the decNumber C Library. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC 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 3, or (at your option) any later + version. + + GCC 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#if !defined(DECIMAL128LOCAL) + +/* The compiler needs sign manipulation functions for decimal128 which + are not part of the decNumber package. */ + +/* Set sign; this assumes the sign was previously zero. */ +#define decimal128SetSign(d,b) \ + { (d)->bytes[WORDS_BIGENDIAN ? 0 : 15] |= ((unsigned) (b) << 7); } + +/* Clear sign. */ +#define decimal128ClearSign(d) \ + { (d)->bytes[WORDS_BIGENDIAN ? 0 : 15] &= ~0x80; } + +/* Flip sign. */ +#define decimal128FlipSign(d) \ + { (d)->bytes[WORDS_BIGENDIAN ? 0 : 15] ^= 0x80; } + +#endif diff --git a/libdecnumber/dpd/decimal32.c b/libdecnumber/dpd/decimal32.c new file mode 100644 index 0000000..d8e3f59 --- /dev/null +++ b/libdecnumber/dpd/decimal32.c @@ -0,0 +1,491 @@ +/* Decimal 32-bit format module for the decNumber C Library. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------ */ +/* Decimal 32-bit format module */ +/* ------------------------------------------------------------------ */ +/* This module comprises the routines for decimal32 format numbers. */ +/* Conversions are supplied to and from decNumber and String. */ +/* */ +/* This is used when decNumber provides operations, either for all */ +/* operations or as a proxy between decNumber and decSingle. */ +/* */ +/* Error handling is the same as decNumber (qv.). */ +/* ------------------------------------------------------------------ */ +#include <string.h> /* [for memset/memcpy] */ +#include <stdio.h> /* [for printf] */ + +#include "dconfig.h" /* GCC definitions */ +#define DECNUMDIGITS 7 /* make decNumbers with space for 7 */ +#include "decNumber.h" /* base number library */ +#include "decNumberLocal.h" /* decNumber local types, etc. */ +#include "decimal32.h" /* our primary include */ + +/* Utility tables and routines [in decimal64.c] */ +extern const uInt COMBEXP[32], COMBMSD[32]; +extern const uShort DPD2BIN[1024]; +extern const uShort BIN2DPD[1000]; +extern const uByte BIN2CHAR[4001]; + +extern void decDigitsToDPD(const decNumber *, uInt *, Int); +extern void decDigitsFromDPD(decNumber *, const uInt *, Int); + +#if DECTRACE || DECCHECK +void decimal32Show(const decimal32 *); /* for debug */ +extern void decNumberShow(const decNumber *); /* .. */ +#endif + +/* Useful macro */ +/* Clear a structure (e.g., a decNumber) */ +#define DEC_clear(d) memset(d, 0, sizeof(*d)) + +/* ------------------------------------------------------------------ */ +/* decimal32FromNumber -- convert decNumber to decimal32 */ +/* */ +/* ds is the target decimal32 */ +/* dn is the source number (assumed valid) */ +/* set is the context, used only for reporting errors */ +/* */ +/* The set argument is used only for status reporting and for the */ +/* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */ +/* digits or an overflow is detected). If the exponent is out of the */ +/* valid range then Overflow or Underflow will be raised. */ +/* After Underflow a subnormal result is possible. */ +/* */ +/* DEC_Clamped is set if the number has to be 'folded down' to fit, */ +/* by reducing its exponent and multiplying the coefficient by a */ +/* power of ten, or if the exponent on a zero had to be clamped. */ +/* ------------------------------------------------------------------ */ +decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn, + decContext *set) { + uInt status=0; /* status accumulator */ + Int ae; /* adjusted exponent */ + decNumber dw; /* work */ + decContext dc; /* .. */ + uInt *pu; /* .. */ + uInt comb, exp; /* .. */ + uInt targ=0; /* target 32-bit */ + + /* If the number has too many digits, or the exponent could be */ + /* out of range then reduce the number under the appropriate */ + /* constraints. This could push the number to Infinity or zero, */ + /* so this check and rounding must be done before generating the */ + /* decimal32] */ + ae=dn->exponent+dn->digits-1; /* [0 if special] */ + if (dn->digits>DECIMAL32_Pmax /* too many digits */ + || ae>DECIMAL32_Emax /* likely overflow */ + || ae<DECIMAL32_Emin) { /* likely underflow */ + decContextDefault(&dc, DEC_INIT_DECIMAL32); /* [no traps] */ + dc.round=set->round; /* use supplied rounding */ + decNumberPlus(&dw, dn, &dc); /* (round and check) */ + /* [this changes -0 to 0, so enforce the sign...] */ + dw.bits|=dn->bits&DECNEG; + status=dc.status; /* save status */ + dn=&dw; /* use the work number */ + } /* maybe out of range */ + + if (dn->bits&DECSPECIAL) { /* a special value */ + if (dn->bits&DECINF) targ=DECIMAL_Inf<<24; + else { /* sNaN or qNaN */ + if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */ + && (dn->digits<DECIMAL32_Pmax)) { /* coefficient fits */ + decDigitsToDPD(dn, &targ, 0); + } + if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24; + else targ|=DECIMAL_sNaN<<24; + } /* a NaN */ + } /* special */ + + else { /* is finite */ + if (decNumberIsZero(dn)) { /* is a zero */ + /* set and clamp exponent */ + if (dn->exponent<-DECIMAL32_Bias) { + exp=0; /* low clamp */ + status|=DEC_Clamped; + } + else { + exp=dn->exponent+DECIMAL32_Bias; /* bias exponent */ + if (exp>DECIMAL32_Ehigh) { /* top clamp */ + exp=DECIMAL32_Ehigh; + status|=DEC_Clamped; + } + } + comb=(exp>>3) & 0x18; /* msd=0, exp top 2 bits .. */ + } + else { /* non-zero finite number */ + uInt msd; /* work */ + Int pad=0; /* coefficient pad digits */ + + /* the dn is known to fit, but it may need to be padded */ + exp=(uInt)(dn->exponent+DECIMAL32_Bias); /* bias exponent */ + if (exp>DECIMAL32_Ehigh) { /* fold-down case */ + pad=exp-DECIMAL32_Ehigh; + exp=DECIMAL32_Ehigh; /* [to maximum] */ + status|=DEC_Clamped; + } + + /* fastpath common case */ + if (DECDPUN==3 && pad==0) { + targ=BIN2DPD[dn->lsu[0]]; + if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10; + msd=(dn->digits==7 ? dn->lsu[2] : 0); + } + else { /* general case */ + decDigitsToDPD(dn, &targ, pad); + /* save and clear the top digit */ + msd=targ>>20; + targ&=0x000fffff; + } + + /* create the combination field */ + if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01); + else comb=((exp>>3) & 0x18) | msd; + } + targ|=comb<<26; /* add combination field .. */ + targ|=(exp&0x3f)<<20; /* .. and exponent continuation */ + } /* finite */ + + if (dn->bits&DECNEG) targ|=0x80000000; /* add sign bit */ + + /* now write to storage; this is endian */ + pu=(uInt *)d32->bytes; /* overlay */ + *pu=targ; /* directly store the int */ + + if (status!=0) decContextSetStatus(set, status); /* pass on status */ + /* decimal32Show(d32); */ + return d32; + } /* decimal32FromNumber */ + +/* ------------------------------------------------------------------ */ +/* decimal32ToNumber -- convert decimal32 to decNumber */ +/* d32 is the source decimal32 */ +/* dn is the target number, with appropriate space */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) { + uInt msd; /* coefficient MSD */ + uInt exp; /* exponent top two bits */ + uInt comb; /* combination field */ + uInt sour; /* source 32-bit */ + const uInt *pu; /* work */ + + /* load source from storage; this is endian */ + pu=(const uInt *)d32->bytes; /* overlay */ + sour=*pu; /* directly load the int */ + + comb=(sour>>26)&0x1f; /* combination field */ + + decNumberZero(dn); /* clean number */ + if (sour&0x80000000) dn->bits=DECNEG; /* set sign if negative */ + + msd=COMBMSD[comb]; /* decode the combination field */ + exp=COMBEXP[comb]; /* .. */ + + if (exp==3) { /* is a special */ + if (msd==0) { + dn->bits|=DECINF; + return dn; /* no coefficient needed */ + } + else if (sour&0x02000000) dn->bits|=DECSNAN; + else dn->bits|=DECNAN; + msd=0; /* no top digit */ + } + else { /* is a finite number */ + dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */ + } + + /* get the coefficient */ + sour&=0x000fffff; /* clean coefficient continuation */ + if (msd) { /* non-zero msd */ + sour|=msd<<20; /* prefix to coefficient */ + decDigitsFromDPD(dn, &sour, 3); /* process 3 declets */ + return dn; + } + /* msd=0 */ + if (!sour) return dn; /* easy: coefficient is 0 */ + if (sour&0x000ffc00) /* need 2 declets? */ + decDigitsFromDPD(dn, &sour, 2); /* process 2 declets */ + else + decDigitsFromDPD(dn, &sour, 1); /* process 1 declet */ + return dn; + } /* decimal32ToNumber */ + +/* ------------------------------------------------------------------ */ +/* to-scientific-string -- conversion to numeric string */ +/* to-engineering-string -- conversion to numeric string */ +/* */ +/* decimal32ToString(d32, string); */ +/* decimal32ToEngString(d32, string); */ +/* */ +/* d32 is the decimal32 format number to convert */ +/* string is the string where the result will be laid out */ +/* */ +/* string must be at least 24 characters */ +/* */ +/* No error is possible, and no status can be set. */ +/* ------------------------------------------------------------------ */ +char * decimal32ToEngString(const decimal32 *d32, char *string){ + decNumber dn; /* work */ + decimal32ToNumber(d32, &dn); + decNumberToEngString(&dn, string); + return string; + } /* decimal32ToEngString */ + +char * decimal32ToString(const decimal32 *d32, char *string){ + uInt msd; /* coefficient MSD */ + Int exp; /* exponent top two bits or full */ + uInt comb; /* combination field */ + char *cstart; /* coefficient start */ + char *c; /* output pointer in string */ + const uInt *pu; /* work */ + const uByte *u; /* .. */ + char *s, *t; /* .. (source, target) */ + Int dpd; /* .. */ + Int pre, e; /* .. */ + uInt sour; /* source 32-bit */ + + /* load source from storage; this is endian */ + pu=(const uInt *)d32->bytes; /* overlay */ + sour=*pu; /* directly load the int */ + + c=string; /* where result will go */ + if (((Int)sour)<0) *c++='-'; /* handle sign */ + + comb=(sour>>26)&0x1f; /* combination field */ + msd=COMBMSD[comb]; /* decode the combination field */ + exp=COMBEXP[comb]; /* .. */ + + if (exp==3) { + if (msd==0) { /* infinity */ + strcpy(c, "Inf"); + strcpy(c+3, "inity"); + return string; /* easy */ + } + if (sour&0x02000000) *c++='s'; /* sNaN */ + strcpy(c, "NaN"); /* complete word */ + c+=3; /* step past */ + if ((sour&0x000fffff)==0) return string; /* zero payload */ + /* otherwise drop through to add integer; set correct exp */ + exp=0; msd=0; /* setup for following code */ + } + else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */ + + /* convert 7 digits of significand to characters */ + cstart=c; /* save start of coefficient */ + if (msd) *c++='0'+(char)msd; /* non-zero most significant digit */ + + /* Now decode the declets. After extracting each one, it is */ + /* decoded to binary and then to a 4-char sequence by table lookup; */ + /* the 4-chars are a 1-char length (significant digits, except 000 */ + /* has length 0). This allows us to left-align the first declet */ + /* with non-zero content, then remaining ones are full 3-char */ + /* length. We use fixed-length memcpys because variable-length */ + /* causes a subroutine call in GCC. (These are length 4 for speed */ + /* and are safe because the array has an extra terminator byte.) */ + #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ + if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ + else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} + + dpd=(sour>>10)&0x3ff; /* declet 1 */ + dpd2char; + dpd=(sour)&0x3ff; /* declet 2 */ + dpd2char; + + if (c==cstart) *c++='0'; /* all zeros -- make 0 */ + + if (exp==0) { /* integer or NaN case -- easy */ + *c='\0'; /* terminate */ + return string; + } + + /* non-0 exponent */ + e=0; /* assume no E */ + pre=c-cstart+exp; + /* [here, pre-exp is the digits count (==1 for zero)] */ + if (exp>0 || pre<-5) { /* need exponential form */ + e=pre-1; /* calculate E value */ + pre=1; /* assume one digit before '.' */ + } /* exponential form */ + + /* modify the coefficient, adding 0s, '.', and E+nn as needed */ + s=c-1; /* source (LSD) */ + if (pre>0) { /* ddd.ddd (plain), perhaps with E */ + char *dotat=cstart+pre; + if (dotat<c) { /* if embedded dot needed... */ + t=c; /* target */ + for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */ + *t='.'; /* insert the dot */ + c++; /* length increased by one */ + } + + /* finally add the E-part, if needed; it will never be 0, and has */ + /* a maximum length of 3 digits (E-101 case) */ + if (e!=0) { + *c++='E'; /* starts with E */ + *c++='+'; /* assume positive */ + if (e<0) { + *(c-1)='-'; /* oops, need '-' */ + e=-e; /* uInt, please */ + } + u=&BIN2CHAR[e*4]; /* -> length byte */ + memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */ + c+=*u; /* bump pointer appropriately */ + } + *c='\0'; /* add terminator */ + /*printf("res %s\n", string); */ + return string; + } /* pre>0 */ + + /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ + t=c+1-pre; + *(t+1)='\0'; /* can add terminator now */ + for (; s>=cstart; s--, t--) *t=*s; /* shift whole coefficient right */ + c=cstart; + *c++='0'; /* always starts with 0. */ + *c++='.'; + for (; pre<0; pre++) *c++='0'; /* add any 0's after '.' */ + /*printf("res %s\n", string); */ + return string; + } /* decimal32ToString */ + +/* ------------------------------------------------------------------ */ +/* to-number -- conversion from numeric string */ +/* */ +/* decimal32FromString(result, string, set); */ +/* */ +/* result is the decimal32 format number which gets the result of */ +/* the conversion */ +/* *string is the character string which should contain a valid */ +/* number (which may be a special value) */ +/* set is the context */ +/* */ +/* The context is supplied to this routine is used for error handling */ +/* (setting of status and traps) and for the rounding mode, only. */ +/* If an error occurs, the result will be a valid decimal32 NaN. */ +/* ------------------------------------------------------------------ */ +decimal32 * decimal32FromString(decimal32 *result, const char *string, + decContext *set) { + decContext dc; /* work */ + decNumber dn; /* .. */ + + decContextDefault(&dc, DEC_INIT_DECIMAL32); /* no traps, please */ + dc.round=set->round; /* use supplied rounding */ + + decNumberFromString(&dn, string, &dc); /* will round if needed */ + decimal32FromNumber(result, &dn, &dc); + if (dc.status!=0) { /* something happened */ + decContextSetStatus(set, dc.status); /* .. pass it on */ + } + return result; + } /* decimal32FromString */ + +/* ------------------------------------------------------------------ */ +/* decimal32IsCanonical -- test whether encoding is canonical */ +/* d32 is the source decimal32 */ +/* returns 1 if the encoding of d32 is canonical, 0 otherwise */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uint32_t decimal32IsCanonical(const decimal32 *d32) { + decNumber dn; /* work */ + decimal32 canon; /* .. */ + decContext dc; /* .. */ + decContextDefault(&dc, DEC_INIT_DECIMAL32); + decimal32ToNumber(d32, &dn); + decimal32FromNumber(&canon, &dn, &dc);/* canon will now be canonical */ + return memcmp(d32, &canon, DECIMAL32_Bytes)==0; + } /* decimal32IsCanonical */ + +/* ------------------------------------------------------------------ */ +/* decimal32Canonical -- copy an encoding, ensuring it is canonical */ +/* d32 is the source decimal32 */ +/* result is the target (may be the same decimal32) */ +/* returns result */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) { + decNumber dn; /* work */ + decContext dc; /* .. */ + decContextDefault(&dc, DEC_INIT_DECIMAL32); + decimal32ToNumber(d32, &dn); + decimal32FromNumber(result, &dn, &dc);/* result will now be canonical */ + return result; + } /* decimal32Canonical */ + +#if DECTRACE || DECCHECK +/* Macros for accessing decimal32 fields. These assume the argument + is a reference (pointer) to the decimal32 structure, and the + decimal32 is in network byte order (big-endian) */ +/* Get sign */ +#define decimal32Sign(d) ((unsigned)(d)->bytes[0]>>7) + +/* Get combination field */ +#define decimal32Comb(d) (((d)->bytes[0] & 0x7c)>>2) + +/* Get exponent continuation [does not remove bias] */ +#define decimal32ExpCon(d) ((((d)->bytes[0] & 0x03)<<4) \ + | ((unsigned)(d)->bytes[1]>>4)) + +/* Set sign [this assumes sign previously 0] */ +#define decimal32SetSign(d, b) { \ + (d)->bytes[0]|=((unsigned)(b)<<7);} + +/* Set exponent continuation [does not apply bias] */ +/* This assumes range has been checked and exponent previously 0; */ +/* type of exponent must be unsigned */ +#define decimal32SetExpCon(d, e) { \ + (d)->bytes[0]|=(uint8_t)((e)>>4); \ + (d)->bytes[1]|=(uint8_t)(((e)&0x0F)<<4);} + +/* ------------------------------------------------------------------ */ +/* decimal32Show -- display a decimal32 in hexadecimal [debug aid] */ +/* d32 -- the number to show */ +/* ------------------------------------------------------------------ */ +/* Also shows sign/cob/expconfields extracted - valid bigendian only */ +void decimal32Show(const decimal32 *d32) { + char buf[DECIMAL32_Bytes*2+1]; + Int i, j=0; + + if (DECLITEND) { + for (i=0; i<DECIMAL32_Bytes; i++, j+=2) { + sprintf(&buf[j], "%02x", d32->bytes[3-i]); + } + printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, + d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f, + ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4)); + } + else { + for (i=0; i<DECIMAL32_Bytes; i++, j+=2) { + sprintf(&buf[j], "%02x", d32->bytes[i]); + } + printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, + decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32)); + } + } /* decimal32Show */ +#endif diff --git a/libdecnumber/dpd/decimal64.c b/libdecnumber/dpd/decimal64.c new file mode 100644 index 0000000..474eb7c --- /dev/null +++ b/libdecnumber/dpd/decimal64.c @@ -0,0 +1,852 @@ +/* Decimal 64-bit format module for the decNumber C Library. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC 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, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* ------------------------------------------------------------------ */ +/* Decimal 64-bit format module */ +/* ------------------------------------------------------------------ */ +/* This module comprises the routines for decimal64 format numbers. */ +/* Conversions are supplied to and from decNumber and String. */ +/* */ +/* This is used when decNumber provides operations, either for all */ +/* operations or as a proxy between decNumber and decSingle. */ +/* */ +/* Error handling is the same as decNumber (qv.). */ +/* ------------------------------------------------------------------ */ +#include <string.h> /* [for memset/memcpy] */ +#include <stdio.h> /* [for printf] */ + +#include "dconfig.h" /* GCC definitions */ +#define DECNUMDIGITS 16 /* make decNumbers with space for 16 */ +#include "decNumber.h" /* base number library */ +#include "decNumberLocal.h" /* decNumber local types, etc. */ +#include "decimal64.h" /* our primary include */ + +/* Utility routines and tables [in decimal64.c]; externs for C++ */ +extern const uInt COMBEXP[32], COMBMSD[32]; +extern const uShort DPD2BIN[1024]; +extern const uShort BIN2DPD[1000]; +extern const uByte BIN2CHAR[4001]; + +extern void decDigitsFromDPD(decNumber *, const uInt *, Int); +extern void decDigitsToDPD(const decNumber *, uInt *, Int); + +#if DECTRACE || DECCHECK +void decimal64Show(const decimal64 *); /* for debug */ +extern void decNumberShow(const decNumber *); /* .. */ +#endif + +/* Useful macro */ +/* Clear a structure (e.g., a decNumber) */ +#define DEC_clear(d) memset(d, 0, sizeof(*d)) + +/* define and include the tables to use for conversions */ +#define DEC_BIN2CHAR 1 +#define DEC_DPD2BIN 1 +#define DEC_BIN2DPD 1 /* used for all sizes */ +#include "decDPD.h" /* lookup tables */ + +/* ------------------------------------------------------------------ */ +/* decimal64FromNumber -- convert decNumber to decimal64 */ +/* */ +/* ds is the target decimal64 */ +/* dn is the source number (assumed valid) */ +/* set is the context, used only for reporting errors */ +/* */ +/* The set argument is used only for status reporting and for the */ +/* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */ +/* digits or an overflow is detected). If the exponent is out of the */ +/* valid range then Overflow or Underflow will be raised. */ +/* After Underflow a subnormal result is possible. */ +/* */ +/* DEC_Clamped is set if the number has to be 'folded down' to fit, */ +/* by reducing its exponent and multiplying the coefficient by a */ +/* power of ten, or if the exponent on a zero had to be clamped. */ +/* ------------------------------------------------------------------ */ +decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, + decContext *set) { + uInt status=0; /* status accumulator */ + Int ae; /* adjusted exponent */ + decNumber dw; /* work */ + decContext dc; /* .. */ + uInt *pu; /* .. */ + uInt comb, exp; /* .. */ + uInt targar[2]={0, 0}; /* target 64-bit */ + #define targhi targar[1] /* name the word with the sign */ + #define targlo targar[0] /* and the other */ + + /* If the number has too many digits, or the exponent could be */ + /* out of range then reduce the number under the appropriate */ + /* constraints. This could push the number to Infinity or zero, */ + /* so this check and rounding must be done before generating the */ + /* decimal64] */ + ae=dn->exponent+dn->digits-1; /* [0 if special] */ + if (dn->digits>DECIMAL64_Pmax /* too many digits */ + || ae>DECIMAL64_Emax /* likely overflow */ + || ae<DECIMAL64_Emin) { /* likely underflow */ + decContextDefault(&dc, DEC_INIT_DECIMAL64); /* [no traps] */ + dc.round=set->round; /* use supplied rounding */ + decNumberPlus(&dw, dn, &dc); /* (round and check) */ + /* [this changes -0 to 0, so enforce the sign...] */ + dw.bits|=dn->bits&DECNEG; + status=dc.status; /* save status */ + dn=&dw; /* use the work number */ + } /* maybe out of range */ + + if (dn->bits&DECSPECIAL) { /* a special value */ + if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24; + else { /* sNaN or qNaN */ + if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */ + && (dn->digits<DECIMAL64_Pmax)) { /* coefficient fits */ + decDigitsToDPD(dn, targar, 0); + } + if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24; + else targhi|=DECIMAL_sNaN<<24; + } /* a NaN */ + } /* special */ + + else { /* is finite */ + if (decNumberIsZero(dn)) { /* is a zero */ + /* set and clamp exponent */ + if (dn->exponent<-DECIMAL64_Bias) { + exp=0; /* low clamp */ + status|=DEC_Clamped; + } + else { + exp=dn->exponent+DECIMAL64_Bias; /* bias exponent */ + if (exp>DECIMAL64_Ehigh) { /* top clamp */ + exp=DECIMAL64_Ehigh; + status|=DEC_Clamped; + } + } + comb=(exp>>5) & 0x18; /* msd=0, exp top 2 bits .. */ + } + else { /* non-zero finite number */ + uInt msd; /* work */ + Int pad=0; /* coefficient pad digits */ + + /* the dn is known to fit, but it may need to be padded */ + exp=(uInt)(dn->exponent+DECIMAL64_Bias); /* bias exponent */ + if (exp>DECIMAL64_Ehigh) { /* fold-down case */ + pad=exp-DECIMAL64_Ehigh; + exp=DECIMAL64_Ehigh; /* [to maximum] */ + status|=DEC_Clamped; + } + + /* fastpath common case */ + if (DECDPUN==3 && pad==0) { + uInt dpd[6]={0,0,0,0,0,0}; + uInt i; + Int d=dn->digits; + for (i=0; d>0; i++, d-=3) dpd[i]=BIN2DPD[dn->lsu[i]]; + targlo =dpd[0]; + targlo|=dpd[1]<<10; + targlo|=dpd[2]<<20; + if (dn->digits>6) { + targlo|=dpd[3]<<30; + targhi =dpd[3]>>2; + targhi|=dpd[4]<<8; + } + msd=dpd[5]; /* [did not really need conversion] */ + } + else { /* general case */ + decDigitsToDPD(dn, targar, pad); + /* save and clear the top digit */ + msd=targhi>>18; + targhi&=0x0003ffff; + } + + /* create the combination field */ + if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01); + else comb=((exp>>5) & 0x18) | msd; + } + targhi|=comb<<26; /* add combination field .. */ + targhi|=(exp&0xff)<<18; /* .. and exponent continuation */ + } /* finite */ + + if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */ + + /* now write to storage; this is now always endian */ + pu=(uInt *)d64->bytes; /* overlay */ + if (DECLITEND) { + pu[0]=targar[0]; /* directly store the low int */ + pu[1]=targar[1]; /* then the high int */ + } + else { + pu[0]=targar[1]; /* directly store the high int */ + pu[1]=targar[0]; /* then the low int */ + } + + if (status!=0) decContextSetStatus(set, status); /* pass on status */ + /* decimal64Show(d64); */ + return d64; + } /* decimal64FromNumber */ + +/* ------------------------------------------------------------------ */ +/* decimal64ToNumber -- convert decimal64 to decNumber */ +/* d64 is the source decimal64 */ +/* dn is the target number, with appropriate space */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) { + uInt msd; /* coefficient MSD */ + uInt exp; /* exponent top two bits */ + uInt comb; /* combination field */ + const uInt *pu; /* work */ + Int need; /* .. */ + uInt sourar[2]; /* source 64-bit */ + #define sourhi sourar[1] /* name the word with the sign */ + #define sourlo sourar[0] /* and the lower word */ + + /* load source from storage; this is endian */ + pu=(const uInt *)d64->bytes; /* overlay */ + if (DECLITEND) { + sourlo=pu[0]; /* directly load the low int */ + sourhi=pu[1]; /* then the high int */ + } + else { + sourhi=pu[0]; /* directly load the high int */ + sourlo=pu[1]; /* then the low int */ + } + + comb=(sourhi>>26)&0x1f; /* combination field */ + + decNumberZero(dn); /* clean number */ + if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */ + + msd=COMBMSD[comb]; /* decode the combination field */ + exp=COMBEXP[comb]; /* .. */ + + if (exp==3) { /* is a special */ + if (msd==0) { + dn->bits|=DECINF; + return dn; /* no coefficient needed */ + } + else if (sourhi&0x02000000) dn->bits|=DECSNAN; + else dn->bits|=DECNAN; + msd=0; /* no top digit */ + } + else { /* is a finite number */ + dn->exponent=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; /* unbiased */ + } + + /* get the coefficient */ + sourhi&=0x0003ffff; /* clean coefficient continuation */ + if (msd) { /* non-zero msd */ + sourhi|=msd<<18; /* prefix to coefficient */ + need=6; /* process 6 declets */ + } + else { /* msd=0 */ + if (!sourhi) { /* top word 0 */ + if (!sourlo) return dn; /* easy: coefficient is 0 */ + need=3; /* process at least 3 declets */ + if (sourlo&0xc0000000) need++; /* process 4 declets */ + /* [could reduce some more, here] */ + } + else { /* some bits in top word, msd=0 */ + need=4; /* process at least 4 declets */ + if (sourhi&0x0003ff00) need++; /* top declet!=0, process 5 */ + } + } /*msd=0 */ + + decDigitsFromDPD(dn, sourar, need); /* process declets */ + return dn; + } /* decimal64ToNumber */ + + +/* ------------------------------------------------------------------ */ +/* to-scientific-string -- conversion to numeric string */ +/* to-engineering-string -- conversion to numeric string */ +/* */ +/* decimal64ToString(d64, string); */ +/* decimal64ToEngString(d64, string); */ +/* */ +/* d64 is the decimal64 format number to convert */ +/* string is the string where the result will be laid out */ +/* */ +/* string must be at least 24 characters */ +/* */ +/* No error is possible, and no status can be set. */ +/* ------------------------------------------------------------------ */ +char * decimal64ToEngString(const decimal64 *d64, char *string){ + decNumber dn; /* work */ + decimal64ToNumber(d64, &dn); + decNumberToEngString(&dn, string); + return string; + } /* decimal64ToEngString */ + +char * decimal64ToString(const decimal64 *d64, char *string){ + uInt msd; /* coefficient MSD */ + Int exp; /* exponent top two bits or full */ + uInt comb; /* combination field */ + char *cstart; /* coefficient start */ + char *c; /* output pointer in string */ + const uInt *pu; /* work */ + char *s, *t; /* .. (source, target) */ + Int dpd; /* .. */ + Int pre, e; /* .. */ + const uByte *u; /* .. */ + + uInt sourar[2]; /* source 64-bit */ + #define sourhi sourar[1] /* name the word with the sign */ + #define sourlo sourar[0] /* and the lower word */ + + /* load source from storage; this is endian */ + pu=(const uInt *)d64->bytes; /* overlay */ + if (DECLITEND) { + sourlo=pu[0]; /* directly load the low int */ + sourhi=pu[1]; /* then the high int */ + } + else { + sourhi=pu[0]; /* directly load the high int */ + sourlo=pu[1]; /* then the low int */ + } + + c=string; /* where result will go */ + if (((Int)sourhi)<0) *c++='-'; /* handle sign */ + + comb=(sourhi>>26)&0x1f; /* combination field */ + msd=COMBMSD[comb]; /* decode the combination field */ + exp=COMBEXP[comb]; /* .. */ + + if (exp==3) { + if (msd==0) { /* infinity */ + strcpy(c, "Inf"); + strcpy(c+3, "inity"); + return string; /* easy */ + } + if (sourhi&0x02000000) *c++='s'; /* sNaN */ + strcpy(c, "NaN"); /* complete word */ + c+=3; /* step past */ + if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; /* zero payload */ + /* otherwise drop through to add integer; set correct exp */ + exp=0; msd=0; /* setup for following code */ + } + else exp=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; + + /* convert 16 digits of significand to characters */ + cstart=c; /* save start of coefficient */ + if (msd) *c++='0'+(char)msd; /* non-zero most significant digit */ + + /* Now decode the declets. After extracting each one, it is */ + /* decoded to binary and then to a 4-char sequence by table lookup; */ + /* the 4-chars are a 1-char length (significant digits, except 000 */ + /* has length 0). This allows us to left-align the first declet */ + /* with non-zero content, then remaining ones are full 3-char */ + /* length. We use fixed-length memcpys because variable-length */ + /* causes a subroutine call in GCC. (These are length 4 for speed */ + /* and are safe because the array has an extra terminator byte.) */ + #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ + if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ + else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} + + dpd=(sourhi>>8)&0x3ff; /* declet 1 */ + dpd2char; + dpd=((sourhi&0xff)<<2) | (sourlo>>30); /* declet 2 */ + dpd2char; + dpd=(sourlo>>20)&0x3ff; /* declet 3 */ + dpd2char; + dpd=(sourlo>>10)&0x3ff; /* declet 4 */ + dpd2char; + dpd=(sourlo)&0x3ff; /* declet 5 */ + dpd2char; + + if (c==cstart) *c++='0'; /* all zeros -- make 0 */ + + if (exp==0) { /* integer or NaN case -- easy */ + *c='\0'; /* terminate */ + return string; + } + + /* non-0 exponent */ + e=0; /* assume no E */ + pre=c-cstart+exp; + /* [here, pre-exp is the digits count (==1 for zero)] */ + if (exp>0 || pre<-5) { /* need exponential form */ + e=pre-1; /* calculate E value */ + pre=1; /* assume one digit before '.' */ + } /* exponential form */ + + /* modify the coefficient, adding 0s, '.', and E+nn as needed */ + s=c-1; /* source (LSD) */ + if (pre>0) { /* ddd.ddd (plain), perhaps with E */ + char *dotat=cstart+pre; + if (dotat<c) { /* if embedded dot needed... */ + t=c; /* target */ + for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */ + *t='.'; /* insert the dot */ + c++; /* length increased by one */ + } + + /* finally add the E-part, if needed; it will never be 0, and has */ + /* a maximum length of 3 digits */ + if (e!=0) { + *c++='E'; /* starts with E */ + *c++='+'; /* assume positive */ + if (e<0) { + *(c-1)='-'; /* oops, need '-' */ + e=-e; /* uInt, please */ + } + u=&BIN2CHAR[e*4]; /* -> length byte */ + memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */ + c+=*u; /* bump pointer appropriately */ + } + *c='\0'; /* add terminator */ + /*printf("res %s\n", string); */ + return string; + } /* pre>0 */ + + /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ + t=c+1-pre; + *(t+1)='\0'; /* can add terminator now */ + for (; s>=cstart; s--, t--) *t=*s; /* shift whole coefficient right */ + c=cstart; + *c++='0'; /* always starts with 0. */ + *c++='.'; + for (; pre<0; pre++) *c++='0'; /* add any 0's after '.' */ + /*printf("res %s\n", string); */ + return string; + } /* decimal64ToString */ + +/* ------------------------------------------------------------------ */ +/* to-number -- conversion from numeric string */ +/* */ +/* decimal64FromString(result, string, set); */ +/* */ +/* result is the decimal64 format number which gets the result of */ +/* the conversion */ +/* *string is the character string which should contain a valid */ +/* number (which may be a special value) */ +/* set is the context */ +/* */ +/* The context is supplied to this routine is used for error handling */ +/* (setting of status and traps) and for the rounding mode, only. */ +/* If an error occurs, the result will be a valid decimal64 NaN. */ +/* ------------------------------------------------------------------ */ +decimal64 * decimal64FromString(decimal64 *result, const char *string, + decContext *set) { + decContext dc; /* work */ + decNumber dn; /* .. */ + + decContextDefault(&dc, DEC_INIT_DECIMAL64); /* no traps, please */ + dc.round=set->round; /* use supplied rounding */ + + decNumberFromString(&dn, string, &dc); /* will round if needed */ + + decimal64FromNumber(result, &dn, &dc); + if (dc.status!=0) { /* something happened */ + decContextSetStatus(set, dc.status); /* .. pass it on */ + } + return result; + } /* decimal64FromString */ + +/* ------------------------------------------------------------------ */ +/* decimal64IsCanonical -- test whether encoding is canonical */ +/* d64 is the source decimal64 */ +/* returns 1 if the encoding of d64 is canonical, 0 otherwise */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +uint32_t decimal64IsCanonical(const decimal64 *d64) { + decNumber dn; /* work */ + decimal64 canon; /* .. */ + decContext dc; /* .. */ + decContextDefault(&dc, DEC_INIT_DECIMAL64); + decimal64ToNumber(d64, &dn); + decimal64FromNumber(&canon, &dn, &dc);/* canon will now be canonical */ + return memcmp(d64, &canon, DECIMAL64_Bytes)==0; + } /* decimal64IsCanonical */ + +/* ------------------------------------------------------------------ */ +/* decimal64Canonical -- copy an encoding, ensuring it is canonical */ +/* d64 is the source decimal64 */ +/* result is the target (may be the same decimal64) */ +/* returns result */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) { + decNumber dn; /* work */ + decContext dc; /* .. */ + decContextDefault(&dc, DEC_INIT_DECIMAL64); + decimal64ToNumber(d64, &dn); + decimal64FromNumber(result, &dn, &dc);/* result will now be canonical */ + return result; + } /* decimal64Canonical */ + +#if DECTRACE || DECCHECK +/* Macros for accessing decimal64 fields. These assume the + argument is a reference (pointer) to the decimal64 structure, + and the decimal64 is in network byte order (big-endian) */ +/* Get sign */ +#define decimal64Sign(d) ((unsigned)(d)->bytes[0]>>7) + +/* Get combination field */ +#define decimal64Comb(d) (((d)->bytes[0] & 0x7c)>>2) + +/* Get exponent continuation [does not remove bias] */ +#define decimal64ExpCon(d) ((((d)->bytes[0] & 0x03)<<6) \ + | ((unsigned)(d)->bytes[1]>>2)) + +/* Set sign [this assumes sign previously 0] */ +#define decimal64SetSign(d, b) { \ + (d)->bytes[0]|=((unsigned)(b)<<7);} + +/* Set exponent continuation [does not apply bias] */ +/* This assumes range has been checked and exponent previously 0; */ +/* type of exponent must be unsigned */ +#define decimal64SetExpCon(d, e) { \ + (d)->bytes[0]|=(uint8_t)((e)>>6); \ + (d)->bytes[1]|=(uint8_t)(((e)&0x3F)<<2);} + +/* ------------------------------------------------------------------ */ +/* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */ +/* d64 -- the number to show */ +/* ------------------------------------------------------------------ */ +/* Also shows sign/cob/expconfields extracted */ +void decimal64Show(const decimal64 *d64) { + char buf[DECIMAL64_Bytes*2+1]; + Int i, j=0; + + if (DECLITEND) { + for (i=0; i<DECIMAL64_Bytes; i++, j+=2) { + sprintf(&buf[j], "%02x", d64->bytes[7-i]); + } + printf(" D64> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, + d64->bytes[7]>>7, (d64->bytes[7]>>2)&0x1f, + ((d64->bytes[7]&0x3)<<6)| (d64->bytes[6]>>2)); + } + else { /* big-endian */ + for (i=0; i<DECIMAL64_Bytes; i++, j+=2) { + sprintf(&buf[j], "%02x", d64->bytes[i]); + } + printf(" D64> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, + decimal64Sign(d64), decimal64Comb(d64), decimal64ExpCon(d64)); + } + } /* decimal64Show */ +#endif + +/* ================================================================== */ +/* Shared utility routines and tables */ +/* ================================================================== */ +/* define and include the conversion tables to use for shared code */ +#if DECDPUN==3 + #define DEC_DPD2BIN 1 +#else + #define DEC_DPD2BCD 1 +#endif +#include "decDPD.h" /* lookup tables */ + +/* The maximum number of decNumberUnits needed for a working copy of */ +/* the units array is the ceiling of digits/DECDPUN, where digits is */ +/* the maximum number of digits in any of the formats for which this */ +/* is used. decimal128.h must not be included in this module, so, as */ +/* a very special case, that number is defined as a literal here. */ +#define DECMAX754 34 +#define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN) + +/* ------------------------------------------------------------------ */ +/* Combination field lookup tables (uInts to save measurable work) */ +/* */ +/* COMBEXP - 2-bit most-significant-bits of exponent */ +/* [11 if an Infinity or NaN] */ +/* COMBMSD - 4-bit most-significant-digit */ +/* [0=Infinity, 1=NaN if COMBEXP=11] */ +/* */ +/* Both are indexed by the 5-bit combination field (0-31) */ +/* ------------------------------------------------------------------ */ +const uInt COMBEXP[32]={0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 1, 1, 2, 2, 3, 3}; +const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 8, 9, 8, 9, 0, 1}; + +/* ------------------------------------------------------------------ */ +/* decDigitsToDPD -- pack coefficient into DPD form */ +/* */ +/* dn is the source number (assumed valid, max DECMAX754 digits) */ +/* targ is 1, 2, or 4-element uInt array, which the caller must */ +/* have cleared to zeros */ +/* shift is the number of 0 digits to add on the right (normally 0) */ +/* */ +/* The coefficient must be known small enough to fit. The full */ +/* coefficient is copied, including the leading 'odd' digit. This */ +/* digit is retrieved and packed into the combination field by the */ +/* caller. */ +/* */ +/* The target uInts are altered only as necessary to receive the */ +/* digits of the decNumber. When more than one uInt is needed, they */ +/* are filled from left to right (that is, the uInt at offset 0 will */ +/* end up with the least-significant digits). */ +/* */ +/* shift is used for 'fold-down' padding. */ +/* */ +/* No error is possible. */ +/* ------------------------------------------------------------------ */ +#if DECDPUN<=4 +/* Constant multipliers for divide-by-power-of five using reciprocal */ +/* multiply, after removing powers of 2 by shifting, and final shift */ +/* of 17 [we only need up to **4] */ +static const uInt multies[]={131073, 26215, 5243, 1049, 210}; +/* QUOT10 -- macro to return the quotient of unit u divided by 10**n */ +#define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17) +#endif +void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { + Int cut; /* work */ + Int n; /* output bunch counter */ + Int digits=dn->digits; /* digit countdown */ + uInt dpd; /* densely packed decimal value */ + uInt bin; /* binary value 0-999 */ + uInt *uout=targ; /* -> current output uInt */ + uInt uoff=0; /* -> current output offset [from right] */ + const Unit *inu=dn->lsu; /* -> current input unit */ + Unit uar[DECMAXUNITS]; /* working copy of units, iff shifted */ + #if DECDPUN!=3 /* not fast path */ + Unit in; /* current unit */ + #endif + + if (shift!=0) { /* shift towards most significant required */ + /* shift the units array to the left by pad digits and copy */ + /* [this code is a special case of decShiftToMost, which could */ + /* be used instead if exposed and the array were copied first] */ + const Unit *source; /* .. */ + Unit *target, *first; /* .. */ + uInt next=0; /* work */ + + source=dn->lsu+D2U(digits)-1; /* where msu comes from */ + target=uar+D2U(digits)-1+D2U(shift);/* where upper part of first cut goes */ + cut=DECDPUN-MSUDIGITS(shift); /* where to slice */ + if (cut==0) { /* unit-boundary case */ + for (; source>=dn->lsu; source--, target--) *target=*source; + } + else { + first=uar+D2U(digits+shift)-1; /* where msu will end up */ + for (; source>=dn->lsu; source--, target--) { + /* split the source Unit and accumulate remainder for next */ + #if DECDPUN<=4 + uInt quot=QUOT10(*source, cut); + uInt rem=*source-quot*DECPOWERS[cut]; + next+=quot; + #else + uInt rem=*source%DECPOWERS[cut]; + next+=*source/DECPOWERS[cut]; + #endif + if (target<=first) *target=(Unit)next; /* write to target iff valid */ + next=rem*DECPOWERS[DECDPUN-cut]; /* save remainder for next Unit */ + } + } /* shift-move */ + /* propagate remainder to one below and clear the rest */ + for (; target>=uar; target--) { + *target=(Unit)next; + next=0; + } + digits+=shift; /* add count (shift) of zeros added */ + inu=uar; /* use units in working array */ + } + + /* now densely pack the coefficient into DPD declets */ + + #if DECDPUN!=3 /* not fast path */ + in=*inu; /* current unit */ + cut=0; /* at lowest digit */ + bin=0; /* [keep compiler quiet] */ + #endif + + for(n=0; digits>0; n++) { /* each output bunch */ + #if DECDPUN==3 /* fast path, 3-at-a-time */ + bin=*inu; /* 3 digits ready for convert */ + digits-=3; /* [may go negative] */ + inu++; /* may need another */ + + #else /* must collect digit-by-digit */ + Unit dig; /* current digit */ + Int j; /* digit-in-declet count */ + for (j=0; j<3; j++) { + #if DECDPUN<=4 + Unit temp=(Unit)((uInt)(in*6554)>>16); + dig=(Unit)(in-X10(temp)); + in=temp; + #else + dig=in%10; + in=in/10; + #endif + if (j==0) bin=dig; + else if (j==1) bin+=X10(dig); + else /* j==2 */ bin+=X100(dig); + digits--; + if (digits==0) break; /* [also protects *inu below] */ + cut++; + if (cut==DECDPUN) {inu++; in=*inu; cut=0;} + } + #endif + /* here there are 3 digits in bin, or have used all input digits */ + + dpd=BIN2DPD[bin]; + + /* write declet to uInt array */ + *uout|=dpd<<uoff; + uoff+=10; + if (uoff<32) continue; /* no uInt boundary cross */ + uout++; + uoff-=32; + *uout|=dpd>>(10-uoff); /* collect top bits */ + } /* n declets */ + return; + } /* decDigitsToDPD */ + +/* ------------------------------------------------------------------ */ +/* decDigitsFromDPD -- unpack a format's coefficient */ +/* */ +/* dn is the target number, with 7, 16, or 34-digit space. */ +/* sour is a 1, 2, or 4-element uInt array containing only declets */ +/* declets is the number of (right-aligned) declets in sour to */ +/* be processed. This may be 1 more than the obvious number in */ +/* a format, as any top digit is prefixed to the coefficient */ +/* continuation field. It also may be as small as 1, as the */ +/* caller may pre-process leading zero declets. */ +/* */ +/* When doing the 'extra declet' case care is taken to avoid writing */ +/* extra digits when there are leading zeros, as these could overflow */ +/* the units array when DECDPUN is not 3. */ +/* */ +/* The target uInts are used only as necessary to process declets */ +/* declets into the decNumber. When more than one uInt is needed, */ +/* they are used from left to right (that is, the uInt at offset 0 */ +/* provides the least-significant digits). */ +/* */ +/* dn->digits is set, but not the sign or exponent. */ +/* No error is possible [the redundant 888 codes are allowed]. */ +/* ------------------------------------------------------------------ */ +void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) { + + uInt dpd; /* collector for 10 bits */ + Int n; /* counter */ + Unit *uout=dn->lsu; /* -> current output unit */ + Unit *last=uout; /* will be unit containing msd */ + const uInt *uin=sour; /* -> current input uInt */ + uInt uoff=0; /* -> current input offset [from right] */ + + #if DECDPUN!=3 + uInt bcd; /* BCD result */ + uInt nibble; /* work */ + Unit out=0; /* accumulator */ + Int cut=0; /* power of ten in current unit */ + #endif + #if DECDPUN>4 + uInt const *pow; /* work */ + #endif + + /* Expand the densely-packed integer, right to left */ + for (n=declets-1; n>=0; n--) { /* count down declets of 10 bits */ + dpd=*uin>>uoff; + uoff+=10; + if (uoff>32) { /* crossed uInt boundary */ + uin++; + uoff-=32; + dpd|=*uin<<(10-uoff); /* get waiting bits */ + } + dpd&=0x3ff; /* clear uninteresting bits */ + + #if DECDPUN==3 + if (dpd==0) *uout=0; + else { + *uout=DPD2BIN[dpd]; /* convert 10 bits to binary 0-999 */ + last=uout; /* record most significant unit */ + } + uout++; + } /* n */ + + #else /* DECDPUN!=3 */ + if (dpd==0) { /* fastpath [e.g., leading zeros] */ + /* write out three 0 digits (nibbles); out may have digit(s) */ + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + if (n==0) break; /* [as below, works even if MSD=0] */ + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + continue; + } + + bcd=DPD2BCD[dpd]; /* convert 10 bits to 12 bits BCD */ + + /* now accumulate the 3 BCD nibbles into units */ + nibble=bcd & 0x00f; + if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + bcd>>=4; + + /* if this is the last declet and the remaining nibbles in bcd */ + /* are 00 then process no more nibbles, because this could be */ + /* the 'odd' MSD declet and writing any more Units would then */ + /* overflow the unit array */ + if (n==0 && !bcd) break; + + nibble=bcd & 0x00f; + if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + bcd>>=4; + + nibble=bcd & 0x00f; + if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); + cut++; + if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} + } /* n */ + if (cut!=0) { /* some more left over */ + *uout=out; /* write out final unit */ + if (out) last=uout; /* and note if non-zero */ + } + #endif + + /* here, last points to the most significant unit with digits; */ + /* inspect it to get the final digits count -- this is essentially */ + /* the same code as decGetDigits in decNumber.c */ + dn->digits=(last-dn->lsu)*DECDPUN+1; /* floor of digits, plus */ + /* must be at least 1 digit */ + #if DECDPUN>1 + if (*last<10) return; /* common odd digit or 0 */ + dn->digits++; /* must be 2 at least */ + #if DECDPUN>2 + if (*last<100) return; /* 10-99 */ + dn->digits++; /* must be 3 at least */ + #if DECDPUN>3 + if (*last<1000) return; /* 100-999 */ + dn->digits++; /* must be 4 at least */ + #if DECDPUN>4 + for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++; + #endif + #endif + #endif + #endif + return; + } /*decDigitsFromDPD */ -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 016/118] libdecnumber: Eliminate #include *Symbols.h 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (14 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 015/118] libdecnumber: Introduce libdecnumber Code Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 017/118] libdecnumber: Prepare libdecnumber for QEMU include structure Alexander Graf ` (59 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> The various *Symbols.h files were not copied from the original GCC libdecnumber library; they are not necessary for use in QEMU. Remove all instances of #include "*Symbols.h" Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- include/libdecnumber/decContext.h | 1 - include/libdecnumber/decDPD.h | 1 - include/libdecnumber/decNumber.h | 1 - include/libdecnumber/decNumberLocal.h | 2 -- include/libdecnumber/dpd/decimal128.h | 1 - include/libdecnumber/dpd/decimal32.h | 1 - include/libdecnumber/dpd/decimal64.h | 1 - 7 files changed, 8 deletions(-) diff --git a/include/libdecnumber/decContext.h b/include/libdecnumber/decContext.h index f80d03c..1a3f15e 100644 --- a/include/libdecnumber/decContext.h +++ b/include/libdecnumber/decContext.h @@ -237,7 +237,6 @@ /* decContext routines */ - #include "decContextSymbols.h" extern decContext * decContextClearStatus(decContext *, uint32_t); extern decContext * decContextDefault(decContext *, int32_t); diff --git a/include/libdecnumber/decDPD.h b/include/libdecnumber/decDPD.h index 3cc1d63..26a21ec 100644 --- a/include/libdecnumber/decDPD.h +++ b/include/libdecnumber/decDPD.h @@ -35,7 +35,6 @@ /* ------------------------------------------------------------------------ */ /* For details, see: http://www2.hursley.ibm.com/decimal/DPDecimal.html */ -#include "decDPDSymbols.h" /* This include file defines several DPD and BCD conversion tables: */ /* */ diff --git a/include/libdecnumber/decNumber.h b/include/libdecnumber/decNumber.h index 0a9fdce..aa99a5b 100644 --- a/include/libdecnumber/decNumber.h +++ b/include/libdecnumber/decNumber.h @@ -111,7 +111,6 @@ /* decNumber public functions and macros */ /* ---------------------------------------------------------------- */ - #include "decNumberSymbols.h" /* Conversions */ decNumber * decNumberFromInt32(decNumber *, int32_t); diff --git a/include/libdecnumber/decNumberLocal.h b/include/libdecnumber/decNumberLocal.h index f1568f7..f2a919b 100644 --- a/include/libdecnumber/decNumberLocal.h +++ b/include/libdecnumber/decNumberLocal.h @@ -100,7 +100,6 @@ extern const uByte DECSTICKYTAB[10]; /* re-round digits if sticky */ extern const uInt DECPOWERS[10]; /* powers of ten table */ /* The following are included from decDPD.h */ -#include "decDPDSymbols.h" extern const uShort DPD2BIN[1024]; /* DPD -> 0-999 */ extern const uShort BIN2DPD[1000]; /* 0-999 -> DPD */ extern const uInt DPD2BINK[1024]; /* DPD -> 0-999000 */ @@ -326,7 +325,6 @@ #define DFISSNAN(df) ((DFWORD(df, 0)&0x7e000000)==0x7e000000) /* Shared lookup tables */ -#include "decCommonSymbols.h" extern const uInt DECCOMBMSD[64]; /* Combination field -> MSD */ extern const uInt DECCOMBFROM[48]; /* exp+msd -> Combination */ diff --git a/include/libdecnumber/dpd/decimal128.h b/include/libdecnumber/dpd/decimal128.h index f8f5b5a..251b964 100644 --- a/include/libdecnumber/dpd/decimal128.h +++ b/include/libdecnumber/dpd/decimal128.h @@ -82,7 +82,6 @@ /* Routines */ /* ---------------------------------------------------------------- */ - #include "decimal128Symbols.h" /* String conversions */ decimal128 * decimal128FromString(decimal128 *, const char *, decContext *); diff --git a/include/libdecnumber/dpd/decimal32.h b/include/libdecnumber/dpd/decimal32.h index 0d53046..5f06cd4 100644 --- a/include/libdecnumber/dpd/decimal32.h +++ b/include/libdecnumber/dpd/decimal32.h @@ -80,7 +80,6 @@ /* Routines */ /* ---------------------------------------------------------------- */ - #include "decimal32Symbols.h" /* String conversions */ decimal32 * decimal32FromString(decimal32 *, const char *, decContext *); diff --git a/include/libdecnumber/dpd/decimal64.h b/include/libdecnumber/dpd/decimal64.h index 549b626..c391e25 100644 --- a/include/libdecnumber/dpd/decimal64.h +++ b/include/libdecnumber/dpd/decimal64.h @@ -82,7 +82,6 @@ /* Routines */ /* ---------------------------------------------------------------- */ - #include "decimal64Symbols.h" /* String conversions */ decimal64 * decimal64FromString(decimal64 *, const char *, decContext *); -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 017/118] libdecnumber: Prepare libdecnumber for QEMU include structure 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (15 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 016/118] libdecnumber: Eliminate #include *Symbols.h Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 018/118] libdecnumber: Modify dconfig.h to Integrate with QEMU Alexander Graf ` (58 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Consistent with other libraries in QEMU, the libdecnumber header files were placed in include/libdecnumber, separate from the C code. This is different from the original libdecnumber source, where they were co-located. Change the libdecnumber source code so that it reflects this split. Specifically, modify directives of the form: #include "xxx.h" to look like: #include "libdecnumber/xxx.h" Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- include/libdecnumber/decNumber.h | 2 +- include/libdecnumber/decNumberLocal.h | 2 +- include/libdecnumber/dpd/decimal128.h | 2 +- include/libdecnumber/dpd/decimal32.h | 2 +- include/libdecnumber/dpd/decimal64.h | 2 +- libdecnumber/decContext.c | 6 +++--- libdecnumber/decNumber.c | 6 +++--- libdecnumber/dpd/decimal128.c | 8 ++++---- libdecnumber/dpd/decimal32.c | 8 ++++---- libdecnumber/dpd/decimal64.c | 12 ++++++------ 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/include/libdecnumber/decNumber.h b/include/libdecnumber/decNumber.h index aa99a5b..fb324bd 100644 --- a/include/libdecnumber/decNumber.h +++ b/include/libdecnumber/decNumber.h @@ -39,7 +39,7 @@ #define DECAUTHOR "Mike Cowlishaw" /* Who to blame */ #if !defined(DECCONTEXT) - #include "decContext.h" + #include "libdecnumber/decContext.h" #endif /* Bit settings for decNumber.bits */ diff --git a/include/libdecnumber/decNumberLocal.h b/include/libdecnumber/decNumberLocal.h index f2a919b..f5f508f 100644 --- a/include/libdecnumber/decNumberLocal.h +++ b/include/libdecnumber/decNumberLocal.h @@ -44,7 +44,7 @@ #include <stdlib.h> /* for abs */ #include <string.h> /* for memset, strcpy */ - #include "dconfig.h" /* for WORDS_BIGENDIAN */ + #include "libdecnumber/dconfig.h" /* Conditional code flag -- set this to match hardware platform */ /* 1=little-endian, 0=big-endian */ diff --git a/include/libdecnumber/dpd/decimal128.h b/include/libdecnumber/dpd/decimal128.h index 251b964..7d9ee24 100644 --- a/include/libdecnumber/dpd/decimal128.h +++ b/include/libdecnumber/dpd/decimal128.h @@ -60,7 +60,7 @@ #define DECNUMDIGITS DECIMAL128_Pmax /* size if not already defined*/ #endif #ifndef DECNUMBER - #include "decNumber.h" /* context and number library */ + #include "libdecnumber/decNumber.h" #endif /* Decimal 128-bit type, accessible by bytes */ diff --git a/include/libdecnumber/dpd/decimal32.h b/include/libdecnumber/dpd/decimal32.h index 5f06cd4..de313e0 100644 --- a/include/libdecnumber/dpd/decimal32.h +++ b/include/libdecnumber/dpd/decimal32.h @@ -60,7 +60,7 @@ #define DECNUMDIGITS DECIMAL32_Pmax /* size if not already defined*/ #endif #ifndef DECNUMBER - #include "decNumber.h" /* context and number library */ + #include "libdecnumber/decNumber.h" #endif /* Decimal 32-bit type, accessible by bytes */ diff --git a/include/libdecnumber/dpd/decimal64.h b/include/libdecnumber/dpd/decimal64.h index c391e25..2f6c049 100644 --- a/include/libdecnumber/dpd/decimal64.h +++ b/include/libdecnumber/dpd/decimal64.h @@ -62,7 +62,7 @@ #define DECNUMDIGITS DECIMAL64_Pmax /* size if not already defined*/ #endif #ifndef DECNUMBER - #include "decNumber.h" /* context and number library */ + #include "libdecnumber/decNumber.h" #endif /* Decimal 64-bit type, accessible by bytes */ diff --git a/libdecnumber/decContext.c b/libdecnumber/decContext.c index 8d577f4..6847106 100644 --- a/libdecnumber/decContext.c +++ b/libdecnumber/decContext.c @@ -37,9 +37,9 @@ #include <string.h> /* for strcmp */ #include <stdio.h> /* for printf if DECCHECK */ -#include "dconfig.h" /* for GCC definitions */ -#include "decContext.h" /* context and base types */ -#include "decNumberLocal.h" /* decNumber local types, etc. */ +#include "libdecnumber/dconfig.h" +#include "libdecnumber/decContext.h" +#include "libdecnumber/decNumberLocal.h" #if DECCHECK /* compile-time endian tester [assumes sizeof(Int)>1] */ diff --git a/libdecnumber/decNumber.c b/libdecnumber/decNumber.c index f9a624a..1bfc081 100644 --- a/libdecnumber/decNumber.c +++ b/libdecnumber/decNumber.c @@ -170,9 +170,9 @@ #include <stdio.h> /* for printf [if needed] */ #include <string.h> /* for strcpy */ #include <ctype.h> /* for lower */ -#include "dconfig.h" /* for GCC definitions */ -#include "decNumber.h" /* base number library */ -#include "decNumberLocal.h" /* decNumber local types, etc. */ +#include "libdecnumber/dconfig.h" +#include "libdecnumber/decNumber.h" +#include "libdecnumber/decNumberLocal.h" /* Constants */ /* Public lookup table used by the D2U macro */ diff --git a/libdecnumber/dpd/decimal128.c b/libdecnumber/dpd/decimal128.c index 54191aa..8f8e983 100644 --- a/libdecnumber/dpd/decimal128.c +++ b/libdecnumber/dpd/decimal128.c @@ -42,11 +42,11 @@ #include <string.h> /* [for memset/memcpy] */ #include <stdio.h> /* [for printf] */ -#include "dconfig.h" /* GCC definitions */ +#include "libdecnumber/dconfig.h" #define DECNUMDIGITS 34 /* make decNumbers with space for 34 */ -#include "decNumber.h" /* base number library */ -#include "decNumberLocal.h" /* decNumber local types, etc. */ -#include "decimal128.h" /* our primary include */ +#include "libdecnumber/decNumber.h" +#include "libdecnumber/decNumberLocal.h" +#include "libdecnumber/dpd/decimal128.h" /* Utility routines and tables [in decimal64.c] */ extern const uInt COMBEXP[32], COMBMSD[32]; diff --git a/libdecnumber/dpd/decimal32.c b/libdecnumber/dpd/decimal32.c index d8e3f59..f8d30e6 100644 --- a/libdecnumber/dpd/decimal32.c +++ b/libdecnumber/dpd/decimal32.c @@ -42,11 +42,11 @@ #include <string.h> /* [for memset/memcpy] */ #include <stdio.h> /* [for printf] */ -#include "dconfig.h" /* GCC definitions */ +#include "libdecnumber/dconfig.h" #define DECNUMDIGITS 7 /* make decNumbers with space for 7 */ -#include "decNumber.h" /* base number library */ -#include "decNumberLocal.h" /* decNumber local types, etc. */ -#include "decimal32.h" /* our primary include */ +#include "libdecnumber/decNumber.h" +#include "libdecnumber/decNumberLocal.h" +#include "libdecnumber/dpd/decimal32.h" /* Utility tables and routines [in decimal64.c] */ extern const uInt COMBEXP[32], COMBMSD[32]; diff --git a/libdecnumber/dpd/decimal64.c b/libdecnumber/dpd/decimal64.c index 474eb7c..3bd2776 100644 --- a/libdecnumber/dpd/decimal64.c +++ b/libdecnumber/dpd/decimal64.c @@ -42,11 +42,11 @@ #include <string.h> /* [for memset/memcpy] */ #include <stdio.h> /* [for printf] */ -#include "dconfig.h" /* GCC definitions */ +#include "libdecnumber/dconfig.h" #define DECNUMDIGITS 16 /* make decNumbers with space for 16 */ -#include "decNumber.h" /* base number library */ -#include "decNumberLocal.h" /* decNumber local types, etc. */ -#include "decimal64.h" /* our primary include */ +#include "libdecnumber/decNumber.h" +#include "libdecnumber/decNumberLocal.h" +#include "libdecnumber/dpd/decimal64.h" /* Utility routines and tables [in decimal64.c]; externs for C++ */ extern const uInt COMBEXP[32], COMBMSD[32]; @@ -70,7 +70,7 @@ extern void decNumberShow(const decNumber *); /* .. */ #define DEC_BIN2CHAR 1 #define DEC_DPD2BIN 1 #define DEC_BIN2DPD 1 /* used for all sizes */ -#include "decDPD.h" /* lookup tables */ +#include "libdecnumber/decDPD.h" /* ------------------------------------------------------------------ */ /* decimal64FromNumber -- convert decNumber to decimal64 */ @@ -559,7 +559,7 @@ void decimal64Show(const decimal64 *d64) { #else #define DEC_DPD2BCD 1 #endif -#include "decDPD.h" /* lookup tables */ +#include "libdecnumber/decDPD.h" /* The maximum number of decNumberUnits needed for a working copy of */ /* the units array is the ceiling of digits/DECDPUN, where digits is */ -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 018/118] libdecnumber: Modify dconfig.h to Integrate with QEMU 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (16 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 017/118] libdecnumber: Prepare libdecnumber for QEMU include structure Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 019/118] libdecnumber: Change gstdint.h to stdint.h Alexander Graf ` (57 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Modify the dconfig.h header file so that libdecnumber code integrates QEMU configuration. Specifically: - the WORDS_BIGENDIAN preprocessor macro is used in libdecnumber code to determines endianness. It is derived from the existing QEMU macro HOST_WORDS_BIGENDIAN which is defined in config-host.h. - the DECPUN macro determines the number of decimal digits (aka declets) per unit (byte). This is 3 for PowerPC DFP. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- include/libdecnumber/dconfig.h | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/include/libdecnumber/dconfig.h b/include/libdecnumber/dconfig.h index ffbad25..2f0455a 100644 --- a/include/libdecnumber/dconfig.h +++ b/include/libdecnumber/dconfig.h @@ -27,26 +27,14 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifdef IN_LIBGCC2 +#include "config-host.h" -#include "tconfig.h" -#include "coretypes.h" -#include "tm.h" - -#ifndef LIBGCC2_WORDS_BIG_ENDIAN -#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN -#endif - -#ifndef LIBGCC2_FLOAT_WORDS_BIG_ENDIAN -#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN LIBGCC2_WORDS_BIG_ENDIAN -#endif - -#if LIBGCC2_FLOAT_WORDS_BIG_ENDIAN +#if defined(HOST_WORDS_BIGENDIAN) #define WORDS_BIGENDIAN 1 -#endif - #else +#define WORDS_BIGENDIAN 0 +#endif -#include "config.h" - +#ifndef DECDPUN +#define DECDPUN 3 #endif -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 019/118] libdecnumber: Change gstdint.h to stdint.h 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (17 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 018/118] libdecnumber: Modify dconfig.h to Integrate with QEMU Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 020/118] libdecnumber: Eliminate redundant declarations Alexander Graf ` (56 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Replace the inclusion of gstdint.h with the standard stdint.h header file. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- include/libdecnumber/decContext.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libdecnumber/decContext.h b/include/libdecnumber/decContext.h index 1a3f15e..c3e46f4 100644 --- a/include/libdecnumber/decContext.h +++ b/include/libdecnumber/decContext.h @@ -56,7 +56,7 @@ #define DECCFULLNAME "Decimal Context Descriptor" /* Verbose name */ #define DECCAUTHOR "Mike Cowlishaw" /* Who to blame */ - #include "gstdint.h" /* C99 standard integers */ + #include <stdint.h> #include <stdio.h> /* for printf, etc. */ #include <signal.h> /* for traps */ -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 020/118] libdecnumber: Eliminate redundant declarations 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (18 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 019/118] libdecnumber: Change gstdint.h to stdint.h Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 021/118] libdecnumber: Eliminate Unused Variable in decSetSubnormal Alexander Graf ` (55 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Eliminate redundant declarations of symbols DPD2BIN and BIN2DPD in various .c source files. These symbols are already declared in decDPD.h and thus will trigger 'redundant redeclaration of ?XXX?' warnings, which, of course, may fail QEMU compilation. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- libdecnumber/dpd/decimal128.c | 2 -- libdecnumber/dpd/decimal32.c | 2 -- libdecnumber/dpd/decimal64.c | 2 -- 3 files changed, 6 deletions(-) diff --git a/libdecnumber/dpd/decimal128.c b/libdecnumber/dpd/decimal128.c index 8f8e983..7551b7c 100644 --- a/libdecnumber/dpd/decimal128.c +++ b/libdecnumber/dpd/decimal128.c @@ -50,8 +50,6 @@ /* Utility routines and tables [in decimal64.c] */ extern const uInt COMBEXP[32], COMBMSD[32]; -extern const uShort DPD2BIN[1024]; -extern const uShort BIN2DPD[1000]; /* [not used] */ extern const uByte BIN2CHAR[4001]; extern void decDigitsFromDPD(decNumber *, const uInt *, Int); diff --git a/libdecnumber/dpd/decimal32.c b/libdecnumber/dpd/decimal32.c index f8d30e6..095ab75 100644 --- a/libdecnumber/dpd/decimal32.c +++ b/libdecnumber/dpd/decimal32.c @@ -50,8 +50,6 @@ /* Utility tables and routines [in decimal64.c] */ extern const uInt COMBEXP[32], COMBMSD[32]; -extern const uShort DPD2BIN[1024]; -extern const uShort BIN2DPD[1000]; extern const uByte BIN2CHAR[4001]; extern void decDigitsToDPD(const decNumber *, uInt *, Int); diff --git a/libdecnumber/dpd/decimal64.c b/libdecnumber/dpd/decimal64.c index 3bd2776..8256084 100644 --- a/libdecnumber/dpd/decimal64.c +++ b/libdecnumber/dpd/decimal64.c @@ -50,8 +50,6 @@ /* Utility routines and tables [in decimal64.c]; externs for C++ */ extern const uInt COMBEXP[32], COMBMSD[32]; -extern const uShort DPD2BIN[1024]; -extern const uShort BIN2DPD[1000]; extern const uByte BIN2CHAR[4001]; extern void decDigitsFromDPD(decNumber *, const uInt *, Int); -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 021/118] libdecnumber: Eliminate Unused Variable in decSetSubnormal 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (19 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 020/118] libdecnumber: Eliminate redundant declarations Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 022/118] target-ppc: Enable Building of libdecnumber Alexander Graf ` (54 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Eliminate an unused variable in the decSetSubnormal routine. The variable dnexp is declared and eventually set but never used, and thus may trigger an unused-but-set-variable warning. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- libdecnumber/decNumber.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libdecnumber/decNumber.c b/libdecnumber/decNumber.c index 1bfc081..f6b6eb1 100644 --- a/libdecnumber/decNumber.c +++ b/libdecnumber/decNumber.c @@ -7403,7 +7403,6 @@ static void decSetMaxValue(decNumber *dn, decContext *set) { /* ------------------------------------------------------------------ */ static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue, uInt *status) { - Int dnexp; /* saves original exponent */ decContext workset; /* work */ Int etiny, adjust; /* .. */ @@ -7448,7 +7447,6 @@ static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue, /* adjust>0, so need to rescale the result so exponent becomes Etiny */ /* [this code is similar to that in rescale] */ - dnexp=dn->exponent; /* save exponent */ workset=*set; /* clone rounding, etc. */ workset.digits=dn->digits-adjust; /* set requested length */ workset.emin-=adjust; /* and adjust emin to match */ -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 022/118] target-ppc: Enable Building of libdecnumber 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (20 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 021/118] libdecnumber: Eliminate Unused Variable in decSetSubnormal Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 023/118] libdecnumber: Introduce decNumberFrom[U]Int64 Alexander Graf ` (53 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Enable compilation of the newly added libdecnumber library code. Object file targets are added to Makefile.target using a newly introduced flag CONFIG_LIBDECNUMBER. The flag is added to the PowerPC targets (ppc[64]-linux-user, ppc[64]-softmmu). Signed-off-by: Tom Musta <tommusta@gmail.com> [agraf: add ppcemb and ppc64abi32 config] Signed-off-by: Alexander Graf <agraf@suse.de> --- Makefile.target | 6 ++++++ default-configs/ppc-linux-user.mak | 1 + default-configs/ppc-softmmu.mak | 1 + default-configs/ppc64-linux-user.mak | 1 + default-configs/ppc64-softmmu.mak | 1 + default-configs/ppc64abi32-linux-user.mak | 1 + default-configs/ppcemb-softmmu.mak | 1 + 7 files changed, 12 insertions(+) diff --git a/Makefile.target b/Makefile.target index 9986047..ace209a 100644 --- a/Makefile.target +++ b/Makefile.target @@ -85,6 +85,12 @@ obj-y += disas.o obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o +obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/decContext.o +obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/decNumber.o +obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/dpd/decimal32.o +obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/dpd/decimal64.o +obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/dpd/decimal128.o + ######################################################### # Linux user emulator target diff --git a/default-configs/ppc-linux-user.mak b/default-configs/ppc-linux-user.mak index 6273df2..260ba41 100644 --- a/default-configs/ppc-linux-user.mak +++ b/default-configs/ppc-linux-user.mak @@ -1 +1,2 @@ # Default configuration for ppc-linux-user +CONFIG_LIBDECNUMBER=y diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak index 07c51ce..33f8d84 100644 --- a/default-configs/ppc-softmmu.mak +++ b/default-configs/ppc-softmmu.mak @@ -49,3 +49,4 @@ CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) CONFIG_MC146818RTC=y CONFIG_ETSEC=y CONFIG_ISA_TESTDEV=y +CONFIG_LIBDECNUMBER=y diff --git a/default-configs/ppc64-linux-user.mak b/default-configs/ppc64-linux-user.mak index 422d3fb..e731ce0 100644 --- a/default-configs/ppc64-linux-user.mak +++ b/default-configs/ppc64-linux-user.mak @@ -1 +1,2 @@ # Default configuration for ppc64-linux-user +CONFIG_LIBDECNUMBER=y diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak index e2beac6..37a15b7 100644 --- a/default-configs/ppc64-softmmu.mak +++ b/default-configs/ppc64-softmmu.mak @@ -58,3 +58,4 @@ CONFIG_I82374=y CONFIG_I8257=y CONFIG_MC146818RTC=y CONFIG_ISA_TESTDEV=y +CONFIG_LIBDECNUMBER=y diff --git a/default-configs/ppc64abi32-linux-user.mak b/default-configs/ppc64abi32-linux-user.mak index 1c657ec..c244d07 100644 --- a/default-configs/ppc64abi32-linux-user.mak +++ b/default-configs/ppc64abi32-linux-user.mak @@ -1 +1,2 @@ # Default configuration for ppc64abi32-linux-user +CONFIG_LIBDECNUMBER=y diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak index 1e4fde2..e032761 100644 --- a/default-configs/ppcemb-softmmu.mak +++ b/default-configs/ppcemb-softmmu.mak @@ -16,3 +16,4 @@ CONFIG_I8259=y CONFIG_XILINX=y CONFIG_XILINX_ETHLITE=y CONFIG_OPENPIC=y +CONFIG_LIBDECNUMBER=y -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 023/118] libdecnumber: Introduce decNumberFrom[U]Int64 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (21 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 022/118] target-ppc: Enable Building of libdecnumber Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 024/118] libdecnumber: Introduce decNumberIntegralToInt64 Alexander Graf ` (52 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Introduce two conversion functions to the libdecnumber library. These conversions transform 64 bit integers to the internal decNumber representation. Both a signed and unsigned version is added. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- include/libdecnumber/decNumber.h | 2 ++ libdecnumber/decNumber.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/libdecnumber/decNumber.h b/include/libdecnumber/decNumber.h index fb324bd..f4bf994 100644 --- a/include/libdecnumber/decNumber.h +++ b/include/libdecnumber/decNumber.h @@ -115,6 +115,8 @@ /* Conversions */ decNumber * decNumberFromInt32(decNumber *, int32_t); decNumber * decNumberFromUInt32(decNumber *, uint32_t); + decNumber *decNumberFromInt64(decNumber *, int64_t); + decNumber *decNumberFromUInt64(decNumber *, uint64_t); decNumber * decNumberFromString(decNumber *, const char *, decContext *); char * decNumberToString(const decNumber *, char *); char * decNumberToEngString(const decNumber *, char *); diff --git a/libdecnumber/decNumber.c b/libdecnumber/decNumber.c index f6b6eb1..6bd7565 100644 --- a/libdecnumber/decNumber.c +++ b/libdecnumber/decNumber.c @@ -436,6 +436,36 @@ uInt decNumberToUInt32(const decNumber *dn, decContext *set) { return 0; } /* decNumberToUInt32 */ +decNumber *decNumberFromInt64(decNumber *dn, int64_t in) +{ + uint64_t unsig = in; + if (in < 0) { + unsig = -unsig; + } + + decNumberFromUInt64(dn, unsig); + if (in < 0) { + dn->bits = DECNEG; /* sign needed */ + } + return dn; +} /* decNumberFromInt64 */ + +decNumber *decNumberFromUInt64(decNumber *dn, uint64_t uin) +{ + Unit *up; /* work pointer */ + decNumberZero(dn); /* clean */ + if (uin == 0) { + return dn; /* [or decGetDigits bad call] */ + } + for (up = dn->lsu; uin > 0; up++) { + *up = (Unit)(uin % (DECDPUNMAX + 1)); + uin = uin / (DECDPUNMAX + 1); + } + dn->digits = decGetDigits(dn->lsu, up-dn->lsu); + return dn; +} /* decNumberFromUInt64 */ + + /* ------------------------------------------------------------------ */ /* to-scientific-string -- conversion to numeric string */ /* to-engineering-string -- conversion to numeric string */ -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 024/118] libdecnumber: Introduce decNumberIntegralToInt64 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (22 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 023/118] libdecnumber: Introduce decNumberFrom[U]Int64 Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 025/118] libdecnumber: Fix decNumberSetBCD Alexander Graf ` (51 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Introduce a new conversion function to the libdecnumber library. This function converts a decNumber to a signed 64-bit integer. In order to support 64-bit integers (which may have up to 19 decimal digits), the existing "powers of 10" array is expanded from 10 to 19 entries. Signed-off-by: Tom Musta <tommusta@gmail.com> [agraf: fix 32bit host compile] Signed-off-by: Alexander Graf <agraf@suse.de> --- include/libdecnumber/decNumber.h | 1 + include/libdecnumber/decNumberLocal.h | 2 +- libdecnumber/decContext.c | 6 +++-- libdecnumber/decNumber.c | 46 ++++++++++++++++++++++++++++++++++- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/include/libdecnumber/decNumber.h b/include/libdecnumber/decNumber.h index f4bf994..9fa4e6a 100644 --- a/include/libdecnumber/decNumber.h +++ b/include/libdecnumber/decNumber.h @@ -122,6 +122,7 @@ char * decNumberToEngString(const decNumber *, char *); uint32_t decNumberToUInt32(const decNumber *, decContext *); int32_t decNumberToInt32(const decNumber *, decContext *); + int64_t decNumberIntegralToInt64(const decNumber *dn, decContext *set); uint8_t * decNumberGetBCD(const decNumber *, uint8_t *); decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t); diff --git a/include/libdecnumber/decNumberLocal.h b/include/libdecnumber/decNumberLocal.h index f5f508f..cd4eb79 100644 --- a/include/libdecnumber/decNumberLocal.h +++ b/include/libdecnumber/decNumberLocal.h @@ -98,7 +98,7 @@ /* Shared lookup tables */ extern const uByte DECSTICKYTAB[10]; /* re-round digits if sticky */ - extern const uInt DECPOWERS[10]; /* powers of ten table */ + extern const uLong DECPOWERS[19]; /* powers of ten table */ /* The following are included from decDPD.h */ extern const uShort DPD2BIN[1024]; /* DPD -> 0-999 */ extern const uShort BIN2DPD[1000]; /* 0-999 -> DPD */ diff --git a/libdecnumber/decContext.c b/libdecnumber/decContext.c index 6847106..8b6ae21 100644 --- a/libdecnumber/decContext.c +++ b/libdecnumber/decContext.c @@ -56,8 +56,10 @@ const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */ /* ------------------------------------------------------------------ */ /* Powers of ten (powers[n]==10**n, 0<=n<=9) */ /* ------------------------------------------------------------------ */ -const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000, - 10000000, 100000000, 1000000000}; +const uLong DECPOWERS[19] = {1, 10, 100, 1000, 10000, 100000, 1000000, + 10000000, 100000000, 1000000000, 10000000000ULL, 100000000000ULL, + 1000000000000ULL, 10000000000000ULL, 100000000000000ULL, 1000000000000000ULL, + 10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL, }; /* ------------------------------------------------------------------ */ /* decContextClearStatus -- clear bits in current status */ diff --git a/libdecnumber/decNumber.c b/libdecnumber/decNumber.c index 6bd7565..6164a77 100644 --- a/libdecnumber/decNumber.c +++ b/libdecnumber/decNumber.c @@ -465,6 +465,50 @@ decNumber *decNumberFromUInt64(decNumber *dn, uint64_t uin) return dn; } /* decNumberFromUInt64 */ +/* ------------------------------------------------------------------ */ +/* to-int64 -- conversion to int64 */ +/* */ +/* dn is the decNumber to convert. dn is assumed to have been */ +/* rounded to a floating point integer value. */ +/* set is the context for reporting errors */ +/* returns the converted decNumber, or 0 if Invalid is set */ +/* */ +/* Invalid is set if the decNumber is a NaN, Infinite or is out of */ +/* range for a signed 64 bit integer. */ +/* ------------------------------------------------------------------ */ + +int64_t decNumberIntegralToInt64(const decNumber *dn, decContext *set) +{ + if (decNumberIsSpecial(dn) || (dn->exponent < 0) || + (dn->digits + dn->exponent > 19)) { + goto Invalid; + } else { + int64_t d; /* work */ + const Unit *up; /* .. */ + uint64_t hi = 0; + up = dn->lsu; /* -> lsu */ + + for (d = 1; d <= dn->digits; up++, d += DECDPUN) { + uint64_t prev = hi; + hi += *up * powers[d-1]; + if ((hi < prev) || (hi > INT64_MAX)) { + goto Invalid; + } + } + + uint64_t prev = hi; + hi *= (uint64_t)powers[dn->exponent]; + if ((hi < prev) || (hi > INT64_MAX)) { + goto Invalid; + } + return (decNumberIsNegative(dn)) ? -((int64_t)hi) : (int64_t)hi; + } + +Invalid: + decContextSetStatus(set, DEC_Invalid_operation); + return 0; +} /* decNumberIntegralToInt64 */ + /* ------------------------------------------------------------------ */ /* to-scientific-string -- conversion to numeric string */ @@ -4259,7 +4303,7 @@ static decNumber * decDivideOp(decNumber *res, uByte bits; /* working sign */ Unit *target; /* work */ const Unit *source; /* .. */ - uInt const *pow; /* .. */ + uLong const *pow; /* .. */ Int shift, cut; /* .. */ #if DECSUBSET Int dropped; /* work */ -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 025/118] libdecnumber: Fix decNumberSetBCD 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (23 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 024/118] libdecnumber: Introduce decNumberIntegralToInt64 Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 026/118] target-ppc: Define FPR Pointer Type for Helpers Alexander Graf ` (50 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Fix a simple bug in the decNumberSetBCD() function. This function encodes a decNumber with "n" BCD digits. The original code erroneously computed the number of declets from the dn argument, which is the output decNumber value, and hence may contain garbage. Instead, the input "n" value is used. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- libdecnumber/decNumber.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdecnumber/decNumber.c b/libdecnumber/decNumber.c index 6164a77..a30632f 100644 --- a/libdecnumber/decNumber.c +++ b/libdecnumber/decNumber.c @@ -3541,7 +3541,7 @@ uByte * decNumberGetBCD(const decNumber *dn, uint8_t *bcd) { /* and bcd[0] zero. */ /* ------------------------------------------------------------------ */ decNumber * decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) { - Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [target pointer] */ + Unit *up = dn->lsu + D2U(n) - 1; /* -> msu [target pointer] */ const uByte *ub=bcd; /* -> source msd */ #if DECDPUN==1 /* trivial simple copy */ -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 026/118] target-ppc: Define FPR Pointer Type for Helpers 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (24 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 025/118] libdecnumber: Fix decNumberSetBCD Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 027/118] target-ppc: Introduce Generator Macros for DFP Arithmetic Forms Alexander Graf ` (49 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Define a floating pointer register pointer type in the PowerPC helper header. The type will be used to pass FPR register operands to Decimal Floating Point (DFP) helpers. A pointer is used because the quad word forms of PowerPC DFP instructions operate on adjacent pairs of floating point registers and thus can be thought of as arrays of length 2. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/helper.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 08f3916..22d5466 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -611,3 +611,7 @@ DEF_HELPER_3(store_dbatu, void, env, i32, tl) DEF_HELPER_3(store_601_batl, void, env, i32, tl) DEF_HELPER_3(store_601_batu, void, env, i32, tl) #endif + +#define dh_alias_fprp ptr +#define dh_ctype_fprp uint64_t * +#define dh_is_signed_fprp dh_is_signed_ptr -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 027/118] target-ppc: Introduce Generator Macros for DFP Arithmetic Forms 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (25 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 026/118] target-ppc: Define FPR Pointer Type for Helpers Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 028/118] target-ppc: Introduce Decoder Macros for DFP Alexander Graf ` (48 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add general support for generators of PowerPC Decimal Floating Point helpers. Some utilities are annotated with GCC attribute unused in order to preserve build bisection. These annotations will be removed in later patches. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/translate.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 6283b2c..7383c8a 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -466,6 +466,12 @@ EXTRACT_HELPER(AA, 1, 1); /* Link */ EXTRACT_HELPER(LK, 0, 1); +/* DFP Z22-form */ +EXTRACT_HELPER(DCM, 10, 6) + +/* DFP Z23-form */ +EXTRACT_HELPER(RMC, 9, 2) + /* Create a mask between <start> and <end> bits */ static inline target_ulong MASK(uint32_t start, uint32_t end) { @@ -502,6 +508,7 @@ EXTRACT_HELPER_SPLIT(xC, 3, 1, 6, 5); EXTRACT_HELPER(DM, 8, 2); EXTRACT_HELPER(UIM, 16, 2); EXTRACT_HELPER(SHW, 8, 2); +EXTRACT_HELPER(SP, 19, 2); /*****************************************************************************/ /* PowerPC instructions table */ @@ -8179,6 +8186,176 @@ static void gen_xxsldwi(DisasContext *ctx) tcg_temp_free_i64(xtl); } +/*** Decimal Floating Point ***/ + +static inline TCGv_ptr gen_fprp_ptr(int reg) +{ + TCGv_ptr r = tcg_temp_new_ptr(); + tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, fpr[reg])); + return r; +} + +#if defined(TARGET_PPC64) +__attribute__ ((unused)) +static void gen_set_cr6_from_fpscr(DisasContext *ctx) +{ + TCGv_i32 tmp = tcg_temp_new_i32(); + tcg_gen_trunc_tl_i32(tmp, cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], tmp, 28); + tcg_temp_free_i32(tmp); +} +#else +__attribute__ ((unused)) +static void gen_set_cr6_from_fpscr(DisasContext *ctx) +{ + tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28); +} +#endif + +#define GEN_DFP_T_A_B_Rc(name) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_ptr rd, ra, rb; \ + if (unlikely(!ctx->fpu_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ + return; \ + } \ + gen_update_nip(ctx, ctx->nip - 4); \ + rd = gen_fprp_ptr(rD(ctx->opcode)); \ + ra = gen_fprp_ptr(rA(ctx->opcode)); \ + rb = gen_fprp_ptr(rB(ctx->opcode)); \ + gen_helper_##name(cpu_env, rd, ra, rb); \ + if (unlikely(Rc(ctx->opcode) != 0)) { \ + gen_set_cr6_from_fpscr(ctx); \ + } \ + tcg_temp_free_ptr(rd); \ + tcg_temp_free_ptr(ra); \ + tcg_temp_free_ptr(rb); \ +} + +#define GEN_DFP_BF_A_B(name) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_ptr ra, rb; \ + if (unlikely(!ctx->fpu_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ + return; \ + } \ + gen_update_nip(ctx, ctx->nip - 4); \ + ra = gen_fprp_ptr(rA(ctx->opcode)); \ + rb = gen_fprp_ptr(rB(ctx->opcode)); \ + gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \ + cpu_env, ra, rb); \ + tcg_temp_free_ptr(ra); \ + tcg_temp_free_ptr(rb); \ +} + +#define GEN_DFP_BF_A_DCM(name) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_ptr ra; \ + TCGv_i32 dcm; \ + if (unlikely(!ctx->fpu_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ + return; \ + } \ + gen_update_nip(ctx, ctx->nip - 4); \ + ra = gen_fprp_ptr(rA(ctx->opcode)); \ + dcm = tcg_const_i32(DCM(ctx->opcode)); \ + gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \ + cpu_env, ra, dcm); \ + tcg_temp_free_ptr(ra); \ + tcg_temp_free_i32(dcm); \ +} + +#define GEN_DFP_T_B_U32_U32_Rc(name, u32f1, u32f2) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_ptr rt, rb; \ + TCGv_i32 u32_1, u32_2; \ + if (unlikely(!ctx->fpu_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ + return; \ + } \ + gen_update_nip(ctx, ctx->nip - 4); \ + rt = gen_fprp_ptr(rD(ctx->opcode)); \ + rb = gen_fprp_ptr(rB(ctx->opcode)); \ + u32_1 = tcg_const_i32(u32f1(ctx->opcode)); \ + u32_2 = tcg_const_i32(u32f2(ctx->opcode)); \ + gen_helper_##name(cpu_env, rt, rb, u32_1, u32_2); \ + if (unlikely(Rc(ctx->opcode) != 0)) { \ + gen_set_cr6_from_fpscr(ctx); \ + } \ + tcg_temp_free_ptr(rt); \ + tcg_temp_free_ptr(rb); \ + tcg_temp_free_i32(u32_1); \ + tcg_temp_free_i32(u32_2); \ +} + +#define GEN_DFP_T_A_B_I32_Rc(name, i32fld) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_ptr rt, ra, rb; \ + TCGv_i32 i32; \ + if (unlikely(!ctx->fpu_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ + return; \ + } \ + gen_update_nip(ctx, ctx->nip - 4); \ + rt = gen_fprp_ptr(rD(ctx->opcode)); \ + ra = gen_fprp_ptr(rA(ctx->opcode)); \ + rb = gen_fprp_ptr(rB(ctx->opcode)); \ + i32 = tcg_const_i32(i32fld(ctx->opcode)); \ + gen_helper_##name(cpu_env, rt, ra, rb, i32); \ + if (unlikely(Rc(ctx->opcode) != 0)) { \ + gen_set_cr6_from_fpscr(ctx); \ + } \ + tcg_temp_free_ptr(rt); \ + tcg_temp_free_ptr(rb); \ + tcg_temp_free_ptr(ra); \ + tcg_temp_free_i32(i32); \ + } + +#define GEN_DFP_T_B_Rc(name) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_ptr rt, rb; \ + if (unlikely(!ctx->fpu_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ + return; \ + } \ + gen_update_nip(ctx, ctx->nip - 4); \ + rt = gen_fprp_ptr(rD(ctx->opcode)); \ + rb = gen_fprp_ptr(rB(ctx->opcode)); \ + gen_helper_##name(cpu_env, rt, rb); \ + if (unlikely(Rc(ctx->opcode) != 0)) { \ + gen_set_cr6_from_fpscr(ctx); \ + } \ + tcg_temp_free_ptr(rt); \ + tcg_temp_free_ptr(rb); \ + } + +#define GEN_DFP_T_FPR_I32_Rc(name, fprfld, i32fld) \ +static void gen_##name(DisasContext *ctx) \ +{ \ + TCGv_ptr rt, rs; \ + TCGv_i32 i32; \ + if (unlikely(!ctx->fpu_enabled)) { \ + gen_exception(ctx, POWERPC_EXCP_FPU); \ + return; \ + } \ + gen_update_nip(ctx, ctx->nip - 4); \ + rt = gen_fprp_ptr(rD(ctx->opcode)); \ + rs = gen_fprp_ptr(fprfld(ctx->opcode)); \ + i32 = tcg_const_i32(i32fld(ctx->opcode)); \ + gen_helper_##name(cpu_env, rt, rs, i32); \ + if (unlikely(Rc(ctx->opcode) != 0)) { \ + gen_set_cr6_from_fpscr(ctx); \ + } \ + tcg_temp_free_ptr(rt); \ + tcg_temp_free_ptr(rs); \ + tcg_temp_free_i32(i32); \ +} /*** SPE extension ***/ /* Register moves */ -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 028/118] target-ppc: Introduce Decoder Macros for DFP 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (26 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 027/118] target-ppc: Introduce Generator Macros for DFP Arithmetic Forms Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 029/118] target-ppc: Introduce DFP Helper Utilities Alexander Graf ` (47 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add decoder macros for the various Decimal Floating Point instruction forms. Illegal instruction masks are used to not only guard against reserved instruction field use, but also to catch illegal quad word forms that use odd-numbered floating point registers. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/translate.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 7383c8a..2953dd3 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -11175,6 +11175,115 @@ GEN_XXSEL_ROW(0x1F) GEN_XX3FORM_DM(xxpermdi, 0x08, 0x01), +#undef GEN_DFP_T_A_B_Rc +#undef GEN_DFP_BF_A_B +#undef GEN_DFP_BF_A_DCM +#undef GEN_DFP_T_B_U32_U32_Rc +#undef GEN_DFP_T_A_B_I32_Rc +#undef GEN_DFP_T_B_Rc +#undef GEN_DFP_T_FPR_I32_Rc + +#define _GEN_DFP_LONG(name, op1, op2, mask) \ +GEN_HANDLER_E(name, 0x3B, op1, op2, mask, PPC_NONE, PPC2_DFP) + +#define _GEN_DFP_LONGx2(name, op1, op2, mask) \ +GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \ +GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP) + +#define _GEN_DFP_LONGx4(name, op1, op2, mask) \ +GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \ +GEN_HANDLER_E(name, 0x3B, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \ +GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \ +GEN_HANDLER_E(name, 0x3B, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP) + +#define _GEN_DFP_QUAD(name, op1, op2, mask) \ +GEN_HANDLER_E(name, 0x3F, op1, op2, mask, PPC_NONE, PPC2_DFP) + +#define _GEN_DFP_QUADx2(name, op1, op2, mask) \ +GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \ +GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP) + +#define _GEN_DFP_QUADx4(name, op1, op2, mask) \ +GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \ +GEN_HANDLER_E(name, 0x3F, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \ +GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \ +GEN_HANDLER_E(name, 0x3F, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP) + +#define GEN_DFP_T_A_B_Rc(name, op1, op2) \ +_GEN_DFP_LONG(name, op1, op2, 0x00000000) + +#define GEN_DFP_Tp_Ap_Bp_Rc(name, op1, op2) \ +_GEN_DFP_QUAD(name, op1, op2, 0x00210800) + +#define GEN_DFP_Tp_A_Bp_Rc(name, op1, op2) \ +_GEN_DFP_QUAD(name, op1, op2, 0x00200800) + +#define GEN_DFP_T_B_Rc(name, op1, op2) \ +_GEN_DFP_LONG(name, op1, op2, 0x001F0000) + +#define GEN_DFP_Tp_Bp_Rc(name, op1, op2) \ +_GEN_DFP_QUAD(name, op1, op2, 0x003F0800) + +#define GEN_DFP_Tp_B_Rc(name, op1, op2) \ +_GEN_DFP_QUAD(name, op1, op2, 0x003F0000) + +#define GEN_DFP_T_Bp_Rc(name, op1, op2) \ +_GEN_DFP_QUAD(name, op1, op2, 0x001F0800) + +#define GEN_DFP_BF_A_B(name, op1, op2) \ +_GEN_DFP_LONG(name, op1, op2, 0x00000001) + +#define GEN_DFP_BF_Ap_Bp(name, op1, op2) \ +_GEN_DFP_QUAD(name, op1, op2, 0x00610801) + +#define GEN_DFP_BF_A_Bp(name, op1, op2) \ +_GEN_DFP_QUAD(name, op1, op2, 0x00600801) + +#define GEN_DFP_BF_A_DCM(name, op1, op2) \ +_GEN_DFP_LONGx2(name, op1, op2, 0x00600001) + +#define GEN_DFP_BF_Ap_DCM(name, op1, op2) \ +_GEN_DFP_QUADx2(name, op1, op2, 0x00610001) + +#define GEN_DFP_T_A_B_RMC_Rc(name, op1, op2) \ +_GEN_DFP_LONGx4(name, op1, op2, 0x00000000) + +#define GEN_DFP_Tp_Ap_Bp_RMC_Rc(name, op1, op2) \ +_GEN_DFP_QUADx4(name, op1, op2, 0x02010800) + +#define GEN_DFP_Tp_A_Bp_RMC_Rc(name, op1, op2) \ +_GEN_DFP_QUADx4(name, op1, op2, 0x02000800) + +#define GEN_DFP_TE_T_B_RMC_Rc(name, op1, op2) \ +_GEN_DFP_LONGx4(name, op1, op2, 0x00000000) + +#define GEN_DFP_TE_Tp_Bp_RMC_Rc(name, op1, op2) \ +_GEN_DFP_QUADx4(name, op1, op2, 0x00200800) + +#define GEN_DFP_R_T_B_RMC_Rc(name, op1, op2) \ +_GEN_DFP_LONGx4(name, op1, op2, 0x001E0000) + +#define GEN_DFP_R_Tp_Bp_RMC_Rc(name, op1, op2) \ +_GEN_DFP_QUADx4(name, op1, op2, 0x003E0800) + +#define GEN_DFP_SP_T_B_Rc(name, op1, op2) \ +_GEN_DFP_LONG(name, op1, op2, 0x00070000) + +#define GEN_DFP_SP_Tp_Bp_Rc(name, op1, op2) \ +_GEN_DFP_QUAD(name, op1, op2, 0x00270800) + +#define GEN_DFP_S_T_B_Rc(name, op1, op2) \ +_GEN_DFP_LONG(name, op1, op2, 0x000F0000) + +#define GEN_DFP_S_Tp_Bp_Rc(name, op1, op2) \ +_GEN_DFP_QUAD(name, op1, op2, 0x002F0800) + +#define GEN_DFP_T_A_SH_Rc(name, op1, op2) \ +_GEN_DFP_LONGx2(name, op1, op2, 0x00000000) + +#define GEN_DFP_Tp_Ap_SH_Rc(name, op1, op2) \ +_GEN_DFP_QUADx2(name, op1, op2, 0x00210000) + #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 029/118] target-ppc: Introduce DFP Helper Utilities 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (27 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 028/118] target-ppc: Introduce Decoder Macros for DFP Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 030/118] target-ppc: Introduce DFP Post Processor Utilities Alexander Graf ` (46 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add a new file (dfp_helper.c) to the PowerPC implementation for Decimal Floating Point (DFP) emulation. This first version of the file declares a structure that will be used by DFP helpers. It also implements utilities that will initialize such a structure for either a long (64 bit) DFP instruction or an extended (128 bit, aka "quad") instruction. Some utility functions are annotated with the unused attribute in order to preserve build bisection. Signed-off-by: Tom Musta <tommusta@gmail.com> [agraf: Add never reached assert on dfp_prepare_rounding_mode()] Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/Makefile.objs | 1 + target-ppc/dfp_helper.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 target-ppc/dfp_helper.c diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs index 3cb23e0..a7ae392 100644 --- a/target-ppc/Makefile.objs +++ b/target-ppc/Makefile.objs @@ -6,6 +6,7 @@ obj-$(TARGET_PPC64) += mmu-hash64.o arch_dump.o endif obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o +obj-y += dfp_helper.o obj-y += excp_helper.o obj-y += fpu_helper.o obj-y += int_helper.o diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c new file mode 100644 index 0000000..b4f0139 --- /dev/null +++ b/target-ppc/dfp_helper.c @@ -0,0 +1,132 @@ +/* + * PowerPC Decimal Floating Point (DPF) emulation helpers for QEMU. + * + * Copyright (c) 2014 IBM Corporation. + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include "cpu.h" +#include "exec/helper-proto.h" + +#define DECNUMDIGITS 34 +#include "libdecnumber/decContext.h" +#include "libdecnumber/decNumber.h" +#include "libdecnumber/dpd/decimal32.h" +#include "libdecnumber/dpd/decimal64.h" +#include "libdecnumber/dpd/decimal128.h" + +#if defined(HOST_WORDS_BIGENDIAN) +#define HI_IDX 0 +#define LO_IDX 1 +#else +#define HI_IDX 1 +#define LO_IDX 0 +#endif + +struct PPC_DFP { + CPUPPCState *env; + uint64_t t64[2], a64[2], b64[2]; + decNumber t, a, b; + decContext context; + uint8_t crbf; +}; + +static void dfp_prepare_rounding_mode(decContext *context, uint64_t fpscr) +{ + enum rounding rnd; + + switch ((fpscr >> 32) & 0x7) { + case 0: + rnd = DEC_ROUND_HALF_EVEN; + break; + case 1: + rnd = DEC_ROUND_DOWN; + break; + case 2: + rnd = DEC_ROUND_CEILING; + break; + case 3: + rnd = DEC_ROUND_FLOOR; + break; + case 4: + rnd = DEC_ROUND_HALF_UP; + break; + case 5: + rnd = DEC_ROUND_HALF_DOWN; + break; + case 6: + rnd = DEC_ROUND_UP; + break; + case 7: + rnd = DEC_ROUND_05UP; + break; + default: + g_assert_not_reached(); + } + + decContextSetRounding(context, rnd); +} + +__attribute__ ((unused)) +static void dfp_prepare_decimal64(struct PPC_DFP *dfp, uint64_t *a, + uint64_t *b, CPUPPCState *env) +{ + decContextDefault(&dfp->context, DEC_INIT_DECIMAL64); + dfp_prepare_rounding_mode(&dfp->context, env->fpscr); + dfp->env = env; + + if (a) { + dfp->a64[0] = *a; + decimal64ToNumber((decimal64 *)dfp->a64, &dfp->a); + } else { + dfp->a64[0] = 0; + decNumberZero(&dfp->a); + } + + if (b) { + dfp->b64[0] = *b; + decimal64ToNumber((decimal64 *)dfp->b64, &dfp->b); + } else { + dfp->b64[0] = 0; + decNumberZero(&dfp->b); + } +} + +__attribute__ ((unused)) +static void dfp_prepare_decimal128(struct PPC_DFP *dfp, uint64_t *a, + uint64_t *b, CPUPPCState *env) +{ + decContextDefault(&dfp->context, DEC_INIT_DECIMAL128); + dfp_prepare_rounding_mode(&dfp->context, env->fpscr); + dfp->env = env; + + if (a) { + dfp->a64[0] = a[HI_IDX]; + dfp->a64[1] = a[LO_IDX]; + decimal128ToNumber((decimal128 *)dfp->a64, &dfp->a); + } else { + dfp->a64[0] = dfp->a64[1] = 0; + decNumberZero(&dfp->a); + } + + if (b) { + dfp->b64[0] = b[HI_IDX]; + dfp->b64[1] = b[LO_IDX]; + decimal128ToNumber((decimal128 *)dfp->b64, &dfp->b); + } else { + dfp->b64[0] = dfp->b64[1] = 0; + decNumberZero(&dfp->b); + } +} -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 030/118] target-ppc: Introduce DFP Post Processor Utilities 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (28 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 029/118] target-ppc: Introduce DFP Helper Utilities Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 031/118] target-ppc: Introduce DFP Add Alexander Graf ` (45 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add post-processing utilities to the PowerPC Decimal Floating Point (DFP) helper code. Post-processors are small routines that execute after a preliminary DFP result is computed. They are used, among other things, to compute status bits. This change defines a function type for post processors as well as a generic routine to run a list (array) of post-processors. Actual post-processor implementations will be added as needed by specific DFP helpers in subsequent changes. Some routines are annotated with the GCC unused attribute in order to preserve build bisection. The annotation will be removed in subsequent patches. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index b4f0139..9e9bc57 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -130,3 +130,34 @@ static void dfp_prepare_decimal128(struct PPC_DFP *dfp, uint64_t *a, decNumberZero(&dfp->b); } } + +#define FP_FX (1ull << FPSCR_FX) +#define FP_FEX (1ull << FPSCR_FEX) +#define FP_OX (1ull << FPSCR_OX) +#define FP_OE (1ull << FPSCR_OE) +#define FP_UX (1ull << FPSCR_UX) +#define FP_UE (1ull << FPSCR_UE) +#define FP_XX (1ull << FPSCR_XX) +#define FP_XE (1ull << FPSCR_XE) +#define FP_ZX (1ull << FPSCR_ZX) +#define FP_ZE (1ull << FPSCR_ZE) +#define FP_VX (1ull << FPSCR_VX) +#define FP_VXSNAN (1ull << FPSCR_VXSNAN) +#define FP_VXISI (1ull << FPSCR_VXISI) +#define FP_VXIMZ (1ull << FPSCR_VXIMZ) +#define FP_VXZDZ (1ull << FPSCR_VXZDZ) +#define FP_VXIDI (1ull << FPSCR_VXIDI) +#define FP_VXVC (1ull << FPSCR_VXVC) +#define FP_VXCVI (1ull << FPSCR_VXCVI) +#define FP_VE (1ull << FPSCR_VE) +#define FP_FI (1ull << FPSCR_FI) + +__attribute__ ((unused)) +static void dfp_set_FPSCR_flag(struct PPC_DFP *dfp, uint64_t flag, + uint64_t enabled) +{ + dfp->env->fpscr |= (flag | FP_FX); + if (dfp->env->fpscr & enabled) { + dfp->env->fpscr |= FP_FEX; + } +} -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 031/118] target-ppc: Introduce DFP Add 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (29 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 030/118] target-ppc: Introduce DFP Post Processor Utilities Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 032/118] target-ppc: Introduce DFP Subtract Alexander Graf ` (44 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Add instructions dadd[q][.] Various GCC unused annotations are removed since it is now safe to remove them. Signed-off-by: Tom Musta <tommusta@gmail.com> [agraf: move brace in function definition] Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++-- target-ppc/helper.h | 3 ++ target-ppc/translate.c | 7 ++- 3 files changed, 134 insertions(+), 5 deletions(-) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 9e9bc57..9f4cd33 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -79,7 +79,6 @@ static void dfp_prepare_rounding_mode(decContext *context, uint64_t fpscr) decContextSetRounding(context, rnd); } -__attribute__ ((unused)) static void dfp_prepare_decimal64(struct PPC_DFP *dfp, uint64_t *a, uint64_t *b, CPUPPCState *env) { @@ -104,7 +103,6 @@ static void dfp_prepare_decimal64(struct PPC_DFP *dfp, uint64_t *a, } } -__attribute__ ((unused)) static void dfp_prepare_decimal128(struct PPC_DFP *dfp, uint64_t *a, uint64_t *b, CPUPPCState *env) { @@ -152,7 +150,6 @@ static void dfp_prepare_decimal128(struct PPC_DFP *dfp, uint64_t *a, #define FP_VE (1ull << FPSCR_VE) #define FP_FI (1ull << FPSCR_FI) -__attribute__ ((unused)) static void dfp_set_FPSCR_flag(struct PPC_DFP *dfp, uint64_t flag, uint64_t enabled) { @@ -161,3 +158,129 @@ static void dfp_set_FPSCR_flag(struct PPC_DFP *dfp, uint64_t flag, dfp->env->fpscr |= FP_FEX; } } + +static void dfp_set_FPRF_from_FRT_with_context(struct PPC_DFP *dfp, + decContext *context) +{ + uint64_t fprf = 0; + + /* construct FPRF */ + switch (decNumberClass(&dfp->t, context)) { + case DEC_CLASS_SNAN: + fprf = 0x01; + break; + case DEC_CLASS_QNAN: + fprf = 0x11; + break; + case DEC_CLASS_NEG_INF: + fprf = 0x09; + break; + case DEC_CLASS_NEG_NORMAL: + fprf = 0x08; + break; + case DEC_CLASS_NEG_SUBNORMAL: + fprf = 0x18; + break; + case DEC_CLASS_NEG_ZERO: + fprf = 0x12; + break; + case DEC_CLASS_POS_ZERO: + fprf = 0x02; + break; + case DEC_CLASS_POS_SUBNORMAL: + fprf = 0x14; + break; + case DEC_CLASS_POS_NORMAL: + fprf = 0x04; + break; + case DEC_CLASS_POS_INF: + fprf = 0x05; + break; + default: + assert(0); /* should never get here */ + } + dfp->env->fpscr &= ~(0x1F << 12); + dfp->env->fpscr |= (fprf << 12); +} + +static void dfp_set_FPRF_from_FRT(struct PPC_DFP *dfp) +{ + dfp_set_FPRF_from_FRT_with_context(dfp, &dfp->context); +} + +static void dfp_check_for_OX(struct PPC_DFP *dfp) +{ + if (dfp->context.status & DEC_Overflow) { + dfp_set_FPSCR_flag(dfp, FP_OX, FP_OE); + } +} + +static void dfp_check_for_UX(struct PPC_DFP *dfp) +{ + if (dfp->context.status & DEC_Underflow) { + dfp_set_FPSCR_flag(dfp, FP_UX, FP_UE); + } +} + +static void dfp_check_for_XX(struct PPC_DFP *dfp) +{ + if (dfp->context.status & DEC_Inexact) { + dfp_set_FPSCR_flag(dfp, FP_XX | FP_FI, FP_XE); + } +} + +static void dfp_check_for_VXSNAN(struct PPC_DFP *dfp) +{ + if (dfp->context.status & DEC_Invalid_operation) { + if (decNumberIsSNaN(&dfp->a) || decNumberIsSNaN(&dfp->b)) { + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE); + } + } +} + +static void dfp_check_for_VXISI(struct PPC_DFP *dfp, int testForSameSign) +{ + if (dfp->context.status & DEC_Invalid_operation) { + if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) { + int same = decNumberClass(&dfp->a, &dfp->context) == + decNumberClass(&dfp->b, &dfp->context); + if ((same && testForSameSign) || (!same && !testForSameSign)) { + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXISI, FP_VE); + } + } + } +} + +static void dfp_check_for_VXISI_add(struct PPC_DFP *dfp) +{ + dfp_check_for_VXISI(dfp, 0); +} + +#define DFP_HELPER_TAB(op, dnop, postprocs, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \ +{ \ + struct PPC_DFP dfp; \ + dfp_prepare_decimal##size(&dfp, a, b, env); \ + dnop(&dfp.t, &dfp.a, &dfp.b, &dfp.context); \ + decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \ + postprocs(&dfp); \ + if (size == 64) { \ + t[0] = dfp.t64[0]; \ + } else if (size == 128) { \ + t[0] = dfp.t64[HI_IDX]; \ + t[1] = dfp.t64[LO_IDX]; \ + } \ +} + +static void ADD_PPs(struct PPC_DFP *dfp) +{ + dfp_set_FPRF_from_FRT(dfp); + dfp_check_for_OX(dfp); + dfp_check_for_UX(dfp); + dfp_check_for_XX(dfp); + dfp_check_for_VXSNAN(dfp); + dfp_check_for_VXISI_add(dfp); +} + +DFP_HELPER_TAB(dadd, decNumberAdd, ADD_PPs, 64) +DFP_HELPER_TAB(daddq, decNumberAdd, ADD_PPs, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 22d5466..99e6198 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -615,3 +615,6 @@ DEF_HELPER_3(store_601_batu, void, env, i32, tl) #define dh_alias_fprp ptr #define dh_ctype_fprp uint64_t * #define dh_is_signed_fprp dh_is_signed_ptr + +DEF_HELPER_4(dadd, void, env, fprp, fprp, fprp) +DEF_HELPER_4(daddq, void, env, fprp, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 2953dd3..b65b848 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8196,7 +8196,6 @@ static inline TCGv_ptr gen_fprp_ptr(int reg) } #if defined(TARGET_PPC64) -__attribute__ ((unused)) static void gen_set_cr6_from_fpscr(DisasContext *ctx) { TCGv_i32 tmp = tcg_temp_new_i32(); @@ -8205,7 +8204,6 @@ static void gen_set_cr6_from_fpscr(DisasContext *ctx) tcg_temp_free_i32(tmp); } #else -__attribute__ ((unused)) static void gen_set_cr6_from_fpscr(DisasContext *ctx) { tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28); @@ -8357,6 +8355,9 @@ static void gen_##name(DisasContext *ctx) \ tcg_temp_free_i32(i32); \ } +GEN_DFP_T_A_B_Rc(dadd) +GEN_DFP_T_A_B_Rc(daddq) + /*** SPE extension ***/ /* Register moves */ @@ -11284,6 +11285,8 @@ _GEN_DFP_LONGx2(name, op1, op2, 0x00000000) #define GEN_DFP_Tp_Ap_SH_Rc(name, op1, op2) \ _GEN_DFP_QUADx2(name, op1, op2, 0x00210000) +GEN_DFP_T_A_B_Rc(dadd, 0x02, 0x00), +GEN_DFP_Tp_Ap_Bp_Rc(daddq, 0x02, 0x00), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 032/118] target-ppc: Introduce DFP Subtract 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (30 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 031/118] target-ppc: Introduce DFP Add Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 033/118] target-ppc: Introduce DFP Multiply Alexander Graf ` (43 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Subtract instructions dsub[q][.] Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 18 ++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 5 ++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 9f4cd33..d6d0c2d 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -256,6 +256,11 @@ static void dfp_check_for_VXISI_add(struct PPC_DFP *dfp) dfp_check_for_VXISI(dfp, 0); } +static void dfp_check_for_VXISI_subtract(struct PPC_DFP *dfp) +{ + dfp_check_for_VXISI(dfp, 1); +} + #define DFP_HELPER_TAB(op, dnop, postprocs, size) \ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \ { \ @@ -284,3 +289,16 @@ static void ADD_PPs(struct PPC_DFP *dfp) DFP_HELPER_TAB(dadd, decNumberAdd, ADD_PPs, 64) DFP_HELPER_TAB(daddq, decNumberAdd, ADD_PPs, 128) + +static void SUB_PPs(struct PPC_DFP *dfp) +{ + dfp_set_FPRF_from_FRT(dfp); + dfp_check_for_OX(dfp); + dfp_check_for_UX(dfp); + dfp_check_for_XX(dfp); + dfp_check_for_VXSNAN(dfp); + dfp_check_for_VXISI_subtract(dfp); +} + +DFP_HELPER_TAB(dsub, decNumberSubtract, SUB_PPs, 64) +DFP_HELPER_TAB(dsubq, decNumberSubtract, SUB_PPs, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 99e6198..d560e53 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -618,3 +618,5 @@ DEF_HELPER_3(store_601_batu, void, env, i32, tl) DEF_HELPER_4(dadd, void, env, fprp, fprp, fprp) DEF_HELPER_4(daddq, void, env, fprp, fprp, fprp) +DEF_HELPER_4(dsub, void, env, fprp, fprp, fprp) +DEF_HELPER_4(dsubq, void, env, fprp, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index b65b848..d4077c2 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8357,7 +8357,8 @@ static void gen_##name(DisasContext *ctx) \ GEN_DFP_T_A_B_Rc(dadd) GEN_DFP_T_A_B_Rc(daddq) - +GEN_DFP_T_A_B_Rc(dsub) +GEN_DFP_T_A_B_Rc(dsubq) /*** SPE extension ***/ /* Register moves */ @@ -11287,6 +11288,8 @@ _GEN_DFP_QUADx2(name, op1, op2, 0x00210000) GEN_DFP_T_A_B_Rc(dadd, 0x02, 0x00), GEN_DFP_Tp_Ap_Bp_Rc(daddq, 0x02, 0x00), +GEN_DFP_T_A_B_Rc(dsub, 0x02, 0x10), +GEN_DFP_Tp_Ap_Bp_Rc(dsubq, 0x02, 0x10), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 033/118] target-ppc: Introduce DFP Multiply 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (31 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 032/118] target-ppc: Introduce DFP Subtract Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 034/118] target-ppc: Introduce DFP Divide Alexander Graf ` (42 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Multiply instructions dmul[q][.] Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 23 +++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 ++++ 3 files changed, 29 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index d6d0c2d..e6c1098 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -261,6 +261,16 @@ static void dfp_check_for_VXISI_subtract(struct PPC_DFP *dfp) dfp_check_for_VXISI(dfp, 1); } +static void dfp_check_for_VXIMZ(struct PPC_DFP *dfp) +{ + if (dfp->context.status & DEC_Invalid_operation) { + if ((decNumberIsInfinite(&dfp->a) && decNumberIsZero(&dfp->b)) || + (decNumberIsInfinite(&dfp->b) && decNumberIsZero(&dfp->a))) { + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXIMZ, FP_VE); + } + } +} + #define DFP_HELPER_TAB(op, dnop, postprocs, size) \ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \ { \ @@ -302,3 +312,16 @@ static void SUB_PPs(struct PPC_DFP *dfp) DFP_HELPER_TAB(dsub, decNumberSubtract, SUB_PPs, 64) DFP_HELPER_TAB(dsubq, decNumberSubtract, SUB_PPs, 128) + +static void MUL_PPs(struct PPC_DFP *dfp) +{ + dfp_set_FPRF_from_FRT(dfp); + dfp_check_for_OX(dfp); + dfp_check_for_UX(dfp); + dfp_check_for_XX(dfp); + dfp_check_for_VXSNAN(dfp); + dfp_check_for_VXIMZ(dfp); +} + +DFP_HELPER_TAB(dmul, decNumberMultiply, MUL_PPs, 64) +DFP_HELPER_TAB(dmulq, decNumberMultiply, MUL_PPs, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index d560e53..ac23556 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -620,3 +620,5 @@ DEF_HELPER_4(dadd, void, env, fprp, fprp, fprp) DEF_HELPER_4(daddq, void, env, fprp, fprp, fprp) DEF_HELPER_4(dsub, void, env, fprp, fprp, fprp) DEF_HELPER_4(dsubq, void, env, fprp, fprp, fprp) +DEF_HELPER_4(dmul, void, env, fprp, fprp, fprp) +DEF_HELPER_4(dmulq, void, env, fprp, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index d4077c2..e1ab41f 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8359,6 +8359,8 @@ GEN_DFP_T_A_B_Rc(dadd) GEN_DFP_T_A_B_Rc(daddq) GEN_DFP_T_A_B_Rc(dsub) GEN_DFP_T_A_B_Rc(dsubq) +GEN_DFP_T_A_B_Rc(dmul) +GEN_DFP_T_A_B_Rc(dmulq) /*** SPE extension ***/ /* Register moves */ @@ -11290,6 +11292,8 @@ GEN_DFP_T_A_B_Rc(dadd, 0x02, 0x00), GEN_DFP_Tp_Ap_Bp_Rc(daddq, 0x02, 0x00), GEN_DFP_T_A_B_Rc(dsub, 0x02, 0x10), GEN_DFP_Tp_Ap_Bp_Rc(dsubq, 0x02, 0x10), +GEN_DFP_T_A_B_Rc(dmul, 0x02, 0x01), +GEN_DFP_Tp_Ap_Bp_Rc(dmulq, 0x02, 0x01), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 034/118] target-ppc: Introduce DFP Divide 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (32 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 033/118] target-ppc: Introduce DFP Multiply Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 035/118] target-ppc: Introduce DFP Compares Alexander Graf ` (41 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Divide instructions ddiv[q][.] Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 38 ++++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 ++++ 3 files changed, 44 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index e6c1098..2dca9d4 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -229,6 +229,13 @@ static void dfp_check_for_XX(struct PPC_DFP *dfp) } } +static void dfp_check_for_ZX(struct PPC_DFP *dfp) +{ + if (dfp->context.status & DEC_Division_by_zero) { + dfp_set_FPSCR_flag(dfp, FP_ZX, FP_ZE); + } +} + static void dfp_check_for_VXSNAN(struct PPC_DFP *dfp) { if (dfp->context.status & DEC_Invalid_operation) { @@ -271,6 +278,22 @@ static void dfp_check_for_VXIMZ(struct PPC_DFP *dfp) } } +static void dfp_check_for_VXZDZ(struct PPC_DFP *dfp) +{ + if (dfp->context.status & DEC_Division_undefined) { + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXZDZ, FP_VE); + } +} + +static void dfp_check_for_VXIDI(struct PPC_DFP *dfp) +{ + if (dfp->context.status & DEC_Invalid_operation) { + if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) { + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXIDI, FP_VE); + } + } +} + #define DFP_HELPER_TAB(op, dnop, postprocs, size) \ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \ { \ @@ -325,3 +348,18 @@ static void MUL_PPs(struct PPC_DFP *dfp) DFP_HELPER_TAB(dmul, decNumberMultiply, MUL_PPs, 64) DFP_HELPER_TAB(dmulq, decNumberMultiply, MUL_PPs, 128) + +static void DIV_PPs(struct PPC_DFP *dfp) +{ + dfp_set_FPRF_from_FRT(dfp); + dfp_check_for_OX(dfp); + dfp_check_for_UX(dfp); + dfp_check_for_ZX(dfp); + dfp_check_for_XX(dfp); + dfp_check_for_VXSNAN(dfp); + dfp_check_for_VXZDZ(dfp); + dfp_check_for_VXIDI(dfp); +} + +DFP_HELPER_TAB(ddiv, decNumberDivide, DIV_PPs, 64) +DFP_HELPER_TAB(ddivq, decNumberDivide, DIV_PPs, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index ac23556..f0c0306 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -622,3 +622,5 @@ DEF_HELPER_4(dsub, void, env, fprp, fprp, fprp) DEF_HELPER_4(dsubq, void, env, fprp, fprp, fprp) DEF_HELPER_4(dmul, void, env, fprp, fprp, fprp) DEF_HELPER_4(dmulq, void, env, fprp, fprp, fprp) +DEF_HELPER_4(ddiv, void, env, fprp, fprp, fprp) +DEF_HELPER_4(ddivq, void, env, fprp, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index e1ab41f..56d331e 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8361,6 +8361,8 @@ GEN_DFP_T_A_B_Rc(dsub) GEN_DFP_T_A_B_Rc(dsubq) GEN_DFP_T_A_B_Rc(dmul) GEN_DFP_T_A_B_Rc(dmulq) +GEN_DFP_T_A_B_Rc(ddiv) +GEN_DFP_T_A_B_Rc(ddivq) /*** SPE extension ***/ /* Register moves */ @@ -11294,6 +11296,8 @@ GEN_DFP_T_A_B_Rc(dsub, 0x02, 0x10), GEN_DFP_Tp_Ap_Bp_Rc(dsubq, 0x02, 0x10), GEN_DFP_T_A_B_Rc(dmul, 0x02, 0x01), GEN_DFP_Tp_Ap_Bp_Rc(dmulq, 0x02, 0x01), +GEN_DFP_T_A_B_Rc(ddiv, 0x02, 0x11), +GEN_DFP_Tp_Ap_Bp_Rc(ddivq, 0x02, 0x11), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 035/118] target-ppc: Introduce DFP Compares 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (33 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 034/118] target-ppc: Introduce DFP Divide Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 036/118] target-ppc: Introduce DFP Test Data Class Alexander Graf ` (40 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Compare instructions dcmpu[q] and dcmpo[q]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 4 ++++ target-ppc/translate.c | 8 +++++++ 3 files changed, 70 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 2dca9d4..1816f44 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -294,6 +294,32 @@ static void dfp_check_for_VXIDI(struct PPC_DFP *dfp) } } +static void dfp_check_for_VXVC(struct PPC_DFP *dfp) +{ + if (decNumberIsNaN(&dfp->a) || decNumberIsNaN(&dfp->b)) { + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXVC, FP_VE); + } +} + +static void dfp_set_CRBF_from_T(struct PPC_DFP *dfp) +{ + if (decNumberIsNaN(&dfp->t)) { + dfp->crbf = 1; + } else if (decNumberIsZero(&dfp->t)) { + dfp->crbf = 2; + } else if (decNumberIsNegative(&dfp->t)) { + dfp->crbf = 8; + } else { + dfp->crbf = 4; + } +} + +static void dfp_set_FPCC_from_CRBF(struct PPC_DFP *dfp) +{ + dfp->env->fpscr &= ~(0xF << 12); + dfp->env->fpscr |= (dfp->crbf << 12); +} + #define DFP_HELPER_TAB(op, dnop, postprocs, size) \ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \ { \ @@ -363,3 +389,35 @@ static void DIV_PPs(struct PPC_DFP *dfp) DFP_HELPER_TAB(ddiv, decNumberDivide, DIV_PPs, 64) DFP_HELPER_TAB(ddivq, decNumberDivide, DIV_PPs, 128) + +#define DFP_HELPER_BF_AB(op, dnop, postprocs, size) \ +uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b) \ +{ \ + struct PPC_DFP dfp; \ + dfp_prepare_decimal##size(&dfp, a, b, env); \ + dnop(&dfp.t, &dfp.a, &dfp.b, &dfp.context); \ + decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \ + postprocs(&dfp); \ + return dfp.crbf; \ +} + +static void CMPU_PPs(struct PPC_DFP *dfp) +{ + dfp_set_CRBF_from_T(dfp); + dfp_set_FPCC_from_CRBF(dfp); + dfp_check_for_VXSNAN(dfp); +} + +DFP_HELPER_BF_AB(dcmpu, decNumberCompare, CMPU_PPs, 64) +DFP_HELPER_BF_AB(dcmpuq, decNumberCompare, CMPU_PPs, 128) + +static void CMPO_PPs(struct PPC_DFP *dfp) +{ + dfp_set_CRBF_from_T(dfp); + dfp_set_FPCC_from_CRBF(dfp); + dfp_check_for_VXSNAN(dfp); + dfp_check_for_VXVC(dfp); +} + +DFP_HELPER_BF_AB(dcmpo, decNumberCompare, CMPO_PPs, 64) +DFP_HELPER_BF_AB(dcmpoq, decNumberCompare, CMPO_PPs, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index f0c0306..2bbae63 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -624,3 +624,7 @@ DEF_HELPER_4(dmul, void, env, fprp, fprp, fprp) DEF_HELPER_4(dmulq, void, env, fprp, fprp, fprp) DEF_HELPER_4(ddiv, void, env, fprp, fprp, fprp) DEF_HELPER_4(ddivq, void, env, fprp, fprp, fprp) +DEF_HELPER_3(dcmpo, i32, env, fprp, fprp) +DEF_HELPER_3(dcmpoq, i32, env, fprp, fprp) +DEF_HELPER_3(dcmpu, i32, env, fprp, fprp) +DEF_HELPER_3(dcmpuq, i32, env, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 56d331e..e708640 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8363,6 +8363,10 @@ GEN_DFP_T_A_B_Rc(dmul) GEN_DFP_T_A_B_Rc(dmulq) GEN_DFP_T_A_B_Rc(ddiv) GEN_DFP_T_A_B_Rc(ddivq) +GEN_DFP_BF_A_B(dcmpu) +GEN_DFP_BF_A_B(dcmpuq) +GEN_DFP_BF_A_B(dcmpo) +GEN_DFP_BF_A_B(dcmpoq) /*** SPE extension ***/ /* Register moves */ @@ -11298,6 +11302,10 @@ GEN_DFP_T_A_B_Rc(dmul, 0x02, 0x01), GEN_DFP_Tp_Ap_Bp_Rc(dmulq, 0x02, 0x01), GEN_DFP_T_A_B_Rc(ddiv, 0x02, 0x11), GEN_DFP_Tp_Ap_Bp_Rc(ddivq, 0x02, 0x11), +GEN_DFP_BF_A_B(dcmpu, 0x02, 0x14), +GEN_DFP_BF_Ap_Bp(dcmpuq, 0x02, 0x14), +GEN_DFP_BF_A_B(dcmpo, 0x02, 0x04), +GEN_DFP_BF_Ap_Bp(dcmpoq, 0x02, 0x04), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 036/118] target-ppc: Introduce DFP Test Data Class 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (34 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 035/118] target-ppc: Introduce DFP Compares Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 037/118] target-ppc: Introduce DFP Test Data Group Alexander Graf ` (39 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Test Data Class instructions dtstdc[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 28 ++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 ++++ 3 files changed, 34 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 1816f44..fcd6fef 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -421,3 +421,31 @@ static void CMPO_PPs(struct PPC_DFP *dfp) DFP_HELPER_BF_AB(dcmpo, decNumberCompare, CMPO_PPs, 64) DFP_HELPER_BF_AB(dcmpoq, decNumberCompare, CMPO_PPs, 128) + +#define DFP_HELPER_TSTDC(op, size) \ +uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint32_t dcm) \ +{ \ + struct PPC_DFP dfp; \ + int match = 0; \ + \ + dfp_prepare_decimal##size(&dfp, a, 0, env); \ + \ + match |= (dcm & 0x20) && decNumberIsZero(&dfp.a); \ + match |= (dcm & 0x10) && decNumberIsSubnormal(&dfp.a, &dfp.context); \ + match |= (dcm & 0x08) && decNumberIsNormal(&dfp.a, &dfp.context); \ + match |= (dcm & 0x04) && decNumberIsInfinite(&dfp.a); \ + match |= (dcm & 0x02) && decNumberIsQNaN(&dfp.a); \ + match |= (dcm & 0x01) && decNumberIsSNaN(&dfp.a); \ + \ + if (decNumberIsNegative(&dfp.a)) { \ + dfp.crbf = match ? 0xA : 0x8; \ + } else { \ + dfp.crbf = match ? 0x2 : 0x0; \ + } \ + \ + dfp_set_FPCC_from_CRBF(&dfp); \ + return dfp.crbf; \ +} + +DFP_HELPER_TSTDC(dtstdc, 64) +DFP_HELPER_TSTDC(dtstdcq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 2bbae63..5a1e05e 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -628,3 +628,5 @@ DEF_HELPER_3(dcmpo, i32, env, fprp, fprp) DEF_HELPER_3(dcmpoq, i32, env, fprp, fprp) DEF_HELPER_3(dcmpu, i32, env, fprp, fprp) DEF_HELPER_3(dcmpuq, i32, env, fprp, fprp) +DEF_HELPER_3(dtstdc, i32, env, fprp, i32) +DEF_HELPER_3(dtstdcq, i32, env, fprp, i32) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index e708640..5dff96b 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8367,6 +8367,8 @@ GEN_DFP_BF_A_B(dcmpu) GEN_DFP_BF_A_B(dcmpuq) GEN_DFP_BF_A_B(dcmpo) GEN_DFP_BF_A_B(dcmpoq) +GEN_DFP_BF_A_DCM(dtstdc) +GEN_DFP_BF_A_DCM(dtstdcq) /*** SPE extension ***/ /* Register moves */ @@ -11306,6 +11308,8 @@ GEN_DFP_BF_A_B(dcmpu, 0x02, 0x14), GEN_DFP_BF_Ap_Bp(dcmpuq, 0x02, 0x14), GEN_DFP_BF_A_B(dcmpo, 0x02, 0x04), GEN_DFP_BF_Ap_Bp(dcmpoq, 0x02, 0x04), +GEN_DFP_BF_A_DCM(dtstdc, 0x02, 0x06), +GEN_DFP_BF_Ap_DCM(dtstdcq, 0x02, 0x06), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 037/118] target-ppc: Introduce DFP Test Data Group 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (35 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 036/118] target-ppc: Introduce DFP Test Data Class Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 038/118] target-ppc: Introduce DFP Test Exponent Alexander Graf ` (38 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Test Data Group instructions dtstdg[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 ++++ 3 files changed, 61 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index fcd6fef..7f18fd9 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -449,3 +449,58 @@ uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint32_t dcm) \ DFP_HELPER_TSTDC(dtstdc, 64) DFP_HELPER_TSTDC(dtstdcq, 128) + +#define DFP_HELPER_TSTDG(op, size) \ +uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint32_t dcm) \ +{ \ + struct PPC_DFP dfp; \ + int minexp, maxexp, nzero_digits, nzero_idx, is_negative, is_zero, \ + is_extreme_exp, is_subnormal, is_normal, leftmost_is_nonzero, \ + match; \ + \ + dfp_prepare_decimal##size(&dfp, a, 0, env); \ + \ + if ((size) == 64) { \ + minexp = -398; \ + maxexp = 369; \ + nzero_digits = 16; \ + nzero_idx = 5; \ + } else if ((size) == 128) { \ + minexp = -6176; \ + maxexp = 6111; \ + nzero_digits = 34; \ + nzero_idx = 11; \ + } \ + \ + is_negative = decNumberIsNegative(&dfp.a); \ + is_zero = decNumberIsZero(&dfp.a); \ + is_extreme_exp = (dfp.a.exponent == maxexp) || \ + (dfp.a.exponent == minexp); \ + is_subnormal = decNumberIsSubnormal(&dfp.a, &dfp.context); \ + is_normal = decNumberIsNormal(&dfp.a, &dfp.context); \ + leftmost_is_nonzero = (dfp.a.digits == nzero_digits) && \ + (dfp.a.lsu[nzero_idx] != 0); \ + match = 0; \ + \ + match |= (dcm & 0x20) && is_zero && !is_extreme_exp; \ + match |= (dcm & 0x10) && is_zero && is_extreme_exp; \ + match |= (dcm & 0x08) && \ + (is_subnormal || (is_normal && is_extreme_exp)); \ + match |= (dcm & 0x04) && is_normal && !is_extreme_exp && \ + !leftmost_is_nonzero; \ + match |= (dcm & 0x02) && is_normal && !is_extreme_exp && \ + leftmost_is_nonzero; \ + match |= (dcm & 0x01) && decNumberIsSpecial(&dfp.a); \ + \ + if (is_negative) { \ + dfp.crbf = match ? 0xA : 0x8; \ + } else { \ + dfp.crbf = match ? 0x2 : 0x0; \ + } \ + \ + dfp_set_FPCC_from_CRBF(&dfp); \ + return dfp.crbf; \ +} + +DFP_HELPER_TSTDG(dtstdg, 64) +DFP_HELPER_TSTDG(dtstdgq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 5a1e05e..dad4b87 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -630,3 +630,5 @@ DEF_HELPER_3(dcmpu, i32, env, fprp, fprp) DEF_HELPER_3(dcmpuq, i32, env, fprp, fprp) DEF_HELPER_3(dtstdc, i32, env, fprp, i32) DEF_HELPER_3(dtstdcq, i32, env, fprp, i32) +DEF_HELPER_3(dtstdg, i32, env, fprp, i32) +DEF_HELPER_3(dtstdgq, i32, env, fprp, i32) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 5dff96b..845d670 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8369,6 +8369,8 @@ GEN_DFP_BF_A_B(dcmpo) GEN_DFP_BF_A_B(dcmpoq) GEN_DFP_BF_A_DCM(dtstdc) GEN_DFP_BF_A_DCM(dtstdcq) +GEN_DFP_BF_A_DCM(dtstdg) +GEN_DFP_BF_A_DCM(dtstdgq) /*** SPE extension ***/ /* Register moves */ @@ -11310,6 +11312,8 @@ GEN_DFP_BF_A_B(dcmpo, 0x02, 0x04), GEN_DFP_BF_Ap_Bp(dcmpoq, 0x02, 0x04), GEN_DFP_BF_A_DCM(dtstdc, 0x02, 0x06), GEN_DFP_BF_Ap_DCM(dtstdcq, 0x02, 0x06), +GEN_DFP_BF_A_DCM(dtstdg, 0x02, 0x07), +GEN_DFP_BF_Ap_DCM(dtstdgq, 0x02, 0x07), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 038/118] target-ppc: Introduce DFP Test Exponent 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (36 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 037/118] target-ppc: Introduce DFP Test Data Group Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 039/118] target-ppc: Introduce DFP Test Significance Alexander Graf ` (37 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Test Exponent instructions dtstex[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 32 ++++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 ++++ 3 files changed, 38 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 7f18fd9..43eb70d 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -504,3 +504,35 @@ uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint32_t dcm) \ DFP_HELPER_TSTDG(dtstdg, 64) DFP_HELPER_TSTDG(dtstdgq, 128) + +#define DFP_HELPER_TSTEX(op, size) \ +uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b) \ +{ \ + struct PPC_DFP dfp; \ + int expa, expb, a_is_special, b_is_special; \ + \ + dfp_prepare_decimal##size(&dfp, a, b, env); \ + \ + expa = dfp.a.exponent; \ + expb = dfp.b.exponent; \ + a_is_special = decNumberIsSpecial(&dfp.a); \ + b_is_special = decNumberIsSpecial(&dfp.b); \ + \ + if (a_is_special || b_is_special) { \ + int atype = a_is_special ? (decNumberIsNaN(&dfp.a) ? 4 : 2) : 1; \ + int btype = b_is_special ? (decNumberIsNaN(&dfp.b) ? 4 : 2) : 1; \ + dfp.crbf = (atype ^ btype) ? 0x1 : 0x2; \ + } else if (expa < expb) { \ + dfp.crbf = 0x8; \ + } else if (expa > expb) { \ + dfp.crbf = 0x4; \ + } else { \ + dfp.crbf = 0x2; \ + } \ + \ + dfp_set_FPCC_from_CRBF(&dfp); \ + return dfp.crbf; \ +} + +DFP_HELPER_TSTEX(dtstex, 64) +DFP_HELPER_TSTEX(dtstexq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index dad4b87..8ffb806 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -632,3 +632,5 @@ DEF_HELPER_3(dtstdc, i32, env, fprp, i32) DEF_HELPER_3(dtstdcq, i32, env, fprp, i32) DEF_HELPER_3(dtstdg, i32, env, fprp, i32) DEF_HELPER_3(dtstdgq, i32, env, fprp, i32) +DEF_HELPER_3(dtstex, i32, env, fprp, fprp) +DEF_HELPER_3(dtstexq, i32, env, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 845d670..dbb56ab 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8371,6 +8371,8 @@ GEN_DFP_BF_A_DCM(dtstdc) GEN_DFP_BF_A_DCM(dtstdcq) GEN_DFP_BF_A_DCM(dtstdg) GEN_DFP_BF_A_DCM(dtstdgq) +GEN_DFP_BF_A_B(dtstex) +GEN_DFP_BF_A_B(dtstexq) /*** SPE extension ***/ /* Register moves */ @@ -11314,6 +11316,8 @@ GEN_DFP_BF_A_DCM(dtstdc, 0x02, 0x06), GEN_DFP_BF_Ap_DCM(dtstdcq, 0x02, 0x06), GEN_DFP_BF_A_DCM(dtstdg, 0x02, 0x07), GEN_DFP_BF_Ap_DCM(dtstdgq, 0x02, 0x07), +GEN_DFP_BF_A_B(dtstex, 0x02, 0x05), +GEN_DFP_BF_Ap_Bp(dtstexq, 0x02, 0x05), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 039/118] target-ppc: Introduce DFP Test Significance 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (37 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 038/118] target-ppc: Introduce DFP Test Exponent Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 040/118] target-ppc: Introduce DFP Quantize Alexander Graf ` (36 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Test Significance instructions dtstsf[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 35 +++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 ++++ 3 files changed, 41 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 43eb70d..574956a 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -536,3 +536,38 @@ uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b) \ DFP_HELPER_TSTEX(dtstex, 64) DFP_HELPER_TSTEX(dtstexq, 128) + +#define DFP_HELPER_TSTSF(op, size) \ +uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b) \ +{ \ + struct PPC_DFP dfp; \ + unsigned k; \ + \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + \ + k = *a & 0x3F; \ + \ + if (unlikely(decNumberIsSpecial(&dfp.b))) { \ + dfp.crbf = 1; \ + } else if (k == 0) { \ + dfp.crbf = 4; \ + } else if (unlikely(decNumberIsZero(&dfp.b))) { \ + /* Zero has no sig digits */ \ + dfp.crbf = 4; \ + } else { \ + unsigned nsd = dfp.b.digits; \ + if (k < nsd) { \ + dfp.crbf = 8; \ + } else if (k > nsd) { \ + dfp.crbf = 4; \ + } else { \ + dfp.crbf = 2; \ + } \ + } \ + \ + dfp_set_FPCC_from_CRBF(&dfp); \ + return dfp.crbf; \ +} + +DFP_HELPER_TSTSF(dtstsf, 64) +DFP_HELPER_TSTSF(dtstsfq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 8ffb806..2b39d2a 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -634,3 +634,5 @@ DEF_HELPER_3(dtstdg, i32, env, fprp, i32) DEF_HELPER_3(dtstdgq, i32, env, fprp, i32) DEF_HELPER_3(dtstex, i32, env, fprp, fprp) DEF_HELPER_3(dtstexq, i32, env, fprp, fprp) +DEF_HELPER_3(dtstsf, i32, env, fprp, fprp) +DEF_HELPER_3(dtstsfq, i32, env, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index dbb56ab..441eea1 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8373,6 +8373,8 @@ GEN_DFP_BF_A_DCM(dtstdg) GEN_DFP_BF_A_DCM(dtstdgq) GEN_DFP_BF_A_B(dtstex) GEN_DFP_BF_A_B(dtstexq) +GEN_DFP_BF_A_B(dtstsf) +GEN_DFP_BF_A_B(dtstsfq) /*** SPE extension ***/ /* Register moves */ @@ -11318,6 +11320,8 @@ GEN_DFP_BF_A_DCM(dtstdg, 0x02, 0x07), GEN_DFP_BF_Ap_DCM(dtstdgq, 0x02, 0x07), GEN_DFP_BF_A_B(dtstex, 0x02, 0x05), GEN_DFP_BF_Ap_Bp(dtstexq, 0x02, 0x05), +GEN_DFP_BF_A_B(dtstsf, 0x02, 0x15), +GEN_DFP_BF_A_Bp(dtstsfq, 0x02, 0x15), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 040/118] target-ppc: Introduce DFP Quantize 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (38 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 039/118] target-ppc: Introduce DFP Test Significance Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 041/118] target-ppc: Introduce DFP Reround Alexander Graf ` (35 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Quantize instructions dquai[q][.] and dqua[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 4 ++ target-ppc/translate.c | 8 +++ 3 files changed, 144 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 574956a..e5574b5 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -79,6 +79,47 @@ static void dfp_prepare_rounding_mode(decContext *context, uint64_t fpscr) decContextSetRounding(context, rnd); } +static void dfp_set_round_mode_from_immediate(uint8_t r, uint8_t rmc, + struct PPC_DFP *dfp) +{ + enum rounding rnd; + if (r == 0) { + switch (rmc & 3) { + case 0: + rnd = DEC_ROUND_HALF_EVEN; + break; + case 1: + rnd = DEC_ROUND_DOWN; + break; + case 2: + rnd = DEC_ROUND_HALF_UP; + break; + case 3: /* use FPSCR rounding mode */ + return; + default: + assert(0); /* cannot get here */ + } + } else { /* r == 1 */ + switch (rmc & 3) { + case 0: + rnd = DEC_ROUND_CEILING; + break; + case 1: + rnd = DEC_ROUND_FLOOR; + break; + case 2: + rnd = DEC_ROUND_UP; + break; + case 3: + rnd = DEC_ROUND_HALF_DOWN; + break; + default: + assert(0); /* cannot get here */ + } + } + decContextSetRounding(&dfp->context, rnd); +} + static void dfp_prepare_decimal64(struct PPC_DFP *dfp, uint64_t *a, uint64_t *b, CPUPPCState *env) { @@ -301,6 +342,15 @@ static void dfp_check_for_VXVC(struct PPC_DFP *dfp) } } +static void dfp_check_for_VXCVI(struct PPC_DFP *dfp) +{ + if ((dfp->context.status & DEC_Invalid_operation) && + (!decNumberIsSNaN(&dfp->a)) && + (!decNumberIsSNaN(&dfp->b))) { + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FP_VE); + } +} + static void dfp_set_CRBF_from_T(struct PPC_DFP *dfp) { if (decNumberIsNaN(&dfp->t)) { @@ -320,6 +370,12 @@ static void dfp_set_FPCC_from_CRBF(struct PPC_DFP *dfp) dfp->env->fpscr |= (dfp->crbf << 12); } +static inline void dfp_makeQNaN(decNumber *dn) +{ + dn->bits &= ~DECSPECIAL; + dn->bits |= DECNAN; +} + #define DFP_HELPER_TAB(op, dnop, postprocs, size) \ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \ { \ @@ -571,3 +627,79 @@ uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b) \ DFP_HELPER_TSTSF(dtstsf, 64) DFP_HELPER_TSTSF(dtstsfq, 128) + +static void QUA_PPs(struct PPC_DFP *dfp) +{ + dfp_set_FPRF_from_FRT(dfp); + dfp_check_for_XX(dfp); + dfp_check_for_VXSNAN(dfp); + dfp_check_for_VXCVI(dfp); +} + +static void dfp_quantize(uint8_t rmc, struct PPC_DFP *dfp) +{ + dfp_set_round_mode_from_immediate(0, rmc, dfp); + decNumberQuantize(&dfp->t, &dfp->b, &dfp->a, &dfp->context); + if (decNumberIsSNaN(&dfp->a)) { + dfp->t = dfp->a; + dfp_makeQNaN(&dfp->t); + } else if (decNumberIsSNaN(&dfp->b)) { + dfp->t = dfp->b; + dfp_makeQNaN(&dfp->t); + } else if (decNumberIsQNaN(&dfp->a)) { + dfp->t = dfp->a; + } else if (decNumberIsQNaN(&dfp->b)) { + dfp->t = dfp->b; + } +} + +#define DFP_HELPER_QUAI(op, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, \ + uint32_t te, uint32_t rmc) \ +{ \ + struct PPC_DFP dfp; \ + \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + \ + decNumberFromUInt32(&dfp.a, 1); \ + dfp.a.exponent = (int32_t)((int8_t)(te << 3) >> 3); \ + \ + dfp_quantize(rmc, &dfp); \ + decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \ + &dfp.context); \ + QUA_PPs(&dfp); \ + \ + if (size == 64) { \ + t[0] = dfp.t64[0]; \ + } else if (size == 128) { \ + t[0] = dfp.t64[HI_IDX]; \ + t[1] = dfp.t64[LO_IDX]; \ + } \ +} + +DFP_HELPER_QUAI(dquai, 64) +DFP_HELPER_QUAI(dquaiq, 128) + +#define DFP_HELPER_QUA(op, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, \ + uint64_t *b, uint32_t rmc) \ +{ \ + struct PPC_DFP dfp; \ + \ + dfp_prepare_decimal##size(&dfp, a, b, env); \ + \ + dfp_quantize(rmc, &dfp); \ + decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \ + &dfp.context); \ + QUA_PPs(&dfp); \ + \ + if (size == 64) { \ + t[0] = dfp.t64[0]; \ + } else if (size == 128) { \ + t[0] = dfp.t64[HI_IDX]; \ + t[1] = dfp.t64[LO_IDX]; \ + } \ +} + +DFP_HELPER_QUA(dqua, 64) +DFP_HELPER_QUA(dquaq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 2b39d2a..362e9a8 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -636,3 +636,7 @@ DEF_HELPER_3(dtstex, i32, env, fprp, fprp) DEF_HELPER_3(dtstexq, i32, env, fprp, fprp) DEF_HELPER_3(dtstsf, i32, env, fprp, fprp) DEF_HELPER_3(dtstsfq, i32, env, fprp, fprp) +DEF_HELPER_5(dquai, void, env, fprp, fprp, i32, i32) +DEF_HELPER_5(dquaiq, void, env, fprp, fprp, i32, i32) +DEF_HELPER_5(dqua, void, env, fprp, fprp, fprp, i32) +DEF_HELPER_5(dquaq, void, env, fprp, fprp, fprp, i32) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 441eea1..c2753a3 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8375,6 +8375,10 @@ GEN_DFP_BF_A_B(dtstex) GEN_DFP_BF_A_B(dtstexq) GEN_DFP_BF_A_B(dtstsf) GEN_DFP_BF_A_B(dtstsfq) +GEN_DFP_T_B_U32_U32_Rc(dquai, SIMM5, RMC) +GEN_DFP_T_B_U32_U32_Rc(dquaiq, SIMM5, RMC) +GEN_DFP_T_A_B_I32_Rc(dqua, RMC) +GEN_DFP_T_A_B_I32_Rc(dquaq, RMC) /*** SPE extension ***/ /* Register moves */ @@ -11322,6 +11326,10 @@ GEN_DFP_BF_A_B(dtstex, 0x02, 0x05), GEN_DFP_BF_Ap_Bp(dtstexq, 0x02, 0x05), GEN_DFP_BF_A_B(dtstsf, 0x02, 0x15), GEN_DFP_BF_A_Bp(dtstsfq, 0x02, 0x15), +GEN_DFP_TE_T_B_RMC_Rc(dquai, 0x03, 0x02), +GEN_DFP_TE_Tp_Bp_RMC_Rc(dquaiq, 0x03, 0x02), +GEN_DFP_T_A_B_RMC_Rc(dqua, 0x03, 0x00), +GEN_DFP_Tp_Ap_Bp_RMC_Rc(dquaq, 0x03, 0x00), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 041/118] target-ppc: Introduce DFP Reround 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (39 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 040/118] target-ppc: Introduce DFP Quantize Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 042/118] target-ppc: Introduce DFP Round to Integer Alexander Graf ` (34 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Reround instructions drrnd[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 + target-ppc/translate.c | 4 ++ 3 files changed, 103 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index e5574b5..23f85c4 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -376,6 +376,23 @@ static inline void dfp_makeQNaN(decNumber *dn) dn->bits |= DECNAN; } +static inline int dfp_get_digit(decNumber *dn, int n) +{ + assert(DECDPUN == 3); + int unit = n / DECDPUN; + int dig = n % DECDPUN; + switch (dig) { + case 0: + return dn->lsu[unit] % 10; + case 1: + return (dn->lsu[unit] / 10) % 10; + case 2: + return dn->lsu[unit] / 100; + default: + assert(0); + } +} + #define DFP_HELPER_TAB(op, dnop, postprocs, size) \ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \ { \ @@ -703,3 +720,83 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, \ DFP_HELPER_QUA(dqua, 64) DFP_HELPER_QUA(dquaq, 128) + +static void _dfp_reround(uint8_t rmc, int32_t ref_sig, int32_t xmax, + struct PPC_DFP *dfp) +{ + int msd_orig, msd_rslt; + + if (unlikely((ref_sig == 0) || (dfp->b.digits <= ref_sig))) { + dfp->t = dfp->b; + if (decNumberIsSNaN(&dfp->b)) { + dfp_makeQNaN(&dfp->t); + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FPSCR_VE); + } + return; + } + + /* Reround is equivalent to quantizing b with 1**E(n) where */ + /* n = exp(b) + numDigits(b) - reference_significance. */ + + decNumberFromUInt32(&dfp->a, 1); + dfp->a.exponent = dfp->b.exponent + dfp->b.digits - ref_sig; + + if (unlikely(dfp->a.exponent > xmax)) { + dfp->t.digits = 0; + dfp->t.bits &= ~DECNEG; + dfp_makeQNaN(&dfp->t); + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE); + return; + } + + dfp_quantize(rmc, dfp); + + msd_orig = dfp_get_digit(&dfp->b, dfp->b.digits-1); + msd_rslt = dfp_get_digit(&dfp->t, dfp->t.digits-1); + + /* If the quantization resulted in rounding up to the next magnitude, */ + /* then we need to shift the significand and adjust the exponent. */ + + if (unlikely((msd_orig == 9) && (msd_rslt == 1))) { + + decNumber negone; + + decNumberFromInt32(&negone, -1); + decNumberShift(&dfp->t, &dfp->t, &negone, &dfp->context); + dfp->t.exponent++; + + if (unlikely(dfp->t.exponent > xmax)) { + dfp_makeQNaN(&dfp->t); + dfp->t.digits = 0; + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FP_VE); + /* Inhibit XX in this case */ + decContextClearStatus(&dfp->context, DEC_Inexact); + } + } +} + +#define DFP_HELPER_RRND(op, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, \ + uint64_t *b, uint32_t rmc) \ +{ \ + struct PPC_DFP dfp; \ + int32_t ref_sig = *a & 0x3F; \ + int32_t xmax = ((size) == 64) ? 369 : 6111; \ + \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + \ + _dfp_reround(rmc, ref_sig, xmax, &dfp); \ + decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \ + &dfp.context); \ + QUA_PPs(&dfp); \ + \ + if (size == 64) { \ + t[0] = dfp.t64[0]; \ + } else if (size == 128) { \ + t[0] = dfp.t64[HI_IDX]; \ + t[1] = dfp.t64[LO_IDX]; \ + } \ +} + +DFP_HELPER_RRND(drrnd, 64) +DFP_HELPER_RRND(drrndq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 362e9a8..776d4d7 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -640,3 +640,5 @@ DEF_HELPER_5(dquai, void, env, fprp, fprp, i32, i32) DEF_HELPER_5(dquaiq, void, env, fprp, fprp, i32, i32) DEF_HELPER_5(dqua, void, env, fprp, fprp, fprp, i32) DEF_HELPER_5(dquaq, void, env, fprp, fprp, fprp, i32) +DEF_HELPER_5(drrnd, void, env, fprp, fprp, fprp, i32) +DEF_HELPER_5(drrndq, void, env, fprp, fprp, fprp, i32) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index c2753a3..2698e57 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8379,6 +8379,8 @@ GEN_DFP_T_B_U32_U32_Rc(dquai, SIMM5, RMC) GEN_DFP_T_B_U32_U32_Rc(dquaiq, SIMM5, RMC) GEN_DFP_T_A_B_I32_Rc(dqua, RMC) GEN_DFP_T_A_B_I32_Rc(dquaq, RMC) +GEN_DFP_T_A_B_I32_Rc(drrnd, RMC) +GEN_DFP_T_A_B_I32_Rc(drrndq, RMC) /*** SPE extension ***/ /* Register moves */ @@ -11330,6 +11332,8 @@ GEN_DFP_TE_T_B_RMC_Rc(dquai, 0x03, 0x02), GEN_DFP_TE_Tp_Bp_RMC_Rc(dquaiq, 0x03, 0x02), GEN_DFP_T_A_B_RMC_Rc(dqua, 0x03, 0x00), GEN_DFP_Tp_Ap_Bp_RMC_Rc(dquaq, 0x03, 0x00), +GEN_DFP_T_A_B_RMC_Rc(drrnd, 0x03, 0x01), +GEN_DFP_Tp_A_Bp_RMC_Rc(drrndq, 0x03, 0x01), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 042/118] target-ppc: Introduce DFP Round to Integer 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (40 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 041/118] target-ppc: Introduce DFP Reround Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 043/118] target-ppc: Introduce DFP Convert to Long/Extended Alexander Graf ` (33 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point (DFP) Round to FP Integer With Inexact (drintx[q][.]) and DFP Round to FP Integer Without Inexact (drintn[q][.]) instructions. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 40 ++++++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 4 ++++ target-ppc/translate.c | 8 ++++++++ 3 files changed, 52 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 23f85c4..243ed89 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -800,3 +800,43 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, \ DFP_HELPER_RRND(drrnd, 64) DFP_HELPER_RRND(drrndq, 128) + +#define DFP_HELPER_RINT(op, postprocs, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, \ + uint32_t r, uint32_t rmc) \ +{ \ + struct PPC_DFP dfp; \ + \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + \ + dfp_set_round_mode_from_immediate(r, rmc, &dfp); \ + decNumberToIntegralExact(&dfp.t, &dfp.b, &dfp.context); \ + decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \ + postprocs(&dfp); \ + \ + if (size == 64) { \ + t[0] = dfp.t64[0]; \ + } else if (size == 128) { \ + t[0] = dfp.t64[HI_IDX]; \ + t[1] = dfp.t64[LO_IDX]; \ + } \ +} + +static void RINTX_PPs(struct PPC_DFP *dfp) +{ + dfp_set_FPRF_from_FRT(dfp); + dfp_check_for_XX(dfp); + dfp_check_for_VXSNAN(dfp); +} + +DFP_HELPER_RINT(drintx, RINTX_PPs, 64) +DFP_HELPER_RINT(drintxq, RINTX_PPs, 128) + +static void RINTN_PPs(struct PPC_DFP *dfp) +{ + dfp_set_FPRF_from_FRT(dfp); + dfp_check_for_VXSNAN(dfp); +} + +DFP_HELPER_RINT(drintn, RINTN_PPs, 64) +DFP_HELPER_RINT(drintnq, RINTN_PPs, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 776d4d7..3569827 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -642,3 +642,7 @@ DEF_HELPER_5(dqua, void, env, fprp, fprp, fprp, i32) DEF_HELPER_5(dquaq, void, env, fprp, fprp, fprp, i32) DEF_HELPER_5(drrnd, void, env, fprp, fprp, fprp, i32) DEF_HELPER_5(drrndq, void, env, fprp, fprp, fprp, i32) +DEF_HELPER_5(drintx, void, env, fprp, fprp, i32, i32) +DEF_HELPER_5(drintxq, void, env, fprp, fprp, i32, i32) +DEF_HELPER_5(drintn, void, env, fprp, fprp, i32, i32) +DEF_HELPER_5(drintnq, void, env, fprp, fprp, i32, i32) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 2698e57..553576b 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8381,6 +8381,10 @@ GEN_DFP_T_A_B_I32_Rc(dqua, RMC) GEN_DFP_T_A_B_I32_Rc(dquaq, RMC) GEN_DFP_T_A_B_I32_Rc(drrnd, RMC) GEN_DFP_T_A_B_I32_Rc(drrndq, RMC) +GEN_DFP_T_B_U32_U32_Rc(drintx, FPW, RMC) +GEN_DFP_T_B_U32_U32_Rc(drintxq, FPW, RMC) +GEN_DFP_T_B_U32_U32_Rc(drintn, FPW, RMC) +GEN_DFP_T_B_U32_U32_Rc(drintnq, FPW, RMC) /*** SPE extension ***/ /* Register moves */ @@ -11334,6 +11338,10 @@ GEN_DFP_T_A_B_RMC_Rc(dqua, 0x03, 0x00), GEN_DFP_Tp_Ap_Bp_RMC_Rc(dquaq, 0x03, 0x00), GEN_DFP_T_A_B_RMC_Rc(drrnd, 0x03, 0x01), GEN_DFP_Tp_A_Bp_RMC_Rc(drrndq, 0x03, 0x01), +GEN_DFP_R_T_B_RMC_Rc(drintx, 0x03, 0x03), +GEN_DFP_R_Tp_Bp_RMC_Rc(drintxq, 0x03, 0x03), +GEN_DFP_R_T_B_RMC_Rc(drintn, 0x03, 0x07), +GEN_DFP_R_Tp_Bp_RMC_Rc(drintnq, 0x03, 0x07), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 043/118] target-ppc: Introduce DFP Convert to Long/Extended 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (41 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 042/118] target-ppc: Introduce DFP Round to Integer Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 044/118] target-ppc: Introduce Round to DFP Short/Long Alexander Graf ` (32 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Convert to DFP Long (dctdp[.]) and Convert to DFP Extended (dctqpq[.]) instructions. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 33 +++++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 ++++ 3 files changed, 39 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 243ed89..050a339 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -286,6 +286,15 @@ static void dfp_check_for_VXSNAN(struct PPC_DFP *dfp) } } +static void dfp_check_for_VXSNAN_and_convert_to_QNaN(struct PPC_DFP *dfp) +{ + if (decNumberIsSNaN(&dfp->t)) { + dfp->t.bits &= ~DECSNAN; + dfp->t.bits |= DECNAN; + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE); + } +} + static void dfp_check_for_VXISI(struct PPC_DFP *dfp, int testForSameSign) { if (dfp->context.status & DEC_Invalid_operation) { @@ -840,3 +849,27 @@ static void RINTN_PPs(struct PPC_DFP *dfp) DFP_HELPER_RINT(drintn, RINTN_PPs, 64) DFP_HELPER_RINT(drintnq, RINTN_PPs, 128) + +void helper_dctdp(CPUPPCState *env, uint64_t *t, uint64_t *b) +{ + struct PPC_DFP dfp; + uint32_t b_short = *b; + dfp_prepare_decimal64(&dfp, 0, 0, env); + decimal32ToNumber((decimal32 *)&b_short, &dfp.t); + decimal64FromNumber((decimal64 *)t, &dfp.t, &dfp.context); + dfp_set_FPRF_from_FRT(&dfp); +} + +void helper_dctqpq(CPUPPCState *env, uint64_t *t, uint64_t *b) +{ + struct PPC_DFP dfp; + dfp_prepare_decimal128(&dfp, 0, 0, env); + decimal64ToNumber((decimal64 *)b, &dfp.t); + + dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp); + dfp_set_FPRF_from_FRT(&dfp); + + decimal128FromNumber((decimal128 *)&dfp.t64, &dfp.t, &dfp.context); + t[0] = dfp.t64[HI_IDX]; + t[1] = dfp.t64[LO_IDX]; +} diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 3569827..c7dbb19 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -646,3 +646,5 @@ DEF_HELPER_5(drintx, void, env, fprp, fprp, i32, i32) DEF_HELPER_5(drintxq, void, env, fprp, fprp, i32, i32) DEF_HELPER_5(drintn, void, env, fprp, fprp, i32, i32) DEF_HELPER_5(drintnq, void, env, fprp, fprp, i32, i32) +DEF_HELPER_3(dctdp, void, env, fprp, fprp) +DEF_HELPER_3(dctqpq, void, env, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 553576b..7c9923c 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8385,6 +8385,8 @@ GEN_DFP_T_B_U32_U32_Rc(drintx, FPW, RMC) GEN_DFP_T_B_U32_U32_Rc(drintxq, FPW, RMC) GEN_DFP_T_B_U32_U32_Rc(drintn, FPW, RMC) GEN_DFP_T_B_U32_U32_Rc(drintnq, FPW, RMC) +GEN_DFP_T_B_Rc(dctdp) +GEN_DFP_T_B_Rc(dctqpq) /*** SPE extension ***/ /* Register moves */ @@ -11342,6 +11344,8 @@ GEN_DFP_R_T_B_RMC_Rc(drintx, 0x03, 0x03), GEN_DFP_R_Tp_Bp_RMC_Rc(drintxq, 0x03, 0x03), GEN_DFP_R_T_B_RMC_Rc(drintn, 0x03, 0x07), GEN_DFP_R_Tp_Bp_RMC_Rc(drintnq, 0x03, 0x07), +GEN_DFP_T_B_Rc(dctdp, 0x02, 0x08), +GEN_DFP_Tp_B_Rc(dctqpq, 0x02, 0x08), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 044/118] target-ppc: Introduce Round to DFP Short/Long 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (42 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 043/118] target-ppc: Introduce DFP Convert to Long/Extended Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 045/118] target-ppc: Introduce DFP Convert to Fixed Alexander Graf ` (31 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Round to DFP Short (drsp[.]) and Round to DFP Long (drdpq[.]) instructions. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 ++++ 3 files changed, 54 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 050a339..548949f 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -249,6 +249,20 @@ static void dfp_set_FPRF_from_FRT(struct PPC_DFP *dfp) dfp_set_FPRF_from_FRT_with_context(dfp, &dfp->context); } +static void dfp_set_FPRF_from_FRT_short(struct PPC_DFP *dfp) +{ + decContext shortContext; + decContextDefault(&shortContext, DEC_INIT_DECIMAL32); + dfp_set_FPRF_from_FRT_with_context(dfp, &shortContext); +} + +static void dfp_set_FPRF_from_FRT_long(struct PPC_DFP *dfp) +{ + decContext longContext; + decContextDefault(&longContext, DEC_INIT_DECIMAL64); + dfp_set_FPRF_from_FRT_with_context(dfp, &longContext); +} + static void dfp_check_for_OX(struct PPC_DFP *dfp) { if (dfp->context.status & DEC_Overflow) { @@ -873,3 +887,37 @@ void helper_dctqpq(CPUPPCState *env, uint64_t *t, uint64_t *b) t[0] = dfp.t64[HI_IDX]; t[1] = dfp.t64[LO_IDX]; } + +void helper_drsp(CPUPPCState *env, uint64_t *t, uint64_t *b) +{ + struct PPC_DFP dfp; + uint32_t t_short = 0; + dfp_prepare_decimal64(&dfp, 0, b, env); + decimal32FromNumber((decimal32 *)&t_short, &dfp.b, &dfp.context); + decimal32ToNumber((decimal32 *)&t_short, &dfp.t); + + dfp_set_FPRF_from_FRT_short(&dfp); + dfp_check_for_OX(&dfp); + dfp_check_for_UX(&dfp); + dfp_check_for_XX(&dfp); + + *t = t_short; +} + +void helper_drdpq(CPUPPCState *env, uint64_t *t, uint64_t *b) +{ + struct PPC_DFP dfp; + dfp_prepare_decimal128(&dfp, 0, b, env); + decimal64FromNumber((decimal64 *)&dfp.t64, &dfp.b, &dfp.context); + decimal64ToNumber((decimal64 *)&dfp.t64, &dfp.t); + + dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp); + dfp_set_FPRF_from_FRT_long(&dfp); + dfp_check_for_OX(&dfp); + dfp_check_for_UX(&dfp); + dfp_check_for_XX(&dfp); + + decimal64FromNumber((decimal64 *)dfp.t64, &dfp.t, &dfp.context); + t[0] = dfp.t64[0]; + t[1] = 0; +} diff --git a/target-ppc/helper.h b/target-ppc/helper.h index c7dbb19..2220e62 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -648,3 +648,5 @@ DEF_HELPER_5(drintn, void, env, fprp, fprp, i32, i32) DEF_HELPER_5(drintnq, void, env, fprp, fprp, i32, i32) DEF_HELPER_3(dctdp, void, env, fprp, fprp) DEF_HELPER_3(dctqpq, void, env, fprp, fprp) +DEF_HELPER_3(drsp, void, env, fprp, fprp) +DEF_HELPER_3(drdpq, void, env, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 7c9923c..f93536a 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8387,6 +8387,8 @@ GEN_DFP_T_B_U32_U32_Rc(drintn, FPW, RMC) GEN_DFP_T_B_U32_U32_Rc(drintnq, FPW, RMC) GEN_DFP_T_B_Rc(dctdp) GEN_DFP_T_B_Rc(dctqpq) +GEN_DFP_T_B_Rc(drsp) +GEN_DFP_T_B_Rc(drdpq) /*** SPE extension ***/ /* Register moves */ @@ -11346,6 +11348,8 @@ GEN_DFP_R_T_B_RMC_Rc(drintn, 0x03, 0x07), GEN_DFP_R_Tp_Bp_RMC_Rc(drintnq, 0x03, 0x07), GEN_DFP_T_B_Rc(dctdp, 0x02, 0x08), GEN_DFP_Tp_B_Rc(dctqpq, 0x02, 0x08), +GEN_DFP_T_B_Rc(drsp, 0x02, 0x18), +GEN_DFP_Tp_Bp_Rc(drdpq, 0x02, 0x18), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 045/118] target-ppc: Introduce DFP Convert to Fixed 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (43 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 044/118] target-ppc: Introduce Round to DFP Short/Long Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 046/118] " Alexander Graf ` (30 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Convert to Fixed instructions dctfix[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 26 ++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 ++++ 3 files changed, 32 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 548949f..41f87e0 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -921,3 +921,29 @@ void helper_drdpq(CPUPPCState *env, uint64_t *t, uint64_t *b) t[0] = dfp.t64[0]; t[1] = 0; } + +#define DFP_HELPER_CFFIX(op, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b) \ +{ \ + struct PPC_DFP dfp; \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + decNumberFromInt64(&dfp.t, (int64_t)(*b)); \ + decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \ + CFFIX_PPs(&dfp); \ + \ + if (size == 64) { \ + t[0] = dfp.t64[0]; \ + } else if (size == 128) { \ + t[0] = dfp.t64[HI_IDX]; \ + t[1] = dfp.t64[LO_IDX]; \ + } \ +} + +static void CFFIX_PPs(struct PPC_DFP *dfp) +{ + dfp_set_FPRF_from_FRT(dfp); + dfp_check_for_XX(dfp); +} + +DFP_HELPER_CFFIX(dcffix, 64) +DFP_HELPER_CFFIX(dcffixq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 2220e62..bc7b2d2 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -650,3 +650,5 @@ DEF_HELPER_3(dctdp, void, env, fprp, fprp) DEF_HELPER_3(dctqpq, void, env, fprp, fprp) DEF_HELPER_3(drsp, void, env, fprp, fprp) DEF_HELPER_3(drdpq, void, env, fprp, fprp) +DEF_HELPER_3(dcffix, void, env, fprp, fprp) +DEF_HELPER_3(dcffixq, void, env, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index f93536a..f4ef9a8 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8389,6 +8389,8 @@ GEN_DFP_T_B_Rc(dctdp) GEN_DFP_T_B_Rc(dctqpq) GEN_DFP_T_B_Rc(drsp) GEN_DFP_T_B_Rc(drdpq) +GEN_DFP_T_B_Rc(dcffix) +GEN_DFP_T_B_Rc(dcffixq) /*** SPE extension ***/ /* Register moves */ @@ -11350,6 +11352,8 @@ GEN_DFP_T_B_Rc(dctdp, 0x02, 0x08), GEN_DFP_Tp_B_Rc(dctqpq, 0x02, 0x08), GEN_DFP_T_B_Rc(drsp, 0x02, 0x18), GEN_DFP_Tp_Bp_Rc(drdpq, 0x02, 0x18), +GEN_DFP_T_B_Rc(dcffix, 0x02, 0x19), +GEN_DFP_Tp_B_Rc(dcffixq, 0x02, 0x19), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 046/118] target-ppc: Introduce DFP Convert to Fixed 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (44 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 045/118] target-ppc: Introduce DFP Convert to Fixed Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 047/118] target-ppc: Introduce DFP Decode DPD to BCD Alexander Graf ` (29 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Convert to Fixed instructions dctfix[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 36 ++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 ++++ 3 files changed, 42 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 41f87e0..24de5a7 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -947,3 +947,39 @@ static void CFFIX_PPs(struct PPC_DFP *dfp) DFP_HELPER_CFFIX(dcffix, 64) DFP_HELPER_CFFIX(dcffixq, 128) + +#define DFP_HELPER_CTFIX(op, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b) \ +{ \ + struct PPC_DFP dfp; \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + \ + if (unlikely(decNumberIsSpecial(&dfp.b))) { \ + uint64_t invalid_flags = FP_VX | FP_VXCVI; \ + if (decNumberIsInfinite(&dfp.b)) { \ + dfp.t64[0] = decNumberIsNegative(&dfp.b) ? INT64_MIN : INT64_MAX; \ + } else { /* NaN */ \ + dfp.t64[0] = INT64_MIN; \ + if (decNumberIsSNaN(&dfp.b)) { \ + invalid_flags |= FP_VXSNAN; \ + } \ + } \ + dfp_set_FPSCR_flag(&dfp, invalid_flags, FP_VE); \ + } else if (unlikely(decNumberIsZero(&dfp.b))) { \ + dfp.t64[0] = 0; \ + } else { \ + decNumberToIntegralExact(&dfp.b, &dfp.b, &dfp.context); \ + dfp.t64[0] = decNumberIntegralToInt64(&dfp.b, &dfp.context); \ + if (decContextTestStatus(&dfp.context, DEC_Invalid_operation)) { \ + dfp.t64[0] = decNumberIsNegative(&dfp.b) ? INT64_MIN : INT64_MAX; \ + dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FP_VE); \ + } else { \ + dfp_check_for_XX(&dfp); \ + } \ + } \ + \ + *t = dfp.t64[0]; \ +} + +DFP_HELPER_CTFIX(dctfix, 64) +DFP_HELPER_CTFIX(dctfixq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index bc7b2d2..69c0a1d 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -652,3 +652,5 @@ DEF_HELPER_3(drsp, void, env, fprp, fprp) DEF_HELPER_3(drdpq, void, env, fprp, fprp) DEF_HELPER_3(dcffix, void, env, fprp, fprp) DEF_HELPER_3(dcffixq, void, env, fprp, fprp) +DEF_HELPER_3(dctfix, void, env, fprp, fprp) +DEF_HELPER_3(dctfixq, void, env, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index f4ef9a8..cc7af45 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8391,6 +8391,8 @@ GEN_DFP_T_B_Rc(drsp) GEN_DFP_T_B_Rc(drdpq) GEN_DFP_T_B_Rc(dcffix) GEN_DFP_T_B_Rc(dcffixq) +GEN_DFP_T_B_Rc(dctfix) +GEN_DFP_T_B_Rc(dctfixq) /*** SPE extension ***/ /* Register moves */ @@ -11354,6 +11356,8 @@ GEN_DFP_T_B_Rc(drsp, 0x02, 0x18), GEN_DFP_Tp_Bp_Rc(drdpq, 0x02, 0x18), GEN_DFP_T_B_Rc(dcffix, 0x02, 0x19), GEN_DFP_Tp_B_Rc(dcffixq, 0x02, 0x19), +GEN_DFP_T_B_Rc(dctfix, 0x02, 0x09), +GEN_DFP_T_Bp_Rc(dctfixq, 0x02, 0x09), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 047/118] target-ppc: Introduce DFP Decode DPD to BCD 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (45 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 046/118] " Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 048/118] target-ppc: Introduce DFP Encode BCD to DPD Alexander Graf ` (28 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the Power PC Decimal Floating Point Decode Densely Packed Decimal to Binary Coded Decimal instructions ddedpd[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 +++ 3 files changed, 72 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 24de5a7..df40da7 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -983,3 +983,69 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b) \ DFP_HELPER_CTFIX(dctfix, 64) DFP_HELPER_CTFIX(dctfixq, 128) + +static inline void dfp_set_bcd_digit_64(uint64_t *t, uint8_t digit, + unsigned n) +{ + *t |= ((uint64_t)(digit & 0xF) << (n << 2)); +} + +static inline void dfp_set_bcd_digit_128(uint64_t *t, uint8_t digit, + unsigned n) +{ + t[(n & 0x10) ? HI_IDX : LO_IDX] |= + ((uint64_t)(digit & 0xF) << ((n & 15) << 2)); +} + +static inline void dfp_set_sign_64(uint64_t *t, uint8_t sgn) +{ + *t <<= 4; + *t |= (sgn & 0xF); +} + +static inline void dfp_set_sign_128(uint64_t *t, uint8_t sgn) +{ + t[HI_IDX] <<= 4; + t[HI_IDX] |= (t[LO_IDX] >> 60); + t[LO_IDX] <<= 4; + t[LO_IDX] |= (sgn & 0xF); +} + +#define DFP_HELPER_DEDPD(op, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t sp) \ +{ \ + struct PPC_DFP dfp; \ + uint8_t digits[34]; \ + int i, N; \ + \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + \ + decNumberGetBCD(&dfp.b, digits); \ + dfp.t64[0] = dfp.t64[1] = 0; \ + N = dfp.b.digits; \ + \ + for (i = 0; (i < N) && (i < (size)/4); i++) { \ + dfp_set_bcd_digit_##size(dfp.t64, digits[N-i-1], i); \ + } \ + \ + if (sp & 2) { \ + uint8_t sgn; \ + \ + if (decNumberIsNegative(&dfp.b)) { \ + sgn = 0xD; \ + } else { \ + sgn = ((sp & 1) ? 0xF : 0xC); \ + } \ + dfp_set_sign_##size(dfp.t64, sgn); \ + } \ + \ + if (size == 64) { \ + t[0] = dfp.t64[0]; \ + } else if (size == 128) { \ + t[0] = dfp.t64[HI_IDX]; \ + t[1] = dfp.t64[LO_IDX]; \ + } \ +} + +DFP_HELPER_DEDPD(ddedpd, 64) +DFP_HELPER_DEDPD(ddedpdq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 69c0a1d..d4e73f2 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -654,3 +654,5 @@ DEF_HELPER_3(dcffix, void, env, fprp, fprp) DEF_HELPER_3(dcffixq, void, env, fprp, fprp) DEF_HELPER_3(dctfix, void, env, fprp, fprp) DEF_HELPER_3(dctfixq, void, env, fprp, fprp) +DEF_HELPER_4(ddedpd, void, env, fprp, fprp, i32) +DEF_HELPER_4(ddedpdq, void, env, fprp, fprp, i32) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index cc7af45..0de657a 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8393,6 +8393,8 @@ GEN_DFP_T_B_Rc(dcffix) GEN_DFP_T_B_Rc(dcffixq) GEN_DFP_T_B_Rc(dctfix) GEN_DFP_T_B_Rc(dctfixq) +GEN_DFP_T_FPR_I32_Rc(ddedpd, rB, SP) +GEN_DFP_T_FPR_I32_Rc(ddedpdq, rB, SP) /*** SPE extension ***/ /* Register moves */ @@ -11358,6 +11360,8 @@ GEN_DFP_T_B_Rc(dcffix, 0x02, 0x19), GEN_DFP_Tp_B_Rc(dcffixq, 0x02, 0x19), GEN_DFP_T_B_Rc(dctfix, 0x02, 0x09), GEN_DFP_T_Bp_Rc(dctfixq, 0x02, 0x09), +GEN_DFP_SP_T_B_Rc(ddedpd, 0x02, 0x0a), +GEN_DFP_SP_Tp_Bp_Rc(ddedpdq, 0x02, 0x0a), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 048/118] target-ppc: Introduce DFP Encode BCD to DPD 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (46 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 047/118] target-ppc: Introduce DFP Decode DPD to BCD Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 049/118] target-ppc: Introduce DFP Extract Biased Exponent Alexander Graf ` (27 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Encode Binary Coded Decimal to Densely Packed Decimal instructions denbcd[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 +++ 3 files changed, 78 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index df40da7..c6c104b 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -1049,3 +1049,75 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t sp) \ DFP_HELPER_DEDPD(ddedpd, 64) DFP_HELPER_DEDPD(ddedpdq, 128) + +static inline uint8_t dfp_get_bcd_digit_64(uint64_t *t, unsigned n) +{ + return *t >> ((n << 2) & 63) & 15; +} + +static inline uint8_t dfp_get_bcd_digit_128(uint64_t *t, unsigned n) +{ + return t[(n & 0x10) ? HI_IDX : LO_IDX] >> ((n << 2) & 63) & 15; +} + +#define DFP_HELPER_ENBCD(op, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t s) \ +{ \ + struct PPC_DFP dfp; \ + uint8_t digits[32]; \ + int n = 0, offset = 0, sgn = 0, nonzero = 0; \ + \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + \ + decNumberZero(&dfp.t); \ + \ + if (s) { \ + uint8_t sgnNibble = dfp_get_bcd_digit_##size(dfp.b64, offset++); \ + switch (sgnNibble) { \ + case 0xD: \ + case 0xB: \ + sgn = 1; \ + break; \ + case 0xC: \ + case 0xF: \ + case 0xA: \ + case 0xE: \ + sgn = 0; \ + break; \ + default: \ + dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE); \ + return; \ + } \ + } \ + \ + while (offset < (size)/4) { \ + n++; \ + digits[(size)/4-n] = dfp_get_bcd_digit_##size(dfp.b64, offset++); \ + if (digits[(size)/4-n] > 10) { \ + dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE); \ + return; \ + } else { \ + nonzero |= (digits[(size)/4-n] > 0); \ + } \ + } \ + \ + if (nonzero) { \ + decNumberSetBCD(&dfp.t, digits+((size)/4)-n, n); \ + } \ + \ + if (s && sgn) { \ + dfp.t.bits |= DECNEG; \ + } \ + decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \ + &dfp.context); \ + dfp_set_FPRF_from_FRT(&dfp); \ + if ((size) == 64) { \ + t[0] = dfp.t64[0]; \ + } else if ((size) == 128) { \ + t[0] = dfp.t64[HI_IDX]; \ + t[1] = dfp.t64[LO_IDX]; \ + } \ +} + +DFP_HELPER_ENBCD(denbcd, 64) +DFP_HELPER_ENBCD(denbcdq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index d4e73f2..1b40ce5 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -656,3 +656,5 @@ DEF_HELPER_3(dctfix, void, env, fprp, fprp) DEF_HELPER_3(dctfixq, void, env, fprp, fprp) DEF_HELPER_4(ddedpd, void, env, fprp, fprp, i32) DEF_HELPER_4(ddedpdq, void, env, fprp, fprp, i32) +DEF_HELPER_4(denbcd, void, env, fprp, fprp, i32) +DEF_HELPER_4(denbcdq, void, env, fprp, fprp, i32) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 0de657a..6aa2df6 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8395,6 +8395,8 @@ GEN_DFP_T_B_Rc(dctfix) GEN_DFP_T_B_Rc(dctfixq) GEN_DFP_T_FPR_I32_Rc(ddedpd, rB, SP) GEN_DFP_T_FPR_I32_Rc(ddedpdq, rB, SP) +GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP) +GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP) /*** SPE extension ***/ /* Register moves */ @@ -11362,6 +11364,8 @@ GEN_DFP_T_B_Rc(dctfix, 0x02, 0x09), GEN_DFP_T_Bp_Rc(dctfixq, 0x02, 0x09), GEN_DFP_SP_T_B_Rc(ddedpd, 0x02, 0x0a), GEN_DFP_SP_Tp_Bp_Rc(ddedpdq, 0x02, 0x0a), +GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a), +GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 049/118] target-ppc: Introduce DFP Extract Biased Exponent 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (47 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 048/118] target-ppc: Introduce DFP Encode BCD to DPD Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 050/118] target-ppc: Introduce DFP Insert " Alexander Graf ` (26 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Extract Biased Exponent instructions dxex[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 31 +++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 ++++ 3 files changed, 37 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index c6c104b..8c8ee79 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -1121,3 +1121,34 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t s) \ DFP_HELPER_ENBCD(denbcd, 64) DFP_HELPER_ENBCD(denbcdq, 128) + +#define DFP_HELPER_XEX(op, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b) \ +{ \ + struct PPC_DFP dfp; \ + \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + \ + if (unlikely(decNumberIsSpecial(&dfp.b))) { \ + if (decNumberIsInfinite(&dfp.b)) { \ + *t = -1; \ + } else if (decNumberIsSNaN(&dfp.b)) { \ + *t = -3; \ + } else if (decNumberIsQNaN(&dfp.b)) { \ + *t = -2; \ + } else { \ + assert(0); \ + } \ + } else { \ + if ((size) == 64) { \ + *t = dfp.b.exponent + 398; \ + } else if ((size) == 128) { \ + *t = dfp.b.exponent + 6176; \ + } else { \ + assert(0); \ + } \ + } \ +} + +DFP_HELPER_XEX(dxex, 64) +DFP_HELPER_XEX(dxexq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 1b40ce5..b99ca80 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -658,3 +658,5 @@ DEF_HELPER_4(ddedpd, void, env, fprp, fprp, i32) DEF_HELPER_4(ddedpdq, void, env, fprp, fprp, i32) DEF_HELPER_4(denbcd, void, env, fprp, fprp, i32) DEF_HELPER_4(denbcdq, void, env, fprp, fprp, i32) +DEF_HELPER_3(dxex, void, env, fprp, fprp) +DEF_HELPER_3(dxexq, void, env, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 6aa2df6..d5c43b0 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8397,6 +8397,8 @@ GEN_DFP_T_FPR_I32_Rc(ddedpd, rB, SP) GEN_DFP_T_FPR_I32_Rc(ddedpdq, rB, SP) GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP) GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP) +GEN_DFP_T_B_Rc(dxex) +GEN_DFP_T_B_Rc(dxexq) /*** SPE extension ***/ /* Register moves */ @@ -11366,6 +11368,8 @@ GEN_DFP_SP_T_B_Rc(ddedpd, 0x02, 0x0a), GEN_DFP_SP_Tp_Bp_Rc(ddedpdq, 0x02, 0x0a), GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a), GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a), +GEN_DFP_T_B_Rc(dxex, 0x02, 0x0b), +GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 050/118] target-ppc: Introduce DFP Insert Biased Exponent 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (48 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 049/118] target-ppc: Introduce DFP Extract Biased Exponent Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 051/118] target-ppc: Introduce DFP Shift Significand Alexander Graf ` (25 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Insert Biased Exponent instructions diex[q][.]. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 2 ++ target-ppc/translate.c | 4 +++ 3 files changed, 74 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 8c8ee79..adb9763 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -1152,3 +1152,71 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b) \ DFP_HELPER_XEX(dxex, 64) DFP_HELPER_XEX(dxexq, 128) + +static void dfp_set_raw_exp_64(uint64_t *t, uint64_t raw) +{ + *t &= 0x8003ffffffffffffULL; + *t |= (raw << (63-13)); +} + +static void dfp_set_raw_exp_128(uint64_t *t, uint64_t raw) +{ + t[HI_IDX] &= 0x80003fffffffffffULL; + t[HI_IDX] |= (raw << (63-17)); +} + +#define DFP_HELPER_IEX(op, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \ +{ \ + struct PPC_DFP dfp; \ + uint64_t raw_qnan, raw_snan, raw_inf, max_exp; \ + int bias; \ + int64_t exp = *((int64_t *)a); \ + \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + \ + if ((size) == 64) { \ + max_exp = 767; \ + raw_qnan = 0x1F00; \ + raw_snan = 0x1F80; \ + raw_inf = 0x1E00; \ + bias = 398; \ + } else if ((size) == 128) { \ + max_exp = 12287; \ + raw_qnan = 0x1f000; \ + raw_snan = 0x1f800; \ + raw_inf = 0x1e000; \ + bias = 6176; \ + } else { \ + assert(0); \ + } \ + \ + if (unlikely((exp < 0) || (exp > max_exp))) { \ + dfp.t64[0] = dfp.b64[0]; \ + dfp.t64[1] = dfp.b64[1]; \ + if (exp == -1) { \ + dfp_set_raw_exp_##size(dfp.t64, raw_inf); \ + } else if (exp == -3) { \ + dfp_set_raw_exp_##size(dfp.t64, raw_snan); \ + } else { \ + dfp_set_raw_exp_##size(dfp.t64, raw_qnan); \ + } \ + } else { \ + dfp.t = dfp.b; \ + if (unlikely(decNumberIsSpecial(&dfp.t))) { \ + dfp.t.bits &= ~DECSPECIAL; \ + } \ + dfp.t.exponent = exp - bias; \ + decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \ + &dfp.context); \ + } \ + if (size == 64) { \ + t[0] = dfp.t64[0]; \ + } else if (size == 128) { \ + t[0] = dfp.t64[HI_IDX]; \ + t[1] = dfp.t64[LO_IDX]; \ + } \ +} + +DFP_HELPER_IEX(diex, 64) +DFP_HELPER_IEX(diexq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index b99ca80..435a1c0 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -660,3 +660,5 @@ DEF_HELPER_4(denbcd, void, env, fprp, fprp, i32) DEF_HELPER_4(denbcdq, void, env, fprp, fprp, i32) DEF_HELPER_3(dxex, void, env, fprp, fprp) DEF_HELPER_3(dxexq, void, env, fprp, fprp) +DEF_HELPER_4(diex, void, env, fprp, fprp, fprp) +DEF_HELPER_4(diexq, void, env, fprp, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index d5c43b0..38e9da6 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8399,6 +8399,8 @@ GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP) GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP) GEN_DFP_T_B_Rc(dxex) GEN_DFP_T_B_Rc(dxexq) +GEN_DFP_T_A_B_Rc(diex) +GEN_DFP_T_A_B_Rc(diexq) /*** SPE extension ***/ /* Register moves */ @@ -11370,6 +11372,8 @@ GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a), GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a), GEN_DFP_T_B_Rc(dxex, 0x02, 0x0b), GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b), +GEN_DFP_T_A_B_Rc(diex, 0x02, 0x1b), +GEN_DFP_Tp_A_Bp_Rc(diexq, 0x02, 0x1b), #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 051/118] target-ppc: Introduce DFP Shift Significand 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (49 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 050/118] target-ppc: Introduce DFP Insert " Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 052/118] spapr_pci: fix MSI limit Alexander Graf ` (24 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> Add emulation of the PowerPC Decimal Floating Point Shift Significand Left Immediate (dscli[q][.]) and DFP Shift Significant Right Immediate (dscri[q][.]) instructions. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/dfp_helper.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ target-ppc/helper.h | 4 +++ target-ppc/translate.c | 10 ++++++ 3 files changed, 109 insertions(+) diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index adb9763..773803a 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -1220,3 +1220,98 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \ DFP_HELPER_IEX(diex, 64) DFP_HELPER_IEX(diexq, 128) + +static void dfp_clear_lmd_from_g5msb(uint64_t *t) +{ + + /* The most significant 5 bits of the PowerPC DFP format combine bits */ + /* from the left-most decimal digit (LMD) and the biased exponent. */ + /* This routine clears the LMD bits while preserving the exponent */ + /* bits. See "Figure 80: Encoding of bits 0:4 of the G field for */ + /* Finite Numbers" in the Power ISA for additional details. */ + + uint64_t g5msb = (*t >> 58) & 0x1F; + + if ((g5msb >> 3) < 3) { /* LMD in [0-7] ? */ + *t &= ~(7ULL << 58); + } else { + switch (g5msb & 7) { + case 0: + case 1: + g5msb = 0; + break; + case 2: + case 3: + g5msb = 0x8; + break; + case 4: + case 5: + g5msb = 0x10; + break; + case 6: + g5msb = 0x1E; + break; + case 7: + g5msb = 0x1F; + break; + } + + *t &= ~(0x1fULL << 58); + *t |= (g5msb << 58); + } +} + +#define DFP_HELPER_SHIFT(op, size, shift_left) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, \ + uint32_t sh) \ +{ \ + struct PPC_DFP dfp; \ + unsigned max_digits = ((size) == 64) ? 16 : 34; \ + \ + dfp_prepare_decimal##size(&dfp, a, 0, env); \ + \ + if (sh <= max_digits) { \ + \ + decNumber shd; \ + unsigned special = dfp.a.bits & DECSPECIAL; \ + \ + if (shift_left) { \ + decNumberFromUInt32(&shd, sh); \ + } else { \ + decNumberFromInt32(&shd, -((int32_t)sh)); \ + } \ + \ + dfp.a.bits &= ~DECSPECIAL; \ + decNumberShift(&dfp.t, &dfp.a, &shd, &dfp.context); \ + \ + dfp.t.bits |= special; \ + if (special && (dfp.t.digits >= max_digits)) { \ + dfp.t.digits = max_digits - 1; \ + } \ + \ + decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \ + &dfp.context); \ + } else { \ + if ((size) == 64) { \ + dfp.t64[0] = dfp.a64[0] & 0xFFFC000000000000ULL; \ + dfp_clear_lmd_from_g5msb(dfp.t64); \ + } else { \ + dfp.t64[HI_IDX] = dfp.a64[HI_IDX] & \ + 0xFFFFC00000000000ULL; \ + dfp_clear_lmd_from_g5msb(dfp.t64 + HI_IDX); \ + dfp.t64[LO_IDX] = 0; \ + } \ + } \ + \ + if ((size) == 64) { \ + t[0] = dfp.t64[0]; \ + } else { \ + t[0] = dfp.t64[HI_IDX]; \ + t[1] = dfp.t64[LO_IDX]; \ + } \ +} + +DFP_HELPER_SHIFT(dscli, 64, 1) +DFP_HELPER_SHIFT(dscliq, 128, 1) +DFP_HELPER_SHIFT(dscri, 64, 0) +DFP_HELPER_SHIFT(dscriq, 128, 0) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 435a1c0..7e00a76 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -662,3 +662,7 @@ DEF_HELPER_3(dxex, void, env, fprp, fprp) DEF_HELPER_3(dxexq, void, env, fprp, fprp) DEF_HELPER_4(diex, void, env, fprp, fprp, fprp) DEF_HELPER_4(diexq, void, env, fprp, fprp, fprp) +DEF_HELPER_4(dscri, void, env, fprp, fprp, i32) +DEF_HELPER_4(dscriq, void, env, fprp, fprp, i32) +DEF_HELPER_4(dscli, void, env, fprp, fprp, i32) +DEF_HELPER_4(dscliq, void, env, fprp, fprp, i32) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 38e9da6..90d5999 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8401,6 +8401,11 @@ GEN_DFP_T_B_Rc(dxex) GEN_DFP_T_B_Rc(dxexq) GEN_DFP_T_A_B_Rc(diex) GEN_DFP_T_A_B_Rc(diexq) +GEN_DFP_T_FPR_I32_Rc(dscli, rA, DCM) +GEN_DFP_T_FPR_I32_Rc(dscliq, rA, DCM) +GEN_DFP_T_FPR_I32_Rc(dscri, rA, DCM) +GEN_DFP_T_FPR_I32_Rc(dscriq, rA, DCM) + /*** SPE extension ***/ /* Register moves */ @@ -11374,6 +11379,11 @@ GEN_DFP_T_B_Rc(dxex, 0x02, 0x0b), GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b), GEN_DFP_T_A_B_Rc(diex, 0x02, 0x1b), GEN_DFP_Tp_A_Bp_Rc(diexq, 0x02, 0x1b), +GEN_DFP_T_A_SH_Rc(dscli, 0x02, 0x02), +GEN_DFP_Tp_Ap_SH_Rc(dscliq, 0x02, 0x02), +GEN_DFP_T_A_SH_Rc(dscri, 0x02, 0x03), +GEN_DFP_Tp_Ap_SH_Rc(dscriq, 0x02, 0x03), + #undef GEN_SPE #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \ GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 052/118] spapr_pci: fix MSI limit 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (50 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 051/118] target-ppc: Introduce DFP Shift Significand Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 053/118] util: Add S-Box and InvS-Box Arrays to Common AES Utils Alexander Graf ` (23 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Alexey Kardashevskiy, qemu-devel From: Alexey Kardashevskiy <aik@ozlabs.ru> At the moment XICS does not support interrupts reuse so sPAPR PHB implements this. sPAPRPHBState holds array of 32 spapr_pci_msi to describe PCI config address, first MSI and number of MSIs. Once allocated for a device, QEMU tries reusing this config until the number of MSIs changes. Existing SPAPR guests call ibm,change-msi in a loop until the handler returns the requested number of vectors. Recently introduced check for the maximum number of MSI/MSIX vectors supported by a device only works for a device which is new for PHB's MSI cache. If it is already there, the check is not performed which leads to new IRQ block allocation. This happens during PCI hotplug even when the user hot plug the same device which he just hot unplugged. This moves the check earlier. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/ppc/spapr_pci.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index c052917..1db73f2 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -280,7 +280,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr, unsigned int req_num = rtas_ld(args, 4); /* 0 == remove all */ unsigned int seq_num = rtas_ld(args, 5); unsigned int ret_intr_type; - int ndev, irq; + int ndev, irq, max_irqs = 0; sPAPRPHBState *phb = NULL; PCIDevice *pdev = NULL; @@ -333,6 +333,23 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr, } trace_spapr_pci_msi("Configuring MSI", ndev, config_addr); + /* Check if the device supports as many IRQs as requested */ + if (ret_intr_type == RTAS_TYPE_MSI) { + max_irqs = msi_nr_vectors_allocated(pdev); + } else if (ret_intr_type == RTAS_TYPE_MSIX) { + max_irqs = pdev->msix_entries_nr; + } + if (!max_irqs) { + error_report("Requested interrupt type %d is not enabled for device#%d", + ret_intr_type, ndev); + rtas_st(rets, 0, -1); /* Hardware error */ + return; + } + /* Correct the number if the guest asked for too many */ + if (req_num > max_irqs) { + req_num = max_irqs; + } + /* Check if there is an old config and MSI number has not changed */ if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) { /* Unexpected behaviour */ @@ -343,21 +360,6 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr, /* There is no cached config, allocate MSIs */ if (!phb->msi_table[ndev].nvec) { - int max_irqs = 0; - if (ret_intr_type == RTAS_TYPE_MSI) { - max_irqs = msi_nr_vectors_allocated(pdev); - } else if (ret_intr_type == RTAS_TYPE_MSIX) { - max_irqs = pdev->msix_entries_nr; - } - if (!max_irqs) { - error_report("Requested interrupt type %d is not enabled for device#%d", - ret_intr_type, ndev); - rtas_st(rets, 0, -1); /* Hardware error */ - return; - } - if (req_num > max_irqs) { - req_num = max_irqs; - } irq = spapr_allocate_irq_block(req_num, false, ret_intr_type == RTAS_TYPE_MSI); if (irq < 0) { -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 053/118] util: Add S-Box and InvS-Box Arrays to Common AES Utils 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (51 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 052/118] spapr_pci: fix MSI limit Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 054/118] util: Add AES ShiftRows and InvShiftRows Tables Alexander Graf ` (22 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> This patch adds tables for the S-Box and InvS-Box transformations commonly used by various Advanced Encription Standard (AES) instruction models. Signed-off-by: Tom Musta <tommusta@gmail.com> Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Alexander Graf <agraf@suse.de> --- include/qemu/aes.h | 3 +++ util/aes.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/include/qemu/aes.h b/include/qemu/aes.h index e79c707..a4044f5 100644 --- a/include/qemu/aes.h +++ b/include/qemu/aes.h @@ -23,6 +23,9 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, const unsigned long length, const AES_KEY *key, unsigned char *ivec, const int enc); +extern const uint8_t AES_sbox[256]; +extern const uint8_t AES_isbox[256]; + /* AES_Te0[x] = S [x].[02, 01, 01, 03]; AES_Te1[x] = S [x].[03, 02, 01, 01]; diff --git a/util/aes.c b/util/aes.c index 4b4d88e..eeb644b 100644 --- a/util/aes.c +++ b/util/aes.c @@ -38,6 +38,76 @@ typedef uint8_t u8; # define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) # define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +const uint8_t AES_sbox[256] = { + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16, +}; + +const uint8_t AES_isbox[256] = { + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D, +}; + /* AES_Te0[x] = S [x].[02, 01, 01, 03]; AES_Te1[x] = S [x].[03, 02, 01, 01]; -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 054/118] util: Add AES ShiftRows and InvShiftRows Tables 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (52 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 053/118] util: Add S-Box and InvS-Box Arrays to Common AES Utils Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 055/118] util: Add InvMixColumns Alexander Graf ` (21 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> This patch adds tables that implement the Advanced Encryption Standard (AES) ShiftRows and InvShiftRows transformations. These are commonly used in instruction models. Signed-off-by: Tom Musta <tommusta@gmail.com> Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Alexander Graf <agraf@suse.de> --- include/qemu/aes.h | 4 ++++ util/aes.c | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/include/qemu/aes.h b/include/qemu/aes.h index a4044f5..c45bc57 100644 --- a/include/qemu/aes.h +++ b/include/qemu/aes.h @@ -26,6 +26,10 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, extern const uint8_t AES_sbox[256]; extern const uint8_t AES_isbox[256]; +/* AES ShiftRows and InvShiftRows */ +extern const uint8_t AES_shifts[16]; +extern const uint8_t AES_ishifts[16]; + /* AES_Te0[x] = S [x].[02, 01, 01, 03]; AES_Te1[x] = S [x].[03, 02, 01, 01]; diff --git a/util/aes.c b/util/aes.c index eeb644b..c26cf55 100644 --- a/util/aes.c +++ b/util/aes.c @@ -108,6 +108,14 @@ const uint8_t AES_isbox[256] = { 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D, }; +const uint8_t AES_shifts[16] = { + 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11 +}; + +const uint8_t AES_ishifts[16] = { + 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3 +}; + /* AES_Te0[x] = S [x].[02, 01, 01, 03]; AES_Te1[x] = S [x].[03, 02, 01, 01]; -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 055/118] util: Add InvMixColumns 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (53 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 054/118] util: Add AES ShiftRows and InvShiftRows Tables Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 056/118] target-i386: Use Common ShiftRows and InvShiftRows Tables Alexander Graf ` (20 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> This patch adds the table implementation of the Advanced Encryption Standard (AES) InvMixColumns transformation. The patch is intentionally asymmetrical -- the MixColumns table is not added because there is no known use for it at this time. Signed-off-by: Tom Musta <tommusta@gmail.com> Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Alexander Graf <agraf@suse.de> --- include/qemu/aes.h | 7 ++ util/aes.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 272 insertions(+) diff --git a/include/qemu/aes.h b/include/qemu/aes.h index c45bc57..c106660 100644 --- a/include/qemu/aes.h +++ b/include/qemu/aes.h @@ -30,6 +30,13 @@ extern const uint8_t AES_isbox[256]; extern const uint8_t AES_shifts[16]; extern const uint8_t AES_ishifts[16]; +/* AES InvMixColumns */ +/* AES_imc[x][0] = [x].[0e, 09, 0d, 0b]; */ +/* AES_imc[x][1] = [x].[0b, 0e, 09, 0d]; */ +/* AES_imc[x][2] = [x].[0d, 0b, 0e, 09]; */ +/* AES_imc[x][3] = [x].[09, 0d, 0b, 0e]; */ +extern const uint32_t AES_imc[256][4]; + /* AES_Te0[x] = S [x].[02, 01, 01, 03]; AES_Te1[x] = S [x].[03, 02, 01, 01]; diff --git a/util/aes.c b/util/aes.c index c26cf55..6058f19 100644 --- a/util/aes.c +++ b/util/aes.c @@ -116,6 +116,271 @@ const uint8_t AES_ishifts[16] = { 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3 }; +/* AES_imc[x][0] = [x].[0e, 09, 0d, 0b]; */ +/* AES_imc[x][1] = [x].[0b, 0e, 09, 0d]; */ +/* AES_imc[x][2] = [x].[0d, 0b, 0e, 09]; */ +/* AES_imc[x][3] = [x].[09, 0d, 0b, 0e]; */ +const uint32_t AES_imc[256][4] = { + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, /* x=00 */ + { 0x0E090D0B, 0x0B0E090D, 0x0D0B0E09, 0x090D0B0E, }, /* x=01 */ + { 0x1C121A16, 0x161C121A, 0x1A161C12, 0x121A161C, }, /* x=02 */ + { 0x121B171D, 0x1D121B17, 0x171D121B, 0x1B171D12, }, /* x=03 */ + { 0x3824342C, 0x2C382434, 0x342C3824, 0x24342C38, }, /* x=04 */ + { 0x362D3927, 0x27362D39, 0x3927362D, 0x2D392736, }, /* x=05 */ + { 0x24362E3A, 0x3A24362E, 0x2E3A2436, 0x362E3A24, }, /* x=06 */ + { 0x2A3F2331, 0x312A3F23, 0x23312A3F, 0x3F23312A, }, /* x=07 */ + { 0x70486858, 0x58704868, 0x68587048, 0x48685870, }, /* x=08 */ + { 0x7E416553, 0x537E4165, 0x65537E41, 0x4165537E, }, /* x=09 */ + { 0x6C5A724E, 0x4E6C5A72, 0x724E6C5A, 0x5A724E6C, }, /* x=0A */ + { 0x62537F45, 0x4562537F, 0x7F456253, 0x537F4562, }, /* x=0B */ + { 0x486C5C74, 0x74486C5C, 0x5C74486C, 0x6C5C7448, }, /* x=0C */ + { 0x4665517F, 0x7F466551, 0x517F4665, 0x65517F46, }, /* x=0D */ + { 0x547E4662, 0x62547E46, 0x4662547E, 0x7E466254, }, /* x=0E */ + { 0x5A774B69, 0x695A774B, 0x4B695A77, 0x774B695A, }, /* x=0F */ + { 0xE090D0B0, 0xB0E090D0, 0xD0B0E090, 0x90D0B0E0, }, /* x=10 */ + { 0xEE99DDBB, 0xBBEE99DD, 0xDDBBEE99, 0x99DDBBEE, }, /* x=11 */ + { 0xFC82CAA6, 0xA6FC82CA, 0xCAA6FC82, 0x82CAA6FC, }, /* x=12 */ + { 0xF28BC7AD, 0xADF28BC7, 0xC7ADF28B, 0x8BC7ADF2, }, /* x=13 */ + { 0xD8B4E49C, 0x9CD8B4E4, 0xE49CD8B4, 0xB4E49CD8, }, /* x=14 */ + { 0xD6BDE997, 0x97D6BDE9, 0xE997D6BD, 0xBDE997D6, }, /* x=15 */ + { 0xC4A6FE8A, 0x8AC4A6FE, 0xFE8AC4A6, 0xA6FE8AC4, }, /* x=16 */ + { 0xCAAFF381, 0x81CAAFF3, 0xF381CAAF, 0xAFF381CA, }, /* x=17 */ + { 0x90D8B8E8, 0xE890D8B8, 0xB8E890D8, 0xD8B8E890, }, /* x=18 */ + { 0x9ED1B5E3, 0xE39ED1B5, 0xB5E39ED1, 0xD1B5E39E, }, /* x=19 */ + { 0x8CCAA2FE, 0xFE8CCAA2, 0xA2FE8CCA, 0xCAA2FE8C, }, /* x=1A */ + { 0x82C3AFF5, 0xF582C3AF, 0xAFF582C3, 0xC3AFF582, }, /* x=1B */ + { 0xA8FC8CC4, 0xC4A8FC8C, 0x8CC4A8FC, 0xFC8CC4A8, }, /* x=1C */ + { 0xA6F581CF, 0xCFA6F581, 0x81CFA6F5, 0xF581CFA6, }, /* x=1D */ + { 0xB4EE96D2, 0xD2B4EE96, 0x96D2B4EE, 0xEE96D2B4, }, /* x=1E */ + { 0xBAE79BD9, 0xD9BAE79B, 0x9BD9BAE7, 0xE79BD9BA, }, /* x=1F */ + { 0xDB3BBB7B, 0x7BDB3BBB, 0xBB7BDB3B, 0x3BBB7BDB, }, /* x=20 */ + { 0xD532B670, 0x70D532B6, 0xB670D532, 0x32B670D5, }, /* x=21 */ + { 0xC729A16D, 0x6DC729A1, 0xA16DC729, 0x29A16DC7, }, /* x=22 */ + { 0xC920AC66, 0x66C920AC, 0xAC66C920, 0x20AC66C9, }, /* x=23 */ + { 0xE31F8F57, 0x57E31F8F, 0x8F57E31F, 0x1F8F57E3, }, /* x=24 */ + { 0xED16825C, 0x5CED1682, 0x825CED16, 0x16825CED, }, /* x=25 */ + { 0xFF0D9541, 0x41FF0D95, 0x9541FF0D, 0x0D9541FF, }, /* x=26 */ + { 0xF104984A, 0x4AF10498, 0x984AF104, 0x04984AF1, }, /* x=27 */ + { 0xAB73D323, 0x23AB73D3, 0xD323AB73, 0x73D323AB, }, /* x=28 */ + { 0xA57ADE28, 0x28A57ADE, 0xDE28A57A, 0x7ADE28A5, }, /* x=29 */ + { 0xB761C935, 0x35B761C9, 0xC935B761, 0x61C935B7, }, /* x=2A */ + { 0xB968C43E, 0x3EB968C4, 0xC43EB968, 0x68C43EB9, }, /* x=2B */ + { 0x9357E70F, 0x0F9357E7, 0xE70F9357, 0x57E70F93, }, /* x=2C */ + { 0x9D5EEA04, 0x049D5EEA, 0xEA049D5E, 0x5EEA049D, }, /* x=2D */ + { 0x8F45FD19, 0x198F45FD, 0xFD198F45, 0x45FD198F, }, /* x=2E */ + { 0x814CF012, 0x12814CF0, 0xF012814C, 0x4CF01281, }, /* x=2F */ + { 0x3BAB6BCB, 0xCB3BAB6B, 0x6BCB3BAB, 0xAB6BCB3B, }, /* x=30 */ + { 0x35A266C0, 0xC035A266, 0x66C035A2, 0xA266C035, }, /* x=31 */ + { 0x27B971DD, 0xDD27B971, 0x71DD27B9, 0xB971DD27, }, /* x=32 */ + { 0x29B07CD6, 0xD629B07C, 0x7CD629B0, 0xB07CD629, }, /* x=33 */ + { 0x038F5FE7, 0xE7038F5F, 0x5FE7038F, 0x8F5FE703, }, /* x=34 */ + { 0x0D8652EC, 0xEC0D8652, 0x52EC0D86, 0x8652EC0D, }, /* x=35 */ + { 0x1F9D45F1, 0xF11F9D45, 0x45F11F9D, 0x9D45F11F, }, /* x=36 */ + { 0x119448FA, 0xFA119448, 0x48FA1194, 0x9448FA11, }, /* x=37 */ + { 0x4BE30393, 0x934BE303, 0x03934BE3, 0xE303934B, }, /* x=38 */ + { 0x45EA0E98, 0x9845EA0E, 0x0E9845EA, 0xEA0E9845, }, /* x=39 */ + { 0x57F11985, 0x8557F119, 0x198557F1, 0xF1198557, }, /* x=3A */ + { 0x59F8148E, 0x8E59F814, 0x148E59F8, 0xF8148E59, }, /* x=3B */ + { 0x73C737BF, 0xBF73C737, 0x37BF73C7, 0xC737BF73, }, /* x=3C */ + { 0x7DCE3AB4, 0xB47DCE3A, 0x3AB47DCE, 0xCE3AB47D, }, /* x=3D */ + { 0x6FD52DA9, 0xA96FD52D, 0x2DA96FD5, 0xD52DA96F, }, /* x=3E */ + { 0x61DC20A2, 0xA261DC20, 0x20A261DC, 0xDC20A261, }, /* x=3F */ + { 0xAD766DF6, 0xF6AD766D, 0x6DF6AD76, 0x766DF6AD, }, /* x=40 */ + { 0xA37F60FD, 0xFDA37F60, 0x60FDA37F, 0x7F60FDA3, }, /* x=41 */ + { 0xB16477E0, 0xE0B16477, 0x77E0B164, 0x6477E0B1, }, /* x=42 */ + { 0xBF6D7AEB, 0xEBBF6D7A, 0x7AEBBF6D, 0x6D7AEBBF, }, /* x=43 */ + { 0x955259DA, 0xDA955259, 0x59DA9552, 0x5259DA95, }, /* x=44 */ + { 0x9B5B54D1, 0xD19B5B54, 0x54D19B5B, 0x5B54D19B, }, /* x=45 */ + { 0x894043CC, 0xCC894043, 0x43CC8940, 0x4043CC89, }, /* x=46 */ + { 0x87494EC7, 0xC787494E, 0x4EC78749, 0x494EC787, }, /* x=47 */ + { 0xDD3E05AE, 0xAEDD3E05, 0x05AEDD3E, 0x3E05AEDD, }, /* x=48 */ + { 0xD33708A5, 0xA5D33708, 0x08A5D337, 0x3708A5D3, }, /* x=49 */ + { 0xC12C1FB8, 0xB8C12C1F, 0x1FB8C12C, 0x2C1FB8C1, }, /* x=4A */ + { 0xCF2512B3, 0xB3CF2512, 0x12B3CF25, 0x2512B3CF, }, /* x=4B */ + { 0xE51A3182, 0x82E51A31, 0x3182E51A, 0x1A3182E5, }, /* x=4C */ + { 0xEB133C89, 0x89EB133C, 0x3C89EB13, 0x133C89EB, }, /* x=4D */ + { 0xF9082B94, 0x94F9082B, 0x2B94F908, 0x082B94F9, }, /* x=4E */ + { 0xF701269F, 0x9FF70126, 0x269FF701, 0x01269FF7, }, /* x=4F */ + { 0x4DE6BD46, 0x464DE6BD, 0xBD464DE6, 0xE6BD464D, }, /* x=50 */ + { 0x43EFB04D, 0x4D43EFB0, 0xB04D43EF, 0xEFB04D43, }, /* x=51 */ + { 0x51F4A750, 0x5051F4A7, 0xA75051F4, 0xF4A75051, }, /* x=52 */ + { 0x5FFDAA5B, 0x5B5FFDAA, 0xAA5B5FFD, 0xFDAA5B5F, }, /* x=53 */ + { 0x75C2896A, 0x6A75C289, 0x896A75C2, 0xC2896A75, }, /* x=54 */ + { 0x7BCB8461, 0x617BCB84, 0x84617BCB, 0xCB84617B, }, /* x=55 */ + { 0x69D0937C, 0x7C69D093, 0x937C69D0, 0xD0937C69, }, /* x=56 */ + { 0x67D99E77, 0x7767D99E, 0x9E7767D9, 0xD99E7767, }, /* x=57 */ + { 0x3DAED51E, 0x1E3DAED5, 0xD51E3DAE, 0xAED51E3D, }, /* x=58 */ + { 0x33A7D815, 0x1533A7D8, 0xD81533A7, 0xA7D81533, }, /* x=59 */ + { 0x21BCCF08, 0x0821BCCF, 0xCF0821BC, 0xBCCF0821, }, /* x=5A */ + { 0x2FB5C203, 0x032FB5C2, 0xC2032FB5, 0xB5C2032F, }, /* x=5B */ + { 0x058AE132, 0x32058AE1, 0xE132058A, 0x8AE13205, }, /* x=5C */ + { 0x0B83EC39, 0x390B83EC, 0xEC390B83, 0x83EC390B, }, /* x=5D */ + { 0x1998FB24, 0x241998FB, 0xFB241998, 0x98FB2419, }, /* x=5E */ + { 0x1791F62F, 0x2F1791F6, 0xF62F1791, 0x91F62F17, }, /* x=5F */ + { 0x764DD68D, 0x8D764DD6, 0xD68D764D, 0x4DD68D76, }, /* x=60 */ + { 0x7844DB86, 0x867844DB, 0xDB867844, 0x44DB8678, }, /* x=61 */ + { 0x6A5FCC9B, 0x9B6A5FCC, 0xCC9B6A5F, 0x5FCC9B6A, }, /* x=62 */ + { 0x6456C190, 0x906456C1, 0xC1906456, 0x56C19064, }, /* x=63 */ + { 0x4E69E2A1, 0xA14E69E2, 0xE2A14E69, 0x69E2A14E, }, /* x=64 */ + { 0x4060EFAA, 0xAA4060EF, 0xEFAA4060, 0x60EFAA40, }, /* x=65 */ + { 0x527BF8B7, 0xB7527BF8, 0xF8B7527B, 0x7BF8B752, }, /* x=66 */ + { 0x5C72F5BC, 0xBC5C72F5, 0xF5BC5C72, 0x72F5BC5C, }, /* x=67 */ + { 0x0605BED5, 0xD50605BE, 0xBED50605, 0x05BED506, }, /* x=68 */ + { 0x080CB3DE, 0xDE080CB3, 0xB3DE080C, 0x0CB3DE08, }, /* x=69 */ + { 0x1A17A4C3, 0xC31A17A4, 0xA4C31A17, 0x17A4C31A, }, /* x=6A */ + { 0x141EA9C8, 0xC8141EA9, 0xA9C8141E, 0x1EA9C814, }, /* x=6B */ + { 0x3E218AF9, 0xF93E218A, 0x8AF93E21, 0x218AF93E, }, /* x=6C */ + { 0x302887F2, 0xF2302887, 0x87F23028, 0x2887F230, }, /* x=6D */ + { 0x223390EF, 0xEF223390, 0x90EF2233, 0x3390EF22, }, /* x=6E */ + { 0x2C3A9DE4, 0xE42C3A9D, 0x9DE42C3A, 0x3A9DE42C, }, /* x=6F */ + { 0x96DD063D, 0x3D96DD06, 0x063D96DD, 0xDD063D96, }, /* x=70 */ + { 0x98D40B36, 0x3698D40B, 0x0B3698D4, 0xD40B3698, }, /* x=71 */ + { 0x8ACF1C2B, 0x2B8ACF1C, 0x1C2B8ACF, 0xCF1C2B8A, }, /* x=72 */ + { 0x84C61120, 0x2084C611, 0x112084C6, 0xC6112084, }, /* x=73 */ + { 0xAEF93211, 0x11AEF932, 0x3211AEF9, 0xF93211AE, }, /* x=74 */ + { 0xA0F03F1A, 0x1AA0F03F, 0x3F1AA0F0, 0xF03F1AA0, }, /* x=75 */ + { 0xB2EB2807, 0x07B2EB28, 0x2807B2EB, 0xEB2807B2, }, /* x=76 */ + { 0xBCE2250C, 0x0CBCE225, 0x250CBCE2, 0xE2250CBC, }, /* x=77 */ + { 0xE6956E65, 0x65E6956E, 0x6E65E695, 0x956E65E6, }, /* x=78 */ + { 0xE89C636E, 0x6EE89C63, 0x636EE89C, 0x9C636EE8, }, /* x=79 */ + { 0xFA877473, 0x73FA8774, 0x7473FA87, 0x877473FA, }, /* x=7A */ + { 0xF48E7978, 0x78F48E79, 0x7978F48E, 0x8E7978F4, }, /* x=7B */ + { 0xDEB15A49, 0x49DEB15A, 0x5A49DEB1, 0xB15A49DE, }, /* x=7C */ + { 0xD0B85742, 0x42D0B857, 0x5742D0B8, 0xB85742D0, }, /* x=7D */ + { 0xC2A3405F, 0x5FC2A340, 0x405FC2A3, 0xA3405FC2, }, /* x=7E */ + { 0xCCAA4D54, 0x54CCAA4D, 0x4D54CCAA, 0xAA4D54CC, }, /* x=7F */ + { 0x41ECDAF7, 0xF741ECDA, 0xDAF741EC, 0xECDAF741, }, /* x=80 */ + { 0x4FE5D7FC, 0xFC4FE5D7, 0xD7FC4FE5, 0xE5D7FC4F, }, /* x=81 */ + { 0x5DFEC0E1, 0xE15DFEC0, 0xC0E15DFE, 0xFEC0E15D, }, /* x=82 */ + { 0x53F7CDEA, 0xEA53F7CD, 0xCDEA53F7, 0xF7CDEA53, }, /* x=83 */ + { 0x79C8EEDB, 0xDB79C8EE, 0xEEDB79C8, 0xC8EEDB79, }, /* x=84 */ + { 0x77C1E3D0, 0xD077C1E3, 0xE3D077C1, 0xC1E3D077, }, /* x=85 */ + { 0x65DAF4CD, 0xCD65DAF4, 0xF4CD65DA, 0xDAF4CD65, }, /* x=86 */ + { 0x6BD3F9C6, 0xC66BD3F9, 0xF9C66BD3, 0xD3F9C66B, }, /* x=87 */ + { 0x31A4B2AF, 0xAF31A4B2, 0xB2AF31A4, 0xA4B2AF31, }, /* x=88 */ + { 0x3FADBFA4, 0xA43FADBF, 0xBFA43FAD, 0xADBFA43F, }, /* x=89 */ + { 0x2DB6A8B9, 0xB92DB6A8, 0xA8B92DB6, 0xB6A8B92D, }, /* x=8A */ + { 0x23BFA5B2, 0xB223BFA5, 0xA5B223BF, 0xBFA5B223, }, /* x=8B */ + { 0x09808683, 0x83098086, 0x86830980, 0x80868309, }, /* x=8C */ + { 0x07898B88, 0x8807898B, 0x8B880789, 0x898B8807, }, /* x=8D */ + { 0x15929C95, 0x9515929C, 0x9C951592, 0x929C9515, }, /* x=8E */ + { 0x1B9B919E, 0x9E1B9B91, 0x919E1B9B, 0x9B919E1B, }, /* x=8F */ + { 0xA17C0A47, 0x47A17C0A, 0x0A47A17C, 0x7C0A47A1, }, /* x=90 */ + { 0xAF75074C, 0x4CAF7507, 0x074CAF75, 0x75074CAF, }, /* x=91 */ + { 0xBD6E1051, 0x51BD6E10, 0x1051BD6E, 0x6E1051BD, }, /* x=92 */ + { 0xB3671D5A, 0x5AB3671D, 0x1D5AB367, 0x671D5AB3, }, /* x=93 */ + { 0x99583E6B, 0x6B99583E, 0x3E6B9958, 0x583E6B99, }, /* x=94 */ + { 0x97513360, 0x60975133, 0x33609751, 0x51336097, }, /* x=95 */ + { 0x854A247D, 0x7D854A24, 0x247D854A, 0x4A247D85, }, /* x=96 */ + { 0x8B432976, 0x768B4329, 0x29768B43, 0x4329768B, }, /* x=97 */ + { 0xD134621F, 0x1FD13462, 0x621FD134, 0x34621FD1, }, /* x=98 */ + { 0xDF3D6F14, 0x14DF3D6F, 0x6F14DF3D, 0x3D6F14DF, }, /* x=99 */ + { 0xCD267809, 0x09CD2678, 0x7809CD26, 0x267809CD, }, /* x=9A */ + { 0xC32F7502, 0x02C32F75, 0x7502C32F, 0x2F7502C3, }, /* x=9B */ + { 0xE9105633, 0x33E91056, 0x5633E910, 0x105633E9, }, /* x=9C */ + { 0xE7195B38, 0x38E7195B, 0x5B38E719, 0x195B38E7, }, /* x=9D */ + { 0xF5024C25, 0x25F5024C, 0x4C25F502, 0x024C25F5, }, /* x=9E */ + { 0xFB0B412E, 0x2EFB0B41, 0x412EFB0B, 0x0B412EFB, }, /* x=9F */ + { 0x9AD7618C, 0x8C9AD761, 0x618C9AD7, 0xD7618C9A, }, /* x=A0 */ + { 0x94DE6C87, 0x8794DE6C, 0x6C8794DE, 0xDE6C8794, }, /* x=A1 */ + { 0x86C57B9A, 0x9A86C57B, 0x7B9A86C5, 0xC57B9A86, }, /* x=A2 */ + { 0x88CC7691, 0x9188CC76, 0x769188CC, 0xCC769188, }, /* x=A3 */ + { 0xA2F355A0, 0xA0A2F355, 0x55A0A2F3, 0xF355A0A2, }, /* x=A4 */ + { 0xACFA58AB, 0xABACFA58, 0x58ABACFA, 0xFA58ABAC, }, /* x=A5 */ + { 0xBEE14FB6, 0xB6BEE14F, 0x4FB6BEE1, 0xE14FB6BE, }, /* x=A6 */ + { 0xB0E842BD, 0xBDB0E842, 0x42BDB0E8, 0xE842BDB0, }, /* x=A7 */ + { 0xEA9F09D4, 0xD4EA9F09, 0x09D4EA9F, 0x9F09D4EA, }, /* x=A8 */ + { 0xE49604DF, 0xDFE49604, 0x04DFE496, 0x9604DFE4, }, /* x=A9 */ + { 0xF68D13C2, 0xC2F68D13, 0x13C2F68D, 0x8D13C2F6, }, /* x=AA */ + { 0xF8841EC9, 0xC9F8841E, 0x1EC9F884, 0x841EC9F8, }, /* x=AB */ + { 0xD2BB3DF8, 0xF8D2BB3D, 0x3DF8D2BB, 0xBB3DF8D2, }, /* x=AC */ + { 0xDCB230F3, 0xF3DCB230, 0x30F3DCB2, 0xB230F3DC, }, /* x=AD */ + { 0xCEA927EE, 0xEECEA927, 0x27EECEA9, 0xA927EECE, }, /* x=AE */ + { 0xC0A02AE5, 0xE5C0A02A, 0x2AE5C0A0, 0xA02AE5C0, }, /* x=AF */ + { 0x7A47B13C, 0x3C7A47B1, 0xB13C7A47, 0x47B13C7A, }, /* x=B0 */ + { 0x744EBC37, 0x37744EBC, 0xBC37744E, 0x4EBC3774, }, /* x=B1 */ + { 0x6655AB2A, 0x2A6655AB, 0xAB2A6655, 0x55AB2A66, }, /* x=B2 */ + { 0x685CA621, 0x21685CA6, 0xA621685C, 0x5CA62168, }, /* x=B3 */ + { 0x42638510, 0x10426385, 0x85104263, 0x63851042, }, /* x=B4 */ + { 0x4C6A881B, 0x1B4C6A88, 0x881B4C6A, 0x6A881B4C, }, /* x=B5 */ + { 0x5E719F06, 0x065E719F, 0x9F065E71, 0x719F065E, }, /* x=B6 */ + { 0x5078920D, 0x0D507892, 0x920D5078, 0x78920D50, }, /* x=B7 */ + { 0x0A0FD964, 0x640A0FD9, 0xD9640A0F, 0x0FD9640A, }, /* x=B8 */ + { 0x0406D46F, 0x6F0406D4, 0xD46F0406, 0x06D46F04, }, /* x=B9 */ + { 0x161DC372, 0x72161DC3, 0xC372161D, 0x1DC37216, }, /* x=BA */ + { 0x1814CE79, 0x791814CE, 0xCE791814, 0x14CE7918, }, /* x=BB */ + { 0x322BED48, 0x48322BED, 0xED48322B, 0x2BED4832, }, /* x=BC */ + { 0x3C22E043, 0x433C22E0, 0xE0433C22, 0x22E0433C, }, /* x=BD */ + { 0x2E39F75E, 0x5E2E39F7, 0xF75E2E39, 0x39F75E2E, }, /* x=BE */ + { 0x2030FA55, 0x552030FA, 0xFA552030, 0x30FA5520, }, /* x=BF */ + { 0xEC9AB701, 0x01EC9AB7, 0xB701EC9A, 0x9AB701EC, }, /* x=C0 */ + { 0xE293BA0A, 0x0AE293BA, 0xBA0AE293, 0x93BA0AE2, }, /* x=C1 */ + { 0xF088AD17, 0x17F088AD, 0xAD17F088, 0x88AD17F0, }, /* x=C2 */ + { 0xFE81A01C, 0x1CFE81A0, 0xA01CFE81, 0x81A01CFE, }, /* x=C3 */ + { 0xD4BE832D, 0x2DD4BE83, 0x832DD4BE, 0xBE832DD4, }, /* x=C4 */ + { 0xDAB78E26, 0x26DAB78E, 0x8E26DAB7, 0xB78E26DA, }, /* x=C5 */ + { 0xC8AC993B, 0x3BC8AC99, 0x993BC8AC, 0xAC993BC8, }, /* x=C6 */ + { 0xC6A59430, 0x30C6A594, 0x9430C6A5, 0xA59430C6, }, /* x=C7 */ + { 0x9CD2DF59, 0x599CD2DF, 0xDF599CD2, 0xD2DF599C, }, /* x=C8 */ + { 0x92DBD252, 0x5292DBD2, 0xD25292DB, 0xDBD25292, }, /* x=C9 */ + { 0x80C0C54F, 0x4F80C0C5, 0xC54F80C0, 0xC0C54F80, }, /* x=CA */ + { 0x8EC9C844, 0x448EC9C8, 0xC8448EC9, 0xC9C8448E, }, /* x=CB */ + { 0xA4F6EB75, 0x75A4F6EB, 0xEB75A4F6, 0xF6EB75A4, }, /* x=CC */ + { 0xAAFFE67E, 0x7EAAFFE6, 0xE67EAAFF, 0xFFE67EAA, }, /* x=CD */ + { 0xB8E4F163, 0x63B8E4F1, 0xF163B8E4, 0xE4F163B8, }, /* x=CE */ + { 0xB6EDFC68, 0x68B6EDFC, 0xFC68B6ED, 0xEDFC68B6, }, /* x=CF */ + { 0x0C0A67B1, 0xB10C0A67, 0x67B10C0A, 0x0A67B10C, }, /* x=D0 */ + { 0x02036ABA, 0xBA02036A, 0x6ABA0203, 0x036ABA02, }, /* x=D1 */ + { 0x10187DA7, 0xA710187D, 0x7DA71018, 0x187DA710, }, /* x=D2 */ + { 0x1E1170AC, 0xAC1E1170, 0x70AC1E11, 0x1170AC1E, }, /* x=D3 */ + { 0x342E539D, 0x9D342E53, 0x539D342E, 0x2E539D34, }, /* x=D4 */ + { 0x3A275E96, 0x963A275E, 0x5E963A27, 0x275E963A, }, /* x=D5 */ + { 0x283C498B, 0x8B283C49, 0x498B283C, 0x3C498B28, }, /* x=D6 */ + { 0x26354480, 0x80263544, 0x44802635, 0x35448026, }, /* x=D7 */ + { 0x7C420FE9, 0xE97C420F, 0x0FE97C42, 0x420FE97C, }, /* x=D8 */ + { 0x724B02E2, 0xE2724B02, 0x02E2724B, 0x4B02E272, }, /* x=D9 */ + { 0x605015FF, 0xFF605015, 0x15FF6050, 0x5015FF60, }, /* x=DA */ + { 0x6E5918F4, 0xF46E5918, 0x18F46E59, 0x5918F46E, }, /* x=DB */ + { 0x44663BC5, 0xC544663B, 0x3BC54466, 0x663BC544, }, /* x=DC */ + { 0x4A6F36CE, 0xCE4A6F36, 0x36CE4A6F, 0x6F36CE4A, }, /* x=DD */ + { 0x587421D3, 0xD3587421, 0x21D35874, 0x7421D358, }, /* x=DE */ + { 0x567D2CD8, 0xD8567D2C, 0x2CD8567D, 0x7D2CD856, }, /* x=DF */ + { 0x37A10C7A, 0x7A37A10C, 0x0C7A37A1, 0xA10C7A37, }, /* x=E0 */ + { 0x39A80171, 0x7139A801, 0x017139A8, 0xA8017139, }, /* x=E1 */ + { 0x2BB3166C, 0x6C2BB316, 0x166C2BB3, 0xB3166C2B, }, /* x=E2 */ + { 0x25BA1B67, 0x6725BA1B, 0x1B6725BA, 0xBA1B6725, }, /* x=E3 */ + { 0x0F853856, 0x560F8538, 0x38560F85, 0x8538560F, }, /* x=E4 */ + { 0x018C355D, 0x5D018C35, 0x355D018C, 0x8C355D01, }, /* x=E5 */ + { 0x13972240, 0x40139722, 0x22401397, 0x97224013, }, /* x=E6 */ + { 0x1D9E2F4B, 0x4B1D9E2F, 0x2F4B1D9E, 0x9E2F4B1D, }, /* x=E7 */ + { 0x47E96422, 0x2247E964, 0x642247E9, 0xE9642247, }, /* x=E8 */ + { 0x49E06929, 0x2949E069, 0x692949E0, 0xE0692949, }, /* x=E9 */ + { 0x5BFB7E34, 0x345BFB7E, 0x7E345BFB, 0xFB7E345B, }, /* x=EA */ + { 0x55F2733F, 0x3F55F273, 0x733F55F2, 0xF2733F55, }, /* x=EB */ + { 0x7FCD500E, 0x0E7FCD50, 0x500E7FCD, 0xCD500E7F, }, /* x=EC */ + { 0x71C45D05, 0x0571C45D, 0x5D0571C4, 0xC45D0571, }, /* x=ED */ + { 0x63DF4A18, 0x1863DF4A, 0x4A1863DF, 0xDF4A1863, }, /* x=EE */ + { 0x6DD64713, 0x136DD647, 0x47136DD6, 0xD647136D, }, /* x=EF */ + { 0xD731DCCA, 0xCAD731DC, 0xDCCAD731, 0x31DCCAD7, }, /* x=F0 */ + { 0xD938D1C1, 0xC1D938D1, 0xD1C1D938, 0x38D1C1D9, }, /* x=F1 */ + { 0xCB23C6DC, 0xDCCB23C6, 0xC6DCCB23, 0x23C6DCCB, }, /* x=F2 */ + { 0xC52ACBD7, 0xD7C52ACB, 0xCBD7C52A, 0x2ACBD7C5, }, /* x=F3 */ + { 0xEF15E8E6, 0xE6EF15E8, 0xE8E6EF15, 0x15E8E6EF, }, /* x=F4 */ + { 0xE11CE5ED, 0xEDE11CE5, 0xE5EDE11C, 0x1CE5EDE1, }, /* x=F5 */ + { 0xF307F2F0, 0xF0F307F2, 0xF2F0F307, 0x07F2F0F3, }, /* x=F6 */ + { 0xFD0EFFFB, 0xFBFD0EFF, 0xFFFBFD0E, 0x0EFFFBFD, }, /* x=F7 */ + { 0xA779B492, 0x92A779B4, 0xB492A779, 0x79B492A7, }, /* x=F8 */ + { 0xA970B999, 0x99A970B9, 0xB999A970, 0x70B999A9, }, /* x=F9 */ + { 0xBB6BAE84, 0x84BB6BAE, 0xAE84BB6B, 0x6BAE84BB, }, /* x=FA */ + { 0xB562A38F, 0x8FB562A3, 0xA38FB562, 0x62A38FB5, }, /* x=FB */ + { 0x9F5D80BE, 0xBE9F5D80, 0x80BE9F5D, 0x5D80BE9F, }, /* x=FC */ + { 0x91548DB5, 0xB591548D, 0x8DB59154, 0x548DB591, }, /* x=FD */ + { 0x834F9AA8, 0xA8834F9A, 0x9AA8834F, 0x4F9AA883, }, /* x=FE */ + { 0x8D4697A3, 0xA38D4697, 0x97A38D46, 0x4697A38D, }, /* x=FF */ +}; + + + /* AES_Te0[x] = S [x].[02, 01, 01, 03]; AES_Te1[x] = S [x].[03, 02, 01, 01]; -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 056/118] target-i386: Use Common ShiftRows and InvShiftRows Tables 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (54 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 055/118] util: Add InvMixColumns Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 057/118] target-arm: Use Common Tables in AES Instructions Alexander Graf ` (19 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> This patch eliminates the (now) redundant copy of the Advanced Encryption Standard (AES) ShiftRows and InvShiftRows tables; the code is updated to use the common tables declared in include/qemu/aes.h. Signed-off-by: Tom Musta <tommusta@gmail.com> Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-i386/ops_sse.h | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h index eb24b5f..886e0a8 100644 --- a/target-i386/ops_sse.h +++ b/target-i386/ops_sse.h @@ -17,6 +17,9 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ + +#include "qemu/aes.h" + #if SHIFT == 0 #define Reg MMXReg #define XMM_ONLY(...) @@ -2204,15 +2207,6 @@ void glue(helper_pclmulqdq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, d->Q(1) = resh; } -/* AES-NI op helpers */ -static const uint8_t aes_shifts[16] = { - 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11 -}; - -static const uint8_t aes_ishifts[16] = { - 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3 -}; - void glue(helper_aesdec, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int i; @@ -2220,10 +2214,10 @@ void glue(helper_aesdec, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) Reg rk = *s; for (i = 0 ; i < 4 ; i++) { - d->L(i) = rk.L(i) ^ bswap32(AES_Td0[st.B(aes_ishifts[4*i+0])] ^ - AES_Td1[st.B(aes_ishifts[4*i+1])] ^ - AES_Td2[st.B(aes_ishifts[4*i+2])] ^ - AES_Td3[st.B(aes_ishifts[4*i+3])]); + d->L(i) = rk.L(i) ^ bswap32(AES_Td0[st.B(AES_ishifts[4*i+0])] ^ + AES_Td1[st.B(AES_ishifts[4*i+1])] ^ + AES_Td2[st.B(AES_ishifts[4*i+2])] ^ + AES_Td3[st.B(AES_ishifts[4*i+3])]); } } @@ -2234,7 +2228,7 @@ void glue(helper_aesdeclast, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) Reg rk = *s; for (i = 0; i < 16; i++) { - d->B(i) = rk.B(i) ^ (AES_Td4[st.B(aes_ishifts[i])] & 0xff); + d->B(i) = rk.B(i) ^ (AES_Td4[st.B(AES_ishifts[i])] & 0xff); } } @@ -2245,10 +2239,10 @@ void glue(helper_aesenc, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) Reg rk = *s; for (i = 0 ; i < 4 ; i++) { - d->L(i) = rk.L(i) ^ bswap32(AES_Te0[st.B(aes_shifts[4*i+0])] ^ - AES_Te1[st.B(aes_shifts[4*i+1])] ^ - AES_Te2[st.B(aes_shifts[4*i+2])] ^ - AES_Te3[st.B(aes_shifts[4*i+3])]); + d->L(i) = rk.L(i) ^ bswap32(AES_Te0[st.B(AES_shifts[4*i+0])] ^ + AES_Te1[st.B(AES_shifts[4*i+1])] ^ + AES_Te2[st.B(AES_shifts[4*i+2])] ^ + AES_Te3[st.B(AES_shifts[4*i+3])]); } } @@ -2259,7 +2253,7 @@ void glue(helper_aesenclast, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) Reg rk = *s; for (i = 0; i < 16; i++) { - d->B(i) = rk.B(i) ^ (AES_Te4[st.B(aes_shifts[i])] & 0xff); + d->B(i) = rk.B(i) ^ (AES_Te4[st.B(AES_shifts[i])] & 0xff); } } -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 057/118] target-arm: Use Common Tables in AES Instructions 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (55 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 056/118] target-i386: Use Common ShiftRows and InvShiftRows Tables Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 058/118] target-ppc: Refactor " Alexander Graf ` (18 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> This patch refactors the ARM cryptographic instructions to use the (newly) added common tables from include/qemu/aes.h. Signed-off-by: Tom Musta <tommusta@gmail.com> Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-arm/crypto_helper.c | 79 +++------------------------------------------- 1 file changed, 4 insertions(+), 75 deletions(-) diff --git a/target-arm/crypto_helper.c b/target-arm/crypto_helper.c index d8898ed..d4e87b4 100644 --- a/target-arm/crypto_helper.c +++ b/target-arm/crypto_helper.c @@ -14,6 +14,7 @@ #include "cpu.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" +#include "qemu/aes.h" union AES_STATE { uint8_t bytes[16]; @@ -24,81 +25,9 @@ union AES_STATE { void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm, uint32_t decrypt) { - static uint8_t const sbox[][256] = { { - /* S-box for encryption */ - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 - }, { - /* S-box for decryption */ - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, - 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, - 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, - 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, - 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, - 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, - 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, - 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, - 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, - 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, - 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, - 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, - 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, - 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, - 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, - 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d - } }; - static uint8_t const shift[][16] = { - /* ShiftRows permutation vector for encryption */ - { 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11 }, - /* ShiftRows permutation vector for decryption */ - { 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3 }, - }; + static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox }; + static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts }; + union AES_STATE rk = { .l = { float64_val(env->vfp.regs[rm]), float64_val(env->vfp.regs[rm + 1]) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 058/118] target-ppc: Refactor AES Instructions 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (56 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 057/118] target-arm: Use Common Tables in AES Instructions Alexander Graf @ 2014-06-04 12:43 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 059/118] KVM: PPC: Don't secretly add 1T segment feature to CPU Alexander Graf ` (17 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:43 UTC (permalink / raw) To: qemu-ppc; +Cc: Tom Musta, qemu-devel From: Tom Musta <tommusta@gmail.com> This patch refactors the PowerPC Advanced Encryption Standard (AES) instructions to use the common AES tables (include/qemu/aes.h). Specifically: - vsbox is recoded to use the AES_sbox table. - vcipher, vcipherlast and vncipherlast are all recoded to use the optimized AES_t[ed][0-4] tables. - vncipher is recoded to use a combination of InvS-Box, InvShiftRows and InvMixColumns tables. It was not possible to use AES_Td[0-4] due to a slight difference in how PowerPC implements vncipher. Signed-off-by: Tom Musta <tommusta@gmail.com> Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/int_helper.c | 292 +++++++----------------------------------------- 1 file changed, 38 insertions(+), 254 deletions(-) diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c index 588f6a9..f6e8846 100644 --- a/target-ppc/int_helper.c +++ b/target-ppc/int_helper.c @@ -19,6 +19,7 @@ #include "cpu.h" #include "qemu/host-utils.h" #include "exec/helper-proto.h" +#include "qemu/aes.h" #include "helper_regs.h" /*****************************************************************************/ @@ -396,9 +397,13 @@ target_ulong helper_602_mfrom(target_ulong arg) #if defined(HOST_WORDS_BIGENDIAN) #define HI_IDX 0 #define LO_IDX 1 +#define AVRB(i) u8[i] +#define AVRW(i) u32[i] #else #define HI_IDX 1 #define LO_IDX 0 +#define AVRB(i) u8[15-(i)] +#define AVRW(i) u32[3-(i)] #endif #if defined(HOST_WORDS_BIGENDIAN) @@ -2338,284 +2343,63 @@ uint32_t helper_bcdsub(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps) return helper_bcdadd(r, a, &bcopy, ps); } -static uint8_t SBOX[256] = { -0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, -0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, -0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, -0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, -0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, -0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, -0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, -0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, -0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, -0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, -0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, -0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, -0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, -0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, -0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, -0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, -0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, -0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, -0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, -0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, -0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, -0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, -0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, -0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, -0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, -0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, -0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, -0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, -0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, -0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, -0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, -0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16, -}; - -static void SubBytes(ppc_avr_t *r, ppc_avr_t *a) -{ - int i; - VECTOR_FOR_INORDER_I(i, u8) { - r->u8[i] = SBOX[a->u8[i]]; - } -} - -static uint8_t InvSBOX[256] = { -0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, -0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, -0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, -0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, -0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, -0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, -0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, -0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, -0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, -0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, -0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, -0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, -0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, -0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, -0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, -0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, -0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, -0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, -0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, -0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, -0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, -0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, -0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, -0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, -0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, -0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, -0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, -0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, -0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, -0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, -0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, -0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D, -}; - -static void InvSubBytes(ppc_avr_t *r, ppc_avr_t *a) +void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a) { int i; VECTOR_FOR_INORDER_I(i, u8) { - r->u8[i] = InvSBOX[a->u8[i]]; + r->u8[i] = AES_sbox[a->u8[i]]; } } -static uint8_t ROTL8(uint8_t x, int n) -{ - return (x << n) | (x >> (8-n)); -} - -static inline int BIT8(uint8_t x, int n) -{ - return (x & (0x80 >> n)) != 0; -} - -static uint8_t GFx02(uint8_t x) -{ - return ROTL8(x, 1) ^ (BIT8(x, 0) ? 0x1A : 0); -} - -static uint8_t GFx03(uint8_t x) -{ - return x ^ ROTL8(x, 1) ^ (BIT8(x, 0) ? 0x1A : 0); -} - -static uint8_t GFx09(uint8_t x) -{ - uint8_t term2 = ROTL8(x, 3); - uint8_t term3 = (BIT8(x, 0) ? 0x68 : 0) | (BIT8(x, 1) ? 0x14 : 0) | - (BIT8(x, 2) ? 0x02 : 0); - uint8_t term4 = (BIT8(x, 1) ? 0x20 : 0) | (BIT8(x, 2) ? 0x18 : 0); - return x ^ term2 ^ term3 ^ term4; -} - -static uint8_t GFx0B(uint8_t x) -{ - uint8_t term2 = ROTL8(x, 1); - uint8_t term3 = (x << 3) | (BIT8(x, 0) ? 0x06 : 0) | - (BIT8(x, 2) ? 0x01 : 0); - uint8_t term4 = (BIT8(x, 0) ? 0x70 : 0) | (BIT8(x, 1) ? 0x06 : 0) | - (BIT8(x, 2) ? 0x08 : 0); - uint8_t term5 = (BIT8(x, 1) ? 0x30 : 0) | (BIT8(x, 2) ? 0x02 : 0); - uint8_t term6 = BIT8(x, 2) ? 0x10 : 0; - return x ^ term2 ^ term3 ^ term4 ^ term5 ^ term6; -} - -static uint8_t GFx0D(uint8_t x) -{ - uint8_t term2 = ROTL8(x, 2); - uint8_t term3 = (x << 3) | (BIT8(x, 1) ? 0x04 : 0) | - (BIT8(x, 2) ? 0x03 : 0); - uint8_t term4 = (BIT8(x, 0) ? 0x58 : 0) | (BIT8(x, 1) ? 0x20 : 0); - uint8_t term5 = (BIT8(x, 1) ? 0x08 : 0) | (BIT8(x, 2) ? 0x10 : 0); - uint8_t term6 = BIT8(x, 2) ? 0x08 : 0; - return x ^ term2 ^ term3 ^ term4 ^ term5 ^ term6; -} - -static uint8_t GFx0E(uint8_t x) -{ - uint8_t term1 = ROTL8(x, 1); - uint8_t term2 = (x << 2) | (BIT8(x, 2) ? 0x02 : 0) | - (BIT8(x, 1) ? 0x01 : 0); - uint8_t term3 = (x << 3) | (BIT8(x, 1) ? 0x04 : 0) | - (BIT8(x, 2) ? 0x01 : 0); - uint8_t term4 = (BIT8(x, 0) ? 0x40 : 0) | (BIT8(x, 1) ? 0x28 : 0) | - (BIT8(x, 2) ? 0x10 : 0); - uint8_t term5 = (BIT8(x, 2) ? 0x08 : 0); - return term1 ^ term2 ^ term3 ^ term4 ^ term5; -} - -#if defined(HOST_WORDS_BIGENDIAN) -#define MCB(x, i, b) ((x)->u8[(i)*4 + (b)]) -#else -#define MCB(x, i, b) ((x)->u8[15 - ((i)*4 + (b))]) -#endif - -static void MixColumns(ppc_avr_t *r, ppc_avr_t *x) +void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { int i; - for (i = 0; i < 4; i++) { - MCB(r, i, 0) = GFx02(MCB(x, i, 0)) ^ GFx03(MCB(x, i, 1)) ^ - MCB(x, i, 2) ^ MCB(x, i, 3); - MCB(r, i, 1) = MCB(x, i, 0) ^ GFx02(MCB(x, i, 1)) ^ - GFx03(MCB(x, i, 2)) ^ MCB(x, i, 3); - MCB(r, i, 2) = MCB(x, i, 0) ^ MCB(x, i, 1) ^ - GFx02(MCB(x, i, 2)) ^ GFx03(MCB(x, i, 3)); - MCB(r, i, 3) = GFx03(MCB(x, i, 0)) ^ MCB(x, i, 1) ^ - MCB(x, i, 2) ^ GFx02(MCB(x, i, 3)); - } -} -static void InvMixColumns(ppc_avr_t *r, ppc_avr_t *x) -{ - int i; - for (i = 0; i < 4; i++) { - MCB(r, i, 0) = GFx0E(MCB(x, i, 0)) ^ GFx0B(MCB(x, i, 1)) ^ - GFx0D(MCB(x, i, 2)) ^ GFx09(MCB(x, i, 3)); - MCB(r, i, 1) = GFx09(MCB(x, i, 0)) ^ GFx0E(MCB(x, i, 1)) ^ - GFx0B(MCB(x, i, 2)) ^ GFx0D(MCB(x, i, 3)); - MCB(r, i, 2) = GFx0D(MCB(x, i, 0)) ^ GFx09(MCB(x, i, 1)) ^ - GFx0E(MCB(x, i, 2)) ^ GFx0B(MCB(x, i, 3)); - MCB(r, i, 3) = GFx0B(MCB(x, i, 0)) ^ GFx0D(MCB(x, i, 1)) ^ - GFx09(MCB(x, i, 2)) ^ GFx0E(MCB(x, i, 3)); + VECTOR_FOR_INORDER_I(i, u32) { + r->AVRW(i) = b->AVRW(i) ^ + (AES_Te0[a->AVRB(AES_shifts[4*i + 0])] ^ + AES_Te1[a->AVRB(AES_shifts[4*i + 1])] ^ + AES_Te2[a->AVRB(AES_shifts[4*i + 2])] ^ + AES_Te3[a->AVRB(AES_shifts[4*i + 3])]); } } -static void ShiftRows(ppc_avr_t *r, ppc_avr_t *x) -{ - MCB(r, 0, 0) = MCB(x, 0, 0); - MCB(r, 1, 0) = MCB(x, 1, 0); - MCB(r, 2, 0) = MCB(x, 2, 0); - MCB(r, 3, 0) = MCB(x, 3, 0); - - MCB(r, 0, 1) = MCB(x, 1, 1); - MCB(r, 1, 1) = MCB(x, 2, 1); - MCB(r, 2, 1) = MCB(x, 3, 1); - MCB(r, 3, 1) = MCB(x, 0, 1); - - MCB(r, 0, 2) = MCB(x, 2, 2); - MCB(r, 1, 2) = MCB(x, 3, 2); - MCB(r, 2, 2) = MCB(x, 0, 2); - MCB(r, 3, 2) = MCB(x, 1, 2); - - MCB(r, 0, 3) = MCB(x, 3, 3); - MCB(r, 1, 3) = MCB(x, 0, 3); - MCB(r, 2, 3) = MCB(x, 1, 3); - MCB(r, 3, 3) = MCB(x, 2, 3); -} - -static void InvShiftRows(ppc_avr_t *r, ppc_avr_t *x) -{ - MCB(r, 0, 0) = MCB(x, 0, 0); - MCB(r, 1, 0) = MCB(x, 1, 0); - MCB(r, 2, 0) = MCB(x, 2, 0); - MCB(r, 3, 0) = MCB(x, 3, 0); - - MCB(r, 0, 1) = MCB(x, 3, 1); - MCB(r, 1, 1) = MCB(x, 0, 1); - MCB(r, 2, 1) = MCB(x, 1, 1); - MCB(r, 3, 1) = MCB(x, 2, 1); - - MCB(r, 0, 2) = MCB(x, 2, 2); - MCB(r, 1, 2) = MCB(x, 3, 2); - MCB(r, 2, 2) = MCB(x, 0, 2); - MCB(r, 3, 2) = MCB(x, 1, 2); - - MCB(r, 0, 3) = MCB(x, 1, 3); - MCB(r, 1, 3) = MCB(x, 2, 3); - MCB(r, 2, 3) = MCB(x, 3, 3); - MCB(r, 3, 3) = MCB(x, 0, 3); -} - -#undef MCB - -void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a) -{ - SubBytes(r, a); -} - -void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) -{ - ppc_avr_t vtemp1, vtemp2, vtemp3; - SubBytes(&vtemp1, a); - ShiftRows(&vtemp2, &vtemp1); - MixColumns(&vtemp3, &vtemp2); - r->u64[0] = vtemp3.u64[0] ^ b->u64[0]; - r->u64[1] = vtemp3.u64[1] ^ b->u64[1]; -} - void helper_vcipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { - ppc_avr_t vtemp1, vtemp2; - SubBytes(&vtemp1, a); - ShiftRows(&vtemp2, &vtemp1); - r->u64[0] = vtemp2.u64[0] ^ b->u64[0]; - r->u64[1] = vtemp2.u64[1] ^ b->u64[1]; + int i; + + VECTOR_FOR_INORDER_I(i, u8) { + r->AVRB(i) = b->AVRB(i) ^ (AES_Te4[a->AVRB(AES_shifts[i])] & 0xFF); + } } void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { /* This differs from what is written in ISA V2.07. The RTL is */ /* incorrect and will be fixed in V2.07B. */ - ppc_avr_t vtemp1, vtemp2, vtemp3; - InvShiftRows(&vtemp1, a); - InvSubBytes(&vtemp2, &vtemp1); - vtemp3.u64[0] = vtemp2.u64[0] ^ b->u64[0]; - vtemp3.u64[1] = vtemp2.u64[1] ^ b->u64[1]; - InvMixColumns(r, &vtemp3); + int i; + ppc_avr_t tmp; + + VECTOR_FOR_INORDER_I(i, u8) { + tmp.AVRB(i) = b->AVRB(i) ^ AES_isbox[a->AVRB(AES_ishifts[i])]; + } + + VECTOR_FOR_INORDER_I(i, u32) { + r->AVRW(i) = + AES_imc[tmp.AVRB(4*i + 0)][0] ^ + AES_imc[tmp.AVRB(4*i + 1)][1] ^ + AES_imc[tmp.AVRB(4*i + 2)][2] ^ + AES_imc[tmp.AVRB(4*i + 3)][3]; + } } void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { - ppc_avr_t vtemp1, vtemp2; - InvShiftRows(&vtemp1, a); - InvSubBytes(&vtemp2, &vtemp1); - r->u64[0] = vtemp2.u64[0] ^ b->u64[0]; - r->u64[1] = vtemp2.u64[1] ^ b->u64[1]; + int i; + + VECTOR_FOR_INORDER_I(i, u8) { + r->AVRB(i) = b->AVRB(i) ^ (AES_Td4[a->AVRB(AES_ishifts[i])] & 0xFF); + } } #define ROTRu32(v, n) (((v) >> (n)) | ((v) << (32-n))) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 059/118] KVM: PPC: Don't secretly add 1T segment feature to CPU 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (57 preceding siblings ...) 2014-06-04 12:43 ` [Qemu-devel] [PULL 058/118] target-ppc: Refactor " Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 060/118] PPC: e500: some pci related cleanup Alexander Graf ` (16 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel When we select a CPU type that does not support 1TB segments, we should not expose 1TB just because KVM supports 1TB segments. User configuration always wins over feature availability. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/kvm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 3569367..0744f51 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -356,6 +356,10 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu) /* Convert to QEMU form */ memset(&env->sps, 0, sizeof(env->sps)); + /* + * XXX This loop should be an entry wide AND of the capabilities that + * the selected CPU has with the capabilities that KVM supports. + */ for (ik = iq = 0; ik < KVM_PPC_PAGE_SIZES_MAX_SZ; ik++) { struct ppc_one_seg_page_size *qsps = &env->sps.sps[iq]; struct kvm_ppc_one_seg_page_size *ksps = &smmu_info.sps[ik]; @@ -382,9 +386,7 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu) } } env->slb_nr = smmu_info.slb_size; - if (smmu_info.flags & KVM_PPC_1T_SEGMENTS) { - env->mmu_model |= POWERPC_MMU_1TSEG; - } else { + if (!(smmu_info.flags & KVM_PPC_1T_SEGMENTS)) { env->mmu_model &= ~POWERPC_MMU_1TSEG; } } -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 060/118] PPC: e500: some pci related cleanup 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (58 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 059/118] KVM: PPC: Don't secretly add 1T segment feature to CPU Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 061/118] PPC: e500: implement PCI INTx routing Alexander Graf ` (15 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: Bharat Bhushan, qemu-devel, Bharat Bhushan From: Bharat Bhushan <r65777@freescale.com> - Use PCI_NUM_PINS rather than hardcoding - use "pin" wherever possible Signed-off-by: Bharat Bhushan <Bharat.Bhushan@freescale.com> Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/pci-host/ppce500.c | 14 +++++++------- hw/ppc/e500.c | 12 +++++++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c index c80b7cb..f672d5f 100644 --- a/hw/pci-host/ppce500.c +++ b/hw/pci-host/ppce500.c @@ -87,7 +87,7 @@ struct PPCE500PCIState { struct pci_outbound pob[PPCE500_PCI_NR_POBS]; struct pci_inbound pib[PPCE500_PCI_NR_PIBS]; uint32_t gasket_time; - qemu_irq irq[4]; + qemu_irq irq[PCI_NUM_PINS]; uint32_t first_slot; /* mmio maps */ MemoryRegion container; @@ -252,26 +252,26 @@ static const MemoryRegionOps e500_pci_reg_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num) +static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int pin) { int devno = pci_dev->devfn >> 3; int ret; - ret = ppce500_pci_map_irq_slot(devno, irq_num); + ret = ppce500_pci_map_irq_slot(devno, pin); pci_debug("%s: devfn %x irq %d -> %d devno:%x\n", __func__, - pci_dev->devfn, irq_num, ret, devno); + pci_dev->devfn, pin, ret, devno); return ret; } -static void mpc85xx_pci_set_irq(void *opaque, int irq_num, int level) +static void mpc85xx_pci_set_irq(void *opaque, int pin, int level) { qemu_irq *pic = opaque; - pci_debug("%s: PCI irq %d, level:%d\n", __func__, irq_num, level); + pci_debug("%s: PCI irq %d, level:%d\n", __func__, pin , level); - qemu_set_irq(pic[irq_num], level); + qemu_set_irq(pic[pin], level); } static const VMStateDescription vmstate_pci_outbound = { diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 223bab9..3e238e6 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -613,7 +613,9 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) target_long initrd_size = 0; target_ulong cur_base = 0; int i; - unsigned int pci_irq_nrs[4] = {1, 2, 3, 4}; + /* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and + * 4 respectively */ + unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4}; qemu_irq **irqs, *mpic; DeviceState *dev; CPUPPCState *firstenv = NULL; @@ -715,10 +717,10 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); - sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]); - sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]); - sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]); - sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]); + for (i = 0; i < PCI_NUM_PINS; i++) { + sysbus_connect_irq(s, i, mpic[pci_irq_nrs[i]]); + } + memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET, sysbus_mmio_get_region(s, 0)); -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 061/118] PPC: e500: implement PCI INTx routing 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (59 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 060/118] PPC: e500: some pci related cleanup Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 062/118] PPC: Fix TCG chunks that don't free their temps Alexander Graf ` (14 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: Bharat Bhushan, qemu-devel, Bharat Bhushan From: Bharat Bhushan <r65777@freescale.com> This patch adds pci pin to irq_num routing callback. This callback is called from pci_device_route_intx_to_irq to find which pci device maps to which irq. This fix is required for pci-device passthrough using vfio. Also without this patch we gets below prints " PCI: Bug - unimplemented PCI INTx routing (e500-pcihost) qemu-system-ppc64: PCI: Bug - unimplemented PCI INTx routing (e500-pcihost) " and Legacy interrupt does not work with pci device passthrough. Signed-off-by: Bharat Bhushan <Bharat.Bhushan@freescale.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> [agraf: remove double semicolon] Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/pci-host/ppce500.c | 25 +++++++++++++++++++++++-- hw/ppc/e500.c | 1 + 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c index f672d5f..ed68658 100644 --- a/hw/pci-host/ppce500.c +++ b/hw/pci-host/ppce500.c @@ -88,7 +88,9 @@ struct PPCE500PCIState { struct pci_inbound pib[PPCE500_PCI_NR_PIBS]; uint32_t gasket_time; qemu_irq irq[PCI_NUM_PINS]; + uint32_t irq_num[PCI_NUM_PINS]; uint32_t first_slot; + uint32_t first_pin_irq; /* mmio maps */ MemoryRegion container; MemoryRegion iomem; @@ -267,13 +269,26 @@ static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int pin) static void mpc85xx_pci_set_irq(void *opaque, int pin, int level) { - qemu_irq *pic = opaque; + PPCE500PCIState *s = opaque; + qemu_irq *pic = s->irq; pci_debug("%s: PCI irq %d, level:%d\n", __func__, pin , level); qemu_set_irq(pic[pin], level); } +static PCIINTxRoute e500_route_intx_pin_to_irq(void *opaque, int pin) +{ + PCIINTxRoute route; + PPCE500PCIState *s = opaque; + + route.mode = PCI_INTX_ENABLED; + route.irq = s->irq_num[pin]; + + pci_debug("%s: PCI irq-pin = %d, irq_num= %d\n", __func__, pin, route.irq); + return route; +} + static const VMStateDescription vmstate_pci_outbound = { .name = "pci_outbound", .version_id = 0, @@ -352,10 +367,14 @@ static int e500_pcihost_initfn(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[i]); } + for (i = 0; i < PCI_NUM_PINS; i++) { + s->irq_num[i] = s->first_pin_irq + i; + } + memory_region_init(&s->pio, OBJECT(s), "pci-pio", PCIE500_PCI_IOLEN); b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq, - mpc85xx_pci_map_irq, s->irq, address_space_mem, + mpc85xx_pci_map_irq, s, address_space_mem, &s->pio, PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS); h->bus = b; @@ -373,6 +392,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev) memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem); sysbus_init_mmio(dev, &s->container); sysbus_init_mmio(dev, &s->pio); + pci_bus_set_route_irq_fn(b, e500_route_intx_pin_to_irq); return 0; } @@ -403,6 +423,7 @@ static const TypeInfo e500_host_bridge_info = { static Property pcihost_properties[] = { DEFINE_PROP_UINT32("first_slot", PPCE500PCIState, first_slot, 0x11), + DEFINE_PROP_UINT32("first_pin_irq", PPCE500PCIState, first_pin_irq, 0x1), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 3e238e6..a315618 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -715,6 +715,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) /* PCI */ dev = qdev_create(NULL, "e500-pcihost"); qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot); + qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); for (i = 0; i < PCI_NUM_PINS; i++) { -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 062/118] PPC: Fix TCG chunks that don't free their temps 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (60 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 061/118] PPC: e500: implement PCI INTx routing Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 063/118] PPC: Fail on leaking temporaries Alexander Graf ` (13 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel We want to make sure that every instruction cleans up after itself and clears every temporary it allocated. While checking whether this is already the case, I came across a few cases where it isn't. This patch fixes every translation I found that doesn't free their allocated temporaries. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/translate.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 90d5999..e609d4e 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -1223,6 +1223,7 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1, } tcg_gen_xor_tl(t1, arg2, inv1); /* add without carry */ tcg_gen_add_tl(t0, t0, inv1); + tcg_temp_free(inv1); tcg_gen_xor_tl(cpu_ca, t0, t1); /* bits changes w/ carry */ tcg_temp_free(t1); tcg_gen_shri_tl(cpu_ca, cpu_ca, 32); /* extract bit 32 */ @@ -3919,6 +3920,9 @@ static inline void gen_bcond(DisasContext *ctx, int type) gen_update_nip(ctx, ctx->nip); tcg_gen_exit_tb(0); } + if (type == BCOND_LR || type == BCOND_CTR) { + tcg_temp_free(target); + } } static void gen_bc(DisasContext *ctx) @@ -4366,6 +4370,7 @@ static void gen_mtmsr(DisasContext *ctx) tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]); #endif gen_helper_store_msr(cpu_env, msr); + tcg_temp_free(msr); /* Must stop the translation as machine state (may have) changed */ /* Note that mtmsr is not always defined as context-synchronizing */ gen_stop_exception(ctx); @@ -6500,6 +6505,7 @@ static void gen_tlbsx_booke206(DisasContext *ctx) tcg_gen_add_tl(t0, t0, cpu_gpr[rB(ctx->opcode)]); gen_helper_booke206_tlbsx(cpu_env, t0); + tcg_temp_free(t0); #endif } @@ -6533,6 +6539,7 @@ static void gen_tlbivax_booke206(DisasContext *ctx) gen_addr_reg_index(ctx, t0); gen_helper_booke206_tlbivax(cpu_env, t0); + tcg_temp_free(t0); #endif } -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 063/118] PPC: Fail on leaking temporaries 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (61 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 062/118] PPC: Fix TCG chunks that don't free their temps Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 064/118] PPC: Make all e500 CPUs SVR aware Alexander Graf ` (12 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel When QEMU gets compiled with --enable-debug-tcg we can check for temporary leakage. Implement the necessary target code for this and fail emulation when we hit a leakage. This hopefully ensures that we don't get new leaks. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/translate.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index e609d4e..6aede79 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -11766,6 +11766,7 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, max_insns = CF_COUNT_MASK; gen_tb_start(); + tcg_clear_temp_count(); /* Set env in case of segfault during code fetch */ while (ctx.exception == POWERPC_EXCP_NONE && tcg_ctx.gen_opc_ptr < gen_opc_end) { @@ -11865,6 +11866,12 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, */ break; } + if (tcg_check_temp_count()) { + fprintf(stderr, "Opcode %02x %02x %02x (%08x) leaked temporaries\n", + opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode), + ctx.opcode); + exit(1); + } } if (tb->cflags & CF_LAST_IO) gen_io_end(); -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 064/118] PPC: Make all e500 CPUs SVR aware 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (62 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 063/118] PPC: Fail on leaking temporaries Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 065/118] PPC: Add definitions for GIVORs Alexander Graf ` (11 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel Our pre-e500mc e500 CPU types didn't get instanciated with SVR information, even though those systems do support the SVR register. Spawn them with the SVR tag so that they don't get confused when someone tries to read SPR_SVR. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/cpu-models.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c index 57cb4e4..9a66c03 100644 --- a/target-ppc/cpu-models.c +++ b/target-ppc/cpu-models.c @@ -671,20 +671,20 @@ POWERPC_DEF_SVR("MPC8379E", "MPC8379E", CPU_POWERPC_MPC837x, POWERPC_SVR_8379E, e300) /* e500 family */ - POWERPC_DEF("e500_v10", CPU_POWERPC_e500v1_v10, e500v1, - "PowerPC e500 v1.0 core") - POWERPC_DEF("e500_v20", CPU_POWERPC_e500v1_v20, e500v1, - "PowerPC e500 v2.0 core") - POWERPC_DEF("e500v2_v10", CPU_POWERPC_e500v2_v10, e500v2, - "PowerPC e500v2 v1.0 core") - POWERPC_DEF("e500v2_v20", CPU_POWERPC_e500v2_v20, e500v2, - "PowerPC e500v2 v2.0 core") - POWERPC_DEF("e500v2_v21", CPU_POWERPC_e500v2_v21, e500v2, - "PowerPC e500v2 v2.1 core") - POWERPC_DEF("e500v2_v22", CPU_POWERPC_e500v2_v22, e500v2, - "PowerPC e500v2 v2.2 core") - POWERPC_DEF("e500v2_v30", CPU_POWERPC_e500v2_v30, e500v2, - "PowerPC e500v2 v3.0 core") + POWERPC_DEF_SVR("e500_v10", "PowerPC e500 v1.0 core", + CPU_POWERPC_e500v1_v10, POWERPC_SVR_E500, e500v1); + POWERPC_DEF_SVR("e500_v20", "PowerPC e500 v2.0 core", + CPU_POWERPC_e500v1_v20, POWERPC_SVR_E500, e500v1); + POWERPC_DEF_SVR("e500v2_v10", "PowerPC e500v2 v1.0 core", + CPU_POWERPC_e500v2_v10, POWERPC_SVR_E500, e500v2); + POWERPC_DEF_SVR("e500v2_v20", "PowerPC e500v2 v2.0 core", + CPU_POWERPC_e500v2_v20, POWERPC_SVR_E500, e500v2); + POWERPC_DEF_SVR("e500v2_v21", "PowerPC e500v2 v2.1 core", + CPU_POWERPC_e500v2_v21, POWERPC_SVR_E500, e500v2); + POWERPC_DEF_SVR("e500v2_v22", "PowerPC e500v2 v2.2 core", + CPU_POWERPC_e500v2_v22, POWERPC_SVR_E500, e500v2); + POWERPC_DEF_SVR("e500v2_v30", "PowerPC e500v2 v3.0 core", + CPU_POWERPC_e500v2_v30, POWERPC_SVR_E500, e500v2); POWERPC_DEF_SVR("e500mc", "e500mc", CPU_POWERPC_e500mc, POWERPC_SVR_E500, e500mc) #ifdef TARGET_PPC64 -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 065/118] PPC: Add definitions for GIVORs 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (63 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 064/118] PPC: Make all e500 CPUs SVR aware Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 066/118] PPC: Fix SPR access control of L1CFG0 Alexander Graf ` (10 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel We're missing SPR definitions for GIVORs. Add them to the list of SPRs. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/cpu.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 75ed5fa..178fc55 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1365,6 +1365,12 @@ static inline int cpu_mmu_index (CPUPPCState *env) #define SPR_BOOKE_IVOR40 (0x1B2) #define SPR_BOOKE_IVOR41 (0x1B3) #define SPR_BOOKE_IVOR42 (0x1B4) +#define SPR_BOOKE_GIVOR2 (0x1B8) +#define SPR_BOOKE_GIVOR3 (0x1B9) +#define SPR_BOOKE_GIVOR4 (0x1BA) +#define SPR_BOOKE_GIVOR8 (0x1BB) +#define SPR_BOOKE_GIVOR13 (0x1BC) +#define SPR_BOOKE_GIVOR14 (0x1BD) #define SPR_BOOKE_SPEFSCR (0x200) #define SPR_Exxx_BBEAR (0x201) #define SPR_Exxx_BBTAR (0x202) -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 066/118] PPC: Fix SPR access control of L1CFG0 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (64 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 065/118] PPC: Add definitions for GIVORs Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 067/118] PPC: Add L1CFG1 SPR emulation Alexander Graf ` (9 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel The L1CFG0 register on e200 and e500 is "User RO" according to the specifications. So let's make it user readable and world unwritable. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/translate_init.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 1d64ec9..07f723d 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -4433,8 +4433,8 @@ static void init_proc_e200 (CPUPPCState *env) 0x00000000); /* XXX : not implemented */ spr_register(env, SPR_Exxx_L1CFG0, "L1CFG0", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, + &spr_read_generic, SPR_NOACCESS, + &spr_read_generic, SPR_NOACCESS, 0x00000000); /* XXX : not implemented */ spr_register(env, SPR_Exxx_L1CSR0, "L1CSR0", @@ -4766,8 +4766,8 @@ static void init_proc_e500 (CPUPPCState *env, int version) 0x00000000); /* XXX : not implemented */ spr_register(env, SPR_Exxx_L1CFG0, "L1CFG0", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, + &spr_read_generic, SPR_NOACCESS, + &spr_read_generic, SPR_NOACCESS, l1cfg0); /* XXX : not implemented */ spr_register(env, SPR_Exxx_L1CSR0, "L1CSR0", -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 067/118] PPC: Add L1CFG1 SPR emulation 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (65 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 066/118] PPC: Fix SPR access control of L1CFG0 Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 068/118] PPC: Properly emulate L1CSR0 and L1CSR1 Alexander Graf ` (8 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel In addition to the L1 data cache configuration register L1CFG0 there is also another one for the L1 instruction cache called L1CFG1. Emulate that one with the same values as the data one. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/cpu.h | 1 + target-ppc/translate_init.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 178fc55..f36c90b 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1375,6 +1375,7 @@ static inline int cpu_mmu_index (CPUPPCState *env) #define SPR_Exxx_BBEAR (0x201) #define SPR_Exxx_BBTAR (0x202) #define SPR_Exxx_L1CFG0 (0x203) +#define SPR_Exxx_L1CFG1 (0x204) #define SPR_Exxx_NPIDR (0x205) #define SPR_ATBL (0x20E) #define SPR_ATBU (0x20F) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 07f723d..fc9d932 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -4651,6 +4651,8 @@ static void init_proc_e500 (CPUPPCState *env, int version) uint64_t ivpr_mask = 0xFFFF0000ULL; uint32_t l1cfg0 = 0x3800 /* 8 ways */ | 0x0020; /* 32 kb */ + uint32_t l1cfg1 = 0x3800 /* 8 ways */ + | 0x0020; /* 32 kb */ #if !defined(CONFIG_USER_ONLY) int i; #endif @@ -4719,6 +4721,7 @@ static void init_proc_e500 (CPUPPCState *env, int version) env->dcache_line_size = 64; env->icache_line_size = 64; l1cfg0 |= 0x1000000; /* 64 byte cache block size */ + l1cfg1 |= 0x1000000; /* 64 byte cache block size */ break; default: cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]); @@ -4769,7 +4772,10 @@ static void init_proc_e500 (CPUPPCState *env, int version) &spr_read_generic, SPR_NOACCESS, &spr_read_generic, SPR_NOACCESS, l1cfg0); - /* XXX : not implemented */ + spr_register(env, SPR_Exxx_L1CFG1, "L1CFG1", + &spr_read_generic, SPR_NOACCESS, + &spr_read_generic, SPR_NOACCESS, + l1cfg1); spr_register(env, SPR_Exxx_L1CSR0, "L1CSR0", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_e500_l1csr0, -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 068/118] PPC: Properly emulate L1CSR0 and L1CSR1 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (66 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 067/118] PPC: Add L1CFG1 SPR emulation Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 069/118] PPC: Add dcbtls emulation Alexander Graf ` (7 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel There are 2 L1 cache control registers - one for data (L1CSR0) and one for instructions (L1CSR1). Emulate both of them well enough to give the guest the illusion that it could actually do anything about its caches. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/cpu.h | 12 ++++++++++++ target-ppc/translate_init.c | 14 +++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index f36c90b..b035e91 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1716,6 +1716,18 @@ static inline int cpu_mmu_index (CPUPPCState *env) /* External Input Interrupt Directed to Guest State */ #define EPCR_EXTGS (1 << 31) +#define L1CSR0_CPE 0x00010000 /* Data Cache Parity Enable */ +#define L1CSR0_CUL 0x00000400 /* (D-)Cache Unable to Lock */ +#define L1CSR0_DCLFR 0x00000100 /* D-Cache Lock Flash Reset */ +#define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */ +#define L1CSR0_DCE 0x00000001 /* Data Cache Enable */ + +#define L1CSR1_CPE 0x00010000 /* Instruction Cache Parity Enable */ +#define L1CSR1_ICUL 0x00000400 /* I-Cache Unable to Lock */ +#define L1CSR1_ICLFR 0x00000100 /* I-Cache Lock Flash Reset */ +#define L1CSR1_ICFI 0x00000002 /* Instruction Cache Flash Invalidate */ +#define L1CSR1_ICE 0x00000001 /* Instruction Cache Enable */ + /*****************************************************************************/ /* PowerPC Instructions types definitions */ enum { diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index fc9d932..0f9dec7 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -1448,7 +1448,16 @@ static void spr_write_e500_l1csr0 (void *opaque, int sprn, int gprn) { TCGv t0 = tcg_temp_new(); - tcg_gen_andi_tl(t0, cpu_gpr[gprn], ~256); + tcg_gen_andi_tl(t0, cpu_gpr[gprn], L1CSR0_DCE | L1CSR0_CPE); + gen_store_spr(sprn, t0); + tcg_temp_free(t0); +} + +static void spr_write_e500_l1csr1(void *opaque, int sprn, int gprn) +{ + TCGv t0 = tcg_temp_new(); + + tcg_gen_andi_tl(t0, cpu_gpr[gprn], L1CSR1_ICE | L1CSR1_CPE); gen_store_spr(sprn, t0); tcg_temp_free(t0); } @@ -4780,10 +4789,9 @@ static void init_proc_e500 (CPUPPCState *env, int version) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_e500_l1csr0, 0x00000000); - /* XXX : not implemented */ spr_register(env, SPR_Exxx_L1CSR1, "L1CSR1", SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, + &spr_read_generic, &spr_write_e500_l1csr1, 0x00000000); spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0", SPR_NOACCESS, SPR_NOACCESS, -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 069/118] PPC: Add dcbtls emulation 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (67 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 068/118] PPC: Properly emulate L1CSR0 and L1CSR1 Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 070/118] PPC: e500: Expose kernel load address in dt Alexander Graf ` (6 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel The dcbtls instruction is able to lock data inside the L1 cache. Unfortunately we don't emulate any caches, so we have to tell the guest that its locking attempt failed. However, by implementing the instruction we at least don't give the guest a program exception which it definitely does not expect. Signed-off-by: Alexander Graf <agraf@suse.de> --- target-ppc/translate.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 6aede79..e205e0c 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -4480,6 +4480,17 @@ static void gen_dcbtst(DisasContext *ctx) */ } +/* dcbtls */ +static void gen_dcbtls(DisasContext *ctx) +{ + /* Always fails locking the cache */ + TCGv t0 = tcg_temp_new(); + gen_load_spr(t0, SPR_Exxx_L1CSR0); + tcg_gen_ori_tl(t0, t0, L1CSR0_CUL); + gen_store_spr(SPR_Exxx_L1CSR0, t0); + tcg_temp_free(t0); +} + /* dcbz */ static void gen_dcbz(DisasContext *ctx) { @@ -10214,6 +10225,7 @@ GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE), GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE), GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x00000001, PPC_CACHE), GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE), +GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206), GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ), GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC), GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC), -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 070/118] PPC: e500: Expose kernel load address in dt 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (68 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 069/118] PPC: Add dcbtls emulation Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 071/118] PPC: Add u-boot firmware for e500 Alexander Graf ` (5 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel We want to move to a model where firmware loads our kernel. To achieve this we need to be able to tell firmware where the kernel lies. Let's copy the mechanism we already use for -M pseries and expose the kernel load address and size through the device tree. Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/ppc/e500.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index a315618..5321f06 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -128,6 +128,8 @@ static int ppce500_load_device_tree(MachineState *machine, hwaddr addr, hwaddr initrd_base, hwaddr initrd_size, + hwaddr kernel_base, + hwaddr kernel_size, bool dry_run) { CPUPPCState *env = first_cpu->env_ptr; @@ -204,6 +206,13 @@ static int ppce500_load_device_tree(MachineState *machine, if (ret < 0) { fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); } + + } + + if (kernel_base != -1ULL) { + qemu_fdt_setprop_cells(fdt, "/chosen", "qemu,boot-kernel", + kernel_base >> 32, kernel_base, + kernel_size >> 32, kernel_size); } ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", @@ -392,20 +401,25 @@ typedef struct DeviceTreeParams { hwaddr addr; hwaddr initrd_base; hwaddr initrd_size; + hwaddr kernel_base; + hwaddr kernel_size; } DeviceTreeParams; static void ppce500_reset_device_tree(void *opaque) { DeviceTreeParams *p = opaque; - ppce500_load_device_tree(p->machine, &p->params, p->addr, p->initrd_base, - p->initrd_size, false); + ppce500_load_device_tree(&p->machine, &p->params, p->addr, p->initrd_base, + p->initrd_size, p->kernel_base, p->kernel_size, + false); } static int ppce500_prep_device_tree(MachineState *machine, PPCE500Params *params, hwaddr addr, hwaddr initrd_base, - hwaddr initrd_size) + hwaddr initrd_size, + hwaddr kernel_base, + hwaddr kernel_size) { DeviceTreeParams *p = g_new(DeviceTreeParams, 1); p->machine = machine; @@ -413,12 +427,15 @@ static int ppce500_prep_device_tree(MachineState *machine, p->addr = addr; p->initrd_base = initrd_base; p->initrd_size = initrd_size; + p->kernel_base = kernel_base; + p->kernel_size = kernel_size; qemu_register_reset(ppce500_reset_device_tree, p); /* Issue the device tree loader once, so that we get the size of the blob */ return ppce500_load_device_tree(machine, params, addr, initrd_base, - initrd_size, true); + initrd_size, kernel_base, kernel_size, + true); } /* Create -kernel TLB entries for BookE. */ @@ -787,7 +804,8 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) int dt_size; dt_size = ppce500_prep_device_tree(machine, params, dt_base, - initrd_base, initrd_size); + initrd_base, initrd_size, + loadaddr, kernel_size); if (dt_size < 0) { fprintf(stderr, "couldn't load device tree\n"); exit(1); -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 071/118] PPC: Add u-boot firmware for e500 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (69 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 070/118] PPC: e500: Expose kernel load address in dt Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 072/118] PPC: e500: Move to u-boot as firmware Alexander Graf ` (4 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel This adds a special build of u-boot tailored for the e500 platforms we emulate. It is based on the current version of upstream u-boot which contains all the code necessary to drive our QEMU provided machines. Signed-off-by: Alexander Graf <agraf@suse.de> --- .gitmodules | 3 +++ pc-bios/README | 5 +++++ pc-bios/u-boot.e500 | Bin 0 -> 330260 bytes roms/Makefile | 9 +++++++++ roms/u-boot | 1 + 5 files changed, 18 insertions(+) create mode 100755 pc-bios/u-boot.e500 create mode 160000 roms/u-boot diff --git a/.gitmodules b/.gitmodules index 444c24a..9da9ede 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,3 +28,6 @@ [submodule "dtc"] path = dtc url = git://git.qemu-project.org/dtc.git +[submodule "roms/u-boot"] + path = roms/u-boot + url = git://git.qemu-project.org/u-boot.git diff --git a/pc-bios/README b/pc-bios/README index 4381718..49cdacf 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -41,3 +41,8 @@ - The sources for the Alpha palcode image is available from: git://github.com/rth7680/qemu-palcode.git + +- The u-boot binary for e500 comes from the upstream denx u-boot project where + it was compiled using the qemu-ppce500 target. + A git mirror is available at: git://git.qemu-project.org/u-boot.git + The hash used to compile the current version is: 2072e72 diff --git a/pc-bios/u-boot.e500 b/pc-bios/u-boot.e500 new file mode 100755 index 0000000000000000000000000000000000000000..bdb2a5e6f7cb6775d8d7de65fafcef54c4a03967 GIT binary patch literal 330260 zcmeFa4|rA8mG{5z%?(^I)@yrdqei`vXcG(&YpgeafE&R19SC-!hC&_G&_D|<cA)Cp zpy%e^O9D+Owh0L>e*%OGDOlvi8J*F}pHR^kJ350c^o3S!sGtD?gB`3OA?N+9ea=k+ zqR#XCb>3&@H;3oB>~r?nd+oKqd+oK?UVELB*d3Gp%H#E@-hW;d<l3W7>70C(>Q7Ui zxKjBlq`WFyU9QsfbEzU_<mVfhrhiHeq^A7ysMLT`XPlqTstAz`aGvWN_dgc_7XcRm z7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm z7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm z7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm z7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm z7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm z7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm z7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm z7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm z7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm z7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7XcRm7lHpg2!umkWrjRiX4N%SVWqt0XV0~n zpW~M|kzZ+BaY&sq$6VG{T%lA&Wk7{%Jj!gSYzx;=uTjzzWiFM}r_3fvQ<d2)=>TOe zlXRdme=MnAnLm+qkTRD`I#`)2CB00Ut0YZRW{aekD|5A^pHb!-Nv}}mT2de@4q2A@ z`II&@V_chgEx){b+RPxo>n<bj2W_S&rL9=S6|BZ9R79D9b8UuFsb;pfEgVtG{OYQ< zNy?LJD&J;PU6B>tyRvQaKQA0@&RfazE8=ElpsJ$Mqh?f6cit-cY*`hRr<9qQ9yae@ z*=CMSuQJD8R%PD3s?EHo-~B!P=?+{EuRc=^$fBJ&X5*7><+Z7!!!RW@&6K&Sd}iXh zaHaB;EKnIUHUyNpHCcb)`d<E0LaHQg?JI`wim@KAc@Jaq(1&g2^guymfpv!Q@Kiv< zeCV9rC!WonE;M<TtaCSYzI%x}-*xKnthY{k;EIZu!PrU7z4X7mT~)k1M47M4wK~P~ z!RD`fuZNhw(btrrZ+nmT!`AKxv_4}$OVavml2$<H+qC5R-$4r;UiRh{cfiNH-reSh z$ieSZXj9DqivU<CbKHWqxnn(6`Pk5x%?T-5W=wT`m#MCr1m2;s$~tYR%NYsxpNoKt zfQx{OfQx{OfQx{OfQx{OfQ!I?KLoy*dev7a4<GxtfBSIgOL@2CkI1`y_;)LB8J?Gy zcYDF`Z+<E7_Akx6{Y%4V%>M4f^F!HpPM;sT<;%KYXn5$BTMP5@3vbKM>5rPd7aLP1 z`}Kwt{qvdAuc?xKc(l&j7Ek-atI_z^gRzts$-8bp<-HY^><cSAS+e&fZ-}9mJR;Zq z>HbGuS2v7ntA3haT-{W-&QeR4sf|nbt659mS97Wx#<p=^QT;mUel?>S{<&|heuZ?u zYN<}>`}NhU2TT4l)xR6uR()=8Tf-0)Xt+%U8z!rCQdPa~=T!}lsEmeXD%9|-%4*oJ zvcuC=Krj)S3z}7^x-O-yFs{_yrw4rZD{+;nRCbn9ffj!MQC-(`|FZpGO#c`ErTWj- z{=ZuPz4YJv|DpeZe&auEx!eE$*5iNb|Ig!ZHZf1ondaY-KC7O)NFQd|`cUSBFVv?K zbGrZ1nEYk+-~a3R|1td?mj9RT@5PJBf0F(?>)-!<{Wq#Ysp;QVYE+zb2|i?15sAcA zS-A>~j(*!4Oz^BQp4OdcR;pl$bvmrlUX?N>36<MOp6N$^(@3w@sn5Jdr~ZO?+T18> zdh}8J)SNenJ;Q=FBU+)_3Upg>75#QaRq|OB`zLu#-R=auB<3g;ot4r?>JvJo{^(;V zZ3RnIn((CC???OMvHkbl|K}b5Tl4;-Wnb|5&)a`@{ddRzzqS4IU(o*jOYZ+}uK2$p z|LkKMMz<?p^#@z4*z-0wywAEeMCCQ!rt%vnt8n8Zs<?5PiZni}#y9R)M&tWx($XQS zZ0T*PeCcF0b?GB&TGJ3Ux9K+ZaMNT})$|Bq0LxUo=~-3Vv|rUVy|0#3cY52tduEKH z+}6T&rD$_o^{>aZ)qFvz1s^D1?CO-Z>Q($YFI+2Qan%-%bM9LkSFx5*?^+p)_pO!j z64es-s8%`eHT@}V+^^?;qglfJ74L=O(^W=1p+fO>Dl5KAWycSx+=NHvB{EfhqC|xg z(^YXIp(2TOYJ6gsG7^W>qy-*TwjfiLFDOw{7fe^v79>=~f^}-ff?aCXf<tOfjYrL` z$y5*5l&Gqj>B_80sCdmfRa>)5)zutQOW>ga9-7U2;o%y1@~8lL>G4bzOs?@_3;fsb zA8{AgT=sGO`^JC${t;7h%@01Vf0NA5eb~k%^(Mzu;%3Co!+#SpKYP)$&-OiwVl$Rn z)=N?3Rmz)9l&w{s8T`zqzH&kz{}^#M<SSxN`qP(q5AvlghhAeZJ-cns3?=n!+f(9t zdU+%6qgc-?o>wxjoOlq;x5R`vbj|9qZ8|TOOh2^mAHGMYb;MlA^W`;SH~Tir_11pZ zX8d{`Ya{s$7vx{to8RitFe|RpxW#+#Gi)5^5;N1t@9+2#Z(^Q0-WCQEjhh;{KG{Fb zCw@k=erT2X<jwv3jVTr4Z#18{xr#oYs;CX9_~v-Jxjwrr+zxh!%gUll9u3CcdNgR( zgd*Wol~S%w?JQZOBE;vI=Ae|eNUh2!@LApAx2^74zw$K?R6b%!&fvexV4qMJ^?8Hl z+umTU-|B82Xm!i8+yP+n#IPVV!r=kLEmf*2a|ZmW&>XY&OF`3@9U;EwwD51|e{u80 z`O?Sm;33bL*H^YhA7HK_FVfGjN_{9iC(iyLu7tnnx6{kQmGG9Le7Q;~+DtRmy+QH6 z!b?|JrBuY{#Pu^NFJ&o{Ra--xl5gsFq>e7n7?JO9@acMosS}DXiD#H8A;BU&OgW)R zER9d+!GCmUX;pOmJ>dQ5wI;qyFme36o-V;X-W5+vq{RaTA>zgcMk15oKRysTgP`-S z@)hJji+p05y22fv<%UYXCEVeaG$-7VB57v0!zbxg;f_>EuMBq#*i1So+%d3))D!OT zlmCUY;f}$Qz8CJeY<YpYVm;SK!tdJc3f9n9<|$&yI*46+Pf}vn{v;`}YyT!Gv1_L# zC3fw7Nr_$iv!ukXeIO~ZYiA@ScI`t+iCsG<DY0wak`lXiUQ%M$dL$)w&8loG?f_ql z@vF1PuQy()hIpk~;+1NNSE`q_@0!j0(vq=CA{)JB)pc26;_u8$q`mXHazR`9%)j1| zcBAsJZiYfHp_>+F=aqkR!03#3)#c{9d3n*mhi%gbsYo=>)(4^o%%iMPC=0W8SWskF zx9j91ugImH9}V>B5ak=%tbA8wDc|Lr#jihhtx9dqv`!U7R7rFKd(@CpJ9jC6Y>&51 z_Q7M`Qof?M*3~AiJ63+}1eFmr?heL}sX*-e=_;~DrA5by45<L};DLvZc=fTVFHk?6 zsRAPNLR<FQ(oT|YgGU7&x*4U`xtXIv%9@_@fmL4l%hBcopQ|z}jWBw4W&ytThM1}q zy<wzy1D{N*b#KidRc&I73XZH-!duW#nP;h=PI{CyDD-Svp52l<{B`#7m$3T{e;H$1 zJ5=TNGF8-}l+A0aN#CZ`tT|R;cs~E8U>)DCR9b3Mr*VH?`O=spGOn@1=c;1w@T+;d zs%X3NQ)ko2wQ69Ir96=}*6vZE4mCZeY_FyRziG@}spsVH)A^hF=+pKLXb2|hMvCfo z%K4>SB8PH=?E1+*h2!Wh2lsG?^6gxw(qv4fZ)WV8D!Wf>*T;7pn-zcS*j&T=bSC<2 zen|qGr}|ix;Tdw)P@b&V+vgbHmp7T;L<iQPqmK@qU-DC{W90WW#sT3YR%@t|HP}hj z$ISSeWASjS#3Obn<f4Q7T1~^d<u)^_>4#|ZVaXF74e#IG=j2yVzMN-uqZBlG9$SCB z3f|Rp{~geJ>5h@;ImXpbxh0fa^3igCCFQQQ%US3cHG^^XkXBHBPA|=N<jK4FggFy_ z7FZq0d_(Peo_@}kenu9kz?}LHHL|{pzFFI(KTiJ|q<<AJmnp*&+%IyZ$HZ&Raj=gk zao<^@W;vMG+IX+woa}n(FPM^=*Ho2SXJ*QHlt23J=<>$~jwXK;{Cgs+(YMvdnrY)& zF!pi1JYKIFxSvjc(ztKo+7th}sx>^HJNvy(<ww^`ek=D!N!Q25|E4N7^Y>Z~DVtMj zeehoYwkWfa{41v%tsVW~Fv}XbI6jnd9Dj2?>1vfeD#x-4a$+4f*DDYA<7qeKl*^)A zmUA6pOtN{F0X_7)=6frt$ip+FB2Uke`boFJ+nuBr@%FjLZ(dEGx2qt}+V!}%GH%}1 ztMD%yG6xNn@fy!|Q~&aUh#phF%%$jrGkMYMjsnK<^vKo7#||}veZwT`WgFgkx5*k! zy*<>+A$^rJljmjfyu9{IHD#`pd%=Y~KldJ)yU2#r+iQ3}`yS8BZ?09>GbXd>M;ZD1 z$UivcXrNH&L^CG_85_g!&V5Ph3SUnB1C)FE<M>6#O||))`?$mB8xBq#)SFK`he@wR zzTzThhPS)>lXc*#S4*w)QRL+_wCSCmqqd5EXq>>BU7=<e-XFXPEzyBs+ui;twBm;H zHX7>c#!~A;U5`3TKBdki%4@w%*$OF3Tc7Ej56-&Mr~g-F7|OSTGFOn&&bi^V`I^I{ z^f%+v*N~M5O0D-Z!K%~n1l}X<B0UPWuRtr&N9)|)XhgM*3R&l;=lrV`onVBcAy1aj zmmh0Tpg^e=QS7YgH;kz$h%m21B6qBDV<&8J*0(d#r{Z{A`;TQ!D{k%3x~`&jh^pA2 z1``vVDmttGTG#M(WfWHgF1K~SN~6>|eZ){#oz>%@)Gn?k3!jGfT&~cU`JTjVdQKoT zDiXhdUZ4J6(U}}yy$&$WX@l)`VB}(K!WOG*R3xNre35~QvDgY1trv_}NkJ&3)2uB0 z@u-kbu}-RJ{ylAdxP7?14<o;d61y+=@UGX-T<l78Wg1xdz$zfRYtkAO;@%t0Kc~x< zS0=8TAvTcg3Dm$Dvd%?sA%=gLQj>H3xu<cwQjIs#?w82RQ8zW-#PzMt^%uF$JErM? z&E6y~JMj-Vx;5X%b@|@dyeHcj|I<?*OC2pbqh`mkGpyI$hUW_8ihaARISG{(UdJ5R zrGnu@$}e_CA``vIz06%1yMzZj;ECgU9!GCf`Q;l9R?phNobi0-NL=dD_i!9rjqx_T zXEwzazFlQ_V~@nv9$<a4TEH&P@SZJ?UioC(WPj>tk)r}XI$`4HszkmTZ%_@iBkR)m z$=QkPX8Hpv8t8}3l`Gpu)`4q_3Qf*F`QhZ72J}$B!F(q#&wMg6!fd;>%KTNy2uCK{ zWjqqlL}o+L9OEqOKrlK%?Tt=E#wV)$%!%sy*%RcM%AcHbuzK>)?0mEG?%>Te>WWFM zGhyDB5E|gyA>)_C*!=m;Rjgs!7W_d%-E98u)+*+1R^2W&Qe@CvHMA;v-#v~k@sl~M z1EI+iPkuOM1N=@zl#XQQnO`p(VQ!%8PwyHLo$_JZygO71@{;|~V%C%evQ`{d*a)Wt zLv1g8^Y_>umq)>-YI4qucc#>i$}?+AtIA(KHFnCejzwnetyNQ=h+j8lrn+g$U#XkS z%6qEJcW$kkQ5#p$)SIiK-~1ca)b|!*Yhh>ME4o4X=3!UUR(5!s8k`(E!~5s=VwJ3o zZO5z3g+r@ktu(xIo@eYrhWCT!@^78|uzZ%?k8rEiWB##h#I%i((dIX<sfzl;;i&hn z5#`^CUpI3iV^_AS4eV9)u2pSO-Z6>Z!>{b4?^S4ChAGdT^jqe+@RGzDc~W9m^w%4< zT>lt7I49HA4<Dp`@*G(9YV7GJ+eG%KY){3OP}43g^WF0j$h@|bTU363nXZ|xg80S! zwrs!un#Kq_R%28va{ldQvcAREc8aX8w`Kj$v*4>;Y{F!Jb|ly%*!Jdl^HIkCC)kc} zBDdRacI0JQ9^(^W9t=V6itb3`I+g3e(c6)eVOmboWlm3d?1$Y&%IYb4jQOURr}OV_ z<KBurrt*hArgDlxYEb$614d5{4j5h7uIE*Isnz{nZ0+0g&2L>(#n=a87G*6Jk#=G` z^>t|EV#_MBpfiCvlB2GVS?%FyPJ0;JreS2g)dPS2*lc8E?STkuzdsg}YeQd0$COqT zjIsW_beBq-oHJmw$WLRY@>jp}LKWlck+H1)+0U!0>z=5R`9FE$fYI=@E_MVRQ(^0m z>OY)8Pn@0|yZ6Ij^#>mYW9vHuv6@4HSp9MAQk8alfn~A34uf$-_7P$iQNBZDr+ncP zqmx*VTnO&7u^|_=e!jo_m}`eRSU2q!tYsaEEh-cK(}cg`cIHf0sm)J^Ql(bUD04RU zz1WdEj{6Mnqw7TOM22X$LE6<mkL13Be)Mn8me;09=+x;_k2=$+b0Ep*PGnAGLUadu zB)142isEXZQxE&`xWA_Qcv{W<#{-6E(0s;f26IN$<ggBVCe@pjzY50IrVIbrl*iL3 zGnq1zqNCpaZOs_vyEaD+jOKKfvETAId%!f2U&;-Sjl&ks`X{;0#7@k_rf;vYltNEv zoej@h;TfCp-<mJQv+yf?$KJ)hgKwMXrL*E|RXn~^HOK#;8WPv5R`#Fk;VoFRhJI8Z zPd7aNrzulQUWW9meBqCJ$`}2lr~LbCd&=v6)>B^pho17q@AgoxUdEU-@zC>XpzJ^N z+><f)_#d3IDNrbVFxMI*xW8}Y3d*qmcIw<opRSjF%ihxN$Ddx+<K>LiN5`qL6`s&_ z&CgP<qj!uPeJ^@m_9=Eh8>{f|VGj;EB<sD%M?+NZJ#%CCE^doG#;=>->cwq|(N;Tj zvl7@FtN|XeJILFHe$>~7XW%-XXOpfV)%#?wAJ^m1BKw!)dE7_8cNB+&$YJ&IeC{9o z-qBF<KFs}n-#Z#e-WPL!=R-$T+$kU7eiZi+=YBl*!?_PR_XhXZavyN+Cvkr{_s;(5 zc$wiDaGrag^Sqq<6Wn{9`>EW&$-S&8!rwIRUlV%)+xr#nEA-y~4&?0{=!@^mm=1U< z9#uZ(|NDZE?AMXc!R&XWK6ZK2E!=zJt5qD?4u)$L`@Q3{8n{Qk**6`Z1C7~?E8}%a z+n~MUwaZ?g8LwcUUHGFt@G>eM(`_cGKiBXseeL7qp<lfQ>ZL|U4{m#8m|s!vVdOC5 zkzqc$)_dYdhIx~?n}#QKzthIGJde}H?0-iaxz3!aWzL8UvVTo|TyzZh)Z6sVvDZ6Z zC*?#>LHEi}r~AWwnw~u$Wxg$e?rqr81GsJ|j+1Uut@!KNAE#dHw0Bh;+@#GHz)}3P z;Y<}^A2R9R(cTQ*kLu&>(S5Jk^v=Cv>%D)S5q`q5!nKyQ#D}q~lxj(3Zn8%eJ1ZBT zk=Ov{Cfa-PqH+T$=e5iA(x9%;p#GWghD+1zEjyF4_(`N)vm*VjI~R%ETV2v_xTdeJ z(BcfCO!CWW$B!thjb8^Z-Px(geO%==FH%0?ac;XxF<XZP&Gx*q^43#3#1B0-qSE9! z{=V+H8&t{#{drlXv@FuTz;2-}_L5n{+Q0i&d>;6>#V4Imt>r)Kw4^;S5}$UqZs#aI z`vv%b4lCb6AO7rjlyBJp<)@ufv@_7*El}%IK5*!69)RDxKbEyBB~1I$_ZDyzpQ!K< z!oCo`>!8cr@+^lg<>dJ(vo*U+cmbpJ;!kBAsFi#3Mf!~Y^djCS#SdHE3w_p^hIg#) zWdp1;ALWfcY2K{v{=6;mSyl_@2}z!WpCyOMd&kb}$H#LHAIqhFB!M2@)K5;np*+d4 zElJ8rg|ip4%V+5Fm5g-?GN3{Vc{(FwDRze*6P3Q%POov&>$QBy-caX1IJV7P!tW`5 zDcK@-rzAf)Cq&mYV)ry2V$OU=d|1}&(cN={(YHO#T)$-2&JCEA^RJBHyH8LiLD@KU zWNszTLgXyLR96QZNV)bo*FLWCY3h8x(`KK4b{*@TZBzF1VJ?0nF;p#=^&Yz|P1a`Q zY%0F^=fZ2%X2X*;Nc$IAPtgO*4Uc+_=V7i}YAl|sGnb3M5PM)x;sKR6Dx|KMo-;NQ zoml$gM()YWj}GH{jLK(jr;DC9yvO5U(YIz!@8v5?e0uhpxtMh){VDS?e0`qu_qET@ zGw!9>&f`_F)!K&fi{2d-%2P?3a!iL@cShLvWx-#oUPofT3&Qh*+WwpI`zmv1XPM#s z%u|ME+<e~eXOGHz?mN@VbXl<<yq{^b*NJ2M`tvw<wu-Q4PU4qk{^3@K&-zwmJe;_x z7en!{hQr?gzeQ?&xJ_*|JU0xtG1B|B^@g(QDHDWdoVr2t#aoeqp07FB*Ug>n5t%vd z<d+Ek%<H+@j`ZAc!nv=giK%8}@`{?Zs?Jbp^GB}IW0(bA1;y=mlqL5>6)%^RiT_#K za^hEvsm<u#7VNH8bpHCdr8dUuIlEA{&*m#}pX`@H_E;SiJE%{F620qXKN+f9j(yYY z^szXBpCrEK_{N0To{RZyVt?ZO$s_WdvB{wQW?7eFi{94$g4jl6Lj6qkj_HQ?XvGEX z^^;j!F6y#t-X`AQ3B|hcg}ajdjG=pkru0+#E4*LSAEE6p|CY+<9MCdrZeWkE&t5n) zH0Iz72*v8rt=RUldTe}rKQf>D%KY`_k1LZrhl<wqod+fD#lAD3??0Tl-<pg4@=U=* z>kQ+ckr)I9b@n+>e74@h1!=>t+h1)R7JVb@s?2+t%h8Z(o1Vj-!|}VB#8j5g_T4Y{ z<&{6`>91qPUh=$XQCCgR@vZh++jY?KJ%zBj#h#M+?~i_&bJc$BFedCn-j%uV3FlCY z&|4>NOpHFh)v?WbX_2>CX!N&dp;s&Pl6ZX-t3~6bp7dSlX}woz=(Ser-CUFM?kC%C zi~NjZ$WQ||Bz<#c<=NkcD?O*hPY3q$tR7wEnVz$#Rr1(l4vtx+KbCTKpWo5@#7nhf z%i+RSboC?nc85FVx5_>>I%-^7w0N98t9Qnuqqw58cVACm(;Xe0<<ObRTzQ6l#ANo2 z&*4||%N|kcVAs~OFO~gd1~EH+e3Dn_z1wVT+Ip2nKg9msW_asvfd_2ccXGjJuk2-$ zd<z})miG0TE!Yv;Z>|#ErT4AOmvB43L-=kz$}jw|Hsu$+RoiK(&CAfeqIX(GwrJT% zOJuTc6(cLF^?guyN}v-P@5BFyeJ*<tWM~e)z%=x}!Y|@4YO}29O=@p!``y8U2=cz& z2*-YYyej(bykK-<PEh=;?8EX$h2G^16JNp)44H#joEZdV4u?CGr_?%mgtpUS+b0H_ zcIx%XUxd$%KIdtj<~@=vbH%|sp6vUML-=p(^{%$4Bf00S=>oHM_LsYBb{yYhsI%us zh2kt|mL*teKN>zQ+VwSN%9+Hn2{IlcGZ#PS*>HVU!Sj*Ws_Y#*91M(%m}f5g*FEf6 zcNfLcfuoN<S99I*S7YCk{dCH3X)osNailF--|R7OJ}B!N?FpZI;qPg#Plcg@ev8N% z3;y~>88^LV-S|&Vy~g|GUd~N49o05m=6QG>cFQhhG$ha?36;+N<dD|GYgDs-o=|y| z2}>ECz2xYGD#kXQG4L0e%G1F7<(J)9qGZhTWL%o26Bk#aat%-8*QA{NUfbDJ@v#Vo z!e`NT&s@W^bd>O=v7^7*ze9gxCOCMTPDo!zuGQFuWL&T(9%NkE3%xxaS?-WIl^jo@ z(SQChK3Zmr-dd2s9NK4i8?R)n=11ak4tD$iv>w4Xdk*}@Gq>K5`ZB)^Z^JDY&8vZq zPo#r+g)i+m=OM=r7sr`{>i7_mEqi|b@l$*P3HD4iH&Paz`NvlH@09b6B>xo~;%cX0 z)!zn-b57pU;P^ul(~!wd?WgiAou{#649V-#K61~}`-Gm1n>?%7(28GY>4fCHQ>Ng; zGFzpL@WlG}N1roC&InJ;^)&Ws)8nLJuoT-;_8Lx^i_U4lt^=P}MS!@(A(!x5#arXQ zR7UyB>hp4jQ)>Ob1lp;Bo%qp8t)uUiTAjDZ8qGI##Bb>-uHfv4{+C+EQ>VN=6aQY< zAw5QYWmJ5D$mOvkHl~LrIlT4RBkOFNOyo%F(x(htug3kz#3{r3!}ERm^!qo)-#UI; zc#yvI=BuB)<jk+2%tOJm)cVtKbd8UnUv!R*U&kJ;U%}2<U$bQ_Mb>Fo&QVf|-ij?@ zU6`(QV<vhP9VHkvjzuSypex6!0OuF!{E+bu6MCnF@1%?%-%0t97!RQrcKV^uVx_F% zU34G)IP=kd{P?_$Q%BaP^I3fuoAdejbk3gO(eVC3{OLNbPI&rweyTUpzk|$6kF*sX znw}^26!o`K??8Q4U)%&X#h{&;y*6{Mxs$c$_qSFRp)2jaRm+)2GxIYeHWc5YIz3Np zkpk8M_6y8C6{s2ArN_klu&7F&#p?H}lGWBeo=vJB#TpaSw#y*sU;_=THXps3xRuj6 zQg(8V3X47E&<e7r@yPjHT~uiQ+tcFjgO0!E{;oi5bw`BrKIh!M3mX4+q(3i-A}s^i zvX9XGac_9v+DM-}a(#U|D!E6fSwyUt_yF0z=zgCslKleX8P$HE#2xfyafhsZ4F!JI zf)--I@XIm=18JLgfmQ3sTKu~$%F_fb)>ZM95-ZYCb~AaDO%Kn&PrePjqgMyb)i(r7 zt$)=#$E&+SG0qxd(Ft3y@s+uKnDl41-5>mjU<3U$+G4Nrr%kuFXg~RB@^Yn&)Mq|; zE~>9F1y5a{u@4#EH@7<Tu^}lhQQjxsen{myI_}}dgvvJOgMsZ!r~hVELe7*p$0=Db zaBpICm*0H$=BlLK2p%&M_jmaUIG;eqyTi=W#$otC@9#=;(u~Hz`aV5zU6+1V5Rvn` zl(uUpcs!GD3=|5FX5HOEv-7Sk=E7S>;4|oyb||NPsQ7*b&oo=+-a9XAjLiAQOqIcp zHS*+D>_f%&nN|c2Ma<s?Yr3))^mJtxDdib4g!{L;LdZ=<_12!b3#z-)7Qpj@(Z{>N zFl@#;w+Mc$s~M~}>EiP)P#z`n#v1!NW&E<&L*~SHzK{8&Z7lkpMtd?gGo;;;rD_^u z`mDJcyG_TsoZBDGyXv>maT`A$t=#n6=!Cn2vF%fXv6j0SUlpQkeXJ#2>?iVMUol`- zY;_2^8c<=VQ}gWone~RW$NiP%vj>c3jt&+qNH3>-v7<O6I<>53ok|y6qGOJ3sUKtS z4<c()n+=uP?d&txlgb%kn7V%hjjTHKV9fWT*c=!18^7e6#3uw+WU4`6>81T(dF6o7 z=#8D6p$>%K48}LNypovG!RaF;Moz|)eQ2nl1gzF^E^+L4!RWAqTcn>$qR8f@+j%6m zx=JwZFjPt_d|g(u#<P+5o6BgUoO>VldEEQB4{`5>?=#$cxo_v5{`eYbV?Eacc=im> z29&gTHgfMTS>w$mMc4S|K);LYA<)}PnIR6nE4Y`s0m?p1`Webbh@;rb^)=ATrR+77 z4RD{%vn<X4I4e^zp+kxd=?jpz8?3N#wY+pPCd|`+^(2r_t$Rr2n)1@u!_a?bRZQe2 zH7xn8GwC9;_CEIfMl)uB+sR#aeXaAd<XXxIjgmFzB}R}oPOi4gpnrLetj=M5$PihG z)reo^{IsI&=&C0=?_y7q8?Ip-HgNvC_6B_CSEGN9&&1}>sDAP9wS8jl6uoouJ!pqW zOPn?eVw;E!fR4j|7yT`kcCjPVWe*-{={{Xu^8_)?p|a{DFR(70e9EqS;ymTj>7T|y z`X}?1^?<dkyItDWG!|+aTg`>khZl#B*-{tT%l>w{;M(2b(A*?#UkX>DB|5ldP4^7p z$KfT@sV8T^AID2Rbu*m0*@9nqhGk(x<1@Kh&MC_TGr<nq<`#!u=0~wR@hs24?u6J; zj8E73i?I_Pgm*C9n<#X~vqiNOOptgq#_?W}5p0jU(W6`^<o7vbV{t_1H&O?ApEG$P z=VMQojo^A}KRV@!d$b&hzBCe_m9-fiN}X6e_3@Pypd;j7>M$NsE-*PqXmQTQ8dH5< z#!uzRp3%`StZ!YniR@t?I%`nZjh{9K)XhuU!==`{M{FCdbDm%pTbLdZTMm5FOIlQz zF<##{US0ES?2e24f6RDU8!wcVu2E9fo&(lY;Z5e0J)e?m^znJ@{U;Sf=r^`Y^nnRm z;OmgoGjF`CO7=YHe*Cx-gHj*f0#a_-jS^Qo=r&syf0)KI*;C27lR>;mnbeQw+#M9T zF15~fNu2qmb=?Q`Jb#rr#96GGRkNlmEph+xZfQ4BEVfUe(EOG$qSSildAXNyqwMF< zJ;;&r>v1EWb<rn&s0w^`iD~p@u^v~yeeT$m-rsLS*)-YvNgmf3QU=|F&0_VC`lV0o z34^kR!4vx6o!4dEve(&T%bF6{bJz9Eh@C%I#abF*4Gk87Utz1zIhyFV9+f%zGzB`- z;2Yhm_KCj0&&<9~o#q<dt7bU5RMxHz^3%!xg5;CN$a|H%7U?TCP2LLZMME9Cob|bk z`7%}VSFpChzsw&)bOn5zU<`=I);cgC*D>N)MaL{%$GQsd$XB_Ho6Qe?L)r6UKd|oU zxF|WZBt}j9tdr#;tF4gOtJDdhv-d(nXgf44-^b8+TJ|H@>4%-N=jm^A`D3ixt7IKg z<*V+q<<F6kpvWA)t^Kxqfw%Cy^B7~%(~2$+XdC%^Vj~|-g(h>=v5~n3tB~Z$erA>Y zO4J}d-}ST3{i~wbqu4OQi<2*O4dxefx^p_$@=jScw&C1pJb``q8}a3y5}cFvVVJT0 z=pN_0_`rH*tjH3b@cy&1uSnJn$5l$Q?j`CG|9FF(>q_}N+UgWPOmF!_?_MfH<gm{M zo!13+;Zp1HEwR=3{E-`NFB4lr-X`HUI_m5e?SG0ZFKwiXPff~+&26an9;A$ivB5^P z_RxO1%u~br>-Dl90FR&c@=(&tLsn6T^4NQTd9#oY;w!&&C32Z>sJC8m#w$pF#m_@r z+_whFo|flfo)h~{zvu(9z11nZQTv)&<Xon!SmwQ<-d!kmWleQg1YXPG13ZtdkoX}( zz2n$_qJQ2QLOBooFdyVx>x<ww-6Qc4l%FmBRpfQAj_s-Zz1C&W&e1UjV!N!?^KiY; zpbhNBcV;^JJt+Gl@omXCBM<WomA9WZl;A>~O>b;ma-Y;7dn7xiiM_$xGS-x-5*Js* z8Kcmb{hguS+$4Qw%<$`UjhB58ZLWZBzV@Td{JqSPRHsZxWE8)g&#|xDDJMFLIgSsk zLhoCV&Aq4L>7%hVj43?j+T--M?d$>49GvQeFUDtt`TWg{_5IVOz1V%}W$+acSt+#+ z9TKdsFJMg~)~P7Y^P*pYH||AvmNMe=Grad5ad?%p5O6xQDYi0QbY_<9_hRRC40J|p z?H>AU?ZN*laVe(IMAouJ*TBE{dWm)Yhu<e<ZF<gw|M<~4@}2JZny#|=j;?Zf_siVy z`MKtX3BN`Eq}uc5Up_4!f^qrIbHYD+Ns+Z_hB`vLLRW=74o9w}4?(9t@_dG&4sR07 zN!Qu(arh2tORzV*|569vdx&-Gm4zLS4+q?f<xEb#$*uQ1XOny8?~DhV^yt;&G^VT_ zvx<ZkI=s9-P{{hJ%-b(xU#>nYHWxbW%fxE#jh0OKPC<mVFAI5K9!9q5J&o-71C#$B z_KC#TM6WIwaT~h++QF>9>0^V;=gy+2mX)$aZy<vO%Clgb^2PrL{a+?y^@oGHugrs` z+jyr}%3x2%R_NH(y(5=vISt6z*Id`dK0!?_dJJ1^75S^JuA-F|v3TgwkkGPPr@()# z&=^rOU*omi!7<<2W2MKRM{f9L7;@*Aco;*yy-v$WOQ*yqYu_?$_-Rk{vTD3tsp>;7 zP)?1neUv%CKFPK-&kqsW;7EK%&y}$j(Fx3_m6U(`1;G_u-oB&gG5WG<kEUG^Q(+w+ z<$X<jJE!D4Jt=D+m9sew><NmQ<00C}CzbUnOdHwA#9ZN#cddNpk)o=2PuEn5X9%}@ zna6L*S!f2ld7QO9jcfL0);{D#{BG!`*UD)>J=yk-OtsnZFLcSAG#^1;p2N5FzxA0c z@;WDo%s;$fA^Y@~1?RVJbows#CT;p!<=jBVh-bs`Pt1=bh*M{-{-EBnYI?ei7-z+z zOKm&z%|~KKWe>0QrC-**dTbxgF6b-oO)OS}NW0`LgT5C}`5CgsJJiuH-ZesWk@US^ z9VwG;*G)Mib?rS|N|)?)B~ER@{axkJVH5Rv2{u+4wpN+wS8OYP^@N79uimW+t0ycC zLPzkOgy|NfOci?SbJ&e#%!}gqQDRs-H6Qvt58BVbA0jq+pdg|?M_DC%>{xw+=ooaQ z$4?uwpU-g4dxE4gmT9Eg*1&$4ip~DG6T=or4Au6Q=;eT{nY1mo<-TYRbkTL3H%!%M z0qu6IxST7qriou=H{~|hfDv*%Le?F_`?V`&jH(}X^r>Ep-e@!*x<>k?uy4x>ZTeH= zri|MgkHl)0Bd7TGTNo$GSI=C94t`6=BfwKG>lN?j1PWPGf{FXVN8We2Yl2{qA+~Pv zp81p!!v_xz8>PIAgN$`_u$1-AvT-@T2id{S`NMqj!qC>f581~~+0GnZcPvPZ+SHmI zT_(QogAxNAYhka)ddU4N(DTT8PTN}}t3A`?xs9`@%qg=$;_00-hPlz$V!mN)i7m_% zc}a_PpJ7~8p2!htx~#>5dBFqlu?>DB%5&R9_U7FaMThN1x9nX=T*$~e(MQ%kDG!~) z7xN2m!=ppb+=cw_5uS8hE`8Us5C4uVY&K(KgVoL4H!Ez=o-;x(_Smnqj24X1Jcz$Y z>sGV7Y>RpBt}UWpMYqDwso2poXGDghIX!b@mJt@-W9L2$GEV9ACqrywvBhOfgpTYl z<^2mOSN+?ogYwL*6b#;ySWS^RnahmFn@5)}M-TsRJvUqN$;I&*oA``;$jw*K!L=eA zu_<EP{I10OANGEP>)XVhs(x{+;5wfB8)M`C7>thjwb<l$A~PAHcdP#(dxAF)ijE`| z-<{((eDfv7Tg9wjv%bIie65^+Y8%CR4t-Zk-r4FWelB%Z+i@3fE`wjeCky@qD+V!k zjAdlax##dj_yy0%n)93SxybtuorZUhtnVK==U|P@kUc@4E&I(-sdaF+=uCJHi!Zo- zsMSLsMu1T^*H%%7yoYA3kvMC|R~2ABOo|;tzN~={(_Xr5Q~a+^+Wd%3M4P$VeqM>L zeE~gtkT~@7$+h_#o8vQOK7R0sGq=S?tBbFa@p$8X`Wwcl?2E1B9mmzg_&$IyVsy`} z*kVJ*aLJVVf!iuulox(QK6yv9YYFvcJ6P%1YS!HS#LFt^q-i@H`zLvJD!NAWipYdx z9|vSysIyMj`I@fBTw`u97v;UBMkXU|XV|*^gH(9bHZAj{nRz4l6UY4WtK!>+j{%a( z`p5O$<QkM*|KxpJ@Nv#+W;S3O-9?;7hpbziHIyfAQ000reSgnp=i0~fH0RpSb%S%w z{=H|LbIthlh@V{QqPr~9xlZRg;#}i1?b+>IhsZzUTxW4z=3HlUt(@yzuCtx%Jg)uD zbv|^KJJ(_IlROu5{hX7p+vL6ie#TQi$+JOTvhF0-pax=p%JI{eIcd3*PIc00PFmrl zGn{mmlg=@`FU?8}MP3#mFD<HAa8Ix=)G?5L``k_5bxPvjhy4uZ;UUg@wH`n>*ze@X zI6yNfbS@q{soOV?D);Gk!Pg_-FWt&|^w$N>7~&s*rg!&VM+SP|ElctsH2V0cM1J4C zQ}mY9Zyd@wP)vLbn#PiTeUtO;Q~mqZpPmUH{b&{&-rEv-j;fBvOZRcN?0+wyCp4rl zNxFUXzTRbc^YuG(HeWBwUZ|7nS-luJHo4O`Ia9^1`ubKw{c)b?AH#d=hUB@ZLu0eh z=&dj7-yY|EY3KaHp)nWxs#*39rPjX39lI=x`wV*>+&8}<WIbW)Qk5lZ0rOM)t9U;_ z&Iy{uHfkK@tbe_G?-#Rae^&o}#m-D+Iy|(P-AR2ly^Hm?LiTC#S$eM>Fjwe(or+#N zj($x&5so|gvj0Y}lXnnXW{#ZY*?VN`Du-{;b<6d;PwK!Rv7xZR=indniG3$_2hTZc z`QIzRh<<n^4$3d%DE4Li71pqIynkVzb!1`>%`yM*JE_yE-*b6cbhqBmuNONVIvc<u zy&zLfk~PJwKeI*FOY$Gb|LP+SQr67F)Za+neAaF`-<b1Ij`Fg$`DWAx|9d5)~_ zHPu~mRxu1+m}S#ZWtz6cNp9-gqHR}i<%6{8Bi}#e34gIU`|2S6ME2Ii>9kn;q%UBD z-S>+4vEh+(0ei2l-+fPFX?UkBi?ffSEbq7c<_`4iKIX@A!@FxnVw^pe%oQKMfY{M@ zu2G>C!|a$Id0x-8ejkEsSu5ZfnIN_Zzl-Q+=9Q|O?Ue6#9j)t&$&+*H<Xmv#@{s8V zIuiGH9e{7Yxp=~s$A>20eX&lzu&XcjPR}hz|0HSj&8G*N!MwvzzjgN1?cxX8)8F5* zqyHY4HB|5~iYNU+4^+^fJ?PIjupbZC9Mw4HJ9}=Q*wTjD&z}0XtNY1aCo~xQ{iEQ0 zeT@Zf%qiBeSA{lt4YIea`G9u7DK=I6<BP@LAo5yjy{_$T+D%WkBmPg>m)bOcdy72> zt>yh_?;g1Vdk#O0*fzG@@4r&}TkuiPW{|!48w=j*I&2=ewQ9kRuC7?i0g*}ZTZDB# zygO%nGM4un*my}BUi=BC47KkmXghnsod)&KAZtO<HH-l<EY{O;(t?QWPkBES8R6&S z=jWHkFAzq4MNX)@H>sm`Fusm{$QQf2h&C7#Rk&NF*t+UI@gKKecMjh};d3KmzxYMc z=Ua|F)xFT3=Yshe8#fi4k`pKtp8?<CVDIp|BZ*P$d$C7ic&lV?lJ~mSDe8BxG|4-0 zE1%c<5%Of;D>hJ|diUQmKGxU74<h?<cu3Q{RcKpA)jYubTczpE(t9WMyJ(HXsjMZR z`AF)QIBD9N>Bxk<)0C%Uw7lEJ#=GQNX!m*A9&DJ4@c)gx|LfqteGm1up5KW~gTJ;% zW&RPD>v!z9Z1h~3%wuFFkUZO`Z{_`C5VYLI>~{(>YW3ON?8No76H)3~Ki?4NS#;>w zV02u`2<#3YzchY<#C@F2p#Qm+Z<3^k!Nu@y@3ohOFBwnqAqjtAc^B>a#rAC4WYfUT z-Y$6!v+cEowsf3`;756he|G3@+ed%<Y+_HZ%-A+DYrl=#-z=B4y=Hx{ehP9g=e&Xe z`qA5oEXX;#-p{d*Ca%wOfIR06mVOm$JAv``EQh!BdD-Z1-aSE2?=31)wX*LOySmhR zZ8GZ@`)JRkM3M5(8|IgHik5=|eeK>rU1=vx)@d-8>j5%nX>*jVOAg%0crGFCTY-rm z%th~}HN36ojlVHP`N#|KEGT?%A7BmzDU;qrd4BNF9VJcU7vv|lu1_$u@jHJA+d%xD z`3^7A=XB@=;MW(O@RdCJ#``?N(}&`3znqwqG|JDF=W=cLOUIhXduCJhI)lE%cXe$X ze<QSfB6Eop=GWV{Y_LwGNo-4l#r^e+C;ag|K)#GcI(Y%|f|N;TeVkz18)p}ScRBMc z4Zjy_T2BjYRLwTjv`jzy)j^(Si5n__UuP`o*TDy!*w_#}2kR$jUy#<l$d1Hq%NXi? zh^<4BvnX*!_u;22#20zB@;0FtrljLHz(0rGs`a|;SMVe47X9GlFO>S^6SrV(7Fn5c zFaFMHDlnyhy0c#&K^}OL-p9NN!SAqF<l3iG<O%*lvnQ%)@*ex-i3h8r6Ut7m_#4Wy z_Y~dY^hxY2C3vhTlCeD_aac*Y$-AhJ&(Ozxa^7I$*R9WDS?A?UJwe~4O?f9QZB`}U zUaI8%|H^~a%qR9#&p+IMJ(d{E<XYOd9#1V}yxC(|bLt1#c5`%aWXrsPDuw*KCA0D2 z3{IDO-toluR-+ye-y3a>O14G&;^)60cAh!h-mCXZdgt(X(G&Lkow85l$;Lyz$K}ZY z1OL)L@Qp~${>jHbiT{mtuhcp+d}NJY2h*A!RjLWux3PHTP^|v#s#wldCs)F!q5fs2 zjGxq#a@^O~AeT+w!=7Pm@D+;>$$<7?(opi;o$G9wr?S^Awf3B)KN<b*k2YPcG4?lo zfwp(*>lUFwJCmebsr8CpI~<<wG%J58-zu==Ox1Z_Ahg9-uyUMb(Z({`2&_WBIOFpO zuk_t#W1-R{f5j;B*Xp+NSl3Sz4|S%n9T@^=d@kE+IKL|*hQ5${Y=Cy`m_3CN-gk-7 zPmMtja<gZbbG;FH^D+<pw3F0-8THH~88=xs=u5WqZ7f?4WB1n0PSUdCBEK@%k*kQ| z{YPJNP113hiQe(e&@u15V?6nEyoNTh4PuK!tjGA%#;X~;OQLwMZKl`@f=|-^K%a^3 z)@R;^`ps3sEBxs>Bm9XD!j+(Tj@93_MKB{z&n<ZK;Xm9W>xkj~hb6)v_F$j?oHfd^ zJ@k7tvR2u0I9bk<LfA9fKOyJBFUWdkzgwBk+)KwM>NdRNbR0Lbf56d=)6iSzZG81R z%+hZ91-LkE%DJVii*|eEZ=i=+pVWBgd^(HvBV2pfr|m0<=<yk|f_@2K*r>bXYffmt zIPZh9?oPQ=+L!t=cBIAHjy<Zcvt<0G52e=2>x4JKlRO{gg8l5uH|UqxDDeEO*oS@V zZDub{&Y4`f_%!C!4;5W!Y$1*iy}*7B-xQeS$R3UFP|de-z_zVEL0i9i(DuQ-KACx) zFW2a+QHFQyYA4=Z^o95xRT1|83TXH1gFd5^{aUH@(wjD2PoN*~*mSCM<VxzcGM`st z$0OIy+}Xz3DA;Z#FS+&$Pk#G+LC%?85uakS)R$NWr>@YE*cy>>zm3=46*`W>JN6Fb zQt+Fm`{W&~V@VoJjV<3lc$@z3l|5TT`XF_9|B7)MdwEm03N%ea|8%p~o0^6{I;yma zHN>$~tkc+}0ogy;c<sFrI>kk;`aCQjjDq&{uOGzMCTHJq#_fRcC*KArwRUf}@##5D zzQjIjJ!W|SKF*jvm(;&eVnj#yl;RvGIR_>YC#rql(smJYR1~-4LJA|QP~@~Qjz9OU zyUPnhDrG_S32X&VS8U}O(Gz*GF?;p<UNMvJ8|ZO*KU1$yH~tek4m+^&kJuS6z9#P+ z6y3|2H8BO+ZpLHEb>T|pzxh3TZ*O=b_0HNJM4zc5#jiulvQb~8JS$(|{+#m4Gsbv0 z?dOt?Lau|!eCmkJF0m*#vp3l0<a>mcZLjY*h#y+cK|;1aq5D4PJ|O3Z(5#jEvLAzQ z$46pyl2>k*e{sIV)Y`Vziw~Ofua?+m;uQAom$NL^$x!u-Rkn|mZ;u$>dp3z2&{whB zHrVkv|2zSD84?RCK5p6!IPF~<`!jz2Rhkd~%D<tXYxVV9X^)sxu>9rOB2#%|k4YSf z?7x0_GzP|^JHxBQ4*0iq+V)(^H!7y#%NJW=+^>T+@4w8cUVUhb&HFE(u3mZ77HAMB zMSaRaYmki7%G<&D1HHa@q^yjY;T?U#wtIX04u6vzI<v#<Kh0XsTlD((Z+iUu#(vkc z$Ww@R{HxGGn$NhzSd4b&KWBHV?f%NXi5M0?vTF!!JC0>*EArcGKkS@t$2U8AbiA!c z|GF96_lOQfUXp9XHYa94+PWoqZienkKA&atyK9q-U#WHKsOU=ZW0zXHJm^_HpSdnD zhhA32eBLVZ{S(%(#!T$#(OsKKgIZ58m$(iX%72^KG`1dibtZidUr_f6=KmpGR@dh` zAT$g$@VwL$jD&ysACdkW-v9Y3eXr~PPTBTd%sJb)XZG1oUumXp9s54<-=rZ=vj3BP z$6WM}oGps(M|Ms=58vC^hsjzoNy?HR!e-U=xQ>YZnwW^(VFyq~-VqZz*~v1{W}kC% zp3o_X=zX9nXqP!RFqgfiqkF9?`o&p8SGz8Q&4-_7cVRo_>95pf4qwKZD!%p;!6N1+ z`CxJ)y|9Dp67e;j$S7>p`K)^<Lg*zA?Wm#%HqLb?vP4%=E{l5E#9TF_yCrVyL(W(v zo*27%_X)nIsN+P?0~I5GtYs`sXwt7h?9b<_<XY(Q4sRgVBJm!a53SPWGHS4)zm1I^ z<2yZ59y?e)lxx~axBYqp@<@G@4~ou+ec{Eb$Qo~i7+{GPNg+Ql@+X41H<vncjt7RG z4tR9zEpN~s6Hf(s@}8wnz7u1|#;0y3kJtxd6)IQ@$zL!VJyE#|x!iHy{O&bX;R^XS z#>s+$yRqZIR^}RgI?Oyp$9y=%d>FkuPv>oA{6g@PR(Olni>=i|e<1TYWO$3NHD_sk zl@@(3QYK?9&uC+X`L}#0>Pqz5D)bC<y1X_}*vL5)G46LHGTA#lik}5M^c<i4C~|e; zDbaam^mSq$x4%UEZMGTRE7#{Gt<L&ERrJVX$aCS4=%~FTqB%>6F@IF%j>6CANkBV# z<+!T)yKK2*ye1_Iz!j+$S(ZHjYxR)Y`Mu|S=~EsH6gI7sefGf-jG;#`6Rem63crFr zuTSpplh5MhgGIif_PoM*dYZ_f$d$-|$P@Wb>#`!R(89+-o-fO>XRsyqH0tN~QGUDK zo?S+bXN-I4mF!44#l4){2efUmCZz*>L*&U`Bi+tpOj`Ar_+?%|SK?AMKVrX>tV!8S z>LI=+SkO*f#J99OonEk3`Qi^VztN?F4St0~_&2sKDA)DX$fcCqA^Umn9`S{VPpta8 z#t2(}{^XH*;M?iEhp}&DlcqBZ{`MH&f|<z1C^`2xyy5eX&h)PuYRjLY{#RonAEg#& z&7OUL@%><vzNS2}gRjW5XwHEVu_kBSkXh>7hpdRrlqT{lYqyk>`VKEk3fcu{Z@Ta( z^q_lJKf3d5x_gpz)42~wSsf?JwV_@<OJAi8f0BOn>^&o*M}HNx`~BV^r>$10Yvb#Q zAOoQV56fIS{k7_ceid~38xs4rFrw#b9vBC!`5xU@@4kXKTjiI0X#<|U*hSi2B7bZ3 z_@*j*{``5F%)L_Ug}cnAJtN9%{l(GU-wm2SWPQZ;<vlwO=lDu&WoQSOD_N!1FC<RS zzml<u-nwUm%^y06^3}c?>iptaea$@Ldeg_0X|(D8;$U<nST!1|;6?0nnLo^Hbm9KO zW@H_ls(C)LQOkio%Yfzv`BoUZdN8=BMkic#QfRGYpNBtUp<Gjc8FN37ctyral{sTo zWO%>4KmH6@!8>iGgK37jaL)*lSwroZN7+aWKSaD4TY49My$%d1d=j(p>kxZ)rF?^9 z<PX`;x9Bx>cjiA^J&m+MeZl)c^cCWnurHVg#LFJ6o-KRNVY;nc@}+-Sr22bOv+?gx zM|8Ab=3cb06uyb8IPef{NPo4BFMEL$@{|7L5OYuR<h&+}{9KubvJP>bCD)=OY#HUO zeudch*v{zu<g<~)ra?Q6eF-`OKLs|O?fX4DhkLz72tD3qVC~c~t5wk#A7YOE>^au= zx#3pcp~5at+UPqxs!Y~+IUAETUgko0y2@(ssAg>SNk!b-cF$jJEw!F!jt?{!tT~Zg zb6wY~BL*oiHhM03J)8v`SaAP|yal6A<PS%uux^GI?6BtGBiJVTt|?Q6(4hf-e%=qw zAr11&;FsQje&na)k$Hdgaa#xfy|&q~wbB}@G(P^Nq~TVN)(N%^``o;O5PoIO99CrV zZZozc_loNRd^hh^k86_tq;P%2S&NW^BM0L`hj?GEU&GD~RHxK9y5Pum>g&B2x>)q2 zFZR{WE%qEqZD$=FTvTDp9?t^WZgk=jWR5wyHlv`>vak*0Tfh~_ab9wc39e%Iv8S0v zSuf)#?|Em*xf=b}K0w~Rnkwx?)}+K4Ptoa8u9)|b=2F%V-}K?A$X=RV&gw|Efv(-h zwU#xm_h2JrQ06AyQCiM-gKvVLeC}`HzMT6TWFN{swuP?)op^w2`L1z<6yJdFRod9b zbrIzwlrM71f01Wf>BByrO{4rYQj<K+KfTi5Y~Iz-eTMHm@r96PUyPUd)u7wLT$a8{ z`wbe4xEhMRv7P()$W_|+hMfB%LX*BvlQKMC4ZXAr@SlO~@=VGh_w5(AC+{3YZ%g_S z^mmQ3Y}q*RG(7voo^`&%CVTS>##ZWz{o&NdADJ>9z8`?^<%~<1>oMRU-*kP9zJd+! z)<DzgPfCB<*e@kcKK(dxn{z#e>zrhHuCKkgf8Z_S@9^ApUg%5z`_q;>$vByd>kHoU z?hKfVFExt2*eYY*$4k#1E&Kf47?CZ>XZ=|A33N6?2U+mWp!~jMUHHl)CRcwy6?-|4 zXU~az+w|U9N2+C*{0iMR&v<{N9$WY(XidGiJ*PZ-UdCVgZ<qfX<&inB$khdM;FOm+ z&%21KILQ~+PM>%`=%PA(*mw@mC+35v^^#?f0phs2<eL<X$8Oe?{m|F3xZIn4{XFu# z%v0e7J|=VCpJwlg|Fn*L9lvDXzkMI^O7i{8V(D9{)p3Y5jdfwivcv<dAEUdTK|f~k z%XQ+Y*2k+)6pKza)ITQZQ?0~1QNN<;AGMAYxf6ectdBuiAE7nDp}mkk_4<0D6M@Dk z!H05b!k73mb$`ZijU34Mm0Ev%-l>0w&D-{~x=g0t59P`n71=NO;fJ)P<C9g4Z>3IY zIavMe8ofr!9^-;B!j3$Bah|kc`wx$0;=733Z5|uK`JIj{lRgnQCu>~4`yP=m{oWlq zi076M->4~d?YVt)Klfp99WFc<RiNAPH<0%R*QyUItDU@j`~j2L4>v>;3HB_l4Xl@Y zq2o=im7HN@>$Q?SI_snJ9e^>lGEQJ6`|RgPFW9F`yUT`(9GqDQ?L6qtg>GN`%sQ~K z_t=h~c1#{V^*4y&(Eb?4Hjh16ka0Z3-gG=?bNDPz7;=Wx^tO&Wk}>me?U%DX+OYlT z-d111P;2kxVZ;JT+%kT~WDEuQYgwOCC68E%O<#%g9qOUHquZDFisU6@tCIZggjf2l z{n&Mtf}<t=pZO(}t&7RJWHsvVZNxdZdV;_C!8>sx6GBJ$GQ4Z0?|tX;hkE;-uj39S ze&`p(GWEuHj}~1dHuOCb3omk}&r`H4SY1EJU`#vIVB43*`)Q`;VKQ@A&e9Zi9`AIB zZRa^%kZ$cQpU<~%{R2kh(@MFyPB7tI_Wl!-Ci~@m<j95ZBM-ICLtDxDGd#=%AG!B9 z_Z8fCbMJNT%eX(seTs7*k#Xlf)w$1eo)2{H1#hYEckTn+3;jWIuj|6Eyl**WkdEaP zUUOxfW9b7Qj)vRw9vb8wieGWYLxWTuY2cwj9v^8oef8P4dC#4CkHO(@!=vnP3$6}M zDbRgSb)FBmpZ9dgyQ1=(y^~kUOr8i9<9Ihw^7THV$K#ZJre<Xyttl;$5wV&-2E){A zBA>aczcp17?^&XsK~tU!O?fVRGh275Y|1|6(5#Sm#HH=n&|d}3?;YBr`DDChPc7}o zuq=qF*h`)HPMzFX!JacxPs+w>_K3a<FxKZq-gF!+bItZ^wH!{$uRb$!=Gz#?Qp++r zz0z8=&bD!j+Nn=WA@j|9^Fc#Bt=}hL4yN61p=Wt#guE+dd_=~iO+#&cTE=BL@+LBF zzaQ38muyqoKp!#xt*F#NN1cvK9{M8rjX%ovor5H>`)z&ToP!jFYI;tT)sOKFOX_v_ z8$i4AZ4R}9{F*f<%8(uHS8&?WF+cEETb~IY#EwyyJ%^{$@ma~7;!IM1UqjXl&YiLQ z^t<Zvj)3-$l_e(lGHjd3hi><5OBCauSdCA7J9`w_8*vYf2A<Wi2N8Pme!1{AiaFm+ zek*$QY;lE3si@rBV0edd2G2VJG2bBaAGGlhyk*=x57(DSjD}DAfpT8THGg-GzRUih zaf~lO{5dfLKG}O`+5POvvB$w`m%7n0$AZG!3SvkSlqYsg<mLeF4Muj7XJ*Y{nN45C zF3r-|KHwWfo<BNaBHvQi-%5}*jk$y_jrlI4?k;ES_A!p-@O~paf5`Lp{<Pv2JVuZM zg?xOU^o#Ukn<^LipzNghT3;X>!*}5M$H~+iT>pUYvdKBjwVZqK<Jx`<=*l_pEN~RP zQ(;<Tg9Uy7ewTB`iG{(*6MdtdSo_ZU>wSYKPeA_b4AI5Ase6t(xvUQ|b|Gi%wEWNy zWU%|J-H)C)eOQ9La#p|M0P-icU*DOf$Cg2Jm|o|Kmkq=3$GMw5N5U<F8Sxd0zIs+X z;LDbCR`?w!V}v~Bh)i;w&M$*sh+h`JJbt;25BOLUwqW1-WS_z~dpanO56NQ+f3lts z?^1<cE~_8rb9}tSzYO#FBu+rf9oHl4^jzwqzy06232{!!-@(F2Xjg+72f_Wclw~~g zkt_L@dT#v$<aaRZU7fm0)<AILd;E<1VugLjeGV^vw6oSsko~4D>y+OsYlo~GoY{rK zi>Y6$Qn?O>pS0G7Ht<n~RxsSax6bT6PatvKiE{bo3p|wB>kYJ_!+jp<TJrQ7%=ISn zf~3Ne<eldFl~`RKYnZjoe5c^IW@lkg<ce}xk7xIuD`eYtA+ghpdBag(uFw&_>5J$Z z(K~z-<wThts|mhg{jPN!UE>5~vO?3X8@bv#Pyff?&U<Vn3C>Wi_hmD82Ub+B!ydZn zmAaTOJFk*`MCDbS<Ln7@mNAa+#}RYo<J$zXZ}z1Nf6zGx9kB;PMR7HxsDgbn*btxi z>mvGKe}|?g*z^nV)wVRakPolv$Yj{?{v;on?6VVg^`7(R>u=1+yI}u7Y-L1r9_y~M zeqGp+jIsQ3n#d=6n{?3u$QWbq5gqjm{^}LBe5uni-<f~%4M@=geACpY-*sMT`G$!+ ziVi|%@Ynd{+)w0(SR}4Bu4*pyW+blnX+0Coo*1k<%DaExS65R`&Nm$0>WPrwBl(O) zSAC9k9$IqU0XE1P1`|B?@oDWbJE8S%l9ts0CeQFZkG2BRj{X(~_sHGh=tN@Xa>~kt z2K4svy-7>t*y+<;#uZ)sB=KjQJ2NKm)<W7%f2TUn*x%`SC_aYph2z`qjPH}g2=$FG z-y)bSdts;kWbn#?zMLJO`I!2*^si4@d53X`BLj1_-M-CUZwexo)$|YOdSsGv#4r1D z1bcX!1dV{47fL)NefLL;ORLbQJ~`u*ch6$xfwEYEod34HuFKxbJ3hsR#)f-etp1O| zCd&7tnWoQQR-b<Znah*?7~f`m2D$r$n8{n4W&YGpVEsT2z%wnr=EPL#6X`VeR2A_} zzKr-QzEJ$AFDo%f=EJ6g(C6KR<|?5r`nTVHA{m$3@BM^Z^PxLSWEj4Y$zETQj3@Lq z9&*xyPWrl&zC!Bf`7S4Y-btT!(oOifAC$F7bTmAN<Xfuxof@%ATCCH|b!VNv!TCEz zO}nFY{o|^YU%un>(O9l8)uFS>!Dfd3w$B8<?L+Lo<BJG^%PiW9km~&#Df36=kv>eC zO<E=VkeZ|tHxVZ#Cip}xsh_m2e~dQ$(cgf)I2C*)FUj*q`MhNx@3eFZtx*$+TbOuC zzSowIEvCP_nxw}&D!Fn!c_M#fhiiK;<iwnNSzo1&v@<bMCeQUZHAs`?``usH|2fyi zLW}yvQXd}L3nq354?4eJ`}#Tad6qnL=oNE4-l=am@+aTmH8?}{6-*3VPy6|lDNA^J z>y$Y>_R`>)@I2`fZJp}h7PP+H|DNk`L4>{M4g9@i))#*I8-u-cZs6Hi)-@$M-F`kQ zLf;1IYyJ1Bc&=z4dr#8|@O`g5{OkGBr%#@Dc^UDqtKvBEg7Kfq+2G={y8QUhRVC*V zYwz;pcw=)r?`e(fq|MxZV;zCc_)_bqPsyAVKKMpt2W8}ZTIRFy$$X4#rv4=OFyNyM zIx~}Wga#NH&}&FyqUAB(H{angatR*CQ@5D0Zodd`{jC<-V_jTVpKJ&E`u!hiBiZ*P z%?saA8_`v2HARUb%5(5e`ebEZH5h9B3G(IqAKmn$H$J)FBU-4_Or7WZ`1sLAsZ)%7 zl;k5ESA#1y{Id6*t&8}X0gdH`TCLlJFCDu{+Z7H@fh3(|e`FkmhHZC_$N+N#8ZCxu z*)DuQ!;ro~BSX`uP%AG*!>&L4K&kcgs6PIG*qM~OOJUh3L&IAc@4Wbq6Rn0fC^}W_ z6w$SO595h`?^gX#|NXB|#&I}%2TSW#o9`daV0^P3J~|5`{l>JPUkJI#?!#etdd*K| zZ}QGMv+`IF4D>VT<U?D&sUq?8*+M@-J?iEf-p9`fUl-8tv#Ej&UuR!6HW??F`y3ea zebc9w8Q!a8ZMi_#5>B>RzJq;n{>As7j6?1u&H;D9Z}+E^%Yv8nhWcp<{bQV`9qAjt z$Fo1V?#-Qyo1*?kVm{gDOzkJTOS(R#?q*^D&-S&oWZS2d=Wl#Wkar0jow8)fr<9*m z)5FIH)aqN{Z!_~Iz&AIr?N{jjF@9Qy8r~)2g-&r?MUrw|Q5))=UwtxqvjU&o;!6H7 zQ)LHqewNdZ7xl@!3~Mj7n)mmW|H0l*Dc>M%m0FA5?^mbgQ|j=yU%vWuzw&dWJTkK? z*{}X{-kz_+vXNik^oi^%NK37!68-AuesX&`=)NEIo12S2Mb2{MeO!5Ob_VNHEwS@_ zi=k(|taI?tyMD;`3gM-;)T&$8$ID`g89QZuoj4eO@AqPR?K-<JIoO8yjyzA67~aoE zDSsvzXC*e0em9hNI2q40vB%=1;Y{}2!~!REL;rWob|!lFLmBd&Z@Z1`ZtUW6`Q|t4 zOrRD&19HWj38ji}6*=1~vEYVUJ0ZN9_r#76t49nebMO&!w#t{YA<8_X&%MXUzIkn? z*j|n=E#3B|)o;EO?s9G{vM6zV4lfTwYqz1+ys7J{ZSqYL?Y||Jy~Z|ZOPM{CnaNp) zdT_!QQ%BZc^;K<CSD$#5=Ph>KXESY|1-5qeiM{08e<xQx&o`A$?4$mTPPzN~l{-K= zvB%%wd8+s}xG(3vgE{xUUH*XnP71sT-NQW3wex?czo*T+agR$qho;!1os<z<ROYSr z`H2kJ{=Pbq|Bl}AFX<hhEWt*9yM(_9ShNtIZ)@^A{fpC}m#6nX_#jq+f%xfaiS-gb z#E(^KEk9y^17pR!n1wHOwSLELFYSg5Z(TZV_MIc_;>^<a8)nEi!0mCksS|!r8LIg% zVn6T&JhOtj>E)Hgmw3P5IkLtld#i^pHKu*K<)+reO~f48`>+h?oo26dCfqupApX{g zZq{P)S7q0{qw3<-C-t|=$veW_zM|CH^qTB3&=;&BzD)AOAEWI*k!!&ZK4ks>_-{tZ zckJa`!g28FNbd1(%3!|{VxD9%PrF{2ZpY0_%oXz{guiZ@eBVRl-+as%A@jlTW}GMg z4jE5mOn*m5@OJ(_pS+_Q(y^4@MY{zL{67PG$8%Tjcsh3FjZ5M?tnuL^YDqyVe`{Dh zzs{i>1OuO;Ry8_()i#dZ&qaFw_bGJqYkI8l`a81Mt7iP2*h{~3e4O%*@ku|lZ*yn| zh{whzyIJ;w&O3XH_&$>!Q_<ml@(4bTY$X4l3Gc&Zz4|fZYR2C>nMOM@|Kqe7(BEj{ z+g*lQs$-kPP8Mu!T(8+6GA!{A=$~{s!*jj`gU_}51T>JDlR-l@zJ`v`e>2ZMQ~2>9 zVpv3G(nW6=YNhN`k(r;ZNbXCWe)g9a<bGimee08Z<T@$${r~QPE&oGLK|h1G?{dZ` zE57C=^07?&f{}f}RNhH94fXgCc*SR=>O>BtAIY<HnKOd1;jQJ&TjMMK{XM<%A?LI9 z+$(n4o%1o+o&j5Iw-qnZR<Y>rqC@DEHgH&T($+uT8|7V6z5Y8Gd&9f*H!9PK;iWHG z`!9hDKC@b9>^))^_3@U;`y~!<@^>X|{%+WNY5r38!CxNy$@>5Y>Tgmv=(r%x<m5Zo z=m0q<NRzq9^DMy$9_9PTY4C__Zk>?GwBvH|!@ePLf5^n7BCsp!;4F(dDRa(zRK8c) zyjs3{Chy!yd^tX`!y*@kT6b2*k@NjD=1NH93cuY385>)UezcH0iK*vrAfC*xIj?0X zY|GH{2W=VJFj-_s*1PzQllk&JtxwQFV7Fiom~Bjs=MG{@9n7ZbZ<NX3<m6j$qKEpv zFOZ2J+!~L(JYya$t>WzbnYl+<;}+n%2cK}OXR6lYJJoaS!}xo5CySB8dThI`66b1o z*3+l|`K)}Ofb_h)V=aHv!Fl$q9WValm+bqESJJQ6QfqybHA&)=o_R>la~Aj_g0ZYq zVox@r`}m1&lo%Er=L~LT@yD3RYvE}fa=c68<9~Ulv##Y|^bGm><<riybb02;Ao}wQ z+lkSVdElwJ-x@FDS!z9Tf|!7GLp@X9^r15O>Gv?C9C@;C_gnKlZ{Rb<#yA;aE#mo) zchwwH={5KA&ddWBtp746$MgJ7+c)fahBk@SdcyfG##8!i%bB|d<>V|z&Ulwlj<}B} zzGkoETi<iyvGQ57uoIS@xAULU@6kB*CsDtE`f~m>iE{9`Oy(E%<`Y-etyS0Zow<R? zyzo>;*~=;0P1z7-_}d3RJ;65?u47(EJRg4#o|Ltmds*ki_bl^8($COdF?pf*Tj+Pz zca3YCs^agfnTC4mN}lEMH-pCWou>$PXBC*pJJ3ASa$g=_E^}_#<FqelJbeEMI_OPw za3sw4-%72<*F`oM1Nlzxc=#Ite|J*WEGSe}=nj08C#NDGY22H{Nu_fg5Wgofk-;~q zLilb5Lc?1S;cuX;eM9WCR^ly6*i$~r_g?PB4_m@FZ12U#RD!JCi@(Fx@6&Alnoq!A z1OAHrV&^#X!=(RWXJBWYtN^>ITBg<Cc`lR>g<Yk>yjOAEiZN;->Gh<wq#2}((1~f$ zQG6>c2Ykk;hq(`s#;LQ7b&#_)zJs|_E##fB*F=7uF{2;NsqjRED(_YIm8(V0rTt{N zS%zwQlX5?z+_Zk>78$DjrGDk+Q0`gE{g86`{mR7?Lph%t%J)j(tsiZCnkVN{CqbRZ zORd)J#InsIk21{59q5l6ZQDxZgzI#^c~i%;Vy?>sH}bRi?$V_ALi)Esp6$|Sc;t&d zM0bcydJ;Klx)$2J2Vsq`pP&}v&k~uF@A_8p-QPN7DX#Y~6L@!nGQ5{D7abyhyK^r4 zp7DHlV<GK{9Lx8{KSL_#bGE)mztE0BnMLHK@=RnL`c|j*zw39g{;Y8)CazAtp(XE$ z#b!zj@&}jO_*vVCm77DG{-Ox|T9ASdU|EjvB06yKE2?$@JT0hK5Az;L72n2)*UeT7 ziH$drQ}o5=r{%p0JBE!p^<z0>QA>m`+lJF~G+x*)b8qQP^6?#<tmPiwmrfRWmw6}a zda*9^^9lNU=X^7lvQsGwwoA3`UmW)-`Ie%ryM|}gv(EVAH#<ptjn8tnG)d|TZTaRd z^<^v?<a-Ww3_{}(%H*1BJIka^d8dIjV4kgC8XsY94lK3S=>E`$NwKx9d<$KTkFDMq zVZG$NO5}p?FF8KRjQSjPgNz07ZqiOOJlq0(nNQ2P7X1fbo@dx&j_1ACIBV*2Cf^=6 zJZqmK|8UI?@>i=R@$LLQ^(gUpZ>pB?dDSZ42{qK;-N+tA&Rq9VrUjZUhN>Mz+RA;a zp=v}oZj`w!-$X9_gL<x(Zxc)Wt)ZTs%$!>;*Mcke@^^lOmX@)^{U@G-_eJ_U;ZGVP z^j-%&_)z`8cH}PK(a-ElnywW3#1Jvxp8Q(f&i_N%`^QIB-TD9bPJ#rCHEqXsv_V4& znrOh-54IB$U{KH-gWF(3K}CgvEp)L9728;6GBX5fVzC<vwjcqaLKk+?4}Mm6vGTJ8 zi(7nrX+O4$ExMsX4HiqlL<2(R`+S{y?j#^}_wz?`@0@e)`SCvQ^Zs?-=Y5>-`}*i# z*LhCM3dYxsEV&!piNW^^c<MgAGT=TUxsm(erm?s1CjGNGCtbtuhvFD!UVE_FRosLr zlrOR6Qx_^v42A=gDfY{_&IQZ-RQnQt-QYR@2yC4-4>so-*@pV78dqn=)npp>_}_y= zwm-W6PJP06No&mTM8@<%O{Vo3>DRq*K)!w|qdi#cNSRaQKTaD}{=G?zRdMPLv$lq^ zwvcIRG6~kaQwTf?VheioEE>C@r-{A&y2>_V+ch$X7kc<L<eTh%>W;Cj1!Tf6aYt$k zer%GljO>i<pz;<c*Ow6^TVrXbCG~ae2x)A!Mu)oeMag%}sXbfd%w;?yp$D^g%6E7g zG%*+ba4Y5U@z~HDC2nH$znnb7OBNtbyanwbCM;vji?%uah3m%02U(4^{(Q1Is`J`q zz<87A{BRZH!?(cfp%(__v^JBsz_;4^f4L^}el_xWIb+OYjJ<v|Ykj#_`Zr@N>pge< z*#p#F=sAl<X<gF~qhHWY4F0&eCewUKeZ|-3m~>0|rc+*in7WG%TJpmIS^m8S*>{)p z>YnxV0UKj|%Q<kKo|V1*xHFB;vdX8OEk1ldTgO^m2H#k&ShmnO#XfKKdE;|u^_2XI z%$CO*eZuy26YyPzOuHqTqA#HvUYEaJEG2rJkss-}#_fMKXCqm|_vq{{c<D9r4dWWd z__i9@fsgQdH~JQ`w~@K8pJ(bPJ|^+P1~Gp-C5tldo#;iE1Dg>Vb4})P>6++hE4tvf zP1r1#QD(R2EH*Zkn#>QeXa03Bzje1JbMoDKt1nFfE+4b6`kAT=>mwH(LLb>jeNWJb ze0xvkTKXXQs;^#%eEMD4Lq4XB%QWx%J?973ZV66>zH?af1s-PiFoLyFd4!l;KO>Iq z!T(inY-QXPXVwb5O7<Lo4lhF{fA1Cl{Dt<gdyYZ3@z2bRgWtkW(0wtOYp(qDlmD>t zT4r;vCA5NdrMO^ulwr+gjBSEBoXZ-^hhOF4&$uPk>NLeSLZ{sohXVe^*|_NzAN;k0 z9H@CEeXUK$KKuBq$a4K8-{~xAFb39)v!crRKK+)=Df@)>W0<Rlqyu%t|DN&X`F70s zV?*i{cUtkL<Nt*IvzPk>@4ve~am!aO5Nj?hTzCx}I}mRys*Nus{`5k{pI(2K`k9}H zjQu01`=j<=LZYwknL`~1J?F9YJll9y^E}LRtm>ez;QT|{|2m*Gnym|XS$)m=%zgS8 zcz?|3uJ|fQ-q3nt9@q;BEz!DwkC-@B*s*;%msqvZMUkT(w!DKoax<O4XrFjnO=i)Z zyl+S*+H@z%a(o_D_I8yO-%uG}-dS{e@;-BaO?>4&%zJ`zAy;?n)@%N}kaO18X&0^1 zT(Ra$lGuRF_pC+3yW~>~pEKp1mS);DXOt_qs?C;%IdcTv%9KmSCa;XA)<bb+o7tN> zpzj##NZMWR`@3Z5e`X;twCD66JRlgJ4?lcw`@}^5)F$FBm@~@45w(dQO{%#VxZ|gr zeCjR5N>Ts!$qt~ljSLV94KhB!3!LYpvx(s{rbcbI3;s2kg&P%LS$Cs6UJc*#<0^M6 zUfbhCXhZyq7+cAw+ElN6aLQN@l1Ig3I(e4yJZ9THtTWj5eVpk-QP2l>g=_@Cu-LYH zLmV4J@+t02B96Z1F8Q$dC-H5@{2I9h8<NI@jtpF<Fy0VpCLWN^=h24xrS?Y(=9SP* z^^Y>1>>2jnBvS_bZ@2UOhUPcPox_a5%w<icaihTlt;y_~T{xI^YV19Ukw<k#zR>bJ zd&a$yc&oZ|$HZ2H$9%g`<?;14w#8t7AUl_9{k5Puf?ipl@`5({bu87;6L0MKYlr84 zz`8n~t3DuC8C!#W-w2LaTh~0<K{u$apl;}-vxEB}wbtNQI)^?2TBSQ9^Gtit5%5mD zEJ}J9AI);nNoZW8^38&Uq*tZh?1{Iy4*Nmxn0s~X{MB38Fux*ZaC(|QZwqXE4`O5W z{IwH%Pj@BtCzJU4JaQ#^75X%DX3GY4(ujP;nHS<R8+$o)gfkJ8W6l)oDwn=RpwBw{ zuepY%%*9^X)26;>$GXNjvtz7lZHunCuUd02Il!m=mo9H?IIdV|Ixm-BlSv;*S7z}M zIsG_%JN|ll^k2^`eaSy3tasU{EsaJu^yff4fO+tF@OGoq8k?w1ztfc8o_VbjIE!D? zmZATQr_R9TUf@FClJ^lG<E}n%@yi-}31uVNQ!sE@#oc<X#s@8I;gXNND3?25fr(q> zh5lh{qN&&KN3=Ge*S+zZKA|}9#i9qyq5LW%ylV~Xtm#aiQ+Q6rzG3ui_}-lOD>*-7 zE~1Fc#M_EJOMc<JJoKDA*4>k=bKh^Wh%#l9^7?;o-auj*A&0Sl>vFf-KGr~63uVa9 zCr$T@t$S$~>i`@y`w2y6U1a3~@VD1ae8F{b$==lJ<H&bf7sm@cw-fp0c$vQzPOTDN z*>}k^c3pf+dte`_7o0ZdB7EGqWNu9+xy{md&T||u!Iot3)N{{#Qt$+JoF|W<e@SmW zUaov}t!IRfYRe0KYux{!9q=YO37;&*kx@Gl>T%U?&;4-Y1=<;*eA*e`+s*?AX=n3C z)_Iz<wEj9bYuv<#y}<g`+Ggx^8n@PW<(v7fTH~Jk=OtQac70E=GE!J+6*1<C7=Mi2 z#GXKBTH?bB8!)^}x-~NOs=9dp2L0y!RC@IBLgQOj8X2B!t*Iw|jn2B%Y8+nZfiPp} z<!5PMzoB1clK=fVx%eP;gd0~MFH#&R=`frVm5;ge9QW0wtFmjC{fgsJ&v|$d<%^Nk zjD1!2A?x>f>$gli&tIqA&-v@rsbgG`KItoh_3QhrC)QiMDD!`xeW5PVzrla+`Q$m{ z+{QR}m~le)=Sc3^8PKQgyZkX)o;}W-pLq&9_3zQ)oM4Y}U^jS{*O<e(FYv2ztN0tg zdyZG3bHc+y;RVD9`sxS$8!9H_XZV<Wk3$+~O!tJb4}OjxpJ1)^pz%g`DxTPfZ!n)m zA7sp%$u}`z`s8mj`PIPoF}3Y3#J(Bw{ZrlLmTy8k+{L_G+Tl(U?H~=l?AF;bH$W>U zkp3`F?M2S#S;g~Co+EhH@hs!1GxWtgzr|B>!`FGrj`epu(UF{6sMoP=!4F*7ZaR{u z*l%TQW_;-Ee*a}lKJA~gTw#3k_u?;_)67^@r}Y;f&U*oMY?|kBr{4nZ6QoRKDRdSY z16g9T;9~B10nZG4ki~8N(67_01RwddQqQc4y93xjSMN43^Xcl{zy{xR%E%@px>|+Z zzu$R%k&L9i6xqH+RHhOcOtBg03pP*fmmV(xzsDJQ6CZ&1D_f8`k~dnJW9zqHaoATd zXUjMFIO0UE6Rxy6aeiy>9{UrzPL=fH;~sIj@)-AA(&9=Z-Xk^$^ZhvTV!Y2Z^vJ1K z+!=r02K?jO3Fgic`rtVYFUYpx)7tL^yseBfwbZLP#Hv^EA;nkgjGXB-U{f`6Z?MN2 z^Fp&atvuABxeR#NM|oHOeb_uBFYV&|)lJyFW6-0UI8$Qz2<xoZR$_H{(Glp$2+27< zJ?Y;<U#57@cVCb^Z)84a<uKNE-#rh}g5}5@=lM4rpDGyo-z*zz=!4l~I6lpD5|jLK zxty&uxMt$RVaHC`a)SFzc;5l=SbGl_G4D#7McQuUp;*Nj`Pv?zBfA1}>t^Ys*v%EI zTJmitZSR)6MVYzexA^_|_kMlqpHE$8Og^kP`f<QghF4izUqa{ors!K^r&uFj^MAX% zPaT}+$OQM>6b0q5W%MnRqD+ClS3c{)?j!z-?r_YP&w}b>eBzM{;RA<xqAT|tl-~t9 zHG5D?rO%_kej}fGJI9Yew4J#(wl3zbcnNFGpSymqX^(7FQAo0?_z*VNo@26g8UGpE z58vMNPiyU%BC>5sMx<S2g)`3>+fdrTezE5~a)P}u(`TI*qEE<CUtdU{Is#uGoj;2& z8d9GquDO8z+)s1XLOqhf(U-sOSzPYj%l*hcbHCiiKbd)42Jc@kSr~XON&T0D4eofW z;6t5jsB;p}b>t&2WUxaY-@rREYvz95H}PJ;`<=XR=3TnR?YuwFJA61ZmiH~ZE1txS zyl>^bi1$*SI+LB}xd*yv&)AIowf?;$<c+X-uambsySM3lkG;_2*oeOO0O|XDzW2~s zQ`VWck#dGcq_!X5Pr27*d!+0WydUtKdCk6E_&7F#@1;p=OBq`8y@z-|%sY0Eo+bRf z0t};~0bXdPe7~|V+|Jxet^psaILH0R%2?)zj}tjNJ!jkfjiZmZH(r@(TF`U+*n&4R zYkc3S;~mHY+ZxXp*>hoPM`oXiv-VWxwUN9__OAP<{ylXYIDGuGlJ0WOZ^YlOD7b;M zKZ(4t1@V`A=Eh$>5RJdRKgt=RlgPwhiN5VrSL8WgrrsA5(e~lV<_+S_1@RxZ5BKjN zd3Y^rG!K~_yT7?>4u8}7BaIn&@KbGC$MN1V&gf>0S(=4x5coulF#FcT=!U<!m2HkY zvW<8%JDsWim_r8}?>#PhFdzBA)&6{Pi#HruQZjTA?LA~<VD_dx_vCnMPpo<pI4B)^ zM2Ir$pFHUQHgUq;lY@NwO6H&`qd8y;iZ*O~&H9I=Gi&c39b~bkacWQF>&KYN{dt=q zKZag88$7V{X5vs+rUDr!1b#Sk236sMbQT|;v!}z!40mykQM_cs%O<dHgBV6JY?kJH z7BppqbROuZiQf{XzM9PZ!PHd%?&9;Jd$#8<(zpEP{o&`NSFRn!S&>%wb!(<2l|YuA zE?NC+%jj#b{5c(8I3LH#r0*O5uk77-?$nyh-3i}rr1g0BB<&Xjwr$yetWIY1YV!L* zSEQ>V1Aa{~>ChSo<iLQpfzQ@A$?4!c9{eUb{`%$#w^-iL&A1|KiBk=1C1+`$k9~~e zXW(BIf;aU;bEa#bVAgrQhD~-Xt-Zd6PK)s|fM&8!$Nb`3r+oroDB38SDK>`3!QYVh zCU`wUcF@%74q*K4w56v-v`ehNo6efwtK5!MLx-_Rc+PjQ|8;P8HV*a9cgFJ$jeg+q zfENVq&_=1?OMU_QhDRYIKm)!#R&j7ebJ$nY-UW9V`}TD5o|CNz*)os*$VQQeO%R&c z5uuJ!;jYrCr?@6F?^MNL?6a#o3RBxVinNcTdl4u<mN7#Q=e=(8i<NKlhEi9F=gfJ- zu9qU!N7-j=*)sV@`DNWxlr5+1bLW*!+p;72lzo-5QOYhluk0jSwyIBA6K8`qD=q{F z(Nyv_+J0ST%79Y_Rw*A=HJR`15>JMgS=|hrHown2pgCpy$Q&Ip&zY~e8fW$u(1rMY zl;56YIo{u>$xPu+HM2)&d;rOtK>9rJZMksK3*9$GYX_X`z5jD?mPVJEdx*d%pI-G8 zf=dx_Ef0S~{~o68W*<=Z(S<78B;TM1lV|k?#qBh*hw^&yrt^gGMq?1)SKL%Xt77uG zJY)Dh-|e^Su*vERbE!KHjVUztWatdvPl28kG>$PeB3Jectt;_{_(I*qI(IxYM!wyg z+bc10O#I>7%-x@|>DOfb;W^P7m4_x4DQ0O+=Amk6OqsbysWr2X_9C=n@0~n-La+yh zwLW|wOhk#lVPvPR@&WlU(d*0GQD=O4O`NI+<qKWnpK-hApw_q6Jaj%LdJ?SNfTpls z27Z*ToN4vk_lysH(G2`;LicRYGb?Ws3nBRa0^efq8)43D@ZDUs8U6V3WuE)R+kKjJ zkNWsG`GAiXXN(<A^Tiw?D|XEEoNrH;{0HoeZ0Wg~J^Xg<+L;+kIny}baDy*Tbj+gs z4a8D;pYNlh_nhs$R5Xsd=7^?||4HUDf{)K9ft%Wxt8(PAk20@|-}8CCt2Rvx2l#^T z8$7i>(btxS?JIy!uPyDvanPHlL=N|>fAe$o&BzVcHyK<S!E>OQtJRM1wHTRR`bDgH zAavX>Q>$~{QSQSfKR?xznS*Zr@8ml+zcA51_H1H6c?Eh}A!S5&u>m<HMn70(bkwkY z-=eluPkfqlbsh679VyzY7xnTu*XPIRLw)uPPS>+%;0Z^O53S#a!?~Xh<G<V3&=L2X zxerl)mD$5U&hYmi=S~+6i@%aT$)_`O66Rh#Lv!ZLGk${dfo^RV@7=9BDO*Zi2Oiw$ z<iKm>8(@4;$xCT{h$c}+`!>&$wlKNvGjo&M++~s-8t?6BY8>6Mxbe!47Ruac?*c86 z%~<!T#Gmqp>+UhpM6=(Hero$S!1mz)buOdsI_`{a;eEO4RXu&`MpF2P*C|u1dgD*E zJ$vCg|KSB&=RxXO!#8$6`7ZyQ!_1H4_ouYqST8#j->&nVui15Tm-fTY;pN*06HD5c zOZxEg?%m)yGE{C;p#RuCkLj$1!(UpI=>e|e)P~|zB0ETDswGcy*Fks)bnMJ@%bWM9 z52CZ4^NrbdZEc|3GSTc_`g?p{y!7JwWwV`Htr5N-Y`<TOtV4a^4!GdAk-u0nnAV`F z*FAot^eL4~J&mt?bBTOsv>rD}ukxI4&Gwx9DQY`0l;5FGFY@coALoTG8*BTtnR4*( z{BrhT%{}TG7wxH@=aB<+?g?DX-v{sCLfawinStIa-8m<=DrXA)>NBRlu2O7n$rjMz ziE2~*XDnMx|AC32Bko@x;`?0L49GWkfdJQBU=*dC8KW(CdwME!`p=Zr{4?fcqZzAc z(pLJIrtYbYJ?QD!lr&bpN8kCB@fCnZAg6>U_Kr8VbE)#3i*+}UWU-z8xQ>jqeXaG! z6-q(Zv?uK}?m#yV^;=IJ@-bk(v3Y2WT34Y@-ecg(`tY2A?ZEknZELr|CEBof^dNpq zia`s^LW&=fyWqc^yagG>4t6(-KUUty-?q#d;Z<|Bv3pekn|0VM2)J?nJp6H%wO zvW@j+aLX~a4a%6k9<A2|ckAkV;8<&9Y3|!#d^%G>yp4C=G<k`;y@@RklSW)h;u~N~ z>ewsT;g@zmZRvZJvwbMSHgc?Sx>MV<l0GeTM$_M1yG|D}<_*|W?pB|mYg5%P`m@3G zxq?1lnVIuM#W{VRB^rj!pjNosXJ66mXa0?`lqI6XtSdD(PstA><WuD1$FX73qn1Cy zc(k7hUDP@-{rA`DJ?Mzb^}7k&rvLZw{W#AV(4qE4%W5*;xEvcxtzzN(`$}JbNcAkz z9b?@2nLKqmESNxV_XF2FGuG{ydilAb`+#dX(#I`s^qa4=)SDes8;-nGuQLo@DBt+b z#ai?Bf-ie4e(b|{P5wgP055dssvmQVyUw6P=z-#61L{cc*U0(;E(OG67u^AmGKU+X zL*Qotag_5LuVTG2pY#Kt@}M8N$834ofMxsTJL2|JAI~<GH+pI)_l5Y-i_P6u%kFnP zqelogifG?G)fLns-$cHf%bGEAn-BYUo>LqOU@|3f?a%86--fO6K6jbEQEW-oPrKhr z-1ilITa<ikuW%#6w~pubtP&io4&q_+@@Q|7?Z0HoLU4!u^h{>tSx0#5C7a=St1`<? z{S6)a?U>BIdlbE$D{L-jZO#nFmh1=a?{X%1A@>G+tS3k=vg0su###GKw6hO6X1^Wh zcj(_j-~Rf+B%fX)b3)4utnhQA4(t$SPgnZTYbj!PP)Gd1qfQR|0UtFd%>0dDEgX<N zM0dzljAdW==k3Ge--K_o&ScB*+^&AfRmAi6_aCu&bsY4ZSubD<Z(&^GIYuX=jW%<K zI(n-=-m~p$S2~M)S=g)FrvCZ%p}X)CyJ)851}}8!Jr>UnQ|~?08|8cKoCX)>R6^Hz zN1qHW=e-EL@O@sPPss5)7i8pg;TPk}hxSZS8a|Z9r`5-MXGwOxLZ5iow%3kMxz6{K zK;~gB2zKTy%r4DwX1$T!r*jXC&l^O4ju{_8^g;OLb9~>yorQIzcgQA6+A7wk@%_Nh zZ4v3nnBQoo+}`BYzlbh&HeT7$?XSy@X$yKf&MbKIgtK7#iQEONPvk9VIFY~L-V+52 zMxO{9x=nw;w+YO_J;WO`@gR|B^N1~mt^f_K@Q6k9AH8uK;)ZAW>&5->Nb)IU7<6jp zx!jH+uVLs9>YIm}^=bHB!}z83Mc4-wvsX40&-wc6qEq0<Rg5h+)o>z0+8)M`UwI$8 z%ah!vE;;Z%Y)r%z=i9-G|Eh1b1}MA2_(yJc_QLNDX2-FH`EffZ3a^#My@}W%PmNXo zQuxDPpTnLzu#PQ9e+pev-HQ`nucn<AjYWITjAgFr@6-Ph^j9+FRMMxIbbOiZI6kSl zz}FtTY3C{5|Mh-+W1Vu9)Bc5D?*5~s6{>#Lfnvb2-*TeRbMF6*(zO;F$2t>Ytvz$K zPDsPf0sYmUt&=-7wfaO6bOL$fjg1z@^ChFCEKi1hT*g>LbK&p#^8(yMPd7YPumGOL z=$!EGJm0rBmE%!%ykGW2G5n6ZE(iF&x~Uv|qVh{^UJ2`>UGjnDPqSE$?UFGVLm9l< zkxd+ZnR&fmanO-DPn46EE4#Mm%zW3TjUWxVVCEb4ca-0(r<t$X-&OoB;P*DZkNJBH zGoQ10<H!R?X09dXtoF5a#zyUUqyxv9&34WD{b@Kcf%GEM=TW|Z^0NJ@d@bpWb>^Lt zUA1qEy-2c*#!^Q*c5SVvnH7w=1h`KD?m3=&@CFO_V&Kq6zB{}vkb#l4>4)1XIPu+7 zf4=^B%6?a8zRSw1f1XEv0eYw8vwZCzMWH9ilcryy4@rCr<KG~kKE|5_$NVR>cOOfK zCeV)LU$ryMwqxuu>|;(~oPjT{Y!fY_QI&0yM@|^}<GJs@VA^dsG0SsiOk~`1cnbfg z82aSz<;LI@QOaIsX&OGD124C5noIf1jorX;cjA*6Bd)eNcOrQqbqGHn+0j|w=p84F z-&Sj81N9%Uv|RqcePs6|_xFK?Ialbz;>hiS?FC^G${7aT6uvJ6XVbP{%$tc<H#4^S zgZ-urV5+)3_pQrRmno+?59O?~-y{DIu=4*2VEnbQhF@@}kA-iX@0tHU1oK~L@J2BN zsHZ0L%|X#=X1z+D*L<XGdDqUnVi}2-M0vt1Kaf1%2Y>#Q&{)m*WwQh>p8KcS;t7m} zIF-mAYnZ#$8R3Vkbqr6dF!WBoh48%SPQf|%PUxV%S05HqAGCrn?1rbjzuWX#<904S zM7dh#youPO-LkiNp_-lOgl$<n4g6X9VC6UPb$!eDf*0$IU>sZZ<VOg7ci%{BQ-0@p z`dBFcMk5o@pUOuv-CpRnMXksmi81>pj!kC{(?$_(q~e>dlYg;OL7<4}IxY~b&iR?_ zA{u9+q^5q+P$w6Ep6<l0Ukl4WNPa=`H;6C1L-rJ>VqE5oV5Rc9+jt>5kjhsqroI`} z*Gzpe%1yI%e)I17MKk;|$)?&EG&jam{D}BoQ}nw$zTOMR7mf`l7n*!MjZBtYG(~4F z3KFxY6ePTf&?NjVV#F(*#@@}%U#U;byxZJ6dk);#=M&tphs*X+EL|?}pZD!iN8{LY zN>bZTEN9L{ce1`X=^>`i@;foHL&Xok8RCnaXf=9^e7^l}9t!+-`h26af3npB=i3VD zQ-|noFrR{%z76b4^v%v+`(gSp)Yez1`oLxFeT0CK_5`5S;3{dp&8>PLbswm>mAT3D z{lLr|60>wiU)wA)usIW{n5~&gW8<k@6YR^hHwl)KQy$%D=LS2c`Z)Or`%K#oV9WUp zHqyJE0S2P;#COc}n6n})s)tt+Z*y{{U?lx1p<hn&#Z$w*P<4^|74&JxTI=JlGveHT z4IRs4%w_6}KM!wrLf3{_f7D|6zomuq$cdA;(TB&{WB4@`7~a76m9F-@kSAa03)>u_ z<Jt$&KCx|MF>Q!0DGsi=+gdm*nl2rPH8@eQwRIzlc(cwKLtl6Xb?cnz>B{=V<u?ay zl+(r_(J|VXpfjJ~OtG<XNk&H>*LjfSt=gx{jI}hyoX-vHU_MTDHv4oUv$wL%;8BU8 zfuUP9-Yr?Uy4Z?^->t@nbb{H#(j31YjQP*4(4IBOk<FI2B8%i${r|)|c-CBF-(&r$ z9e&R=G911K**!tG<8qy?1vcZ%-VFKyvT1?l&~uMBqxTempIW0uykkFa)4TDBH9EU{ z78w$|fpp)MJEc!-RXqmw?9)VPH&M91mVNqn<qHh|fUo6@O(y^7^M(fXbLuGS*vnX! z>s#zl&#?|S2xfwp@#~OW=Dv4SaFgEP!#-1{y&!ZEqthk7@khQrz0rJ2dGq}){0>O> z+_PqH$8SHhD~X@6<zbsV=k9H^?`7-ZOpC4S9_rd`=1ybkt?Pat-aVVxgL=r;18u(h zA@J7o=W@LEg0uVGI|ln}gmqD6<}rJA;qZRXZGWzJ{z5}-eOs8XGn!w)gt4!e&7A&^ zpie%GQ=(}ZbH2nMmwU9&xORHZU7UY&w>FMGv0Hl^o-^?`k}aT#)687U-(x7W02s5c z9PI1)@%Zp<lDtuq`D%jpb{pRio%MOk%E<1S>Aih+t^9jpFKy1F{Jx-mTesomX5Ln6 z{@fDrA;z|U$zXH0R{jd`44&E4c$C=0@N3@=GU*MoP88d7I%&eqHL~SRnun}2K;H}2 z{Pyh|K{?@#U#?nlcP;*gDR1;v;U;olKYkzZVSBP#V_{9lvva)`I=l<{+C72a_vaqQ zRucwp<B(Sl36FW#T?qCLwMj=bX5=t`T?nqw0enA4@ol}v;yKeK?}hc7r{ZBtXUP}e ziERZ(83$()0{I_Z{LWHvDe9-+y!jkDxYp-;;8LOF*!Yeh_ROE~&G}HiPg)~|;Ku7& z|FW+m>olBb^PDNap<d|U&2y-;>H6=ZGg#iT9i7zLrQ_N=_UY=M%HRn_e0vypEjILh zCv&t$I^mQ>qA40v{0aK;@7FQrBS*k*;c0~S?=;^?7i>7uPT4YkA2VZeJAP;Bf$+IQ zY2r!HiN~{a!p&TsOl0XqC+%GZ%sLzIJwf~i{~Lo7oL@6G3is5jwr%mz&9t>#^^SZY z(>?NoOm`(XhYU7}^j57w<?(yG_HC2Z?}SAM8{RN?>{X3?0h>u;e{Jdo@bq`s;r{6_ z^&>w(N5qE@8^HJ!asE^PNxIGu^#5gj@~-~_4}E`Faz&eH;BM$-H~l=LHWH;hbJfq} zqh3_~jK5#;dvHs7@*vw^=Bj6y>=Z_CZa4|8o-F-WI;rH0dV{B-vCEmWUb#{92>#Fl zuD0w#zE6X*qTR@+;6`!FA<kyIf$Y(SA6U;PsSBB9?0o83o}KqJc&2(>XO8rEf8N_h z0H*`+fMML#$l7oVDyM4?{v>nnxC`DqY1Zh1?I-gWtUig~(!^bjqfdtE^J~%{WSbN{ ztu%A`rxk*e&P>w32>oN8|2hbG8y_RSS*&#+`2xH(Yk{$pvrf??e*dcCiz~lkEHT#N z6Q5NX>}ln8Z&}~?v9(+Avo!k^ndi;CV0&&@|1YB3CDAs7ct`Vp=EZE@qNn@jF|TJ< z86M7hl|4vuisv4BL+iJaSWO<G1w{)ulUM{CXL+GmE^zFXgVO$ds0^^QXQ1BH8K@1S z@tRBNfsEJ09?;tC<+bgDKFVvmeO?O=8Qt7{|4zQeMh^{MW$<jP_6E}TIYpC?_8V>1 z5N#y?O!;ld@NMWa+X}v%+;&@d@;2w{<i_?|{Frl-8^lk#?lE#`%HPwb-oSqoxogY> z#x+fNl*N%l&_>B3=p>3k&G^=74UH)Z*?WoJENE;v8DT9i7q06(DDSOieX1VOLHHQy zH>3`_<@iSCU^C5~bZx;%oy&#}agW#);YpRqgWyl}5WY6d*Y#I%fSXuVqf$9e#ns5C zTb&ko2l^Lh_ZB(j4>r2;;jd5M@02V!0$%jvtY1Iui9cX{?s3YN^f$6g{?co}ImWnz zc;F8<8o!c)M&7^C8grKN{1I`zm-ffb{UmFqKldy2mtBN)#e3}g=q2BnI6VHV!NZjn z{}u0V{~;V*@08dW;6~<+|2bM)_g2Ra`V&rVKUrvaAZr>}-w3{}5q^82QS$R|$-;GP zcJ0kKbQHNjF!tBr!7c2W91@Kfn+laJ=sD2>z8G22;La}mh`&S(-cmn)Ec~dXV!ZJm z&q3EJK*lbXuc_XJ8=4FH-qdIyhM&~Vb+hg!E@=i<LS*pvY$Y4d^jLxzTzV^=7F zKIT@$Sby{%UpY51z?>h+Pe|XJ?dufK_GRje>S$QUnp^7>vF-|kzBNL3Do`e{bNYQl z9ui-sZ@uGLBf9Xm`0_GK2eBL7F_^l`gT67{B@5C{al`#9jXdVLM}s?93s^t0QESaq zRYo{ZNxzfywKC=F^o;#nJqVg)^q~7S{@Znqd~u@mGjkKA?y`mhe+W1H{-@e^iG209 z1tZCu!1&DlF~(Nh58Cqmr%h}k$%^K@p!5d#vAqkX?0S3w=u5Hsm8{_Y!!HsCnRoNM zd9z~uZl>P4$+_S>eTlF5e0Z|omnUe;!~_X!F=``#rLQ}1U*=%!yW9Syo;pi-FXV}@ zR8Lh_Z$@VZ@8+6&y+f6?;N3^$QKK)vbRBTO2F$u^vGS>SrH_Muh=C8Y#mj`B^mmGQ zn89tyS-Zr?+9xt!qUD8w{G_`0?gsmfIsd0T?4$jXD<aGhXEj$A>A9aek%I&)&beh} zo{?MCU-61yt?XcomQPigwIW^UL-e!4KtFpO9q{cvhNp6_hxH~pu`IwH`Z-<q^-4BL zHJmIl`vTfSb-pb5e-`x0@N2WTXU6sR!**QkN1rrjOenjAvQ?%|cmzD-M%fHyFHEkC z3itAptwr#p%tF2?H*MVi$9m~0d@G-F@$)G6E{YC(gm(y@%t4v>gm4MHE#%L`fz6_= z$gM}L{UFTx&SQORKPXS<-=H}rcABLP%*&r&4A!m20bMGRE+5#A;_FW%vwZka{0Gn+ z{9R;Yp>O^@@SzHi{$+JhWWxaV69PJwxZ>ve_zS*18h<~~^$)<aj}B`@_L7_p4|1i? zX#9d1XQN*+@4hVW=j$$LKkpgjI-h3*-)7~s<4er=^c^sgtfp^}H-9I+h_Q7Wc%YNV z{~cLw{VzBh(y=}MLh0|904HRG+W3)o!gU)N|D(0&q_=6GY#%m4|C|6eL*TfTxs4F7 zeE1Ufrlq6s6yFG^`Inx>*}OYRdl;JyF;J50-w9K1(PZeS!3X*l-+C=DJw3SPJ8W+J zm~u~2Zrjhpns>@hoBYq*&3X10Va`_NB?|8dCx4<nMfR1K+kPxJ{TQJ(6H{x46Ys|% zzE3W{i?e;Wi!}CDNW*3%xkS7>qx0SDFMMgfeDD~Hc)0N?%dQ{bX4j9kNBw>R^4ti| z-Mz=s6!uiUe2MDgd71jmyV(nte;M`ToBE}w>b+2%I-BO>>hHRnZ-#e2=3GlZ#%aG@ zbk>*W_MJtR^Y{AT|G-3hG4e4fYnox&t6JkfN2L5`S)Xrr`D4X)m5D?p2PDRHm&-;K zpV1xl`}al3$QSIN?b{T)r=q?^g1XI_b9di#>aT@|6qDysPCmN2OHMKPL-PF~U-t@_ z`!6*2&DCa{+~bxxrnSbMC&28c*+D;TpU#yN-RwO0e#yvF#y>o(bG^2^CUa}Q#-5W= z**+?-f;K$`9?7NwE%Dr6Ugpo28^ivLOnb}g$(5q1uI?yy#7mG1MHf==gD$OC>HoYR zHEYqVwOi8c)ASRLv+o#Ak3Lx?TU?^L{hYIA@?&Hyar<0YH{0BadN@A2XKrGMS4&>L z*~6S&!<{WAZ*P2dq#Ju%r(_K1{qOYb?ZeqUz3n=!v>UrnyUC+h!0-I~>u6(s-`}(G z5g~0F=g6Hzk#qH=(&M@}w6^#62l^e;?=Qd6eiQHc=KWyXO@4XBDZ|e*!#q5-6S(!P zgI1ffSe{d@n4+T5CBEO_2;H41ShfnUz?ZDP+}FO_Ylr;p8GNjmlfRcuA{0mOW_?F^ zckv71nNfU@DD4-Lrh3bm!#w6U*X$Lt?t|areM$p{#>Pe;J<svBX<f#-UsZRiYHXqb zz3cOT8T=P6CYsKTgWK!p_*?D>I60rQpZKhuY?^ixPyapj5;Q{TeS8f&KBgZ0c26$1 z-`3mu;(h81+L+cS?E-Clm_0MGV|uR7XVSTx%l#aF1-aOMa^Z=&Ba9r^hAcNd*V3=w zY#=u4t6B@9Bfx_D%iak~4^C#T#jY({Jg!=623?drpj_r<<qd`xrcI0??yk+H%xb$I zd9u}WZhemSNL!VLHr5K(y#FSUcWN@#oJ~Ht#>hEG;6Ki-oPRmFPQN{8<ee4MbIVoM z3w=Rr{$uFSe&n88Znu4BPj>tX`Y$@JJKCVLH|!7Ku6hDo>z%{>%QT09FCchC+>?_j z&BgL>g1?H_%)90@n9IKP3CAx`=eYEhCugZ2iPAg5k0W@C)<N4kRnMer|8skM_8npL z@$EsK^sU!E-^VWH)7t-!*gYo~H*P;U6T6;xNkLPB`Ga0F-nG){@u%s4&du`EwEr=_ zd2y0<nNzh3EU;CTvtM>*bHH=9PtUQkNKPGkN_{1BWN>2*`)7kg`IQc5Yo<9fZ66jk z-g|P&g4Nh+u^kyaNauv3Yjd!1hp=0;oRU0+Oi0^qoOX4_ave|n<hToHNamD{C)mRG zvBpC=1*x@spAHoyyEx-wXzAD^_|j<qDo?Sw(t~r%eId!C<UiFGWBrRxf=kyFRGxu$ zxjXtL&vvsXcyfc0@1?J^M`3h)XZ#JlxOU5)UflZ9+0^u$0_r)KJVP5Jv%VfhmDt`B zl`DTgsFX9FD?Q+5WM6dEaib~^X<Roy5tNUA=X3RS-@OPQI_`*m>m_h@+~r?=#oV=} zdzIt#)!6%apG#Xh!#hxAd0s-jVcE)7UImXi+O08-doly<_&j%xl%i`juTk4!?L#Ly zSH%1^Q3jjPc<algd)u7IN|!mJU&+kgTHydb7;}8Q&#Co7!#ACSQ)$Ziwy8p6d&tI4 zeRVmoVNOS$1;?gXnK;sXv*E`#2nNtV@rgXqLil1x>!GrZ_E;<IyXQj7txWRrCE`!i zx4CkSVlLkNj6bhuA6Gj3JUA;3EN`lgPRnWc+-+mOL`*GgL5FQzFzE=-^X)unhT7%) z`pGRmUAXxkoo^uBS;{)_ae7!g<J=J7bb`B}x9vjb^T#@sJD>Bj`&+5N#<FiSbt0pV z9H8~Vy!7#f`=#~=6u-k=@F(mTtNNF~NBWHMmy5{DQJL84{`ulDcKid8CuaLL?Tb2- zE4Qd#&IO;`>Dvo#Qk*Ae+KgYahqLwerC$?1ooeorhTq268|e@Dk?E#h?D{8>Uq%~W zVqlH!_~c%*e<0b#xoM*D7fU%IU{r3)@2km-I-xO9zL@g+`;;GS%VVEA^*Vd;#92J~ zT9Cis%9C>zym@k2y65Cf%`Ni>of-QsIMI~8_vD0;Dg3~%Jh^zm=#z7oHXD976`N&! z`pqo=t6O=TdFe)`E@y6voJ+7{wygM~c^?ApSh(T_^1H+bx;LhWQ^&n0<H_rPT@S5X z&b=w(p{b?q_zXbDQp_*Er?u#L<;j*MSExTR$!o!R<Q(ACf&aix&lz)e?rf(m{%vH0 z1tHeSn0M!X(`n;9udbfE7`J5FCU4^&sa0zP7vz9$`RtdaZ!~o;S3j1N@J^qCepp^S zO}I{dtLDz4{s&dRyZNhkTr^sDC?`Mli}1)hGHv>ujNBH!{zuTuJB(by{EV5MeEu)> z>KEUnWP43Ut_ZW=-&XhSi$;@Q?f220dF36>edpv;w&4!h&&Lea_jR+NGYj14<bnUW zJ#m}#v5U6rjyK;Yz%35G{py1kjUKte2@n6YGj7;Y=PQg693Op1^0vxwevrO69lAr6 zerA%9JHoLaVe^}0*1GU@+@z9==BI1<-Q>gst9e759n=#cy@9kbN}Ep1(n&+Of4bVY zmsL2x?J~ocCNwk0$!5vW?0=(IECI%RKOzlI1a=pG7sr0cJ}9)eq8gvy*?jZZni%>S zHh<(M(c~X7&#N-y=>K5Bo_<Fs5BSgRf@yNVFT&g-x?OWiOs1mba?>7i%cw4mQ)`H^ zOrxDVmB&`Pr~(>RNk3QIN1HKc2v4`-9;b+>;=}$O&zzN4>C930(B`i?4(}JCt0=$U za@IfT)06-Fm->cPPcyeUBd!O&=m{O*&SLO$CS!G$qpJ#kR+NBCjD@rz!ug5{=hODS z<9yyfrSWO(iR-<Iv9v2b;nIf&+Cq<Wwa=zL4OZLycACHJglJ<i={el1)23JrGM-RI z{nL5*!<5OH<XtpBJ8!p{c?**k%v&CJPsG$$>d9T<e;?y}#RJ~de5diB=%@NuFn;PD zMxONj<>d9_n~PRVH0grf0MeUC>(AW(-HNNYo3J|5O<LUObVbe$E5<k%!^h|I+a(|0 zc<!7naz0;)>_XlpychBO1kVPZm+~i`TuXiqPmibc@)*y4Jfl20kMET8?9a1=C-f8D z!*K@ijPT^VEjE3}xtM1j&wT23M^2&rG4wlX+H)&LnP&*OM)PxL@~U5i$<Jv>E_oI_ zDQ$*cY2M@fUJ-RdPu44L#{2hEXRYd^UdPm@xgEp2+4@wM>RD-UsOymG;oZlfF#!&} zKM1_J30NEyE>Y((OKahkmByEWJjPWy%;$~&HZ<UkMoz{z0{YGw%f51R6|t{;xmhu@ zJ?HvC)@~YMj{?8JlLu%6K3X-H_GGWyBAU<dPcD7R=i`=F%^~lg_LgYBD++vkUiHG- zAHfGb=OpojvuTL5Bh}x}iC0l?dBcY<(YI3*M8hSc8op8L%Qxt-MOuf6d%i-M)4G>h zv2LbFHt_GJ9(v5!T2{IFl3Aqp!Bczn!@jahR&LpSuqJcQ3S+ZMIS0>`LtZ+>_r7nM z<dFpZcVBuH*+qV|E_)LtqGR%_q;F>=)9CkF`&;{AN++#EFiQ^vSGczhnkye8Xj`Tu z`Ob&t3=8Et^nLJ~`Gamd<!gJt30>$LooBOk$~N+mI{WCN5#Y|b(xDEpX=7jFY#{3p z-^Q&d%4Bwo&B}JgI$!F`>%Y`Fs7+Z|;@?w~nL1lIZ0x#<g$i8@;N-bKe}*}04}LdR zGj})t*67gWE#X{yu4Eqd1-K|ZKPXGSf1a%x+xzUCpCKRRUO&jlC9?nIOI`pbVc?$s zul{@9N}h?*cf$C=wb3WZaz(zKptyi>cIZrJFwQ`~!k%mO)n6QhwiGh9KK*}DvPyf) zY=e94;Bq(qvb0;F{r>{tt`{1zo4R#2w->j@W@SaY&-jZJbbUk?ZrGAIvo8C)_HK)j zvqck&c*^FcX9&GaxDsjH{+`BJz*Dp<kEhNZW&7B8?@8p{7soe#&)~Pg&*Y3h$d?`b zd~q1D<AwKrx?mr-cN4fTelq#ZKPsMIuJ-Zbf81XyJDXrlJ9B8eAoULL99XV>wL<N^ ztuep9px^mTe%`b3M`O;|?{lY~i(Xn;i{A8JethE}!e*Zne3ss%J<UYvZ}C+Z&G^#0 zd>>BSb~>#6VCHH$>Clw-{1_+3=KrNvC{y73wnKOM4tSfrC@=K+aaz}kwaI*G-=stK z@nBx#&DiUR!KpDP#^alKbxnPgSQG4x<$iR|cjeM9_Jn(Xr!n<eAL#glk7;e3H?M)d zQ|zyYog0ADzU;gzHt-txAly00(vau-u7}13&DFoJXuSKpIYHhhJ>B?7pLES3>w)yy zN!EbTgBK`f&3h5g`Qjw{J4JIu+;ZZ?P0Y^GTJ!rWW{z|hFnP}=O8+GK5z+jLUYYe& z=!6n?9jFEVTYb4){tU*xQRLf5inIrEPOO-7Xaf5?J`8qjV2vDZWL@y=v~;>n=f#<y zb#swJ*n66ig%N&xoOi#`&<unB&cYOTo@>5*8}z?DtTl&iKBPL6+>Oqfh)^cbiP*#V zH~)UsHr844=<nlifB1W|ZvqbrVz?$(GG_Om?pNQeZqY_Ochg6s=M@?Hfsd&_W}i-6 zCA}}ZuOhuqxVC*4@}RH#O+fdv@glcxVNJ_c*CD;#j@z7*w_~o#j@hjD$zuaL$(lE@ z9(u?8!Xk}XbtK<99d2xRudwmn_lkyp#&L#0_ZmmPSKN5zdnLo5e+_Rq`xo@QSJt?? zXQuImHMXr0E0BE)biP8iXy&>w_87mhE3ff?=bPAi*q%LS!~?P|)MRP`-`O?Nf54>@ zVsGmV*)ZObds&jN{43?*0~=Yx#0!BhwHSR5-s#WP^RH@OCsA0dc(3L3Az$~h@lBZa z^EdnNdCPf@{SozK-U%a1iZ6MBo92P%G0ltUHQy1p)9jg`Lu3}xUXgu9;O~Xd08jIj zXiVcLb7h(6FLv`<o~*eZ?TNK3EuaNE=%?mQwh8EbVXqx{Yj;iNi;s)Pf?H<Y)3$%U zt(SkHd;jaZSG|QjfwcqNjPDkGe~mU~dhVt-v`(mJe6q1Srn6dVn?7O_8?>P>9_<+H z-+iO~0{St*?CYN6AG>uf>$==?N&|aocJG5e%$9vZJP01B{zhag;5mh-<}FVDnhc#u zv#-Afnb-Z-8@0#K$R4zOhWvgGpBPVE5%%|Y<<Hl1Y-zQD`2=D+cFM+0J;i<LmFNB+ z_+QU4^77Qa%29s`-?>GUW#25bSv0yPGX{CtUC8)3mpuBc@u_ors*OyLGUfhvWt-+` z^dZVkrQAf`e}_-utdz#(+e;#{4O2HUJl-2&-kl*wDPw$(&nvT$GErM*Pil2$Li0H4 zc?>*bKFO={oFUJUe(b#T80k+iriB-1cM{(z-ZXOQka?78y+9f4%kO!%%<c4T{{_li zLYWD+Oeyi2_ny}WY;!|C$=tCH3~ZhSHsJB7J-{?3c#CJM-kQu8rUR=x$lIuOt+mH} zCGuU?KDqGr8NSJ*OdVwwX?;lk^+KO3)Ls(l+@WyR_|o!@zIk?zO{ea&)3jc)YsK2P zWK*N;(^@Zq@0w5NUz8naFn%m~oNvjO?m#*8n6sDLZ`P47J{|G<aK$EQr_Ods2TO^! z@|;VXe{<incYVHC=eae+v+P-{c^B@nXTOv7`hg!OgsV#T&$Pc+hkmkxJY);SqIho# zzl{xyzQD(?C=U3#+CGP$@5;)!RtDU1fH^6UAEoE)yNCLUME{jmw<j0-%D(la<=5?z zt!1BLs#zKE@}1%pTJyvD$brN9IicYfInMUAz5Da<kBDSm?Z@`U3ffW+y`Ku5pVoNg zdo!W$vlhJh-kin;XgqM%o}uRqf5GrLenV#?QSABj;Z@Oi&fM`%9O%bPI`Dq=a?$uT zX#;!g>CUG}o86RlJ|!MOU9)vIuO>5op0&*y+dAVcv1eTa9xydA%GpodeR;rKt#9GC zPivliB|X^5Yk0|<X!g?-GhF`m>Nm0+bouct?SI11{&MOQeP@3tQ*57w(D#V&mw9x2 z`W_KIKOi2N#Ze1KgKuk{f#9f>um2sLYM;5|kn$nM%NpKynedR`7xViPe$VE8px|ck z)7f`t({$&Or>W=ZLn{B9il#&4NnT~|NMiw)=6cSsQS=MHyU!l5{rSY-=+7s5`}1$h zJ?Gb_)Ry}1xA*Hs%!g>xe9tL6YV$%iZ??^2ZpvP@dAT<4cAE#CFMH1BU1alauz4x+ zo*?g1+B1G$wEr;keJSlNB=2DhhfD2u_xymeM$U8gkJXsjchh*AD0{oDXJF8Vt!FWL zH`qLLzXNStX7gIeyUgZU`2NQ!o41Vn_XG>|?GnGv|9HdZ0jKNUuz8=bdAn?0D|x$Y zp6&O4thae<$Xic+1?1cDzOsw{uS=yhm)AApTmFejrTw=f&tThi7qU;Jy(8JhSkD)E z*xT0VTk0_TM4t0XTHjK~2EMPhc|I+3Ub)}qZ6a@&&9gBlU#Yfvo5}m6%`@?osB@Uj zd){-d?Xr2r{y1OJSy{EWg}m2op0DFLd%JAjR`RxyCp_}+zH?p~wZ_Mzo#d^xdBbg; zgKge!@)p@Tjenl!>|JZ?+)LhU@-!dDSBie#ZsEF*ykP!E**b5qdHcx==HK|U@?9|h zuaS2d^^MUts+;z(DZO_<-(pYSZ~J0lz4tQP7hqi)%)f>8-eCR@k{8VX<$hoG2J_!W z-g-NRD{Nk~?dM_gnr+_aY~BMlubsRHY@VIJy%TNTG4dwbyg~N68*N?(c{h@$dAQQg z`_&5;)}7>CZu9KC|7wNJ>-L<Ivo`PZ_Pd15J44<fn`d$2SJVBxPKUfbHt%Zt-FTaa zoK~`tJmIdzmzVdX3@&x%k@vXGv-tAzMw^#U-aK2U#fg_s*g6Zyn`HC8;J5ek?`&R} zyb4=q)aFg{>wFJfDj7sxA6)ts7aJM611^=gHqYYH%SUV;xOB}C`tSQi16R*^`TkTx zXGCps)>vy(by|FR`5FJa&O*L>hCI!~XKY`F`Tcy4dAMeY{m$aj%MaQ1z@=**vUwJl zUcS@TSw!BQHqYYH%cJaf;L<gtY@WrXmj~PLipd*Hp60>g(w<R1Tslk0>u2*UPV5<M z^U6Hu>Z3N#&ikHzHm{t#S8bl1+ucWP-U#xZBd-rF*kkE`XOz4rY@VeBdoEi8EP-hi zc@Nt>JMX(s*}NEe_t-o;@4MfydE>|%Yx73<u-?7P=6U1|wRvB(dFyT71o8&hJc}>8 zn{8gL=L~(<<{7^{&)NNe&8s8tH{|ufrQI*sdDutZ3pUT<((V;D4_q3$!q#c&((cP` zoe}a9HZSJ)^Ot9B-W2kt+q|1>-XWVemAvuH>o}!ThIRGJ>A-SYigiX_spLR@&*XiO zFCSdGMe<)D8%Q1u<i0@OlZ{;ZpJYH^rhYa~9kaNv^mXiT(p}i6?wrGK;=gvz<+*D? zPv`svZ+6yCelm5X>@<}{{5g&@{3`tHUYJs{a<DV-UtQ#{7yfU3Wt-9G!tlO<iPHY_ zjSaZfSvL8@*l@<;Bp)%p-{x!x_wRMB9nAhaHt0#ExudUZ&YVS7pQ?UHFEKJ+%J~Fi zXAk6;!;s;M%^ha4u^`vUzDNHCs~me7I{Q#0nbYk3_U7A|Iq&QKpZ@YaK!2Wz?sJvS zN$?&E<i12oI{hc=fZ>|HFq96leY&qd1G|~PuB2CPekK}Q<sQb)k{jplX!#B@o>uKe zV#oe8zH?0#G5jxpMWWg(9~E=hue!)hl+;#WlPX~Ek~_iV|KUypKIli|S4p>)e2ML< ziWnJMYt}CH^da($y_$K7l2_0tZ;y?2Q(Va$P%dQViEpJl__|N%u+kQs2If4M0DJz7 zp9fETU9Nl%ohDB{GsKsFzH*vx3)EbX+~wqHZwVOJCcd=uS>|;(^~M?&?yQYYcft*e zp01Do<n!T%AO92^&6QnG&bR$0&zI4k9y)n8cRl0BDu0ytcQ`v7!4G8l2Azl6tUC04 zO=i#v#hRt=Jlc1a9*lAFBly|7KYc?!Ch^&?4{w~#UI*`!ADL1zsWf$E@{t;RYn*~f zrLp09zkX##{`J#<ZF|Kie1FjYP5cyMQ0ZO)#vmKB;&Fro55aBhcI+3a0Ny{HXMH-g z=casDwjb#g_;s_@=$5hHnQQBM02wcajQ0RItaAo4nWJ)^#O82WUnY%MN3PoauIzSv zU+&{>=P>fybY_+Q<TFRHWW|R+PF9@yedCqyO=X?sqL0lShD{!wY}SJ9?@e2<x--r< zc{;akVzQgPufdmHw*s5n$X^S0bbn((a+UVPoI1558Jm4^>22_v9hWr_O9fiOJ9?Y1 z&%sZ2OxGHN2JsH;*E&~|_8fHXYTqBI=(*&!)8RxFcP2LPm(6K|;=m+F?gfX7p75N( zefImfcg~C{BYTT*N9zu|(b@T?Kh{<n-D&a)ZQhjg^03*Q5UndAKR34OY_xBF@@o05 zb_6yEm$h61Eu7}>zYR>WmOsYFZsVMq%q6c<-s;c;<Nr<hs^*)GjmP*cOMjL<yBA;9 zjD^PdejLmda|!KdpJIj?Uy=1&j#$6tK5KW)0QG^m7iVZ+_U_&oo#42&`xf_}``NGs z9J4k<_HNMku}ySlZN2Oz)?~&`lC4jBg#LM}OewZTpRPa;w67>Urhf-XC+1e>dD8G9 zx#AgUfau~nei!)P_Pm=O<>XsDzYe^f37%g^ABw=`tNA^F=e0bi@*K*z=Tq-A-mfRE zma^AVR(g+g`YGh8{JrGKe=HuK`JwJi0Dn09JhMB>b6mX9#BJsGY4veLyz$iUd2(0h z=YGtySkL&(%YPqlG=65{St-xCQa<Uv4TkY~PQg*(9k7M2=Pgs--=$dJr0EH)_x6Rg z^5K^OyzL#~|1^OZf@PJQo2vX7>+sFY?giUB7m7Akruf5FEV_Zb*g5&LMPE#Oam#SU zgk}AW5UpwW;Qxf<32%7nC!+0_Tl+10YM+I6={(evJ7q(P@cmYN{4W(v1om6_y$Rog zGw_gnc*p^B&&Q42^HKWGy>XuyV@)QabHat1Pu}GtTEe@NV*T@bTRiEEn4FOxu)DWU z`ue~>cve#IayRwKYo-qQzXf%0&l+*jXLQ%rCFQ^Erj%!K9{cp_6T!Q97J1lDSHF?W zT!Fpb8G(Ie;d$kEU7$SvbXS10nK|c`ec}RT)AH3$wmDZ%&KSS$j`O~met~ap@8jz| z^StsmT%i1*-ZqS{_~LWFfe118@U?-xV_wDCdi=@pA@}=ce8}tgE?09Q8kgE8z2d)K z&^N$X@y>i(y3V{2H<sVby`jeiN&l{s5akxLK9!D~M?6LUJzucZyuvFDok<@3^}~L< zSM~foG7e>{$itV6dsm>r0lv~sxs|WVDN}CSk#9;d_^j^=gR;D{|7mDf9#41j0M4;Y z**{U|MPq5>lOh{#zVec9`TpjtwWt^Br@ii8f80Y^*{M$Fa*Us5Hb%wMow7Hxes#8= zbrd!+MLAOp4-0jtI7?$;&7Q)OhZw(!RnDC_2g#G(V`L+E9cKfd+(mv)BkA%DXRHy* z^pT&QTx<3skf+%LE)|`lOaV_|=pJCa2k6J*!2aerm+wj6cmACqoh_7W@n!Y$U_DC? zUq*U8J{G#`Lwo2-TTa>;(yk&+_ZUS?d-M@{hzt+y{fUve%P8AQdnTr?=ag5_CnF1x zzJ_u|JlBzbqiuI~a+QBa9_brMAH=$BRi63|&kjd-$?jS{o%B4(Q<U3;>@kPuX3=yL zo6m_H@$0)oa$nHi^L%4;4&T3X{N?sc9Cq!_Eq<D7^m=m+ZjI*bjzRif@D}_<>nXc6 zwOo0~JN_7r4ytcF=k{%V+S|$aUNe0skG|WxMQ**s)+spdrp)F(Wg_?tAMKOBm;9FW zU~|`<VrxpSW&CCi(A)6WqF>PDCghk1F*c2!!_%ei{j3pmE%}vpz9#s2&SzgmE()jC z!vC;)*JQ%L*BM9t0h|8}d12*MrPx;xtlh!#aaFze^>!YljvM)gIsR-~e1&&>W;KVO z9c1cm=xif4DLzh}hxtuk2aci~@WMZur_r-w+J8A)$C|?L*_Dq+TcDTh7z^+4_k)WS z-+^!JeZXthP)7;znsTkryv`$io&1X!XZ_>VS)cu5MphvPU3zq9r{X!N&Bl9s;^}I5 zrad1(UD5Q_$hf3Y4{_R!&3r#T9J#^SMbB+GYv)t(2wZ$Ba=(NRKe48O!})vqZl0BK zvVJfXj5EIBI^DGr3C5%|dA@%7)N9P!-uNr{Q?zk^3_b_+13B6$gExK)T#NYqGU;Dq zjI1M*rdXLRyz891aG}6{ultOP6wj*pmMknb-$*QP_K(90Utz4bWXIYzZIP4Gy>rl+ zf${Z~=4>I~Lu-<QDvHo!v=5f%jLvk;^<`uIXJJCH)!Cv%k<K3(UU1$%zatvCMSCB? zoKl|?e{_i85VLTY03O@D{?+^F-!$oK{EYy|3v_>*p?_<g2r(4%_$wzbN}l4OlvmPE zeph*J{WGMQv(Lb7COBt&h*BFRBZUuHel$Vjj2~f)+N0RT{g!-R;qXVlm}5V_8|#NL z7V_OB|M@w&Y-+uqQG2B84nEJ&6*p6M{#>7rxBeWjYG;ni`{EgMSBAVPAF}DZ7wMi~ z;k3p}d!qY!27jSBif!fNZkJ>-t+hI>CE+4_KZ@h3^PgU-p({7K=BhI)>p7o3O1TjW zt=|Xb9<n$bPOZdF!P++Q9h^_^l8;cb)x<)5O|qofvv7N2vI~gTQ4jl&W^ZxUIcs!! zR+cOlKa##sc|YS=;|!?$ez0C!bsj7?wYsyTCNs?S_rfyIr-$&Z_OI-jKAnjT{EXEH z;uY=gv!}S%;7*=B&jrp{{HZecGN2C_TR;q$Ft<L;TNkFjZ(!NN`k4V<#8^)=G#-Al zj@&lJrL`qJR%>oPX`-dN$IbXR^LtaG`YX^&AGhT5Oxkj#!H-?q(p*VL2+GGz9(^D^ zk3PBhM7ao@!8xM(FFk_Jo_1$08pJxJ5bdHf=q{GbLFSJ&_Ng2C$YRjlAH6CWNH`3h z7&%xt0*saSoZwD1(<tL=-YHX{Gq=>0&wJCTB4Rg`=KL%%rv2F<c2#1`J7J4^qUR=_ zhWz=crwyD4@oj;T5wJ0N&L`LUF|)AKF<-Qs%i7~Upv)O`%XhIi<q8+gT&leLech*; zmu%z|g7mP4t}t~Bpzc{(e?d9T_upRwe4JqYB?6uaz3y4VcaiAM+$&Sty9!f1oyStZ zn0hXwo}%<kew+A3r?@YTHIBI6&{c#!B>z{fj}nWoW^Op&xEcIkN15WPl<>LWRp70? z&?tM|vWIn?gI~L{yvOcYKUqwjW!E=3(={fZU+0Oe>rCN0SG**+2LavY;E45_W2bh} zEzI#i=D5k|h0+xcVhe*0ca^{o<%>`df12~-yR{d7@%@4$X~i{}YY*`>@gb<MQ{M^4 zc;C&t;u|ver#I8@tQ~L1VCKi?mou|#u_#!BE9O#PiROxVlaGMUGmFGC-NondOq~Z` z<rEQjShQ%A_L)8R(Ib|2Ko{YsV;EO;mWOPjPp>hiGT%Sh;apy4r)*Ar`7HD=!gsQH zg(S=R<3a9Q4Nhn;dnj^~``sr3y^VIdWluA<w4^uOzmsI(iR8+5CwbQuVPJ9C-?NWQ ztcbB6y_0o_d?K5GY+B$xI&+taKj1l^c!T;{Cwatn%wVU*SMl-wtjQ*1)&bxjbeQ@& zG>^+);e5qo?Sl1d$!6~D#ZI?kKqdoD2mDC;Es^9k$Z~!7(bBY2zH~Z1nuZ^Jdys56 z@XJZ*vDl-SSJt`KW`Nrx1S|Lx^Zkjj<O^r>gtN@;G|%ncDcTFnviJf1$`{C-a}~ZO zn*P?=)}Pc1{x5;U@^6XKZ)*$am92L5$|3O7{Fbz_54k?w{K>fV=&mT^fS()w8cu)S z$;FPFlK)vCTk5`D`kiCv5nGKTT`pHX3&?b{_3qR0ZplL*u~CVh#T!i=9lOSUychk( z#77oy1*azZc>cj&zTe+Bz9jNPiEv$Yh!(YQAEMv)A1_R;?m`||QK~xpzGP&3Dktuw zY-QQ?vi%VIvcY<h&L$a?@q(Y?s{=*bZJn_Ne>UrK6Zj%N61`4O@sTFON5nHCygx`@ zIZyGCEu_`?bM7wZUF(hccNbH?q0^+rBtyzZF8gLp=IVE06YJoWy*l45vNbGzReKwh zFR^ua>R&|+TkU{5!ihV-!aXfME`zhvlEkPp^`>3<Lg!YB2HothRoX8}Ui<6%L`4K2 zvdnJr5uLxR$@G7Y_3Bhy1^!|0WgJtCOt^+K<<hryq2E3#I`Gf{6AvUs>=mCz$D%uP zerRZPvw_iE;6F}t;<-Or&-ycdT;RhZ`rjlyjkpiGJH3E2Jh{lg&_O4UyR1vB3@W}> zOMAqty6TMQ&R@YC%MUA9H)`*vL3{9pcIc+oPE2)EuUTu+Rp23V5HjqMmW1JjUKDyp zKVAe+MPt!bx{CZW69adVb`H<z<*z@Oh+d`m-SoMqjWxL6U!PqOaH*}YY};4v^YLbB zN9?EA9M%|mJ2g@DPB^*aFZIpr1+ivEiBHpyagv#m3nR5g_nX@NY%(spV9t`t9mr%) zMi^6Ouk{xaO?uwQoled?XdQKA)@hCT@>*vLeL4`x+B@7V4=Xb?kyt9+(Och(*Gs3- ze(Uv5U6p~(<X5IlKi6sh$hKkhQ`%???9t%NB}RVJp7E&Pn(-tDMQW+1s1kjE=LGC} zzY`rc{;1pwZt8n#uM@B5Ebyvs?rXvR3rv|Sv*)m4OeVuzOvvh5&VU=J$HXtCE^BMg z%uEumlJ;jY-V&cDy{B{j*}cHNI)xAaAI+7VFwZk|t1h756)_15W==n%Pl&EZ+kBk@ z+|1{X*dTKz@@=47lt5D@Zxl!Iw+2^>z=_8-UcoT>HDmjQj<c4~5r|otZ|OL8_nz~7 z@?5Lmy5U}*yd^ss<1ibmhIox#+IwOxEz{m#-tx8bW$CK3eqrd&;Zx9Pb5?w8tMw~Q zi~gRzEQr-1UtjI%hzD?|dV%r5c26q)U9Vr_+N>OZUOdGm$SggpG(P6b>{Dr9(qqd{ zw3jjZJ^=1X*_wNCZ*5jS$DTdJ`mnbgrY`(rjjmE;$ABF3=)1r-&)h8mueJ61`||FI zz3I>6UpvElR{aln9&L3nw<fk1^KRhS8yBEup>Rvz31;|@n)`L*Gq~@pmluA7AHhQ` zA8Ls*2P+s`LDLLqg?qwNd)akm+v`(4FC7BUkSE}e>@Q^GzgR^3vi%!8Cv6mI`RWU? zL7r9Jp4-v!@%8>AGV9sFzP{vCY2Q_JiaK=%wf5a~2XzTg-90TiS9eiIW)E@d`p8g$ zOriF~|1LP^{(AYxSR?eR@lQ^!)(vMBza`mP>qU1Gvmf|`=6fk+mQsfLr2A&!A{{iC zi(c6LumhNsNmihLgRM+9HHuxzbNW>SlL&rG@3Q8!rlc!ClXBnC8WcZBttQCL8s~o_ z+x5}Y=RIN88)LRSXeRl@XziMn>gk%|>j}B<Y7ByNR!4A;Yy2JYS@8NiUv|<tmY{yx z?013w!zcWHc<wy;AOOeX(Z1vU=r@md2XikPFIoWJzs~qrmy6!@>-cLYb?lUU74(Jk z4}ooHoNUA9>^nB(_?gQ3B}0)(V*IuFGRer@nV!lwAK%<~CHLDaE*tAdvR+M3<~PZw zHanH<*|FzRn_PkX+Uj`bK2^!stEz{awRS)897X3_IYU&rSN9XpM`y5Tu=YTqgL%n| ze#tuj`U=I%<&6KD)SJlL($%dF=($C=TfH!xzPD?R+EAT|d#Z=)U3kM-jX#Leh=tb1 zm_LGl&<Dkev^Jo{JHZzdn^dwcadJY)SuN-d0sV~xHUg~+<O1nna|L6`FWjZwG<hR7 z{CBE{vla?SL#{XbZqga+(pM1=aUl4ucn$YCB}=Mh)50#}=M|BcZ{Le~FG%0pQ?Ig= zgC}R@^9W<ny(8*dOt?@t1HHoH)JO5*2kor;rbKCEI58s1g8oyV+28c(vheCy+y6tI z=vdi0OFpJf`F4kHUuE_J|GR$T7w^|8xtzWh1@-zkdo1=puj?`PJkF`B_}sew(g~ak z&AcHO-_Bb8_%-#|I_5z-i0*`k#`Z{_WbR(9@cZ_cb^nj`)ty&gv#swkTVI{(lf3;u z=v!W&y294?Uv@cL=N7x>|Kj}5>ui4hZ`7Ig`?<yJ>3i-wn~*Cu_u`)G`8thT*OGS2 zTGqPdExX(iEr;Cb64$L-GT4nR8S9QS^d4GL`DXJR+VSI15<@_;g!;c?u*(@C?dQ0I zDh9h#_|DuN%X>+5txKFmx7c$V?+o-W_**Icg5J7Dj-_8=`nA7Lzl^@t;<_UO8dmvc z(`x}dSgR$HSES=f-ZA&*xeHG9*5C7rt-svJrtZ<_KOSG2=A*-AV*^pY)_GN*v6jPI ze*->?Kf~M3$~LOKL}Cba&4qTk;HHTmBzOx?eY`kYrFH{3Bv|Xcvd5!m^!-b_KB9Yf zP^a@T-|Y^*gVyxb*|YpLXiG3TS8sl_1xwp(Ll6C!kJ4`n(l?{q9j&bxy8yd};alxK z|2vOPQJ?6qm3<zKvA)8@0gqvO7JZ9Smvno{_JTu*xqiUfn+sEXr}@x$<9XbzJ6Jwe zr*(!5zK1^Hw&w${Ub_Rf2H~fT=kME$(Ys~e_GOUo??dLTuj%PNBK))S(?nWayodBx zg`+lIx@O9zzhKj*(9a3hZeDU7Itl!b*qTm=xgBAAo3OjEHc$C`{Z7?`v&?<HIzL&C z{IO8_F0zjNZHk1eJR`Ij0#~I=gy4nifI&NB^nFg<w+oqD;fv&?LecY&$IV6T!FDwf zcd|<~QoL6-70C*uFD6~KD!sQLCm}PO8O-}K()ZZ%xqZqnCtZE*Q=YRs4PC9Ia|X-Q zpVz1S8qyQzmEYy#$DgOs?_U0#&gzeaf&(@OYY$n3Ts?YE8hMm@y!3#~KKwZLS@~By zS7XUj%mC6t`VCGMaQ<2MTovdpI@X-#MCBsz85?&bvqfp-nHZ|Vxth!ey8kjHnS=K| zrY<W}`SbL_bIj!v+&8p_`)Zoh&v<M1@OYwoxDUH`FQHDw#wN~Ord@N$SdEPUxiDmG z$L<j`ZsAWruXIjhM<1QY$IXS<ATpbD<~I4(J7MH2gZt4G->rA{*Yv#q0Qpmd_hw8_ zdH9YQ8Fh2^H#Q^HA)GbmW9f_M9zJYnO70cmZ2O{v)Elh%-u2nI4jE@k%Qq$K^lU~( zk<7D6ziWEBET1_nz4(Ij=#QguN@GvgR@q`X`<pwt)fpL|(N<ge^rgoYBfD~22eQ<q z8P>jN<}~3oFg~R6I^!(6KJ&&oPR5++d4+g>@<EK*axa>4)sb3w=cVYxMd>TMHUn$X z(%f_&u$mRAC2dQ~EThi|hf4Gf@w{s_=QG%g;w*74^l*#p$H{HAwdU-qfz?~*(0%F2 zABE8Z?z{<&NZp^|?uf3f6+<)Kb>GC^bJ)qNo6)~VHnU_?)Jg4ia_e4pM$-4Gn)}2p z#MF^a(J#}TDDi3&x7`#bmQfyOzw=Ez>~{QGG0-g;K;N$H+DhCZbjz+ysaNRZW97`X zyOZC~8#z4F1D|#`tKJscLAMahMx@qfx`mgCp{oDdF!tZP<f0;@TSEu(TNd%R&cI!J zxNdyI7s9FaPVU@w$gvBcYsBeJ-1Y_alY4r)wlapi=pyR)ev#@gL{A9wSJ3hb^}IqJ zbpYQm<??}j9(~DQauNHA)Dw&)Q9ThqS2y>%$GETspDvAU(rxWM=u~dv*3ZnHbXz1E z|5dbH@Je`hgyX-etZ!)t1_Mn$w@&hY-he$cmv0Lu-TIsD(YFoHm_S-M+V0#94#arp zZery>J(~P)(WkQOnp~UqgC5epOIqZ*rhawwxq-6zlWv`_y5bsV-Jj{ho-c&c^gY>B zuCbO^#DLG+#HzkETAm(H-)<!i^1z$xTaNhl8I4zEp(o)K{jGc3;hvqS{5jj1oP6*x zpSjE<?oS?bskkP{;D@HNc6#j?gR^!Kdj>A0ySS!kJ)_SWn4^Q5^=*HPSAx?QnX{9$ z)mizLb1^jNGr%D{IfL!^Dfff1+nhSan+Lsu9&~M;{7!pMqV#ka+{w4=D^f888Da+U z=Act%FKxTi2~W>Y=YV%Zu$^iQ%)z8mhuGY1)#Rf;PpTeh?KJ!m&3sIL=QoNsB_2M3 zv@rXZ{(Ln1^D+6Ir$>|T&quRAACuqtK@VyEd^Go~1I}hXCciUZb;S*SR7awTlG{vw zsk@dw<xa|jj$~rB;Fi{XKJkdO&r~H`gASI^=Y0AvcnkJ<i6J+IS>L$<ZSb7jeT>(R zKeL&(T(y;&g)9M{CmS`F?ktU6V~%IMpsn)6kkjF5??5}yKbgz$(zk$5N$)xk?TH_) zAYMc6EcJ(V5azEyvO!{qIdflsU9-Xe*rZa6``3W`rM<Wx;C&+Rws5+HapW)#=BR}^ zgO-U_?weH7XDwXw->ijeF0dA^`5SBDn*U}k6xp?K4QpX2YvCH!!hru~Ei~J;0PZu6 ze8!W<IPw{f?j3Lw)vT=nUb*IgwM1;g7;zlkSYl{Qe*KY2w>cvxm2$T#v2_wx$0TQV zVt?5>X&kt5%U9~-k8+1Rd@Oap(a{&DXE1Mn?~F`bHKq3YCW9ly88{u*oC&WrXA9o~ zF9wVqzT{T=@eX)?FLd@=Xc}h-XeW<(G`KT;pwCYb$6Be&;8$YEUFYDF@NH2ae534K zAHPaix0(6!kBL6*<jviS+`k|*Rq@N`jn_M|u5V>bw|VvSBbRxNL^ou*#k+*l$)*zU zFmoW?UwD{T<-^6;;Y4eS;{Tz&T;ac;FWAHu^c+KG?9f_==jJuyTQvC*U@_)EEp+2j z;JTTyZWjMYR{bHIz74)E8uJ*o+cCF=E2|4GoqU&bHFPhpvO4hD`rvl)UhVa=F6xqv zdt=BXhMpu_#iL#H`K~R=ReMcr+r(XWgn^%>SzTL`-}^&&2ImxLCvWL&GtM^VdNZ`r zx&BeZ)AN^ZFfv|2vZ5V+^&jT@2mhJaVMV|kU1Kn`Q@)bPdwv_{-s{@RyDrVBpUG<W z28>_X`y16q;PSls5>LSU>4W;BJzVuiFqv_eY*C&ApU+#$z7XZ>u3IU%Fc<Vsw4Sn> zi#h2k_Ou=$E^5r_2MnW}KkZT3B=MJ*ke2{{D$5@+Akkfj(Sz*xs@ey}8w6Lyh0?r{ zFM5Ow)wS*;Y4l5N^JnNyVhr?#xr(hiT_n7m(eAj@**8vo6BxY3{nR<!p8?KtFJ3M_ z^Lg--67F#9hM#;y|3RKBHs_V_??xsIRlfP~KEVOmGOsbAeX3Ilvq#eE7#Tu3A28WK zEY|MS)0s2LRi0C~-pDTD$+O{Wi##(H-Mt=Nk5Ba?rx@7H<oW63(GPW2VjS<E)4b{4 zKJ`&NwgR~en3k|dQB0cpu6S=s*WOeCzx5a9cLaDlny&!1<Qv<+<kXs;zs%#e_?h%% zs~7zt_d;XWSj_kvhdk_$y?(#!c+qJF*Uq4`aSyPG_4qJ#9^<$0!0<}odU546bcsg8 zPxI=S|7emua^m>ZWV)+;TX|+nV#tR-u6!CfuJjZ!Ym6VttjedfmYn@bV%>mi(aKix zN43d!-_)OMJsnPSuV8XpTdnv@Vw6`q{aWZ?)otM=Q=Qztyh`PScgbxv^-IlsNT=+Y z%^3n8S1JQs!LE_`Ls)nMjWu}Tm*HE^?<_TQ-E~7WVekc?rvv-Xkw08;OZu`8voiF4 z3$yRG3TBnS9-dZWbt!c3561g@#ks`obuLa33$601OgDJ@8NsdYG&ln+Csh(ZK=&QD z=A?wniRf>`lIK_xqG5#^EA+i8QGJJKQSLna2%(E}m98?P{mE;8D>*b4{Uh{f1-!Y{ znIasPJvkYHws23B;`A;Zz?zN%zcChO8h0{thCR-?);?WCz4=;e;8s5C5u6Mi6TS&w z=l)r3yPb_Y%s9{ocGjlO`tlrfuSoq#UIV?UF!Fn6MWy<~oVU8U(VsJ)oFCHJ4y}nr zQ_XreJOrF-G3%rGEv=7P=pc^P$dXa4dDaI{&LzNiM&TcoG3!M4|K^#sLK^S+lu_Iy zm5ESBYo>_w0@CH{qBy`2-V4buA}?3I)>=b6MW6IrW7Zn<?>Lv9+ta>6Ff{Wr%7>$1 zvJ^UWKJEagG7H1VM`1{vf{VWg@VtQqdS@0EeRw0|Y!WPh!%X^pK{$Y;0UTnKxgZ=U z6TqQRaNu{*`LIy^tObW>uGWO=;wc!MF?xQ_+svNR!QIvmgUk3eo~5qLnTn}gTviHB zM&UP)867m-Sd}?5xdL3Q_-&YPwrGr+XU4P4j;D8Ct8AO_2s5u$tU2J%cjo?LGq0r4 zpM3a;=wLxb6@T}cc`YGb?-BAe_hFu4@*{lD-LCAd5Qj}X1f4?sCD-VQw`J$o_&V0~ z{CS(~Wt{gK#dmX)cXE%+pkLM}G~f3)xuQkPL3Gk>{d+_=l8=0)UNmSabYjWP@HS*s z@fNMaKyK!2*a_+?(l^O#zfzwZ1)rv_H1~HHy2G=QH7|bT@0-6Sdq+oEzg~OCc{()w z=)n=<@4!TMvqIS$*(WpSxjgrqqtJPdwaoTyqK0m}uN710X3E3@8wPb6TeN7GY`U6T z=zg6~^S|9z({p5_*0;X5d%>|K=v$t9?+w6LcA8rDZ0oaonePAHseV`OMAkjehDp8V zUcu;7z8%805jXb<xc6R0ee(5#Pn=WVTxevK<vV#g=e7vA`aU+9&c90;JKjflxAwCQ z|B}C}?gH~|m%!}X(BI5+$)_Tc!)hz;abnsBOO)1fhb%rn+weC!n)9<Il|Ef#&ccfZ zG0r^VzoI)ON^eq3#SZmD`$>tL@$I?xHsQ7LlQ7@GTfsZ_q<_0Xu(%K${ISoQpK9pB zKJ(@w!B}<(@Hu<V)N}uT(%wHl>gvk>f4@V32}T?=_7mHHg9MvkgwUd$kbt3r9SC-V zO$t`ju!I)6unQmYv$4)F6M_~j?I$R@XoDsd{D5nB;alCsl^?N1gce<F(PE2htf1hc z#a)G<koi7e_uk1&Fe-iQAM?2HdB5+EbI(2Z+;h)4_uRR6NZ&4;Sbu=u)_+cY@>$$Z zeXF|bO4Gw7z*yqiTO@hF<uUhdNBnuG8ZTo`z`vr)BGqObpr?rc(r4Mf!RNwF)Omn5 z2UjGrQ*~yXDV*1qQP(<rXg<$YqdI3+b-g)S<!FClZ+&)at-06I;&Ndra1gWftq0LX zbckL=%MpLN?le<9Mf5*EevkGQoX2P~JVo<V`(5kz*OEM>Ipk>Sxb%ykK6Zb%h4$Lf zT^)j+Hrh7!?KH4{cDV%Qq(47Gxkawr%5x|eq1;Z&X^-OUY5Qu<p<Ix1yD0~+PAVo9 zxY$=fx!v%AP<Q{FueQT$Mfi0uWbyj92b#8j_yKivT3znpGM-Pn=PQ@Ty#n-$x+AlJ z=fP@2XPbB)!t<4qb9la#=Nrv^N^>~#qx&OufBljZ=qwK%CC#?=9eOQ6oJZ;#1Wy3& z69M=BIi7QQm*@UJm3h7ixe5PRZ>4y4)59NrARTzqEhm`gAMcU>X4Ci+dFBl2k`wu~ zCwX;77+Z+)tG+NgWb$t7KCf@~M2Dv73<Wl)yIfmpLuZ4{9Oc|iuHsFp40R5dkA8eD zvKr@7z;QU@zqk$@r}ewakBkUUDlk3+@LP-D1=@$|ZWXJGq7Bo>uGfuEm7&$Rk-4>I zo0z)v7nv}*PdaScLO1=Q^?mtFx?3QhB<S@7<CUCe>EK1|fAFWzEH{52<)GISA<DTq z`NF|-D7S`k(CZ28c3r1zdoKtlpVwX;<)GISMU-<kj~C`^jxLz|W#VLC@@;tJXZd!( zKjs%i{Dpl}Yf{bZKm|B9_A$+E2TQ)5(KSR;`R2mY-Q3>*Z%nUW_zJtRn<@WOol(lT zZ=3f1W-I!f2<xJ;$FBM^^2JbOkRrxuZPtdSb&Rc{o2(Z4Rbp*nubDgEE0<<%!EdpU zAF^jwO;cRHd5kk_cN1&3^6IP`G+G4B7NAaiR(u<}$h-$z-;i<6AMU;tshoH`bDa79 z*Q2Rl{7-u_Xh*y+s~Y+ij?d^DX`A{id5RQy!mmePna!E7BIaIcRq~Aq@YI~DuJ?-Z z4J~R)dYh1iGRFiz?i2W-bvy@Mo}jHwrk}}^W-S6<eGl_}J>Ng%do%S7sOoz6Rh#eQ zMWY@ub88IwD##ae<&DkIm9OMI{`bibC|^y!iTtmnp7W?@)e2;I<_2fTy#k&GyK@vl zo^=*dXIsr3=h!}Pmi?Ua5z5b_zW=8DH0fvA14zCpl>AK_?OK-^v#HE?<Lkz^0C67* zNpnd<q`HGVpL;+H;>+J`Ab+2-N{=~xX<xI?O?XG}EiWP#Xx*w?*?UcZE^amF{N~br zbyf29`)Ow<vd=`#YhbK^-(1GC?p!LRZ|7Ha9eav6e;)a3$p19FLcWpmZ!e^6=H*G* z4`eSJNZu8KS$*KAyU>k)8+A#B)?Iud#mAS-qC4X#!`{@Mlfs7iq38p>*<yI@RP|dt zlGumP&S32D$!(PnpJ|5=>;+!wS)ju+^x=%oIcaT~5%Krn>yV*Knc()utO?CN`V{%M zN**IVu<k^(Ja8^+;)xkm$(LWX?fb^})6(v(w`=Z<>VppLyPOwz$U6wU`{bvq`0J9l zq{9-=G<P|A$By!SgYIbsm)g$-!tLk-l?PrOZVl4k_ZIQq=)N-E{hTrK%>7T-(4Og= zq1l;L$=BY8Mx-ZSOh0qcqYMW>8jm{Nqu2Zl&yUFd_8)^aHYr#n12Z;*$OoOiX6(Oa zY^YywQ<rcbV$ERQB#)3zCGAju-LpC874dh=-th?;*Wi<NBo#x|;_`bX#Gsj`^$uOf zUEu_{Z1paP{)&AHV;S+@y`42)=g{z(J5gVi+&@Qt0_Y6_jQ3pSsp>kg_P*2f!#uw_ zJUaWMJo#rkcvHTL=s}*B&wqN2Yjk66W$yy%JS|M$T@5VTBnz-#d>`7av@oILflo!e zV{d5Og@48@Ke3dyTD{7uu2-)*t4-Fr=V#Dn+V<0kOlQ~C63H&*k9u2Nn;~?|YZ#Z+ zYJ<5T`hQu^>_66pcX%7%c|W&%S0ii8uSy=wAx|A;Rx-ZLChzNBOE~GZM%NXI&Wn{F zTvfPwRx<~w*B|cQ7s4mB=eGS&+u$(%nEKf7V)dUn;`VpDn(4<U_68}r*7jk}48~|- zRq~IE%vdD<IFJ8}`9I69VY?*%rTur{Ek+N;*gM~oF`93#E@D8>eP4Kn7t9y@<sC*& zYKZuMYsQAYPt|+L&Gbur4WH(}z0#E_p>ILrotk;W9rA%jUvkqQi&-OdMmg7>r8zoJ z`>6OM9q4wFPXcFY#DA`($C&w+PN3hC=!4eZ-NINupLNt@y)^R=y-}s`A((*uD$5&? z-Itt*f^*Hkgkrr{C0}YQ|7mGz?@<qZxpnWRGVu)IZq(gL*}si!W%<OBXYD-Wer%oP zg<qt2foL$|y>q?h31cljy^K6z-mM@-p82o$6+eJ<c&beFSHE=g>z#`QGx=6hZh2Mm z)u&YdeQVJxJ~Ij*`V;0{e{>u7zH!cg@8VYx_pMpDkM7WYaIbdX<!0dZm%QuxuXU99 zbcS`-*o{m1zlQwR-*<}pe;#u4HaYK<n>%*Re>m9+Z&@h%;~vdy#$yBiCh7Pt88S|6 zY*j;4KCMaYQ(wB)(a&EWX#BE~aS9C&D>7@0SxeA`1e?}F_iLf8?ODext;(h#TFW|y ztWn50wHfqNdN;Fffa6@=rDYxXt)V^fXx1BOuMpki%Z~Oc&-w;m&rZcAFn9K*$Na`g zPS(ja_-e_jv2xCdi^Y$utn;B{inC-L?~s#qTB?!<YMb7$>pf%qD)<F=zkk>E>%Elx zB|2P3pJv+ke?H&As`ndsKhciM@6BF?=O<WG0?=TI;xO=klUrj7IFnInbv|>Z8JLm5 z`2Hk&k~g69<;1TJ!jEz}mm$8g)7+`f9k8(qXlN}q1$<m$!`~5IY>BTR{`T7B?i9YN zx_)<5=XQW+rI|<Gpz9^exOQeTmOgxctNI`wiA<yWnI+rglZpp~$P+-mDU28WrlG9T z`%c9BLUH3z{Bp1H>PbWJ?fE><<ymFbRtQ+yqwB7KzJD*Cs{ZV(O1`p@=Pf+%7OwgK zuJFt|`3@WT$H^%xGi0EIlYRD*f18ti6xX%@*z&8A@Aai!$v%!}crDafKpXosmngGB zeT(?Boor+I2fTk>Bl=yHm7Y@cNSXb-UkNPP_k9d~BPY2z6frbk-u+JU))?l)OeX`u z6V4PlnaSYN%1n8j$uKe#a3r@d_hv-=_LZvB?K3{Pc1mBx`e}4|3D0l#*)Ou+u>A4X z8CA(2)EYW#VVzuZ;s7!evAVS;ynH<{ne~RY+SF&Qqg7q6-EZl0$<x4RVl5e3^Zs;~ zeIGw6{~UY?XCm{qs6XO=Jh!^%T<(ugH1{a`=3R+xUTb14YhydSp0=uzfB(KoySBf^ z+HH8T#xmS$_ozBQ%YA}c2RekyZoR{-?tO6~el^~z%fWfV8>Y3=?6vHDH0-f%sf+m6 z_eHLe>{1%5IKbUbj2-^+>A7D!Su#X9_EK;xeXQiGlwT<F%8vYVY=7)0+rPOZ;!nNn zv)ixP^V#ihU!(TB`wsn@^_o4U)>_6|cWKbqo9h$XPaKT+f1^E_k&7y~YyWCw(2V|U z*ZQBPA+5o(LqR`=Zo1{Kn>nL&0{G|W7@yDtYq-|=!<rZ0dsllQXft0l$9;jP&ke?z z?Z9{lJ##ANMxM?v3C0JJZ^3(zJG2+9VLU|d)DQl*Y5#u?{hz7+AE9p3f9R;Ux+kAi zw{#%qQg?v5k5Ts|Gmm<&dw9>fw;nsUx^H@dx{sqvJ^C4S`)AcHIq)3dzNwnJKcMa( zTl*<{xnUN!@LosfX0Czftrh21=XXw1XD4-*eSV$K9HGv%+ztOVwC3(^aP%wxE9mz- z8>p9aopY^R&pd>FgPI$ThJ)~3L&t*M$|TP$J4cu!iR~vn>b~o<=f*SPbBFiFPU_^W z)ZEdg&U1qI-}Y1g?(Vrf)Zrt=zquz$>!0H1GZ!n;Jp9Hri6tikRmp#U-^@WPYx6(Z zS8dyM=%jQH`&c8<*_~t_{rhvkXLQ~0TO%hiZ|~w=zLC{=m%7`6_X~91M=?05i*@&8 zf%L7^(Wv-auKp1J7x9gC>)+?84#DDNeq{QtJ(4-4cWQe0WKnqs_0cc#myo|qavsm6 zl4XE1pRqJ{(ddfKf0FD^o{M?MUDmSiCJ(uGq#p=#50iA=n^Jh&{w#8qcouY|H62{l znEfm=w56pPb?9qe(4N}ra8Hh@O1}7%J4dYkmGWO_`SctHXXrOyyx+*>ZQd}uHhp}Q z`1Zr9l1J8>deC>07ah}!3tT?q3xWP)F!{jEk)LPet0dnfmrpUF@@<``Kg@t>B6)_M z1=Ao0Qv{g6>5Ig8IyqHks**2!*fZ}7hsm3ZoSI*ieEVWz)(*p0J4qarEM)6E)?w}` zG<Vw?`O(2*VrYY#&A@ya<yK_CTumFROg+T>sVyc3><Z-FwVV&P^7T;LhmS6y>`=9t zQMQJ%wHYudzCk7oI)5?I)noQN$f-7NKKoAkID_&RpVhy<8Mw%+O78v8!A87Y1DiRc z<?0N&F`GbLGcCUMKG(Cpz1mZ0yoFol$KLhP^7Ev7L+^jGu4(+q`uoe-W75~9T_=rB zW9fgKoNw=>pE+4;JLM(o=-gStwA*U;O%Z?AmD<}Gzo@R=#l}_vy_mZq{E4YG!_a`r z>74D7UB6I$W6a(4UC)20*kaPDyE22^TF|r1ThBlTA3tmAKz_2Y-6VZPgYzjeJkrQu zYm+mWJJsCvG_ePdoZ$2=Ey#=7^CM$PhS2%(C~}kbZ*~sV7A77(xv;A1`Kuf(A<b>g z@e1U(h+p|2xXYG~hkn$Ncd_mN^M)sZqfqK>x%z9$cwP5XMt09q@;iL(dfC-q^ojg_ zk?hDJ@q5VwlnYZXYTMam&Mx=f&Ra3cF~-=dkS(kn@zhlCu%?@bv|0T;{G*ilSpp8` zi(f^5n$msLz!OfnvGa{y$MLp0=mq`wO~av?MAMLy%b=I#cK^;9E%9d2h0#CUda>@d zlDt{fwQG>ZO=GMWwGsd8PDkQrr+E5OU|9+*zyyyyRqXKcB=lNn`kdU;&Hois1-P+U z%-ZbM;Ue_3I@cy0aDmo&CyNJl?z1YnNAz#|Vb_n4%F|AY)@s<}6)LXolAXUWvL*XB z_FHG3b8u8>4+xJgz$Z=mpfSK@&W_Qy!^#7{DW#1<`2R}M`J|j*^6E)flg=bvLs~=H zLORvP#@M|lwU$Ku?+h0nrPJr$Y|e}%JE=27`k`cV+N_~mkn*isUw97iysjtCZ*DWT z55_=s*>Sk}$7aqTyV`q6PHw15?#8BI<cPW4_f*hhUG}YvZPwuKHRT4cY5R!|@s@~R z_n~BZ{ItOT-%ZQlgHKSe_EcNoGn)igwBkJOraAc}w8EI~9t~Z3g71F(QN**#fx+r( zrXLplQMTUkn272%w4{7r(wv+5oXQ$LVeF01zo9xTzdJMBjX{O6F@EV+jQR7=>YK^K zyv45Fs5Z0~<I`2ZSn6I|kG;RfNwzL06B@ld>+b&-?7=&<j%nT1-lHvZ?@@gO9j))^ zB%k#mfc`h_-_c_~wOKMy@3L#pI#*L?&N<eZILA6!mp@3+`{%(~a&C40)iLV4<lNxg zbbvaKYwwxjLz2xheRM>#mjC|MYUE+|b2q=_#<f8EF^y%!zvcGm?EKD}*@|h~y;p@N zZEB$Yw7lKu#tVHev|OTf!qqK4x`ld7Ts-#i6P;eO2>GyG{L0L!XQj)%*~E1~r<vRI zhS7%``O)NouSfhFO$<KC;}*7m?seY-uQ7YobpO8jB=r2Dvm;2335W(&2R>BNRkJ7g z=MD5Ht*f5p<mEK|8C`X{U*DXI&(zCi-dVW<xo_vTo^rrWV^d*%O708reJy?7Y33SZ zp?(3^%^7v<CeIzJ1ODS=$DQ+l)yR&Tk9@z8I`$fzXwFg(bzEX}B%F_<EvHx7IhuT1 zd*-|8{fvD3)h_k9xJLgZ-N)`sdfDN46Z0>(Cx5!Wp1t#{jOzg>cOR@u{>td9;h_%h zUu{moP2Z6(f7NDqn&TnBJlKqf;cMT&LpTwy0e<+}uWm=L7!^Mg4}+g|z}F6Zl8=3B zu;XLWbBSkH8r-&mTiUUFZ2B3=E|Qbt@F}Bj$1j351}Tr>S(CK?_~3l=tapZg-SBLR zf1$r*KAhZQY3`;ujvwdKzXKV3ErASh(9pE2*N)A1Vi`C;B%D<xe|djK-;Q+mjqx>b z*QNOM4dc$Ce}jAP-!Dh^?BAK;J^MH9ja2{O&zZ8^8s<ZoI}^p{(z+Yy*YM-i{fv@d z(Bs%SUNwV$)35*9<6`oJ8Ao{4vp1&X4QzhzJHCY;_~dcE5yv(8-;PE;;6Ha>n>8|@ zw)1+l4gINYXfQLb4Ey*g2l11NNUlUyz1``K%w9=yAny)KUSaJF($+TGVo#s!qJOmU zk5AIZh7@nyE?I*%mQL{MqOW{aXPIZ}eh0~D#vkS+wuV90)*$->Z8yYbat2krio3p5 zcR94`V)*6~x7@z-%wDupbJxPu{-EY$Ro4rR!i{YGDSi%KPTM)&etR^kyWISVoICKz zTkH15A^!K_|0ILgLecTDHt{*yZ!WLkjF)J;>xJRwd$!hPd<ksqEAZawRV8<D|Ao0H zZn5FJt<aj0A8TILzJfg2aZ_%``|Q*4v+#oVU2N`p``fB6?y!Sr7<#j?-zAwr?VI-a z7V&F-ti8RJtEA`dgzxQ`7K#$*v1{*-xr35*Bx?ijbF~jqU3|YQ@s#z)Q2k@KdVP@v z?}{!qy41Yr?cTm6k334h_9E|O&6nKB^Mq8Jz`)&!ovC$EZ6c3ve@*4ccL{BFQf>_W zvHMeCPxYO0E7Ek?nMdA7DceT=?6ECgzv<uVH(vKPRCWEP+upTg&QF2)WJ<4CDm;w^ z58%r9wYa(mlIPWK-<{iyEi6brUvOYMT$2Gm{XN;&!r>>rJ*?k&Y&<3|!jjo)>%d*A z6WBhsJhC$%7^g)StAD>KgHC3Ev;Gz@zbWpn7kemcA-wmP(f7fd^TADlrLpaU41SVb z^92w40mb<Yu{N@{SIrYFmX~*is*>AQp>x@4&cJm2de5kPxf_LjE#F%++G3pl)A>hW zzquFM*{+ztorP)-*iTZ=TIk?pRoAbP>b-Ts8+!a~Y_@^exGD01FNxo6>_vsK%OB4p zmXpq-2<9SJ$9vRqBW1C9c9!Ta72B6>leDI@&IFgN7i~O!Kkx;B7k{8%UjmP=AN7Fe z-HZIm^W1wkn!W|@W8S*?ntz|2ufb8~-ovgZ>2DN1F~jow|2Km(-=!6G3C`%|S1Jxl z;;+3@XCwKvI1ccq>&5_Q=`-{XKh81Xp}oXVoaJ=l*zMstPQQMgCmG1e$dygoJ4=6f zh8SX;u?feCC&}Kfs%uM5c|5t-(XO*?dwESs=JO**pvB|?)}wYS+dL+p=QJ;O{1pD5 zikSnflUAxtx7XnwPHYqj4;|ERR)~LaF7Jq2TPtW=_bldH+&ng)x<BD3KwlIKLiLsc z$6apUSkib)XK9!i`1rPmIhz;eeA^g&(#LS_DcpRdd+#kit-Um~_?Y$u@(Hg<@oLE^ zDZg;qsgYl}ZEGUupE^r9pE`!~5c-9yy8d-=;^EFQ<Ox=F{mYzjp@gUW__X&~H54C# z@k#l`6_KtZEg?NXI)=1_RIm?^cz^dauvDAz@Yg4lYU~B0qk&J#jj|8Pm#B#!y4F;j zvSu4&61+?-jriqd&||>e7vglE=3b9d!&9AX3=FF@&dqn)IY|t!^N@GsFQB<mVfLG5 zz5BOu%roK5#Wz_e|Cfa+yrIjSYu4}<6Dw)8i4XO()5V-f>0+*34IQXn_Ai@`BJbW& z`7^H)+AFc^)>BVe-jM77uM^$7n0vREd|GEB<(2Y#cpCY)PrdRmX52|M`mkgt)=cMP z@|Drp$*Rl9E1Q^f#Ib89|C81s>dB3-c~kL`J#$wTYm)R3%**>tTP=NZovb}qaSiEr zm)T!(4j;ItO1~pqRCPURbo}s^iF(I4%z&1ltFmq2eui)_T&pbj%#F_Zg?uX1|7yi` zG_oLMsrtDi!2|bpA1i&QbO#T6ot#@%3{O3)T#YH$S8MMU`kz&A{02FTCLW|V$TNd6 zJ&4{UucH0&$17U*?ycMP_~Ui!_wJ32C@l+j08_hndCjg%yJ91X%I0#$6rAZCepW^6 z@#E25WAp0PA3v^q`tH7ESF|QQ`;7zQJ--ERAC7+-<@Da=4+`(mx5i?7>zvvACie83 zv2SvgfU`CMo~Lr|rldR}8|^QyBu^dx@h$tsP}ZB(=t;W3X^>RsGNp^r**ahAl$CQ% z9~SM<);juIulH5Sf91rXKZAT8_4>kRns!ecx&l9y!WZkpR8zkl7wy-A8lyPz8_82G z{~c1rZ#O>JjA=Entw;V0Dh@gPZ=JzAW1=<6%|GR7R9(O{7kJL+c_+TnCBgx9gp@bp zk2GsL?TeP@i|<t>|K$zxu4%lH!{{B4KVIf}UftV|Ki<f>;@IWkvWoV-d!yX7QuFqu zU3I${$Kj=AbKkb(M&7K7cE;`Pujke6I(}Sb^<Cq@b9O~L<7U1kO?<kHZ-Lt{XWaOv zGA@5G*8l5yIupmaeeFR4in(cZcH6FG?wfnxBYx`^=qrC{v6mGqo=og+Z{N@y?yQF9 z$|h%fQ7`+6Xh%&+Zhw?xo?lY)cHawY19g|j0_6?*7V~OL;G+TaTuHtGHlO$%zRr2( zeTert_C0ezajoUEQgnq<?En1F;(sBjbn;VywXn9>pGX=a&7M;nkc^zi^L2BI<@e|X z<`n09)TOf8&k>iv&$eyVmW1oN`R*CVcaIwy4)ly+43Bkd&v?a$ui(r`URjQB`W&mA zR8p2>`){AaLEA^Y59g<!i!$C9b-xD&?(!LV*se{FEEYb)^EeYEeAX3|<g(u|_?-QJ zx6hsJ_34)XW?SEF@`pvoiU+2$WjQxho3b4fyT>B&D=)w1o&F!;^L3$cQ1cFP3N$9b z?)sh9yA18#8<o^>@1S^@)*a^8?)Z0xx&7I=c6>%myNt&np7Vi0bw?h(#*0WV$UEr5 z!V=3E*F{B!hFR-4djyY;_*Wj)IkQnK<gb<#zhBvF9Uin1u(+5Nz>mw(l>Aq1U(z(S zXtGB<B=}98_Z8R1l^Jb3K^xBg)g_-Y?iIgs&evLKe`&IWZ%&WXwUPB$`^gIYX7b8L z+%(g+Gqsy`W08Gjl-Uxy8C?VL#9OZ~kqpC{vVeM>op<d@#w8zn)P>liD#|K3yE}#Z z2(drRDxToQA`#8oLO1Sae)JsolU*7k)#t`4Eq67h?IF-;ff+08idJ^1$YV`d!8&R0 zOP6m-g8iI@FQrE;(Kt<SS^6LGZTNB{<Jf+fxses|uaNHA%p>6f8fBl`vYYv;`w1>$ zyh|+HH`S<IPq=^IRXQ79Gy9StI4s4scfNEl$lnE;?`0!qgbY4I;M2|d+F^g+1%2-$ z9?n?x)wLr(b{ms-n0H^>FmLIo6~Q>~CSIWw*_r=!{O5jz;GLu;q(y>F<IM9K-hqEo zct~0CpTF#EgQ_!&Ji5<>`y#y({`;{J)ukwl&Vzn}I8FCsY-IBZ2zJhc7CE?p-|?~x z_!o`vLgdd^J<6*x4+68wAd{N1l5OjkWt>BL){bGC$BeB8r<R{4uJ4s+GA4}8h#M`> z_-Uo;tXY=z+mu|Esgt#|P<Hwp>+Eame8}iQIkTVau5&^+oF+b+)>~tPduUigyrrnr zwX=bJh2iD#j?*Q%m)iOIy<{KJ&`j<v6s_leFNwSaPNygP<TaM3@_%|?r?+%2iTK6y zQhP(@*S7RCegrL&gKW%cVzr0BhtbjR0A}!N<GCRV-o?3SLvxksIebk=*PkKNWbD?? zu%Z2q-r-2M*VU~j0FD*qb;t(^<Os<rMu*Wgbb3o}Mbk&Aex>p7_ea^|vPLVGRH{B= zMkJ|c!fkgVe=kjLO}$57Va|zIIj3tV;}VkGOAL99_mP@q@MgD8)h`Q#b~s*O_<(e2 z=+*3)gmX1VncHT*MH96p<%l}a5bI9S#hhsoEq`Jz-aaCzJ!7Gb1)to{cm+3CbnmC| zKa}3Z3*J7W5;-Dy1YV<fe(;Ai(t97dVwrcT;1gU1Ce{$<*i2x_7oTDd>Rzb)XZW6g zcd?hvSFAqjG50NokwGLsfrmT9vu3Z$5Ah!z$eDSLhYj8o?S@DDyVI`yBHB0W*^V~j zUr{2xWYe3U9FK6q8x(Gn9z8kD?g6}oZ9^p^WUpH^0yz{OFg@At`?HhzzWQ1gI=v*G zjD-1bbX?Lwy8M?dApfX)5=I`Moy-!wBVShPe_(dfm;CAG#q~z+;Co7Uh=1}w$o66Q zy6|QEL1ZUzIGEnj{KeF`;<GXDd&{bqicX@-jJ*~dovu~i4X^h9LH+N>|JNV!`htgU zeW#^~tBx@i3CTrfEF@1cHZ>~}L&Tfs6lW7-^@@hF0V%qeR8roWqM6}}xz<fjnQObF znbNOumj|@G-_c0nGqj)RImUS!FN=eej`o4YDI6G>!9%x>7J6}Thebb*cF^m0Ze$F5 zS>H~M)_8KJOLB_Edn<E(u;WLMCk%g$RrWsDDI;7Cpq=x<3**EcfPUf8bX}ib&XtMU z`88bofrW1V8JREMik#x$n7*z5nAsbA3(Kd-$Es)cHlO`v;j<3!uAbiIY4Sfn-f`*! zGT8vuzFbo2;!17#fv&x@JXIU$cln$^e{WWxPd6+oPhSSIX6BLV{6Fg|G7Nh(+qc5e z^v&qAu1T0!HiIqB(VZ|R&`Z5-FKFf73>h#sq64|f#Mwpu8+J5<UQSY{>OV{7SY6XS zryIR|=7Kr<0$z)p-;lW*hX0F!QFBgl5fp>m+4ZwJ?EB;~_S-*l&&D2EmHcm`OR7vH z(T`^tUuI}ZXU*U>A6uV$;&EA8&T0|w$@p$`#Pa!q4-6FC`1d@ys7SmcYoW`VO<m|r zKeFc;T9RAbd)*N~fcM6SggRQOBe!-$-|sJq7~WIZHo+TEJEi-79(|e*?ArU(gQxo1 z;=UtBamfb%3n)9l{?9f2NA{3xQ#opd`JbQuZt`pY8*=p-JrVUvH*e%DzDeHk@m-O8 zC_0c|Rt?X2<@ofQbuw|NB)7oMr`uL|iSpJyM>M9>*Z#f>zu3pV3J-{HI~t5{Bc{zZ zul}}sSo0Fx9olkf*D&sqqz%Q1$x=D$Euekv&z9i_ze?i+oi#W-^|L(s)XyD#eL!CV zZXZ#dflK)Ksg&-0A2#87>dRAJ@baGcIc?_iet^Rl@B964J66Vi%f6SmQ+D2HFC)Kr zLqj|#My>60#I+UVf0(rhebfiHJDBQ(8}`AL)-(1h#84Q)ent2mLz!&KOmJn4?EM*K za*V73UqHSQZp_$dOauqE;unl93O*^iga5ORtdiZo*S%a6IZb*)%ST6jfDU+F<B-ml zrY80`<FJVy;Ubi%H>h?*=xW_N6i+J7!;posDgJ83T8xc|RHMgXUVi;G*<++1i1^v} z3lH+AmYpc#ePeB6tEcla**Ys5pMx$iai%0X?@UR}#_PscZ`?VudgIrJRBvn_NI$Gh zO<a>k#VpC(EBB%&xTcjjdfV>)8F<VSzhG@HrQgUfmri4UmRmddy7AK{?;JU8^4Et< zo7_GSSsWc#@&I|Xc4y$||H|JxjU!|Px6T-zV(~L_AACW!VCn9Ti9UsM=0RW9%`s(_ zibEGErH!kB1K*hcdf$zy;fK(n@h_(A2HKtozwj&#pEzp9Y^m4W+Q#~3c?mJIvX|7Y zPk5Vn$C@_D<(Y3__lGP}``m4xq<!%@(Hi?2Ge>I3!#TGh@&{77*0j~?S6Ui5d5ZV! zZ-<z(5BA$vq1%&hxcm!%FDUs)ID%&zI+AP=@qcm%JRNVG$oM)r)5Lb+|0nksSFVHi zGKN-fVe}xqj3I4)CE^cmgH~D3ezN@R`W4%0Rqypr{0r)z;Odtgw6Dh=W>)uDkI`H= z`(^C0>HSN|A=3`A?9ANDShI+$^)JzJ=QZ4~I85-A_&o>8c(;Wy*4&o<KYJDL4Icmx z=3MQBl)ejH(5K>~V3o$o>IAzopAWO|i6cj?ZloU7ODvr&J#dU(KH~p)jQW`xqa72_ zPwqCh?J*ix&3jAJCEjQD4c`d)LzH)*ORY2OZ?)NrEW<XGJabC>gz3rL3ib*PHyQi( z5&gHU0!HRT!0c~y9ugWdcBN$3VCi7uKQ(vOZ(?kmEn#K1%zL(ss&TO}UlGZKIa78* zcAY4FAbfE(@qvv#E8g0>Ow>Bt`)0)dQn7G2`*HlkK8H?Q<I4ZVQ!am>bICuO`w1!Y z9JCO2y2hEaH>CAcy^X)%LI(VZaz8e7<LK^F`(fdl1rFI~{YbvCN0`&;xD6R{ej0}( zSaXgIb^Pgw(PeRmgr#qEggJH%Pb69Ae~AAj`~_OBwBIL{bnDkb>AbAjN9m_*dhnJ@ zUb6bJRGn$MfF2Uek6=o^qs&6`PDFR4aVssWOnyWhqHs@`CY8{>)$fJOzC*I0;x?!5 zk({XfiiOAi#Pws6_EgA{mrN2|+-)VjU4hNlZ&PMI-FqecSsr(fCmeRqonG-*wDWUl zP-}BOG*}@T5Z*L?v_IF;=iKQV`ga<9vX&zY_^IblrwRGX<lk}bG?9Njc_pW5{7j6u z>D%acCOsLNSs~kJdhPSO_gH4_GxkOF2GKvH&fk4`f7>uGqP2!T!soK?XhXlNGnniP z^gmzm2o)o9!rH7{>0!7ZJX^3(M*6`#<hdK%TD29NY+xNbu5}DJyT75kImowsyJj8r zMXSVQ*v-D&$>?XSoXtIB5$>XkcYfRuyXl?0yTam$-03pK%xS0FnN)I32w9=*?$*W` ztY_F$48AjTKIrw(5BmvAzyE8{*UD1+RmlqGE<7*((+>KWTmxL%L+Y%i#(8UbU7sVZ zJG?1w?Z(gI)LQq<+WpZT3+GDi@Fj2bm2M~Ee_^xj*T)y%raM-bCU;WjfzVnn9$hvx zShK8unAqEWQgu?_^*m3VzAm>y<+LVCo}i5JQDna3i}KN+=^FzTiosL!{mPLwvwt~0 zb}hXA2UR0ED=WAU*f!4$2M*1jEx^y5OCIBSYN{>j>W94Xn%ax5web>amSy8B(z!?N z*g8(FpFWSaj6Ie5fr<7fQ%^wagu~M&#;VzVJH45`l4NajmpOR{Lo-vUPj@onFO$qC zud~6VdByba2P$fdmyM5&{nkjeg-$HNJVmCxJJN$@dzIIQ8{0?uM#~T4t;f3e*wP^@ zJ}x@mK_;H<_|6TYnb_p&k%|f8?tjsl-z;>tx@)9zGc-@yhja>QKhmkBUm^V_{Tjn_ zDsL)}`F7hzqxVtS%FWCZQ<lDydYlow0op3L?eUPYyM1;&+0v<PEerXcs|VWRJZ&X( z9>SIi58ZsL_s!cL&(`-Ttht;Q^g=vWlR_WKm3k&!)?MaW%3SNp(68<?!)zIiC;h9Y zoZ$5ZFTZcuF+IG%tse{d)@S;*K6$H{6J?=*fsgqieURbBj`v0WC+*UP@bxXtJJGM3 zdkgt59(O)6uo)-82D}ky>q7P+KE6rd>EoeJey+58zkfxBvND?XHJgW;=iKSr{(1Z_ z+Pr}B2v)Vj_kNP=Ri~xBrVjX@><zcW*J`jK+)mraNb^XSkzQ2Ul2u45m?}wgD_i_S z<R@0Jzn}k#=?E_j!q0rp-vr?ySyQ2dE!ZJCtvsJq!GF%i2l0RMcT*<l$_(UxEAKC$ z40c&leh}|g^X@{%tCVyI|D%){LK*g|!F+w^e?D<W>q);@xz^+#j4livu0NM|*ORw^ zbTY7R0**fb2j`J|@zzTI|4jd>U;TK9`WBP-A<7WH-P&77W0Vy>?xb7^=^gyfqkM?x zm4cu2N4yJD$33(?gZe(;8C#4$hHq=gqxv7<oBGdwCb*S7KR6-fPICS~#s7BxKgIuC z;F?JtQ+fY1?+@_)Y5FMMrh0zIyZyZT9eMM}TVZkQb?|*J-(Ti?3*TR6-P+6dlntnz z@5|5$-6Q@;9(1;z^efu8X}_(#V>7Anv0SuInjp<4l`nB$Qq75eq;pC8lh%=HPcVZt zhg5S?_il?HoJU$onoAlcm42|4bRcOF=>??XMY4~`jx>lgNUHG;kY2P3{ikSEHYND% z$4Wm<hGEY<Kyn~*$>mm_4rvd-*qAv~sCmWuqH~S;t&e&?NX$m}hVE|R`sAM@-dCS8 z^STmwDaSit*HHE`mCTb&+c$89k2?FeHx8S(+w*wHivcTJK6tCQ8kpIuUvNfsp1mH= znUb=fU!T%9Y2H-3GTQ%&zvNrFDXq7h6$o|fD|?frD345j!3uCET><A^FNoQ?ob9oP zo+kTGw*FeHmpQxNlf8BeciPTOU6OMo7vv@4UXXS42f|;(`-+p@f(AY#&l~wGZq7cF zr+ZHg-wLv4OX<1`<+EhRYDjfcSLe#cTRIc8<E<KjP5qY6<+T-7KO?!k>HG56N$Y6h z&-@9U4e}U!FZeTlHqDC~$9J~Yj>sBPTlDoIwNsE227Ifbwy1p|^7FvhlxrJmi?16W zn_Sg^tn9_g-xvvvdFXkv8^?n4oFa>J`8b#}4NG=HYdy|@d{P%MxS2K+*jr2tQ)0pr zOTBY>V==nXDWR(syIJ=ea{qYlv>fy`Ip}M0+6RJ1>HJFYk7;dVA33d%Z-sm-Y#+$k zpEA1+8GF6vq`5;e;xEx2Xm_{#?sxBfE7JR)!P!mMa$e4yIXe9+{Sy5f+mq>|q30Qv zj_4;bS}M>-X<Q}0MpjgK_lO@#u5PO^Yr$mT6o0y&w8-eLQhWOz^yDo`(Ub9MOTKYc z;vj9`Et^7Ch<YDXpW*F!PXASD^QY%c?Et?rd^B97_tDmhlH9&_KGm<c`?F~4xRUVE zvd{j$EBRlviQdX@Npy8SQL~FX0iQ1&DL<_!abLfg$PQ75YnwLQoSieJe<Hlc`SrAq zDaq|;+g`krwTwMoZNT?rGhi$>pyO<x6Zl_xZeji#nu)g44_BsUSJpS{cR83lkomfO zguGvxzO_#(F)6lJ>i8gW8o$)Hk=cG|^j*Pml|TIREM&OYfa-8~ql2lnq#GY8_@nK> zpMrB;(5v5VU=7slc0NDwC+c7QDPs!nH)9%@Go{qCW8(Uf;Y(BhcB&tfO6E*CKhYaJ zWjPj~nK)Q1c%FCgJnv`Mzdgy&T(o0SNssY|2Kk?&zr3ccJg+r8rUlq%K#Tq0jrpdG zp<OR*=!SCel0^6*{B>iW$25=S<5fE%I5zPX&r`nb#lFGZgO-dh7P8RSz2qTe#MaiW z@cw8f@4xbCQ~zXZoBA|;1U!}f|A68ZmwJQP=UuqsR`24(>mG7^Vn}VEa%3z})xi5; z?Ue54i)xG82fFupu_^GK%dt03NqFI-H3lCsvxd~z{ek+F@GhV)esl$WqCfN{uXaQ} ze!ew5`s3bl-_9rcxX<BJe0pLUZ_e&U8=tavpijuTUU(6HEMG5aQ(fpSTEp$0H?P>c zXf%3R>kn5QF01sstBTQi{LI=<YQGU2+gN}<*V{LE(Id<^&Et0F>=C<0MmwNaHy5s= z9_?e<AMSPV_J_YTz$0=<7xE6C<4JE)@5bsabjrvHR~DQ9*sFl?9sXa^hAj&Ha<I1e z_3br}pWIG4$uyE5vWWd7ANWws`u_h?TMTW`zu0iun!UHsKU3co+g$tNf7rc{N&LX1 zrnpz3y{LR%i5qA3=#>v&w9xp#GDc4R#?JNUHnUg2W@hggzi28x9<m+Ezj!Xs;=l5@ z0gqOXetV&J9y~=dQ)Msp8QVPj#wY1l?xJGuS+aSVBW$#+T}1Mk`o{(3*sN%S_RPB6 zc#~Ix-t?nYq~ysJFQ@H-6*qbRfKEwkPSEB-_e>t)O8<GDPu&IB;Bu)CJ;U&kDc&ai zHt%E`qK!U@rfa;4rc0ci+1pu?n{Rm~vCi{_Guo71ChxYsoV{<w2Da_euIby>$hUWs z?z1(%BlufS&+q?#s*)@Bm@_xYSMI00;E@kxm^!Qvq?J=;FJnwEz-H+cjH^s|=;lK_ z=i6sr&$;fom3mmq{e~2uP#X8JVfP}dt-8_NTMO;?o2GK6OenoiuPyGAuRF0>x3Kwn zUx7Z5>-r5hZKT%0488fHFGI6Szfhgl0e+!o(L^s1^SsMz1DAHy2G-<<_qh3xvCf2# z`j95`C1Z{>?EvR%wPyN?8G0``(D*|){z1tH(6H>b*i>I@%%DO1RD!$D`aa9(n5^9v zyJ`O)EW)1|z0DJn>3+JyyI1+ax#R?B`en)S?5khfD4WoPgumFzBX2Bl|LcM0KEcEO z<}91!!4F+q4bZP_kxwcg`ByWp72rqh>Rtk5+>|dsTE?vn^xtB}0No+<t$p!oU^#~U z6J3&bh<Dnnul}_1=o>9Br99=HbZf~I3wLT<yv4QGF`jo<3XgLaA7(yrPZzS_V$BWB zEn<!?rd*VF3q?cNXsleLInawN4;@Z0@ZwuxanvzcII3(kKL2CTy;U;TOBNq8dXPfy zK3>RJTiS&8t4{9t-ju3C^N03x?YIw&-1oHL85n`LoFYBW`IHLE;MbRY&&-jv-Wqt3 zXUDtWvO0X&h>7-sfnn)DV{_xb;=%XgH?sefp__-#-!C}EReHtDkueq)qhn@2k!Ac} z!W-@TXoeh8x8A$PwYvhF9(uG_YHhpcE8d%(OBs4d`p(^QhQ_$Js&75Gt4#HqK9|m# zlHdK`;_{W0ecQz$Irx&*b@YiE985;mLr*ULHZGL4VODXU1p5H(N3%!^P<z%ud$Mh7 zZ`()jEWDoL%Q0{MVD73RMsp#wI)J&2o;@){bwqsssLR`jyy#i}Fxa;3cZ#l|kGk3- z?`r0f*<+}0l&eQqRTn;zJcBHUUc=`;+0G|x-bMyJ8Xg(@a$5g3F62*`Rh(N*zYE=S zDbM-t+43{jr`Tl9N)~%#YKvc8LY{h;ryW`5h<lbk@}PTe<$2$N$ypmlt?1LtoGW$D zr92n9=Mc~N?pf#1j%cn?x7HNDqQjq1_jYbO_w;GKc*5M*hd+dSU+vzncJD(ABL0L? z%X3v{!aZw`y@mP~F8BuDewf?Jw`TWk6W=7;t*q$C+EDj)pHf%f+;n}wzPyj%s#y>* z&mqdprOd<y-{Aib`y}{Q;J!8UZ7SaiSYOqLa9JRELTjy~wIZISzmT56=UF<8yiv=& z3wf5Wt@L627&qu8c#u3v(FwW+_~?M0q-RLC+Iixqbp8ElQ~Ok{iQ*fEKQhPqJGlUQ zd3%M^%T<eB<`pMc7vo*fYQ)jiVDg?vT+fvKyC^-6y&-k$8?j@(TI}k`C8n5k^Cspc z?HT%~ZOKfzq&d7RrTw62)y|#YFUYXD2brq@%~5M}Kk$;~kK^~!i^y+EYpm{D$s;|_ z)q6hmN-rZmoY8)cSvSb1xs{$%t$kTDe(Pco<gBC(<LBb))O})t6`3x3H|xO~p1~b! zv(d4?ezWBr+0vb$7wVG#m*kp@DEF88a&@=s`iZ{MXRc*MT%DQyD|F+LXXp7VSGjqf z2VIDs#s~)b8KNv})&<rESDDs}kjK~#!2c!8y{)~pQIIhfdD1s&94Hrdbr+~^Ywu3g zKS}FXVMe)2DEF})zuymXbRiva3w22LGwV-^23W%vxI9x;2jid6_*183EXJVgi0ikZ z8S;;F`3<bJ6;FM)ZN9SBtm_YVZ32(Sx^Z$VI2qw!&XAjEC*;asV)45FHCO)@(G&bL z<x^i!JEH$b2Ddq%+4nOJj*CCP@B0^7TJoxU?>ln0m7iSS_fK&7L(2cjzQ5eYcN2>R zS?mK>_CnXMzP7A?P~(pL8~`_&eu&~b=z{uQ2489A+22ea=F>`WWNZ($Q?keF+oH*T zPD)?T{&FS!$;Pi;uCWqt(!R3qWh%=vcbSC@zn;apAC<|VlM9LY{l0@K!aOtnf5>SQ zfo~?VyVgX}O8{ACChyR>n>LL8S8%jlWA<U<=czHwv3>pBC8`&BCJGG4dgAc6XKb6^ z{tQ@x!lfOz{ce7HPr7oh&fh-g%C%&a%UQVo&q-HqxNS4pK$}LU6yL5b%6@B6w(*O~ z$A_?J(IobzmB`prF4euMKIi?j;OR5yLjlj?^C4313e5L-&Zn+?WYg~oe>_W0Ej$a4 zIaSHuN&a=?p1oCg!Nxxd`E@TccsqE5fBE@oUS{pL={fk)QQNm<yVih3#mPrzjlhP) z7@|8^DZc;%-#rFC#e)LAKpkUa;Nv+2Y`LVBq}gY|C)~O@@jKtOGlTKO4&q6UclOLb zV6#mc+bVE59`};t(a9p=yl$hnP<5-UqlJ*<n+20uyI17415dDKec!k0)&~{}o|^Uj zF0WhfFLdLWXUFNcF*i;tv1RU~9`<Wp`-B^0*VDq)gom@m$HmiGH@Z@EKrHV7>*ZcU zTinsP+SU6-OLP0y+rD*0Gw9=s3)jEy=;OC;{&k6#d)1rQ2C{x)<V^Mif+gbh*|7Om z-Qi&5!cm(USITP5(A^TjHvUVl(|ZR?Hn1Qs?sG8u)v5fVtDf}y?;lz`$mZb}8JnB$ z4G>>g6zIBi(UjB4&HNV)sGUWH%yZ6&ux|<JeQi<yt&92^x(>GSpZAsS{SOxP@9{q2 z-iO^haQU&Jsvh~}nmrzMPsuVg2h8IA;w#o()MCcM(x4eHPvaYcR^?m!7|$s`TV!i< z)-YG!kXyxb2BdH!-8^F>{M=#3%B<H0pR`qyF>cJMecB@!+%p!)R$1oG9q_)@)hFLU z>U#0#uC8^eJN2z@{e|)$lpLe>a$KGSboLX`n8r^$7XErK@GoRPb)_q-y)tz6Vy%(o ztiA>r&)V&o8>#PCnRU+YmE|-0<f1PdKZYleOX|z<#f*3-hTmp={x{HvPP<q0TFS9| z^=#_}H~-Otr1$H<@WM+D?z!NTHrS6FA8O9cGe49!y%&Ej28_s6FAjEP#^^gS@!#OR ze3Ax~<IfTCJ}kS<`gJ6Dj~>SO1hrGf@UICi-2H0xM3Sc}c{cLRtSQR_?D<Mld%m(t zAA1-6=IA1%_hC=?Oa2$lnv$@7JXRN!*LD+j!5n{KDxY*ni?}13{d9g=&d|Eld!8k? zm!f}qpzTZE6792V1KH!tCJ(Ixj=-Ei!ZUf9o75Rq{#04%<-mh<Nn?0sZadpR2eOyb zBaZXB+Ghngw{@g4JSX6H`x?2jI?v$B7FoN&xtB#}=L<*1_Z2(@W=(1LVujW6<zII@ z_dAmYZ~wBVyNY+y$0HWTlx;Ar(*UmSKH~rE^b_gtwSm45%n4-rNqxFsbqZHylW*;% zo<4TZ4K6J#&Q@{`eFlDK+hGti_FfvkIe|bo{B71I^dMu0EFXM|`IfQ?<$tnV+8@x& z5$+$yhliNAom&#bOu0gOe$Jcle`{5;;aO;zwYX1x<1L-b(3@N!zQ|gR+~Zx%KDvc? z6rQ!yg)KbLBI5(ShP(CW=*$z?kOCGK*=Kt{pG<x0Tz%5Z2B0(fG!!&`2fH-3m!ZfI zu_@Dnu_>JUp5o>3UHZr(QrX6^otV9k*69NH%>dfXq8{13<(ne=xc1Whc^{|^RF9}F zZv8?mr>Y^w-H^5qZj9+exw9u{o*@K|{OQU5m(NamAC(P2&mnmb_?QEgrf-#u&j71; zrLC#VEA7Q5c7M+pKh}`$c~LewW&28xZ{~MvH+(i{T&R!Y;}<&np>)W(<3blPK3-s4 z=)BZ7=A@<fc!zvZQ*@rLd-+G+YIFBId>J~wY*rv4+yuiN|Ne0-5DxP{tD@t~>AJU* zuj{`ZH|TeK=Sq!j_n7xmcWwXvA1Qy7wuLWrK}PS4esyQK!#`rbU8VD`;sX^1@6N8C zd3L}4?U11-)zh181bS@djP=>{xI6`0_-K)%N9YZh`S0iv+eZiVxTna_W3=Nc?3bx? z@v>#6?9G(x?q6+*9fOWN;X31wQ3D-$(hG8*(_;L~D){f~+35m5P0xl;!O`WiAyp-h zHruuF&l9m%6k*%O-}2UuM(Z1)bK3aFcms*kR+Qm)U#M}Soc6w=bF)7nl|NV?(h|x` z-m-Ho#F*z;dR#Oj<i$eB;>DMC4J|glW2sm_Yf`rBSi-w}+q1|{)^~gUsz$G%yw3Bi zFF;qMX?*9JrXii}OS?LEHr>*>dg*_3?q0gRGrIKQ&W5E+Iu|d!rE}rZ@tu2@4(Z(2 z*wwiozHtzIRaPZqd$i{9ypHE>;ya2tX!w;mBS(Bz#S-hI_#%t1m+wGT^3JQQ&HBzO zsizrPz}!z{zI81e?EbGadAb&!e_s?m@oD0EZDkJyU72_#bEuQLBEEMO`MdQn5%0o_ z!B;=tWuxEer?q<(Yd*TBlzvgNCI1J#+sOOGlFkF{F|ycW>?YM3qj)C=ktMZnPL{Pp z2Nl?BD!lpp_g5YC7C%_w{fM8@;hVNw#Yewzif{RXy*Wx;qcdJb0-p`;MOsE%hs|>W zJ?IW^DgR$~|4aD4od3_c|0DT-H~*h<{{#HLhd$-F|JnTi0pHyn6t6xvvJZ0py`F46 z9f?OIZ~gD16E+$DBBL{czD_`EeZ)@;{G9D53vJvjydZB!d2T0NQWol$AWbL_vfKkz z$@asI=nR<4;=iTnTl30_QnZ)0*I*|Iv2K7*?hn4y+&z+Nr$}X8efLr4Pk=!@TDq-& zP<~)OL|ScWq5XWT?=Z1WOzbB5GT46mV<WsI`@Wgz-8rMoojlq1A$u|==<HsZlu_=O z&N-+~=rIAEnHZjxKQnC|=lz)YTbzZk@qG-<vFDstR_R?MxMGw0JQi-pA5e6=l{hJH z-r11A54kG2=zhu`iQPJ7BtCpu(Ooy>)$Gb1kA3@iXxG2}+oMTuNzIGd<KsUu_sJYo znI*%11f4Is**y1YGIvA7cHO3Tlc}pE_N&_(rXM;z9vYQjAvU1j?y+*PS1Fqyv0$=e z<37?|+F1|c`zYTU(m~iMcdIP%)VlG-eS8;VEA}5GwfOq@!R4%(%eQ%h6i<2iYu<&+ z&v+ND7>rLed8(2NpSyRP7rGapzI$U{;k`Gb%QACm!~%1cg0ohdv&@-E__+|v_q6y? zu<<o)v>oDa$%&2d5BS<#*;8YQ#t`v|59n@XXdxKIb^#x%q)cvfk9iK2<s`cr3nhC$ zI$rAperBG|{_rll_8YBVFz=6689NQ%0<}|IzH70MPL!U$^}|`k)!w3S;N#02B`%iv zA1l5#RVMh&gz;5708WD`zPBUOpBFx5`Q52%{D-oqClf<t8;yAR!<8})If_?jaN(V& zxbZo9);IWa5WZYU-2=%7y$|?Mv3wWK!_T^oI6AX0)!s&D$aCEHm-T%vaa5wjQmdK$ z>JspUzwwQVebCL9GkJ3K-eC=CzoO1fOLuzSQs8VF=9ikd)Bhs9`em<u`($EB`4@6S z!eisr=XIvm0r*@2b{WnJW%*<O<@}Du3FwNgJwCwy_W0ZQdnb}f_A1HpN_!4R^bXve zjs1};zrj5JvR4wzzE(P?V04)`CbZ0sW313ThZaro{ZaS$(&=nX{6BQG-+<>WV{E_Y z71XS^W7fQd@w=8Wox}e*`1=DV@4VVc-QTk*Te|R3vlq{=UzP~eEwlTQ<~7DQaVGDw z>y}lTbzbk{E!Et^#62r5)!K7%Pty$f8RW)dH<`GWvA>Dn?=gWp(m4mDeE00L`F?c3 z=DU-8-}zQUc|K!Ae5&x<^!FOSl=yuf{_NRWQ$#o6cFvW;8zWxMYf8J{n=#Ls*5n)e zg?wN9SeSbguc$KXi{T%C6G48R5Ogq%aWLe@fdQBbuV}F{<tS46;B1ccA^c8WJU<e? zv<x5oe!uE&)4@?&UdA4~lDQ&yulaS}IIqLQjvnBb&lm^fcf9Hn*2hb{T*1qGY%{*{ z5Fg$zRljUq7mqXj;m$c?RW@)B_<*uE;Z=7%YV<D95A!@QxQQ}qFMdylCzu*9^GXGS z+Ae!lKK4A@Scif5#{X=9&wIjcth`Dw81l5|G-I@)-QZrdrdYP|Ih;|gW35kkerUaS zX}kd*<9~Y)^Gr67pyURf5uxnL_(PmC&^SKSp}L~+pN3S|V&Pe^l~K>Cky=lD;UTc< z4rGLHf`h;1j{1@8>HFHY)DG=sjlDhDF?J;Tp@fy~#(L1bUweOQ9z^eE?lJdcJ8x?+ zaVe7@U&XwT{rl6~`w8v+lWQ+_AQ+$dQc&^NR9^Myp2AeS@lBF@K6)cQ>34Q+t!F;1 zw{uH);W-qa@<)AJs56BrJdJ%S*-nhocgs9KaNke7BHAmtcOd!$V$L=H#H+Y(pch^> z5W6n-{wen6lENP~#QTEl%eh<ZMb_3kfNKVDZQIS<d6t+xAKknp`0KpbOZ4*>|Jd-E z@LX%)nVJa?u*`zC0{3lZ4PHfz%0b8k;H`O;m)E@63$B`mPaC*Q!BV~%n%=CwpE_KI zJRv%ajaXhiu5$0*SyT4D5G%&Nw0PPpqEo`*nDdDd?-JczpUt~^-GOA*i>n8E<3h<Z zvx>WRxc>psa_sP(;@i2FzWZ(_Hm7+`eZw#Cg1TMaz-Hc4e@=?lps9o6mEw``%cSFz zMi0|?^#yq;o?2UcVmrFGAnWU(44ZI~+B0*hH9MR3gAuRq`EBH5-Mcsyzs&9dOibAi z62u^_O3u?cD*C1M!$;Oi_02Q9eAU%nk*V`Z&Ko@IU1<B1{S^AR3z3yN6TjtxfOT(e z$F~aG|2#jj!>{j#V?B49@jv2S+&7W*XEt8y&q#esyzbY)1K{%)zG`7cHcr=H+sbq5 zy~=>EEXg+!RN(s0d7Ymp9`WmqTqNGhJA5N@n&U?93p68lX5ck1vBTO#RVQ-s(2Q^B z3e$Z~KM(X0ZI(6+9KgfAU>o?nP&j0*DbPBVnWt`-ba2^&QhlU<L)0hA-F0@k%sjSS zpI0TjMEn~H<=Y-^MX%=0AR{l>JHOyV@C~oow{fqm-0*&=s%v&k^_keB+q52k>3aR= z%<~HB%%{#=>P(-3YwJD}oN@m9_`aq`CA*$9x>5SqFnwEMh~d-7uc{Aq%qr8yv-sFc zCNb}_8o{N}dFq?PO<uS)dlUG<Z#nB#c$WM$CxQ!TEb9)&*4U>_UA$koEBX2+`|V{b zk4&4{1Kvi)!R`@FTpPvAuGyLxV*7tw=b+4*jNf%Ar4JFmrw^=AZfyAm&6RTQ-^|4X zvMA?!^9y#dmc-Ec492H_7ySP9ujFw*o%Rd5r!GYP!d3l<=W{pt2U7>~>8k7S^Y|`h zZbmkV5hL|-vmf@!S4zGx-z)h(k@u14>!sDyTRAQSZz<mULUh-Vh0$G;Uom&>fv;v@ zBBqYJr|-j8jlAvX85>IX+|;>ZGZqHt19QxOaF!ki?-b*}{l1;Dvq&!F`4o3JoytyZ zW8e3>m(6)s_6>7xX5SVNo{6W6&)Z)~_Di3oZiMH9Ywe%iT{B~v!GAL}WAXjolhF7g z;sobI`zHRH<k6~R-e?o6GQk<pM=b8)E9eK^x+|HLKHy)v0(zJz{IZt|B(|S2clfZ* z%l2gMRuP?qJBVjoTwTrkTzu^sjm%4V-Dg*oyx@J{=N$N7l>&RG<_U8mw{e(X;m)=V zP4J)iN&&@Jax!>kzRGjVH}M?vMb0tb)N{;N{b~7P%Wa%S`h7fg4k5O@&trCM-py^i z<y5e7gpr?fV<Yf2E;eV$kXMo)JOf^}$7%jP@($~Q!^`n*KEro6&s^-sV_O=>p9(e| zHTB8&Av@kA*_63(4S9J+{>euN<!Q`mqXT-&uS)*)DaOajcmDOOfi->JxY4$uJw?sz zyT=<|)`FbV9mDTf4SP9r_Kx|RZ~R1&UnI9MA6|oY0{G*Y^UT~8sqy~{>i*A8>K^3g z*x7a8*t71b`~SkaTY&GW-s?W|@>zBFj02Fu33ILoPKbwP$MrwaX?5M0TI;k%2?wm% z+9&0Sk4naq9)Y+8iUk4BpPJVz{GZy!JKR5U=EJkwK>yN98>gSLZB%Xg3)>KUtIlo% z-Aiw66uUO2em2d&lP?+t4?*~UF0sW8-_M}?W1{=mu&Ra(n(zJm3^87GSApbji}$1W z?m_<>4Sc(s)@p6_Hcfwoy)OHu>1z^0_`l}1qy0_XIIV}Q&jZ74(w%f2{m}$3clvj{ z(&^vnhui`$e8}*{dadE)F>5CIZg%D5j|hM6x?VQl);E|Z#fmS3th(InFAL~jcKnCt zIjFeJ%)LsTw`Q*u(3vB<$4TxlC-z$Wk#_AN=dykUbXL7`ZE|YUHu9`B^E6B>X3e3n zS;PIw2N*|m!R)bsO*}iC<M}%#u&>(6J?iW$fum(`iFCvG&JUZCS3Zw6Z$hr#a6`kQ z^VmBs^%|nPt7R8k$ooKJj$-P<<BJ)S$3xYz7<=KF?1h(`J@Zu8r`-688QN1-G~L8K zQFo%>Dn5`G3%r!dr&N2b0_CH>d8@v`y8Jz4#X3tfWh*^@jAv}K^}O?+0cOTI<apbG zvPxtF)(6Gg(Ef~AbM{Uo8!NtK75P`q@^bBXzkNV@9C%m({f&g%eJ{*7m>2=fMaJee zN4wH3npoau?y)9G7F1sHJgq$NF4YsNO5XfnVixOMBQk~2wM3$tGmY2!rP0<a8Z>5Q z_<ZbuX39Glo2}j&#z6RP9(=3pP~iL88}iB@r;csl`_PDng+DU*o*&D`t#PSW-}rsj zzA23JJ@^^pqe&{9vBxjf|B1*fLCWSu*U!j{E}NDYUuN<tRldUbU8TaU<QaG?`1<u% z@}j>ft#009ajg3uuUctvywKnnSiy0=!|^_?<tZHRm}O;4#VCijk750Gapm7y>~LF1 z->TU=dfY!9Fn8D~{sQ;dfxDv__$`$l&+s*Pzw|_99=M_m`JT<daZy!r=2gNm_(dl8 zMn3pW%etxYmOP{Qf^8-?qr1cO@FDh|cQiE;m-ErP6$9YI=`G&X;Z}45cf(I<ll5X~ z#CxXJj@@<bnY;)X0z00y>sfjYKD?5#KXe7(!2MM6$nWS0{!8DT&wqR``~v>VmM8zO z1n+eB;~L)eWo=!~|9<>$CY6ur5%R3$nX}Q}ljIplIo<6o|FV_*A3&KX|K-oPj8t*& zkkL%N@}F%cPmnxnhqKhCew|BcCeJcxw1l*ol)bLEoOF!Jl7>keNGnJel2($=C7noG zM;alWK{}PRnzWiULRv#wNjifxOgfXal(deth_s$GL^_ug8^Njhq(Rb!qyf^!&wx|t z%g863&&{rxP2A6>FLvKgCb~oB&z7HdblH>!=>%(*y}D#BICV6+DMgRl9X-~-v!TZt zBiA|}Kf5#O`23rPnjSutyR_?6!_xma6=fe>lhUy={`OqO!+yo|Q_siIg*ZO$ml*x5 z)x8e1GVq7Dr^<<jkYiZ~K3vf@l)2AYCt_@JM<)yPTJJc1XqtOL)`)?rHNw@GMY#d4 zzUw6myZ5PgW$5o^CkQE~e;K|*#L~#Z?!aFDMk^<y8)lBY!FY=gO>CXT-6T=Z`&pxx z`!m)Z#m>0wHpRg>bJg@icaNWb_@BC#eD|jf@h|_TA^LspJ6!%~gLL#uHvS{^+<0ZG zPv{@p;y=yTUGxFP!EK~X^-FCxj`QWms`gBLiBuWRS`JOGM_o@akE%7VBmTA3%+uqU z{5dt37$+xx{wb{WS2otFu3LsvHb^<0f9*((FJ&x0*W4D}U|*xWy94A;>}Nm70sn@t z;m32r#W>Bs;t@~w>>%~$Mdx+?Q*?I!#ng|@;OmE|KP?{&?cOU_7+oN=6Mglo4dt!g zWV>d(u@1VelZ`|63Bf=dwFN(V1Al@?ylZG9SMmgTBE(f4o64ts40&^YN<Q+BWABy| z|H$a{xeFk<FTP^8!6mje-<>0Bg%)+ceAvdJ`?_L%eS*)aeZ|2A4+FtN_kP*J+Hsn= zZ7(fvgQlDf0YAPa(8^}^k<#;-7(qtnhX3*Yl=hdjS){!nF8=Mr7V#RHld;J+DNbCj z#;>d{=n?BVv}(3jsQEYgI{Yw)`}>Jk6^dQX9%PtT82iSz8qB%DfWJTb>uVdL|5?>A z`fuc4;jhjtYwn*~>ODc<jx=U7&kMc6M7<YGl~t_RuRex8{4Rfg{GMwY;{Qnf*}#O& zCRJaoxHK3G6cew12C@X}T~lQx{4Y#u<{bHvD@;6}!q^q1d9eY-d0O{Y(cUWBOUW3F z8Ga$iNs_g@<&I?X8DM}vnf0%??~Vtp$)xQVw(jlRjiUWkbU*jDUVdH!<1-(dchOVm z6QY~Vm}N)*yWGh9x`(v<KVF|1{fA)<u?w$l7(3d_{`TnL*zykffxUkfG@U>4BJ3B% zT*Xps{6h2LTM<K7?K=PS{$?|W(RVpoL(lsD@J6fGhPM2C?4<HLETWFFqS07!q;tu& z_chd(XOAD->Um#%h8SiK`K!T00{`qNvWo61om#%bGqwrcQ6bxe+95yjYu+EHcd2%v zMPNO?S#37?*bB?NtA{<!+PcQq+M{?@S4&2WZ}j%5J>3z7-8fJAv3r}iYSP)JWB@B) zoiTh3IKm0|YpN})7dXC6cMrjX3XoaMok(YWU%PRFxyw3FeUCZ+1Y}x2R{X7o&EQn! z;*Tu%QspMJbZtUkmCt;FmmI&!=_GTJ_X5g;FU6@;Uh<sJ`vmU}H!`lwo4M8wIbQm# z-gyf9;3)UUXx^#~$(nYqzE<6ItzXkL+n?Fg<j<ha31<KO*xd`A-Yj3Tdvs4}b<Hl_ zb@gY(jL3H1F0tQsr@qzdzx(z@V1z#YJi+Zp3_qc5ucBS!b$U|b56Fb+{Gpm%%dRGW z88oMue_7xup#2AUt}tg;(`9oKf9z4V(3XAgOlDcezQn;&7;X=GYO5;w-m4jHUJi_` zXYW0ST}tgtHTH4ZQGVjxv=LXJ(A8nip49Bx1&r@4Xw~~P?C93sYjka!I5>=DrtUEt zy>hnn%H+FIyfxxi>|?Cb>&pZy-!WGUrL#zn&mY%u#{_W}(qk0eRa6Zgzi7wf-8Xv2 z??;F6QwlZypa-0njs6>W<`jQ_?RS>}%eyZ){Dynt_oI#MtwN1=_9%P#S!Gu_oXzZs zvyT=u&ZKO#8*hV!r*v82@7*iA^Q3Y3m2@5h+i38_I$16reLPe47r)C~!-cO^!~B{2 zYWU5F&P&<4|Im<l(=U}zSXqD1uiWbE4j1-3zLz-4nQz5FK=)%}A+&fi_%Hk3LFi^R zb_D$wO_U@yB2PY#o{9Yn>n!&imx{kXnb^a(x8d=3hqbR+SMUz&SCV^s-bRl}dFpAV zo|@08XZ~6B%si_e$+;2PH9n`F!n5khJFA|VW%wDwgNm-ghn2JNI0^%smEDjHI#=<3 zX2$<U{?EwxzliZbE*e|Hc<h7z26W3tPWBaVfquuN=(ncj?(vq#95_;yeCMd<$EX$k zbT$ir?SB2^KYdfaQk)6#WfR^>Kj&lTt(VOvHMdgs9NNng|CC(}d)oOa`;X=(^Ynb# zXjBF{Y(c!Kqf+vO<VVBP9gV?rRyD<CC$eYg+`N|00{-3a$W}98QL)$8$(O==sbCQd zDR^XC5)T7kD+Fr_Ch|(}-&<bAfx9^#{iEcYQq7f!AJ%<R*){jvJ)W3wBWpJFQ_M8o zO_5tWg}uf--)g8?*Ele`4Ebf*w;Jk~CA?;2UgPsHOy?u|Z;x&qVSMpc3`gOUV}0Qy zTReEVjbHRXtbc2&{%GsSbSx0+-}Klg>zDq#=J7`2-Xw+~=Z%dn!}oO36_Uqtqw9w? z)DwTVd1D%W`S7bRv5YfZf*m`CiM{kcguNR#Yo3FTQ*UY?_dmdQ8XxVWN_wmFFU5iS zA8ohy6*xKWcr$zI)V{y@QDPTq4MC1e@A+R|%|0RlkE<YEMp{X_oOB}TO40~vGwD>) z)!N_kT#XEQ4m$Xk$24As!DWOe9h>w{dDPLGn1`MY9>M%X?i*nIt}3@1ofG?!1A{G3 zxH_ey`HcG&_wT2^HG)Yx#AfP69xus&Z9_LdX=5Fx-|&)|<*i;H%R~0BQF&)0sACRR zgcFSKEcP{B*Bv%{SNIdpS0bMT_5Qv#`j3u||9PZ^q=lsTzF=F^{ehgrA=NpE5NT;u z@+XI}F_btPLo0oo5%I4I!|#q{z?SP^E6^U_!uGq<8L*Y6cm=SeYyi2cH-%Ht&wWSD zUX451gj@J&UGg2;%a8bDc5A)sZV!C9_S|0ecRKTgPhMa%>5uuX;CC0lMt(7VcksKN z-y(hs_|4-thu<uIH}kuZUoF3B{I2IWncpOS6ZnneSH|xuexvza$*-8-aDGGi4d%zW z(=Pnzx(4w(pI;8YzWjXl`Dgf@;`brH_xZic?<l{+{NCXA8b9o`{huTM&n@kI^&tK2 zwwdw$X68S8Dic5HGwo~S9ZlZ+&&YdZ)Lr<XIlb(T#%^3X8{=;)S${TNp**jBwSm1` zF8Or^a)a)I)EXxmi+Fp+F*gEQ*WxRT-hVmc-BMQRohQFZbQ7l;+u&W&n?F)5nIVCH z<OjTy9&3YWvnm<6p8wKkJ>mXyr!p^Q{|bH9vq$gyllJFH6I0Z^d)diX1y#xG<R1yH zlOIri6Lm>%Yxa_)q1!g1V_2G8Lw$N5yltzO&42PGS6iC;%EF#F{`eGlEBFk&WsJwi zFOZizOL`v<;Wm23c@3i3h(CHyvyc84Jh3L<PdOtar^?##9&Knlqs;voWoA*PNb~2c zGF!zji6z)Kwbq&Y1x6^oNAie~4f)P}P(J(QCgpwbTCa~uhuO8pe8ZRAy-TIp$b<dO zyFT{(h|1O6)6e*6^6b?t+hv~Dpz}+W6~F!;wOQ%fyjJHpk_l7qIkv03XW`*Vc(%cV zz5%CM@6OIAz7DRA>HYHA$P9g~%uqAC-+1-Mz3-cT-{0Jgrg0UWcF&<t@S_*GEBddD z9hQ4{1DYqg)1bCEbaiw#@uFr|JrMCnb*i4vsACJX`k?MQsHp2;PF#n4)ip@;qP8i& z<#WnIZ^;|e<tI`8%u5;NMW08QLur|{4ZDS1W9;2--TUDe$1wj3$_i1)-g4?m=KuMM z<rMvXWF#=%#k_w~=khd%r*Gr^yd!$Qz|ON#xdvZ}44(4|e7&$2SZ}v;VPuEPpY`du zc>#NGa+1s6(+-;12jDM%GnusO(F@XX=UUk~nX@v^8D;2#b;jKzHM0I3;4Gxw`(3-? z&xdpG2jrjQ@&`=*+4#gb-di&}I5s8EXuexG_sZ`1WOQCWI6O1Wmc4SXDGM)4mF=b6 za@uNh`CDB6&%oi{8RTE&^3Oj<*tlmn1>5Pvu59V&!}gnF8L%k^y5`Sk!1kN1Y1m4n z6X<oGh^Llwm)i7XaID4MZ<^W9%rP)BZ_q7+!;eLW?9ob=p97o|Y1fT!$&7P=6TMz) zd`pUyKeoK*U7l$<_18xdOOged_LWcTm+i~1w<te0jAu#1q)*#^T+#kH<r1uiyQ`9w z?<+qt6f5HuE0v0;iFepE_1~s?mx5jOr|2sKe$IrQ+9^3T-el~;xw7jsrvl-5Ug+HW zwWp)0>(o~Kpx{TzRjh5@Yp&K0!EAgh{1FF$<3P9r{UG|=Zn~d<&H)}JpB3gz2|C=| zk%Ln{1ACgAmYizGp0tHFcE;!Yu|c-Ps^neU%5UXvBF%T?8G{q{)jB7GoNH|E$S1kP znU_pIF>z<Nd>`aobGF<2N;WqBQmJ*=@(=a|x1s|de`>32CE!D6G(z!5_962m*U-ln z^pVE?Z1s`F$LUvE$JK_e#PVEoZ=fCf-R)@{bu9o#xw09g+7+IJqvlzXkGk$pkb*b# zLdC7rotDd=wYUOLhM&8->jkU!Fj`Nj+xQBl>UMQbaCIVk7gzUyx3Rm<LSvJ8Jr%ou zx9mBlUVPR9_^e@nJF^+vdjMaxT=~b)7WRNQyZgajf!Jo;ultDA8^_n0^D^97d}^=! z)pRbQDmflm`^;wbPdJG9MOy?<4;gksw+ve-JG1TQ^HE|^C&<^IbHojjVI|KdzKj1t z!n7Ai+>QKtxE%U8^Pt8O8qgju3OtJ6P)N|YT(h5Qg@1V4ujhTX`dqmkTepW_-;z`N zu1REp$1%oEN%^9T{DYNO^gy}3O)>1i#GB@SA?5Z{=6c!b*;gLo|ADGx#k<T+$*Kow zH!oe!wwEd2UvYZ12J<aH<J;5Xfs_f9ci4S>RafOu>EngJ_;tT)(0)vMOvZYgk=4Or zRo69VsMFIod{b7^{z0wX_TKA?r{$-jzVN;SxN4)1{O1Gs3LX;gC|K6#NW}a31il^N zTNx?5y<#-!aVx`*x>@<uZ#U134UTzGXKD0u(SOf9i0H%4fr9k-J-3xHsAJp|n|a1( zkKf0yGAG=6jt-M?0#~^jKj8-0ScgylICbu3?mUBM&I%YmoP5K_{L9Vy-_2*9wKOGo zqR)L*yvD81&lRzz%yV<!%pKLOcGPe2uZVwn0e$?8wP5GL#FDPMbLW{mpJ==#xfeeZ z;;MT4#D5u|V7w`0XtpXj;X~W*@O8A?n(D(gY$t|S{vB(f<(Ku*`>>(Df(;eEYUjyL zbce}W=H|quN8yK~;ANcAz3gkmpg8M}t0kj}pEmm6^5V%zDft4mW4QxsEOC>^5;u8l z`@r}^N2K!&#QzOD)I}e^vgDzM^2XL+qq^avyd^h${6N{Cv0Yu#)G)S{a{|oSvUblK zTWQZ<l!Lo)2MfX*_|pvKn{3-dHShd<cu{V=@HY+3Z@@peHyj_>jpPX?^#8$#7j0Nx z%6R9;SAYCKyyes@@s`$U($^?&{K14*)*(5MJuxuF0;l+`sg5u2sE%E5ZNsR1c>NEF z>+z6R4^AuN_qHo<UVPi1I3KaSbjb~W%42MoYYv$+9I~-J_K(2uzg9RJNUbNE;`eMX zjjx5jy?1BBk}1E;Tk`TR8q7JD{=d>3ok+a}vR7&TM*q2!yWFpupg!}hsF(VSv5Swf zZ6qZhx5O^!tmfQ}zvPv#%T5=d@7Pwm4heqh&Na5_UhDe8YZ-MNq^@e{r7q$RGxgK& zgm@};pG=v|&<=E87;a1X5&g2LsVliR0q?-?VPC|%NPJWF0`ct5s$@9kcvx8LhvQS& zjl>Vme^%wpd&<Id2RS|g{;W)5`NL%$nmZ{PPRSwZ`S)xq?LH-XkIv5TteJg5SH!>U ziO(rBzi~YCr?`8qFXjJ+=y$)=ptdE`IG^=`=v~7aV%L7lj1lwtsh;!tvWdO5BcJ#T z__8Bj-W$j_q!&Gx;u8@sce3M$8GK^s2h=BCnBGe^TE0VlP9M|0Npl_io~}xMZLnxX zeB0dF%G%2rj*TWBSF49V&qto!-(1Z-+J>$Q#OI+6tEXY@wLH4(W$?$^K6HM~JnqSx z$31!TxF>HOv67MLBntvpx9)L!o3ov>p8~F#(SL;}O7>>YSDr}mk#=O&kI#?ZZuA^| z#ZSON(b7F$KJ>OW9{Un!h(CH)>lp9#Zbdog&2(;w|IFjvrPIq^#UCQM2pio*^h_by zPT+a@@|7Pt1;3mDzs!r3|K@>s@t#+rv!}3+ZZC~Kc%ZswS<x79eM-0%Evx>^UXlGG zIlSq1WG}U&cA**kF-zkue*~6fj_wr{jI51kXfLtkt!Ely<G%DjblxSe#D*QIj{cwD z;!pD??QuS8+?%h&hvk>XSG@5`w1scWUVVi&@9JJtfH8wsW^hlS#&%1Jj`2T8t#MPM zf6w@>874mHc<}ZEOCN?l$1p$U2{&B}gd1!++m`IuU21Uo_vmbk;c>;gtNDKYVthb3 zqkc@|2@Qv;l9S9`d|LbEzfjdxdU(_W!bji()hj+b_M}(z*Ejt40M|wicpb3h7x|K9 z0!x1Xi-xwZ!HZAoPS9VDpEhFR$lA%AVP4S;{RFn~t)JvzQpGD;S3CNb_$efl(?(Am z`R&mru3ccs{f{<`y&u1Y)ywgJC3eC6hA$POmu(n420i}QrsUDK<ia1v*T|PC2_Hxv z9P$)?I?O|8$%`i+&uc@@W?Ztn;rNbh#Aj|4KUp$|Gi|$mVdR?Fok#Lw-+3c1HhVXH z7-Ytu{d}1A0=4D8954BCTKUA0)9<wKi8q%M^CaGKz{0l{__muk#?6B(u*<}y&p7?Q zgAExi*>UMMy+1NC9)E|u-szXy%F$=``Tx0l_wcH!YvFq(gs_1KQ5P67mJqRqix3d& z%5Af`s3GCiZQK_Owt|<6VlBm9mas0l0pW5K0`(vS1r&?e!=Y4qLBNQJ6gh~fDN;Qm zMTy`Mv<Mg>`}>W#_735qJ>S#k{r>p=*w0*ht-0nHbIdWu9COSu$7%?+;wCg&=*8uG zF$wt(FlU+6OJyCQzH!)E_fF}@sd;&fg*A~_FXjSw;~3_d+h{v~kYyfXuIYe3v>Chp zx<T>wF6S&+!@z~a7!t$Cc~xIDBR$_av01P9mDsBtH1~A(N$$p^1$jkUXLn`;eM`!$ zev0q-6?*y(`5$?PPe%Mg=&1MvJyO~-K;>v4mjVLNO#aFC!AgJ2J9&XvO#Ja&H^{oC zdQ;0g#4{7yOkbbU#z^}(>9BqC9?i?bE}_1}qRBTq<(&jP6+admk<<!vs)9L6_Son1 zJ}|M1Q{JC{n(JTD?xvOoS+ff)i*Z$F9wc9qKeiyz279{9C+QvIx|O-78Tt)Q5?#)j zzAR~nHkd!R<<7O?tBlw&c^^7%gGNbq(WplDC>5>jB5l{O`sBiD2fuKi*fBSwM7|NP z)`ZZlIMI*N*zlqRe6j0GTdtiZzUcY%10EvYxH$v6g#Dol(C#T{SJ+Cskie2PCi7)c zEA4<O^gEw+!(MBJiw*<sMH1UEe=M@SDK>{Z7(%x@tDh3OHD51q+R%*{zH{l;<*hi~ z1m{f7$BmQs(KTNydRdIM({l8}G#HlGii@H_|H^Y{kVSi}17maA@XtQQKTpNxoK1t4 zqaF=z$h!ay_9f`<@lW8DR=A1={X3pZ19#!!#_Au%7J&Ocazkj*dhtW<L!Q6xC4Ff_ z6ZQ#P)Hg*$20UK6Xk#0ips$igOB>$%CqGhjVZ3bPaHISDr;YNydu2nAzMA$AzlN7$ z#{{<X!KaOONq6-PTlHNO;U(G;y?Hh-4gI3EKT00@<tcfX(#lIY=#Xu|IbROHm6xvn z;sSI$M-GQR+6q_EvF|JA(h*)52Myt+6Q7<#w+rx6+O#%wV=pgBbkaE9{f`9As(%D8 zU62O;|7pcV(V*}3=g>grC48a(Z+L0Q|6G6u=kSvMjQ&$J=(F)$8n_F8|1G?9{M~bC z!XERvywv$;ZS>NR(%7{Rc(zzl?HQgr&RP`R1W!ThQ*C4|kl_2$SkZsA(nrZ!pKb|R z8@8$C0CcHnBV#HT5<0o!92q<1$=G%8UVtvO30R(t75%Uko}x?6iZgU+`MKyBC1Xy@ zQO2~k>KkNiCNlObnKQrIsQPwBUkB~N!;N;IPaEBt`+`aqe<iZ`)vuw~sRSI6J)r}8 z=tV-aVdSe+^i^{E)dPw~$V3~tJ0)@_cD&4i)&mU#)?-&yB=Nn!UYz&jydf}hq4zO( zN9<vvG}iA^Zyp`|7WZX8xtMPx7GKDYKV!qMD`cIs02@T@^E2P!_a8j3@<+%cbDj9! z=JoY-wTyw%Z!PGvv+Iv%%|7Rx`up0{KXp$1LDa7}r+#gszN~kOle%sBZoFTt0q>P< z+l5bdRG@zba^8e~=(27jp77TRIMm<Krha;9Y|!(GXV{q^#Nmzx?!tsEEB;t~3uony zvW9jxl|K->R;>^4F?jxk7t^p`YvVrDLRpLFHIT>Tspi5er#VnCPSXZt@c&26Bdh$) z#Z}*H9)0b<YudHlHEsNnrP}zN70l_$LCzv*74=$;u|Z-%|8buuWAc5@WbZ7{y~KYn zWzG4a_(VTHt)4GQPOp7g>mutbVs1anyPBBuVenjjXYz}-KkoS=wOz(y&ZrF=^>9Hi z)?VaE;C*jCSd#QCygJ8F_I19R|A8?_)?cM9S5Nc&WJyZqprKD}A7Z?JhtIf6UI72B zt<~6fj9ShAuCfmor$H`dvOJ&nL#>v1AuXRcF8Eb)zjk=wdQIZKg4~mDy9LF@GB{UG zy9vD_KFS5leyF7|PD#M54UfWJABDZ%C*}JCX9nnNY>hk9lyZZ8{bbWwrwxg$d(Xk& zojdF?t^crD_!}grPs*$Gqqp*10&{8IAAmJZOPc>jv7@x#R)U{*u8nwK`bUiMyMl}K z#k2js_#m$9(#1Dh8XNc%-kU_<lB93M11C!iF?^T9bq9%W<~oz>B*}*a%yjCfIPI!g z$4Vb_ityP9oS(Q?a~=XX5|_;VtK;ooRM`u<F`u}@_#Qkm4!+ts_YBq#XRl$VmS9(l z-(U4B1Kb5hM>$V1tp4;C?EI!Ymv6<)j=gACSK>#%MErMa68yetSlo{$JkA*e^h8MU zx~zlWPVo8fGD};ox<mMDKD1(Ol^%LP`$2-ogufUs`7S~l^#&CzgV*rU8qcsEQ9jx1 z72xQTZ>*A&No<CJjNdWg8KINxJ<MZ$2EY5NHZ`YI{V290zX3Y%E<8H0SbKUDYh3Xs z3r#Z??Zxgbr!8;pm9~!3MjH92B|o;T;e?OwRD3|ZAZHy!c37L8y4*G1FvX|9`tsR< z)%eDqN_tk_75*gOa;Wlp=B=m2M~BaKCV25595bY^at@<3cKCW}7keO+`6wa#hDY}! z^YZZ-F&0@)jg0LNJ_dhHa?W^im3^&uPEx}T)9w{MJ0tf;)Y;^~Q?WnstT^7@FwR&N zN^B$RBVEy>Uh7}l(ko0Ir5mJu?+o*ykK_ER>XpX&Z!B0UG{wK7c;fS~oDVKvExhja z<IqpyxWF&5+{C!3zQ%K65hFRO`Vv`V;Fm?75_I(V_4G#J6YskJZ8CrJt}eOn;_Y7q z?7*4-pPrUESM;=uoBPAJmChhnb7o@vWgO;R=gFzy9p`C$O8Bx}Eyy<qC&9b>gx3=M zD}BxjsQ6&z)0>B$gNNhibXMP4>2FSvISkwqGBVo2w<P`-_#y6B!B6$H(oGr2oA|I~ z?8Wz&1#NclELrZ+M!Gx~9%GzdWd1;&x~9c(I^*Yh#gi$)L-6tDivQRqe(s7{t@D-1 z|CKUli4PJ#Vv@|e!0RP_0`^GumVA|0xAItK^+(Eg0N(%8hq-TMJf>_&#eMM6H0F;L zqG$f+YL5?M@2L54JntZ9-rU&qsG_C9yGsbX&+MlyYxUv8eRKc8y0htWqk<fq%n9@# zS`6tX{AMiW9zL?tmYzQp9~{pF-v)`}VcqcOIR0~&4b_ZR{{VUDe=;f-8#wdG?a=Y( z@Zso$e~E9Z-@%y5IYPxlyf>!xJ$w+%1Clob{X%Y+mo>3dlIF*>UHl(IzKb0K7rc^b zr%xO<Yt`5e8M8QzdSfr)Tgv{k)GdwmStif(;2XhR_=B;;XLwQJSv09U<F8a_b>Vk! zEPt!PS9i{RK*sBnuect=e4@>NUfE3x=2w%WgEo2g9&7y+o_RjXS;gJmRihfY{|a`) zNTpNIPsE!8yYmXcfjl!BIcE62W}5hYcgeZA1g~%U$QvW}1~hnUh_XxG=giNRzPdq< zm@~N!UYJzX(tKwnI<>kZXJqiL<z;9+t*twA`M%%~Yikd^mydngkA^*5`8{y=!9Pt} zO2IJg8i{S^+~5#=Tw-I6t9Yt8WZ!r@H0wpK=%hd4Z-`locjj6P8}i(#J#^0b)Kt{c z?@`*l*bhmvFNYtDb6oA7vleITa!!vi5m~~|+k7wWTu(cb1UG9DexB!vANx~I(47|F zUtteI=u+Bp<u8QBVh_W=y0tJX=+?yRKr^>KoBRY#!GfvC>Jr5_==`MIM8Cm@^H=Dt z-vs0=^F!<{^{h<t>?6UCyuU*P-(DrLeRk4q4_E#OI+Oql`INq3FI^*jh~_~r`XRQH z^hJ#s`!#Amu_f~@^g-J>drdX;w7%YvD=^eqU*>xGc6y@Swsdi;)mc38RZKwNg@h)8 zx7!!I|Gdp$8}c^jd#Cl}?N3x@&<1S^&N5y?XLl-lB^|YU?T+WsTE^}n8N1S0&)0;< zX+OiVw(IW5w@v5cm!NNEH<1tYYA)X$><_P9a9={?+~fJ@(K`n^=4GWQ`B!`1BhXO~ zvaePGtvlZSgniZba;@6i8nbFr;QiC_7^aS&skVu)Oz`pf`yMM-md3t+5&X|OpyLKr z|Gr+0-%%fa%qfc3pJT`4Qh0Ao#owVJvGx_ukVolYEVeN&GZO1j@O<nW_c!F9o6!{T z`m{30o}T2VZBMCNr;U^IpFs{bdiAQ?q3?-L5Zzo5(2}aAX`!n7IGfyF%dPrYauy&9 zH4VY4*R&x887(pEou#=|D>xhZ_QKrC_L@<7BXjr6Y`uD#HoE#g&Zl<VtmiL?#qu9v zZ{Y{%!U}AIz<Rx3C#}n{C$*fJ_iIVB4>H$mXFi~`CkAufPjYjuHwNqQFJ})2>vrl= zL%uuep5ofdU0wU3mh=pHGY58NE$JJQYu^+M1{P^)i$4{geLG+H$En9By(RI2?MD9W zA+4*78$4yWoyG+M3$={e*RfX)5_`2Zm<tS_ojP21ZyJ|tj}DSwh_gefxrXh#H&^l( zCGZ5tq*;86F7H7PPd66Kb^49TwcYYKp5?mTd7%-Wh%dK*>#1W_&;CM7S~ib9`A+59 zcLjrCH}&`<UkF~w4}~Z4ovXWUH{DL;Vpymdw4LM(^6-&+_Qk{XVG9`t;0hlLY@v_S zH<)Yt%5-wArMq_lzcd(>m?^vGNpQY1*Nxq++xPMf-=4JlWKzhUcrxgAUdc7<>i=$@ zgT0yM_J2cc_0ewU+<-m%PeJ?1yLE8rZ9jlak*mNSRBAq!rX@XfvHHg6N#MWeq*a@e z3z2!K9p_M=5L;1VOnA1z)l?rQIGyJP?Qvs(mm6>{ucFP^j<#+7+fglP2{a*Y_#`4o z-k@@+^IJ<~xgj^0hs-+N$E<d^pT~LDMIQX4cAsS3e!7^sELP#+ti^GTO={bITb!kB zv14ZTXRNmp5Yi9Zxj(s9`)SGl)?aJ4q#ylwV5|u)`v#^mmoFm!S*n&i`!g+R@nLi~ z`P8LvwL2Jd-dXsDtm%>hKO029-QpnnHDeZS3cn~^p@-0<Ur*}KWFO*5tuXZANhfb2 zag?97d(QsZSks<)kNMoiTJj${YRN)_Xv|k=_ixtiiOqa-ocHN7FpYsdwWQ_9necR^ z&&UC{4bldL{&Lc>pT0-M+WcXtdjC|okGx-^-kpR@z~f76-_Vj4{>8(Ew&ucflZEHN zx3^n5CRgyWCk70A_T74Tj_@k{GIiW)bXN%em^=4X)?f|V6?0!x`g0tzG+AVc_xrbf z-#y%{OProl2>#Z|)wORSlV6BEathu~eUUag|IC&5Vt=CD1&qZ?w*zw-JneRD2n<_z zN(<lA)M9;NaIP}L5E&MoBQmMx^=$#ec%7VguQGofYzmTt9DZvE{u$kd9JJ5tlO)g5 z=Kh_0d&E4=L-))>_uw}Q-cq6VJ0}^~(+NE(JSMgex^c9`P>60M|3&<}=FjA;8|Be7 z??z~sg<ct@csnQD*H?(n_1PoKBsXwUxCEM)mg&nLBtDw)`W+=>`F>u7)|DKonmx1K zbK#l1Gfc~|`<4vAZWjA4J&&9p)N5i)G6v3JkTrY=9!^PtP2^JNToChIfLQG$!E+&Y z)sr1*AH29u;krH7so>y~GeqDhx^7o^l&`ShBVY|}g(dn(WK3elW$l>d&Ox8RdlJhb zJnzm71_B$n9>u;mc*y$-mvQuOoUd?&D|%SFZCFJ+i*}B}SGs3owtEQNSrfFom-o7e zyvlpO8&955u8kyY$9?5GWsbYFTwf}(Fi}f>W+Q8tE0gs#J+%~}6*ha4diQzer;n7J z<%aL`6<W{s9pL$PB-gC3(0#e@fap^C#~Rw6&~AYHa=!sWbJ}<(Zu3gKgRD_9SwoX= zqWS0f<C3)eb*EeM8&9izz4@%8cvj1^NzfwQ?l!`-yN@vQ$7z?!y9E_mQuTA#7VIPE z*CTVRnfleY|4-JQIbs9y?YkCxXsKC{g`6`ks-KL}z;;Sj<$MC;kUYjMz&?8PZ{~0K z;~dTj=4+Z3Ig#pj7cG>%$==XDBU<h&bh_;x;6`>2h@^XYjF@9J>W*_e=LD@wPUcz} z4Y~GM^!U^|{mPTEQ?9uu=-f8nj80|#v-j$bQG45>D>QA<H(Ju~$7;#$)G0bL_F2Jw z%*$8o$)%6J=+u*rdruG>Fm^J2_Ej$!iykTo8g|KE@tydjFQN6mLId7*N9@+0nWAMC zkpD>bR^^@F^B-DdxYNe5&PfU^U8yC@n8+Bp(~5};ily6Qmm2P3vFBpGfwMh(ROSfY z3AoU}Egct(l%?l~f2H8$xOeRex*O|s>++Mi&fnMT;?IE2X(A8EKyR@(z%4U+lCi&R z^8jbew%Y=gD*iGla)+<*hH}QIDt5r?agsg%-MZ*UZ>(CZYGfih1sZ+*)@r$S^LFb` z5?iCL@7S%oc}+n#uluCm=ZlVN86)^&pJ&;{^r2SSq`L5d?B&~6GtZ4fmPg*18>&gq zx3A3Btt)%2UepB5o8W1_C*)2DC|ZYo=;f3+t!q`A{f%12VwTW)xX@Y;UzO@dUIGRC z@GHPCo(~S+{!QM#mOE>|K7Tqk^)<*4aAkaC&5EuQKlohHXP*B?`*|htwW3qNeS(ak zu@70&cy|<ePWko==go9}K7JYK#v!sM<0t-rG=5q9a`^S<m&?!KSC}`deeS%Dyf=y* z3Zt|jztMt+zy*)Q8Hpyz|J`bzp0{>hvIjkJOwMY8-ynFWY2b9NkaC~Ms@T-v{C-{* z*TkKmvoq*RRzg4G7pUi64tUF1Hu;94@?WrK?TwGEH}|qw?<TQ^&M}r=oon~;&g$S( zlw2EgWIe<hGBZ%Gz89jo8(Axpk6iePX9L~mzduRzx7>s0e9?^^{CP#Oli0x>kWFd7 zx7Rk~9&cN41vY!CT5q|Y|17=@@??AK=@vezBL2!)GbMf-`M#wZw^Pg)8O7S^1466T zGeFwudC)-eILZ2PT;*Nh#kvccgcAMbx|lW7kc4kv@JQe!>#(*s5_@%4oVAQs99Q9; z7H~lKpPqm|O$t3w;}6}F;%6*|%p3{*AMBy`tBxI|-)V)MU%<E7Rq~LLPe<<kya?L^ zTJg<D@=vOLhU7nSeypp|iS@>|O^iLZP!PUfEpv@^&v4>udI+zlE8QLd2D%+Rz3*H& z!n5N`Vqd7WQ}Jz$vahOg58dO%DH;2c#u_UQ1+7o931?kp&f2bNvsPhyAHp{4q_uNi zU8~RTtEJ2?(b_wISf$T?P)nUX3t#kC>xs|f*(%L9`w;nGE+by=_<DWjEUi;*Ct?E( z)`8rcNq(=|?b=1I=mhT79@4thKFAtj%3fXFTTGmwTyJ2_B-f{#)wTWf-Rjy(6I&FU zX<WH3*RoDg*PrlxcCM}ad+3&2AMD|+3;N{i(4o*CG2#iMrrR3whc{XeW(4g~Bc70J z=|6N!6B!=wi+#~=S~upNmQyN*toABoCQ0<nj>Nc8CdpXIxg)NVh3@g|c5SXx+FZA9 zbDi4ex<i|5@`JXv)3MEUr#9D}+gzu$xxT2)b(c2RUGcwh#?fn6O5u;ts*n7_Gh$ys zm;Rwu+7Be(vG9$oYlLrvN2se?O$q+WSNui&qpkeYj<vV%wnl3Lw3Kyt8(y-nQZdxx z`%DrYwjO>(j~a3f|F*8l+4BmBEoe<vayiFaA3uqFcK@vUOXL$j->|2;@2kQeEV*L_ z&Q&@oy>hU3h9K}%_btez=)2CymiX(^kU{a2Ev%lbrOVu2wVS*agSp=eedlkkmz?PM z+6}%%Ug*5_dz1T_++T`~@+^C3EBT+r|KC>rck>$d(<=DioBwktIjhq=my&ZE%?l`r zd2D`>atOI-HS#-T4qMWF2)?a9sqZ5<@qOeD$Yn>RC$l79Ej*Uy<yW|L1N6-qNPh2O zPhGmFb{96tAlB&VVt+T~$~UFl`oS_@nS4{~vR+qemxX;zEqOj{EuPU%Qaryx!=z6& z&Sh%BpEBnStexExI*j!ErHQ$$I*<B2jY_`JiG7HTn~c9NBTtLX=6}axt@?6lk8g`; zavzut{MY!OUfGlRp;qZg{1LI(+--bQ;8V5E=^dRx99ZpUzx2`Aho7&h;EBwG<eaZH zM5m@f2m08lFk0KePa8h&$y~4{TK|zBTJ)Ct^v6eiiE&QH|8a_U8hA(Y<t9bzUv9CQ z0=e*z;F5^n*RI1xbn8D#kJfkCK;BBu1vf7fyys5VhRlDO`F$zB3h{%sJmk^$60`Pb z8~Pqh&^P~oMc-&`s-Je#<9$f0TPrlW_~auq_sO?7(kkH}{vT*dtLTi^Tjn-t+9NZQ zrH;&N8H=I6j6t-1vwV{zng7tfa)~z<TC(6RV<5Ogr#Nq1yy2hVehs{F&A0JJ8=QRe zYqb>qr~j;@!fA+%T>>xR1BF{{jo_9Nt-s07y-wiRxmc_CI*wzzZ^1F+pWyhN{M!ac zJvt-R58Zsx8Jnd{YlH81(6Hi;IDRQ@@q@?GCw-D4^vCCtplA9+|B9>$uJA%2E)zmi zebT3jo`nfoo<GL!p9Mc~$Y|SFWC{C#IL$b}B6IC!{JlOayq_h{b-)=o+jQrtoR&W8 z&Fjp8k1Kh!=wFtnOSHm@`{7S)JY+1F?|$gyi^-7uJ(9cMdYn1&p26hDRC4CCo-=|@ zN;SUN)R~G#9{w4EzucF1iZ!>r;LLO2*9M*RDZ1U&2!dY#{8aw~Pj$_T>j_yir?%qW z!6!6d>d9W0Q%)b|6AeG|%bfo`8dxnlEWXC<&;C)SXWvL(6Y?ysV68koM{@F|TL%WM zmhXtn<$k=MKIWed)JvcA7e(_N!P#y<!W6tY%V5k)(h7?;XB0m7LiQ^R>4UuM<VYXz z=dqq5ul|HK<KTnOGTZc{!<l}hx9!J}f6|ZM=kz1zU+;%q`Q81vXz4lq=uJO-f`6NF zop6TtFPikP@cy!%S`W8AkkIX0h|L_A;N3QO=%Irzi|&)}#3fNG{hgSPI9c)^GA5#{ zi7CF*<B_yI|3rU$r;dxxXy_8Hy-CeO(HUC?*uH!{T0i`IZtZ>@dUQfwGv?Q^4udXj z@J$mLX0Gf#AKPF)wn7~?MjduVK|o999fNO4!%JN%Wd2FuPu`#FX|r>p57Oqqf0ulx zX*x7WiR*>J=*kXGbR+)m`jNTRhvz!)@cP>MvwzapPU!Pa-=@!*Gh3qdCmrCXaJ>n5 z5_d3?Qu4A&DSKXG%c^~F=F=MLj^=+y$`Jo8O7hhzT{DJ~?>UGqpw=4cJl{6&67~NI z>JjsKbQAM3`8G~uCHjOta*g!soO!1|ZHVuncf6k|-`3B#-SU2PMvXsOo8q6qen}gf zVF&IT;bGA!T?B{3n29d(^gwEFcd-$0C;UzM)37^Cx3*TDlX7xqo8B07s*!jJrO(h0 zq8CbAlAcuZL^}z6;7-_sPXZgw=jk@SU0`_lcN+O^_|r$R$-2@1Zr?giGg4ckwg25> z985}zPXD97-;AX1iQYq>rOb_K<LKAD=(Rhe_49?kUy2W=U#<2%Sr1}Qz%Lya(0{Q9 zCQzme9ngDs0(+8&U&m)_*R-)|RwQhiz6qP=JNYQo<SUF$>)_az4j&-<8`1iv7Vw%N zV-220*oU9#<q-p*`2=?c`N-;HYh-N0srXgthxPX00fHO-VPA;4vFir#T<kWPzb4R^ zOYl#<lh?C-!hU;*`of1DjHk6pT+8=TE+szZAtR=R@_Hs8<(rOgNxThnhw$Mp;X`!9 zT;92O{$1Jx-jO+E9P4iJeI{AcvgvD5lRG^_?M+!b2J16ZwWOtdTg9zy5`O4CJm9lt zrk|mc?Mu*Uxa>`A>o=WmU@jrXqm^%cqiZLfsc+qrsNaL{VFiQ^?+fp{E1QDkdNYJ} zLMx%2_2CF;KrS=Bt$|*7h&JOkT!)k2)~2G_Ht=1dX#9@wccOjT5PNwSaBhfB@32YW zK<{>T&*1~&aw-0fXMx8z>$IP@fmi!a;I&J@Q*!K!ou++9ctF~xonnv2It2bnI~~qx z=j-V7RNDEAwA0z$I9&9vCTnqbMwX0+=)x=N>iFIWV+kDcn88E$dvpxl<I&OXd4=#& z8f_$5e^G1H_dPzOje6_^7k*(6sPbt|eSgAgmyv7WLt+2qB)q2~|5prq>dQ&OdwEae zPwT0EN(UP78UI7}^m|x?wv+ghB;iNl!MW%N&b}L^v4f*3xaN$x5$DIWdAo%dQ^kIM z2>u(#d&$xU{CF?#j-gG_sbT|-Va;uXYLE%qx1P?1&p!DYnI7WBlC|GJy-TR4^_!>m zf7ALcP7)t%Z`uwCKGHYZ_4;-X>mT|CJw~28PbKCki2+n`hp~@-ChJ^T_sV*?in**h zzRo2!Z=738z7!uZzOSM0+6PwGeuAt_hxgc*wmvBkU5dQ4AN?Kj(jdCkst}(D-+Aw- z9c52ylHjY>x!8GvzZJ(>;HkY~U$U;?PK(1m09<lB+tcBTISDyUdFMOe{>iN$lIuR# z6cqSwePOQqo2DSX#sGYu20bss7I`S#A@xPprtIyid#qbh#&B<P;vQpwA19?S?Cao% z{>8j^sf+`3FZSjPEd-t8^H<8Z>i>iuF!nJ{AL7427gz@wCz;1)7;4TJo<}Fh9Ht8l z#jnB}(1)=NieIrUof6|>eH>V=beN0_I?PTT5g(U!FMbDo#0PLx#w9TxR+IQ^660Yg z9=gzYD0nG}@n8?Wbv)XQ{0?}n<B`x+p{CTy@Pnc~bned_{!Zv1>w8V>#yE|H7RBFA z>*Q~>|IVTH$nT)_NXD^0dSWE-bL<Rw?TSFqoq^6?k}PB0UEq6rG077cgOT<X4aENh zL@$lxJ@)i-f{f=7@kdxI4T;f^?`-AR9RfjXWsb}dDb{m+bv5Q3k49#Rix^>YKTYmg zE4BsQ>3ftN;{Nz=<g#t|95@BsAMXjmE1I1eQ0phVy|LQ9Ja4tk9js@LsXBT2y6|A& zssH&C?PYp+CN;>j0``QSyc|1-y%hR^y+(X=PvQZoj~pJOete!un)^>|mhZHqD=)#{ z_fkVp)@HV^ug?4{Hf^T5rUX`h{-?{D%bK=L$)ebr#o8ottw~(tr<W(}V(6Lf*8bg; z`3xD&icXK)=)`$Mr*9b$oiY4-Dy{@uow^xu`!AERlQqm0;-i~4*qbMauX|ShC+t9; zUmoYB1Pz29;-3*%@Ls}3(klKXdeG<idPm|jvjiW(O<;pldK-Lt$UWeu6$E0Zg%$+? z=BJ^2OR&w_LiST+eUZ@H;Hq+^u>Wxx`80Cfg`A;$Dk-OWE&j+N_8`1HCY|e?__aaX zqlxS5jsH{a#b84vRZNCQMW56JbK`Mu5+_f7sn|An<wdCv-V)cI%dfxPDVR$vd5+8z z6&u+no{AhS&cU`}ZmoltdDohj6)Zh{`~kK9!h66Cfk&?77qy;eUy=IAhsw<^_2oUu zfvV0BFIMkf>lW^jII^5Xn=1bNN%idF`Lred5`1WTh_nr!Id)-*&fd73d6fJEzIeU< zYQLO3Gj4r}&iASNL!%UE;B!7$6XY5n_gbCt@o|ql0}bfcL-Jo|4A`ULnv!dYp%s}a zl)WlS$;p_ma3}sx_*$M@OR|C<Uq3AC8Tk5>VF|vjybHKJ*{{n&mw0<e<h;-Vc1L33 zhH4t$FvLf%4GH&o&k6T6a_yWl!K1(X{O`rCO=GPnc{KXRW0KQpKMS4_J1&Fr8_IOr z%M>3r|79Pm*2_V#|NTT9g~X|eufdu?F8hGz<CX6wy!;Bj)OcKl=SQ#HSJBe^PGAFe zSC(3v<yb3&t3yBD%wAMrfZ8{DZm_BB_tysxuwL!K_nK1t*Gt?>Rcz0Bxir2rmag*7 z(w3H2ygje|5-)w!T5%?p&bUwO8oEdOK>|l?t$6N_%KoJ>?bG;s2Jg*H>~GqfiFrAR z_%+!dAg6f2c=(N&U~AD;ri!Jmh<%~*NjGSP(qG#AdBJ~IoWzD3&6%i`6`Pv(SSJfi zJCpUF^4-UdQ37xOpW}O$5*zw{Y0C-D18aB6__=xP125C``Mu!1VfdB`i-Vk{N#Z@p zTa)7DeK|Nx&QS#Fh!gT+Omoo>igy^>OxoO6+H(9g+1D?P{k@XCK(XJ*l@$91nLI#U zmEUM!P3#-HV^h#BF5_E5d>d|<##!N5y}PkEDDUEbK+pVr7&e23Ejk(+O;Y)ew0$Rq zzB6xZ6OTTN??Ya#wL6EtNd^Dy?f|E>pIxKv6aE9Y1K=Y0@28*>I`OS%nX@xyw%0n* zUT4;J<OUAlLn+g#W5l29_Kk7B9XwATj)nX3?FsMQ^PlzUu))g}$UcQnOP08r`1c9q zTyaxr%U9tzP11~gl4rlgi^0_P8E5a;e)th%s*`W-6gVq;CZXTxQ^vHRi9H~`FA0sP zqxS4QUiwhw#F6hiAg4($S8D2;y6ktWZ}=hKnZ_Y(Rb)u^IYplB`(!<-S>(s{kr$VF zEvbh1WM9QL^v(=~96I9D6CM4KJ7bLKj|{Q%=p*M&44x+~<^A5_oD9SI*a+I~hU@sh ze6*2feT+RwDg98-xAxW5bJ`Xfa6b)OU;)=!UMK9xnb;-utd0M|`m#TE^gVa$q4zWR z=EHuy`Y?KKB6dFULlv3eG`pF#={~{dfV-4E)2EvRSJBz;$a%oIe~F!>Orbm_u}jyN zDEV%h*ACrrzk+?#^Q(Z%IQ4&DKlXF6Z{`eSPboYK`0RHYO~hUBKKi6Mj&q=bw%r<h z)Ad@Wd|!$Gr-;{yah*b(>Pc|Ogg&g1X+!8y3vE{_I;0K3UPjL}FecEiSlUQS&|Y*C zaR`Z6j9{E!ih-Z(P7egaeQ2-xZnf_#xY;*hTRnu`4}S74xX1l_F&!NVkHzGf@LK&# z@PdK7%3h?5yF4fELB1uJCNL=_o^1@jJNX}^3`t$qm+JgdBA!5E<k`0mTCZj6svQkl z!>`5K2Ysw@=;m?I<B%3Cz|NESLuk=o#@^PLD<&|8J{h~LfZZ9tH26xtm{S#=@WLK< zrrJkqa64xqKjea6q&>vAjxl~iY(PiaoS73)bnP@;xBg-Tq4OBk?-}e7Zo)ojP-B@< znM0p)Vkaq6C>bBkH-wl;Xx}t<mGXV`SM)3?(dTX_7cp~C;=jmQWnW^!R}=@SduLqE za=ACAg1%bM1%jLpNt1J;*37Kn+*#D!!a0{->e~zWPQg{hLA*asXeF_UB9lTdYXx-c z#M-f=qD^nUui_()I!)FtYOkUmd!ts_B_fx-p~*gJPsT#*0l6NH&63EkBI64TbZ%@9 z`mv$yJTf3v(>7INlQNeuMk6K1ojPwu9E{8@`3>N+=Q=b087;_MlH`1>?JD^1DQn<O ztzeXV>nOu;s@0jdZO+VRO!t8`4_AN6eDE~uSN19jh>OZ^RQ$e@c_G~{!ms#gv*2Cf zE^eSsY@Zw3i)?be1fN>ZS52OclkZr|nPD$aSj(p>?@R^X0w)iQ^=IPoi?-{DI;=17 zO?-2$?DGI~biqEQ^F~T87BybjPT=GdobXdka!;QOI<b?6w}&1Z=Po`8?AToB6B7Fa zoM<n$fw@I;=>;UF#+zUEN?yk^XLOL4INdVUc@!@{9dpa0laQw;p`)CU6W#uq<jRp8 z0HrNQUZYKQeyv#BJ4WU!`0-5a(krcPiX9+rk?SV*ZyvAg#g5gohSZSI<|<-_;g^}@ z%?<ZqUgEnZ{BNh`sFD$;<gu4~$f(BHr@+%Y<XzycAr{}qw|&wW!<530duLVF5MTXZ zU$gLyrfqgfv0-feW5g~gH;sdn{<aYwu4;$Rq&H_*Qt+D`(0oPdf1Oyh1wBg)MV{|j z)7rXOud3l(%Sh}3-z?%wn)RxYT4r@`iD4sdVr7Y0b%6Xl&uY2h62m`q!&jD#OxeZ6 z`uh6vK5NqA66~#UerqfBiLbSNeDCYvaJ{JGE1N<GYyF0A=jYZz_UpElnO0N4u(Y-K zrprvx8OD`e|1<1c<F^CY3#^;0eS^8L8AD&Zxz^ISE=i`&*1iJUY9J<t*f(3tH|+p* z*00R9xVE-RotrLIIP9Yh@UR2JO{;-AYfs;7X<Q$aI=@a5d<3q-rvZHSQRmMO@W~DE z!KY(fxp2<~@%ioS8_(c#;y*8l&mZCMR(!_(uKHQ6{{?ZfXa2Airz`%dXmlP<znD0; z6{jmM&aS=}`}+cP@=razuobUMe>T7BUbb~=w89JFSM-nP9&N?1>xjoLgj>;pQ7^XQ z*45YRLi8#+dHj2=xOKhy?zVUpH8%{C@v*dA#+h-F@$35gK)58Qb^MA>fB#2nd^CeP zjE#(6*Yev!TZ{cxeEf>O`1FsKjE^S#LMh|d_4QSugOggvujp9gK;ail3sMJOk@4%A z{==|uX)8Y!ok$*eK0f;GXW?^T&+_x}`K0nJd`=yF=X`v=*>)B_pY_^*K0g2T$yxaP z<JB9^$EQQ%S@;}3_U`%kTr}e>e7?T1{Cs@$|2YevZ=OGJK0cqeKMSAOsiWuP^UTS! z@cHuopPr9T@_T3D^VPrg6@2oJjGiT9W_Lx#;^QVbDS4Bz>KZicBQjP~^rB<2X2B)z zNZxRfefw7AR!cUEzMe7J<D27^;gYOYzVYxZGmB3DWQoT!<Fi9s$F%Z{hvQ(g=pUy) z_V~p}3mvRz<rj}$`DW3{XJ7Vs<<Q8m?@z6~;?ZijS#+xOLl6F&&tDM!m&af7;FpfO zAp8@X8a((LCS4HzH#v(v_|Db~!vEsXG7tVW%@>4!{GB5n{M>05gx{P}>%qUW{RQEF z_TIZ5{9Sn$g#Xni?|bl{{P=?K5A<B_!M9Fc5PodSZ$0>t`z{3EKj>H=fuBDp+oS(& zp6>UTjp%1<*BSX`v42;3YPab7WZnPB3k$*}x&Hh|uKJDWfB%A03+zCFVf_PLkN(JC zuryEb@vpmYY-nrHpTF*oS7i?HH$Hxm)iA=ab&nVG8+X(RUj7rYqoISQKmWurTljKl z#<Uu1-|dDSX8uBt6lDDHEx~VS-cMJCeJlM1dCslEpM^Co*9v}CBXb$L&8YcgpWrvN z{29(~<oXNBN2vK}=+s+$3cnK`eg#u6UMBbrtv_+Q;8#%ZR0)1VH*PFY_~F+TSt;1~ z<@JK!&{*F+f?q*w_e+9b(VW9G6n=Mj_~p%cd!FDYxGA|2oVIv42|j|0nkR)u%^nT{ zUtp^_dJ8nU0+=<TSF?$2Fg^J^01fU0Mvcg4_L=rmX#WG+uMvID{Y3jCX`gR4SvA8= zr&AU4Znj>By+M3=+F7vDJXrRR%b9nxb-qD}T$+CDY4#XsSKwYl>?v@q->`-RHfvR% z>R+GXI(AS>-2T}UdOky~r-zd(_vK!!FFf0~zr=y7T!-E_%CWtE`rB%9E7*OoPiO84 z&_=r0wAfARToeDrU!g~z@9A)!Mto^{^nuS`#&0nCst53UyZG#u><M6hWvCpv_|ott z)<~{saztm8p5A}C_^|Mwq_e+%t=O4z9+c}Jy7j<(iE{zuH+2gS=>_=Uu#5ZS*9<6M z%ju6kP(B{@?pI%^cU3-w<GrxC8~QEMhFXiZ1&1w(?TS9D4VJnVXLO@0Qa6>J{z!7S z=M-yi?ht!6PvaX1zIZP2wl*#2t0mv0XNNvqU)fvMKc8>PdY-oLB_^AE$4|B+&b&es z8}oA3SVIb4mVWJfH=Zkketp&YO**cp#qVqM!=OJt+PWeB&a(KkF4U8Fa+U8^>}Kd1 z<iF52#Is@2S736s{@B+luh3HJ${FR;`~DJtChd>m|NjwNyI9+)&eF!$r*n(4?!R$- zpQ}6{2XWkXit>Z`in5OU7j>tN@AJY;$;B(at)i@j>&N$bzeW5`{7)~+N*_GFPw1C& z{)Yc*eapJ(=Uiv-!&X1NOyK|>Sp&!!@=3I5LFYYfXzb<6^<wVj8^!S2PYn3x&I0-+ z{&QKI$eI%0g`Q}SK6NVA?j0o0q8kGP<l7OJ4NtKam0Semevx=zdB;ay@T42$%n)bX zgwE2YjJeRbSo^Pi{c5zN(M!~NV4Lh~2yUCenZ6XtxpmrjF>fSmR5?@GxAY0gooT(R za`|dKV_G|D-+fwg!ji`>_GzQ@L9fRAeOf#Bn{Q0#>CL+M!=2~bJ?B2XFX$HXKeS(0 z`9I+Ags%#I(cP&M%f3e1*#(}tF7L=1*uJB9wcUf?<)c>H<)c>18kTkLXKp=fwffjf z)<oN69p}bgdP3-d@2!^p!Baa9$eOB^)~}qqo|?Er<@do)TzdKgmA9UEWL>;wBXz5) zwTvqCM%AmDUWJZ{EY0yp)*kg2HI`QueOX?WxAV~_^Nu|F<m`J{d*NH2T|>P8v*;PV zy%n9>&}H@kEo~<2B6n)3$@6y6`i3qu??o?cWS=M2&}CK%XMCS!|HONq9G=tArFM&! z6`t78C6dnd0j>AU6!}&s<GX@)M{50N9e^%g{q~`)z)0ac$Ojv`gneB1){NOBvDJYe zE+H>+y@J~zasqf6{PJ4wrAEtnhj!z2I?6llMpd7f1XZ$L=DByxcQ<$*Q}?^ZOYeQ} z-o^6Vo}->$8ZR$VYf<lBH~YxleEX9+6IGqd;$?SL$GdmAJa^L7^DE+I4|yKHzEYlB zE7bFz@$!4}Jbv9vJ>ROHUuAh^wtDVeU#*@WRL`%myz=|%xp&=1p4&e4ykETRE6?NC z*Q)0w>iIz1E6IJtbMJbPJa<m0=hwx{!SXzQeZ4$)Gt~1N;^hzIdHgz0J<n6m3tX?v zSI@ocBK5pnJs;|NrN3}Nd6iM~=#!D3AN5OJt0q~OXUt3KPD6?5?^9l7X$y_~L61Jk zI@xpv9b#Tg)}0F0)Y?kJs@aRJP-40-?KSP4%;^<5etReKIh8q^|4v}JX;nz9#!<e# zv)uFp&$<|!;4Ri)8teOcb+kFj$Y1d2lg=Qn7c}ePok#u7f?0a#;vBy_bu;&7>GoUM z)T14ZXM?g$>ypW)ePos%nFl;df4}l7!O<yOYB*(+O>17Z9$7%$-gSET%N&2<-0~{g z*PXg#>?EmYQZJd@*pqeZu{u367<_8#bpMUzRpBE?{rP3|_mX7Y{&KnLl+_xML9|uI z^?)h#yG{?)3I5c-3Aog?cV-#(&MBr-w_KOLI-$vWs7sFDKLfaB0%I0-q14l;H_Nn- zP0>|f9-pj7ZlSHN^l!mry=a@K7wjW*S(k8cfb@Ne?(bV(6)6KR83+32+?H%c9?yXm zO9ig(3`*wvg0nojQu=S8KK)nqp|=yKv!X3@E;=dW3XP$kl=fT8Su4pHWEsvN`gtpT zq#yQ|-Z)rw9=-i}2|8<v&dxmgD`PUmqqBdJM`!DjY}H?n&e^8@&SX70)#rEOv=$mW z3!vXvkACi{{iaoy4ZV{Uz1{kJ%4E~6-)=_heSV?8j88=9PATKyzq7o`UUJCv=+F7a zjl<zN#)olpH}2+}KEMkw4v(RCg%=oyq7UHrE{ucQY&wjI8!O|TEW_SM>^0+p|Ip;T zI^)56^k2rtNxPddXAB=-ZWetA%sJ~#(cNl{=Il4abA0e1G-Iq}jMRAbe|T^Hpu@|o z7s}00SK5G1_QcJma~rgXkC#31kmBv|M4w;eLGe7a^!Iysuhq4V?>8S_W*_l*+4{Jz z>GYnWTU)9a=k03jts43;2tKOeePpKS0Pn5XZQ8q%8B1WVxZ8Bnmz$ht^~-qLUse%I zG1&Cq`0!rE8)ekly4Q^4LQ`mFZ7qj?C(B+X{i!1N{Vda;N?oBnyl&r|Z;C9*b$<Hc zWzOK`*z5ZlrzyaMJ_oZ+rwe>@(B}_bLVucu10TL%to=7Xyw~;}BF8*(09^6a5o?F8 zNcLn#cnFzsJC&Ick(=6w_sV$XF963bv|rK;-KtDy2)tS{*mUMi#_oqNWPFgDNIL!B z{_tM+hV`a%G5y~OekbmRK6SuEK2GGDkrTjs)6*GhoOX(wc;n=b*=&klax<X8ZB?e5 z0q)2_Gy`5hJ`(y$=;k+o^XPWddE6T#H;*x8oSciRIDcDaM)RO|?iAf!wA&kd#z>9N z*SuHW7g~v|9bV>^gKK)S$$9D4@ew`hFMoKi$du4Y^r(!F=oQh07J5(QsC9g<@Ww}E zNn}XIN3Ol`5&6k)9UqY;86PE2$WiOq+{xG=M~SiV<cP67M~-A%5^^N+Q}hA-L4J%b z(E2gPNX92?7T;Oe3oVg%<Vfi@WJit9hw$ed#^hr9&-jQOCC0~2$PwcsdcSpi+Q`uv z8LBds?4a{Rc0_KhE!n1wk<vx-9~o&YM<OdCCy8-VdXO>lr!fBTvdEXxr@=ZsAwwct zB0oxw%BpmcBQ+LWD>-T(mm_%}IkM8@GBnqdAt!y7S@g-{nU+?iM}i_ZReIi$4eyIQ zh0=2b7bR0NmP(F-vrXrgTEj_SYKSa}969Nam`+#TN3Rqeq^&OV;hhcdi)`6Dsrxv3 z1-Y`i&Nb{er?O7=<jPqvMUS9&JbK{UYI;0V!G4T!AIKOXXZ9DsN3NWU+rbx_;S8b; zWJ~1A83bJFsc}2>c&77MwSp`1C3BeQ6D41dS17m%`9c@yk%0+50q%)7T;$a1ihLnw z_CDlX<SgqMbS8b(Dh!b~Pu3oxFUh*lsOThcZ<+1EMc(Y4OAVog$eVL(t%BPsZ=9VG zJu7sQb2LR?$Kk@WLL-qy`xtPMKTDr)T3zNE&VpJ)WKhZ90{Tlmp;u8eaJ#hg;3~U@ zx<WH#(dnvraFIndpTQ%-H$o@jm!fata0dVv8i`EWUjkR;u&$apr^0Z`G~yS%dCe&U zF7-sNicSG{z%vT2lE<ADhN2nsnlo^z2RA;iSsHL}1+LP~z&-834M~5Yk;tcg6u8Kz z(}u4S^V?Z`6+6RMBA=~%g?zU1Ra`#L<Ezi&{e29$&`9Px#aA-dwdE`3Iwh-Z`Rec) zz7qLO@Ri7}6X&ah+@8l*2jXyV@%T#QSNKX~w=G|Z?26o4S{uIl_zYi(94GinWH`ZB zG8f7`D7<tQUm?#*j)cx4d(4T#S0cY{`KncZ+wv9io8T)?em%Yt`AzUutNfnJR|)wY z09@fKkze>q$!{CJYL(x%d?oT5=POTsJ-$-%8|SNp{GP{GC$`^{cjT2uky|BuBDVvV ztNGDBQm14#K_ex1C%4}tGN|5Bb0o5-<aHKvB=b>Xemqw{eI18`oGMupIqh0!ihQCU zJsFMDM9En*aF96#2N_i~QSzBgeeg@j=ehdmn>ZY?H$@+bTs~f<>`c}X%GONKK+2+1 zz(K|Yj>x2<fs)7NzyZI6op~;woc7=-J5%(J$l<M?eJOO1xiKM2QWnLw-y^z5;HWtg zS(5otXdwMh%#YIdv-Hhp9vqQ7p@Fh7yFvrxP3WLxE=~iHp`yd|2VJA!Aag<kPu_q* z{}b|-ph2sCIS_{<b}0Hq$r*eg@+EXoHfEd#iVr?M!v`WK(s${%eGBxCkG+(3SLE-= zUSx1TCAwoL^Y{_$M`%&_=JtC;PK>RuG=_IVukX*&3qRj}kCh5du4K;JTE)KdD~-Yj z?#8~Jy+3HM?%a$%osOJzNXEVxjBLUWVpr1d!VhS(mcHKAj9rvZZbja|hPl``OZ|6` zOfjug)~DcLH4N7y#psu<l<<JaPEl9h?~DE7d!^C&jJ}uDnT`*A``BdDPA|jG1NZH$ zTW{XXTwJCX-4drm3FCT@F`Bg;eBh%J=utA5Tsqs;JRjOh`@OTFO_^SJaQi*sPT<eA z^v~K}$NADJ)E{m-*I<hZZeIY)$NFRzu#lOeBhcj_`O<_>JJIfqeW|}(@r1Q{vguz3 z-eqNKo(UbwVZGpEUxGex&sjHFcV-Qzem;IV=(Ux4CDQLQZ26;p@=y6H@MSrZ7wOJ| zwYvDm#V1~ePphsPUn;(WKjZHr)+s}L=;9j}zZ>^eoKM0>%75h-6`v^At^QDXKj91I zS})3ab@%u_A06dd#Sfk3?~MD{@u^CVk+{EeOfmjW6-T0C7wfMw!v(3E$Q6aJ{iOKX zC6+^c?Ziu|IHZ(#zM#UZ#^M8idY8oI=2|v>@|wRxJN)SP;D0^6{lAnSnLL8TB46v0 zi^px|TUPi|-Ddpjg(~($<&YLXIdwX=@s)oTJ)jMK<YWBX_{zaAUD}Vg`wQ`(7HfZ6 zcvjz*;md2ge?Z)f=g*BkMBI)>OixO<V^2rE$tymia7WIX+{_vBVOr;fAK^E=xyDb~ zF?{o8f4DFAdud&HMo#G(sdJI!T@80k-9(*E#6#b}y)O97CI7Ja&JA)(9u@yEzUFyt z{KVpWuEZZK-)hWxvPjdGaZM?)*Z3+o`?*e*Ysz-iOQTGoj+E`WpBAr^D%afWK%I0- zA9bYc$bI$#R6CvIntPq8qf@3)N6L%1kN;2A=_1$M>q?yr%5>^Tc`^4h;&m>OYwlfI zto?B$G_Gy+;Z_nC1dS6pUybp~Pi={h-lKJd{+_;3?kDzH_+P316GH?oZi5c^z5mce zyDK-oqNU@bRsLIit10+UmH$?JvG{e<@ad+<{h95=kBWa+7e8v;zng&%H#7b`S^T@R zMiR%L@bC84dgI?!{#)_q&fJ3kwuUnlo=>!Wq>Ov`ZzF>mx`=;Q{CnY@4PD~?!VZxI zo?kcqKedf7(eu}Oe!<RhU!mu(_3nB8TF+11HSRC={I%Xa<*$wVelLxe%3mA5?xuW= zp6~avxDQzQYU9_+R~z>OUlA{ruQq<Ie6?}EZO?eAe6{gw<*RkdlrQtDc&U7~@oVL) zb;$3C-~5_*seHBZYvrqr`+fVxOXaJLUwgjVo$CF8wpV(-TJPHP)h<xauXDW8^VNFS z%2ylr``!>Qm9N(BSSouxKK$+mxaG~dS1T0XIx%^&SCA=mi#*cMg_x?W>JjWGdj8&m zP}53(#j9HH(4k%aiguhmV^1OeEZ=5s3pE+ae=BoD{C<%=VHI<b!S}nxFU{QZh{AVh zy!01NA3n>d8MsjRg1mpa+($?H)Lw1L-MT&RZr#1Pl<#pCvmVuqaPNie%U)-Ozc0Qx z)`{N_suH|1>`rTSa7wdgWb1{8e|7_Vxw^B8xxG`6^P3~**(Iy+6|HCPW8O+#=?{0> z<+o;+n%4F*Gn{I$KRnnBO<(A@Z!Xg%KG7{n#+ES*YeunQPb@G)Gl01@pAwjq(VJKL zB@a>2FV?*R-7;jZ%A5Gjn|3GqJaN13<$znoy!YuJ?1^Q1v;=qu@y$rw7Nxa4%digT zlgo%byNUF#1M}K1Z#P5RS)0GHkh$@1D|nCpLBIWAnQ2GLu(hfG6>~(GxiWH{X?0s^ zIE`6`vyT7wuhK&ucKJiyR{EWF;Mu`YrG0a*;k;R3hHu8d9$DyjURb3&jrh@S4*H$f z^G*8~CAxJaU-!SC7qt$q(yea0&HTpAW9?t8H0<ufnVYePSFX~-zl3HJcKP{+q8Xk* z+uMel*74i<Mgnyja}9C`8P>0}b?40y@B)1}4lL@1nt(%H{|9$`Au%xdjTe7m`&Q}p zFOp5`*DDQj^Z_H;3_Stf>*>QHfw9{REds{g-Q*A~00wm$gNEIM@xVTC-hA5(_n<%B z1;%c!fk9pWhjjt>*4@CUde$wcFTXCwo>*yE-IIaAda4l^OM%fKFo4+rjD}>>jf?;W zbs9O>7YL}h2j|UpW;Afr9~GKWHyQv2b^W_u$P}A3zwt-!S{g9k%{J{YwEAT^Ft8mX zz<|c#Qh`x!hD(9*26%LT8yM7S3>a4DU552lKK&SLhB`wl)erFN3=Hb}ckl7pKP?Bw zs)hDMXcZo8T3^wRC!p^-`1Ck1o~0iL1V*+QIsgn=zy7ivFsReG%dm-iv%3uk2DZq( z(CU}c5AeGe7}WK@bxF1Lcs4M`CRsJ~<12Wq8!#H7?>c0nJ20N3AE^QZSwlvgt>E#* zSYS}6Q8TRRV+=RU*pROzG@X7tAuvRafI(gVYrO|sZw>~=v`yAl`q3@lbcI&%vhZkB zXtipUk`1TPlMM%Xv>LAh26Y<87)nmMF*a|;WusAGcyb|i{X4^H5+{}4Xupb#E7=ga zu#Q7t<RT>f_>CtU!uLupgzu3bZ~#V@Au?kBg0X2UC)7>Ii2t3*n?y$P8-Muogp9P6 z50MQeBmaVYh-`>lR4vnd{&y=r6#2++{9Q|18By}_#7h6aBqMtkzwgON>Tmw9$;jKU z)O#}W#n1n5$w;)j=@%Ih`G|I#fUa9>M!T=wBxU6IHorY*l^*$OlDZ!`-qa%Zo!_p~ z{qG)FoZtAsE69RwkA$BOWU+@h*tCylD|u3~b&gE24|YbT7$;}Pg=H%8%L#sKPB!aV z)|DTx*CW3&;nnqK<X7PJSNwcGn1s)Dy&k<`o8S8nUMIkdd;Y&3*_7XS^K|5gymrW9 zYOcYY0$zia3@Uj%M-GV_JR^tbJ!i*-<uLloNq)(jU~L7j&$sK*M}gmn|L;-YzsFwA zA0~j;c0KZE@KyiUZgTV1n(n~uy8pedoAVo&Y(?hCd5`>-1hM^*pX1(~reydW*|m?f zkzI79v*W_D8+`(LjFx!~ypHYFql*Qvy=HVVc>Rriq2q$rUOn;+c&Y#3H5I&mx>xuA zt@lOwjmvf*)7S{ZO{)WQ!@=R;mG8}iBKPOWyNwLD$~(N{>}WGDwvqR$S2%<A8FTGH z@H)O<k8arJkNyE(YTR!|H-Ovwls^#Mcvc8*>OZ*EgWKc#nM<$zG{3R`Pvv{VmT$Ld zPY4*cl*fnbGKVUC!Q9w(9<`6aSB;Fh%%kXKXUB!-(dcn#mL|Fa+)f_Sqo;*ths@|{ z@cMuf9<+~e-v%%BAG|h#*MA<;{U4P4BEPX_mCU*JFO$*bYp@@ZO}lxmns?P4+!&vG zDP_L3kF3?z9NY+A=yGSr1?FDrMtVS>9c$?Wc>SYUkM!K;cgvg2NYADg7hgwok>Eux z>!(e>_aD4syG@sSL+`rtcLn9ozi;(O)~!X%m3wy?Zh1NW)ZJ>X4((k@Ti$#vrPBaC zkHGJHN0@FoIHLdE(e2Dg1OAA;3sv1nL(nS&;4zwYbNLkf)gpiFTL+q2ln-nvI^;-| z?sP?m{HNf@Jim19CMoTs_^KZNWpmz~+P(He<+`;a+q6fIGweCprq!8P5a##r=#}Uh zZ;qGJEnUN20ygXD-{UU}7!tc}&mC(<OR*zHV_Q-uS{hVkq~A8bJ@;;WZ0t2;A)i{g z8R<u!?#|TN2QCxqbf*+uahO;{bq~BIg4g77-QOAeF#WbNYc4u0IM}p~R<LJ7nZh0s zHbLkpyq_Mo3n=ZHUEoy(F4!RHYYd64cP>GPvA-OiyHM2)*Dz<xJI}&Tmp~Ktl0r)b zFS!R^DcBC+C42l%@9lc{0C=f;Yc~;(q2e9<y;ly-AGGx+)?4VBFUm~&;#&4}%J65+ z@^sk6;58_2OHewg<G_pdF1`mp*)GFrfPV&GXGT&P$BV&>I+0ZHl6SU(*I?=n!Z+3+ zc*#BR!hbI3^}{~~pZ0t8@O|L8f@ePlFG_1^U%l|PHSLV8*K89TU38eUJ*ae;m5QHf z`!0WEE4DnkHnJVt9Gk-Vezi&bDf)7p;q<M*Cfu!CyKgrmeZlMd3%$C1gQ{+1I^&2B zOX5r;6&_xZ=^kF83UJvvS+}?D*F)364_reP;I$Qc?Ho+(#>;mYm$<JBpEwPyn*tj2 z7;ZW@C+pFhclo0M@FK1@dNX)Y+BZYbvSiM3%m%*-!>+qqx4Oi2SOC1JBQ}ea<VEvY zU6S=m(PbKY;$KekhYmu+GU~jJu3+B)zoZ^|af08u`H&v^4f<jR_R)*rcW}9BeaV_& z#@2oL3p)Qp;)UJNTGL*z)WH8{I>pQNa4r15fbm>_9;-D}Y59WSw_LY$)&&c|Rru&J z^ca4^kj{8gH{@eHDWg7cd2G2Zd&SX9&>dxR54?(pn^nVD1Ny*uH*&D8Sr2UkH|~da zBLluV)9ymdbMd<?^ULPl?3AIOp4e?V-PfSYcANI@wR)sGV|od=m0=5X2e$|~*R{j9 z3xAb?;}e=8u@X+?_hzJSp}!6qMV>h7)qeu~s4qA;($-|~Y@Dn|9!7WUtTQ8%(H*<% z@YQbCLnqN6yV;-lasuyeHbW<w=P8|A>hz(Pq;4<BxaT%^40<Z#ZqqRu*kiogwD)e- zBl+NGpwlvTn~{7&mCoL!hP`vM?(BJn^|NN!x1iH{ylqDIEcA0m*%#T1e^%=6MXym- zbI<KTTkFwp8Q`~C@Z<S<@MA6HmM_x7mqNe2<$AaW^qaEV3}1@QEnj51x9ryaQ}jOh zkMz0UdE{>0>0cGsZIo}L+ip+jwnb+6b_0FIJD08jKXhA~=(eSX@RmJ)u^CN+e&fmI zc<E79FM6ryw?$?Z_w4z1>ydvTA9KL(bHQ(s8TkkJy}bxu0QOlJ`n{d4M{b9HkE}8y zVdzKcJiJKv|Nfdk=CA8C%~^-u3eIA0y8<0I%e3FE(nH<Qap{b2`YJQjjq#<lf879n zqT^mwI!^Icw--#&Z*|M?iT#@KrC#{gj4!3w*-p1AJ$gOkn@+620KspS8ND9--UWws z=-w#!z1vrhhQV*$dNUdo`*OYMtj3P~YQPowCwdvqiCMaJaT)O-@cW=L)BY=a*8k4< z&I7+e>&?i&gCC`H**Ne^=(+~O5njCEB~$cV-A9b?W#A|EF9ScyD(*Qq%+jO30>44v zr}z&Xeg%HmlFkY2wMW74uY<8O!S4ii+@s(}>3qIkA9}<8>0gldlT++>;ag9R>%3&s zey_~adGEo0?1hQWbNhmSUbSiOgy-_cc{;DlX1*1K&dXcq=ghiKbf2n^-jn*(y%=BO z@1svLz9r!In9vWK@=5T+hII4x>XDbg@4bBN$_c!?*NnUb|53UFw(CP5z1=97deNos z)MRwua?{mB_boT=zoGjybl(-=H<kHV1HW<LJ$5$uC9?-!Vc3CM!+s229M{eak6q}; z5AO@JR+su=*6C8edOUjX3fg*U8~PCZRttW6&FD+uhb`$&-LFSZf#2VTV_$;b)ct1U z6!=lP5AW57F21i*LH#2kw|=?q>T6qdpZz|%uRfvs_M72)#&^Mf)5;7ozHM}0mnz+< z|GO!AZ+@lb3uQ9C)C*-YzLeG6b7(tyit$|lexD0|`_1Sn@OvK|>JRDBBJg{^4jU8v z>ap#Lz>m^>Y`;Eq!!I8!*x2bMY&-Pd=D7abY}y~J)gxEJf6D$nWJaz8KkP$ii3Wb~ z+!O6g@uevJ_rYN^!kV322)@V?@S|R23HVV~bI+lzu(B^F>tTf-d+6AiHg=`E5nIj$ zzYlg}Yl7d#W;5!7AEmqckUsQu<*Nm;zYK6==rr_RtN#0NvmP0m(0|QlWT@!BX4Cm_ zDfm&ht^Vuzji>)U0>2L#U+P6ZWPB+lM%?YWSr5D0l>Q4pEc9zO!!G!J2oA9+dh~Jh z--nBo&1uKL?{V;pO)=fioAvN5EB!^Wy2*J*`cJbTzgu?(R+;v#CUzy|oGE(v)?KtW z#SGtS5VOTQT}1C;+wNRyxLwy6DnB{#F3~Q?2e?GL9#!?DU4yE=%)1iz6?zQ$IC8fh zngf1wCYzzhz>gAJP>;R<{dTO<qrU}Du?=5fexnrLE_!HrL*B%uW%k5#^xqrkzs?E$ zCq5(5f4p<J0s2w*XdC_4d8`>e3V!2}kHd^F^}>f4U&>1EIh|?i1^5sB7g`N|J8AC) z@WTgXPt4Y%*m(9E>#;$>Z(_C?Js>t{wrM|Ht{2W;*~6&$ajDpYXX(E!=)anT{>wHa zHKPBrO(zA~D*ZPVTd%>>f4#3#`fqL}<C_A0)QhBmA7usioZhqa&=ybsg?0*l*=A@9 z_-)B%pBS5O8u)F&7Ola~sv+)Zn%JU!P3tjyz|U?TZLF9*$y#xa{(CL1|6aqkTH)zG zYZdzMYES=JE6i5?XRSj2U42IXsrq8~QNLmt<9lP79{QN^MgN697ySB~p^w4uHE>wL zx*eO;er@mhHtA}yNnd}+*m~PDat`S%{m1_(KDVeQw%=egir-D0<-7@<hyH7|{opMt z6<;`Z-`rOi-<yuAdf}VI{u^voa8K<cr+WG?+(q!iE=~o%t=Pp|Stri`KV_RjKjqsN z+Z4MH+qCeLx8@rMn=Tg{QR%;9OO@?szmEPpi2gga61|mgh7XGV<DCu{(0?=Vo1_28 z+3O2+V0@_;>cIF?R&dXmv0RVb?CHPAErMUZ8Mzt!UKiVRxE@*wey@vd3VsK%|5l1^ zI^48A&)17OG(MT<OYLp@(0|7_pV5EY(0{&!{u^#ae4_t`n@+6;{m#*U+eRq;N8V6h zq!#?B7pVn5%1Z7zv=uD|KkUD#!Vep@82q*kXJ6x=*{8?4<d<DPP3%M`V@h2AO~F1z z{~6#n82XiMHX{c3NlaQ?_c>zsVgEVX(KDUkKkPp>|85ukC;Te<ugt6*hW_hBTMv5r z&$CZ?{vh~mFEj0u-Fm1Qx!sQLIb{0Xk}@;YjQp1DHpR9aT9Q7opnT~hyLpQ4<X4$a zxvaUXO#98<dZZluZe5Aq+HFS44Zq#YJ3CoJ_do}J&Kz70ZrU2wMfk{jc=K<RcnMjX zM>X)Htbl&9Zi*}gzw*g(`!v~%ECs)YWYZb9NDpg_@7v|dPIVq(?$*Tq;~Dl}(c71= zFuJ_b-C^D81hD(|iG4u1D_IZkga6bTmv{C-KP}mGgRg=kvc&q<4Kx_a{?ouO7{?F$ zK*hRZA4vTw@RNAS$Wc!|Jo~iDj2s2OozP+DDm{#S>U7Cwu7Hl%hGFbeDeYa8b^q$` z-H^ZTA)m8umTrGh7q|Z?yP^MnozQ>Sw7&+wL95uS*(LTXx{@`x=)Ya?;`J|>A+i6K zAs^kqk9whQ;76(K)9bPS#6BHVrAKoofxl;;O6jDp_xy`%`s$HM6L_}X^D|P4UF$!3 zO>zE-UyXK7)agzg{I`29Yct9}*6ESIg5Pf8Ki>H(_)$7HXoj<nx`VL~%HV}=@NE?P zba320y#f5B{te(qsqE7zwu#uMWz1o}06(#ju}_taybitm9`ySPJ@_v8t=n#f-xK>8 z`}B{i^r6=e`CUQYhIMWp{P*T^)9uRqaAdjZe9gRlIr^`w@E`W%<?tV+b4M+<Hg#{s z4m_e6ZgjV9fBl9TxfT1R7xH_@QB^N;M^Kf@K9#n_J{6zqzk?sPvDl}|Mm~XkdIfTE z1NP}<;CEuL8M#92=e^*7{rs!E%z~+Dzjvp4`p*q5Rr=2@z-Ai@ej(_$V6Pb+3;ihV zZ{`|q-g5ky^VQndx*T3y{5Lav4E)BUpTB{A)C+$D{V2sgbr#bW_NlXAyB_`XBxNIu zeX49^a#Te&fZwCT<M#7@GqM5uC2zm!7GOU=dCPkR^{YzoIqGg?Gy6+xSpRM|U2Cl# z%EUfU_Mh0B;Mcg{bm~n5-zoMV^KT=(P{3N`{l9zmUnTUb2S4gX>cNjv*{AQL|HM9R z+^a{w0Y7YGu}_ta%vra{Y4BTI7Pp_V9Z!SbRBS^F`}w7@OA0n_zt!EiS+`iPdiLLL z(_MnjDuVyi`j>Z#4D{I{)A?X2F{$vJvj0rOxwB4puf#q@|0(<Q1M~~^A|Ie%D8)W? zuf+aaBKmJXHaYlV8;6&GpV-Lt&3bew_-$Aex1X{9hJs%`w&4=&=Tj2~6vTe|4}6g5 zzvQ_7OE%q?(OGwaU-?S(R<jwo3;ZbEp6Hd0o(>fKXP=&;yLWw~^xyoCu>X33AN8U= z!H-her+4l4?9=i?de{a(Y-6!c-Itq9=ZCYfQSa96(@lo`H1msV`lAm|pbk0?J63FI zDeWDT^`W2td~QLk>T|0nx-SM^<bM(!=*B$#=k5dVyI#d6M>og7Q}o{w`1Z5-9_C#O zRbAP`l)9m((Rpdfx}`C<F7faRJ?-J;#>(~RZ0Ht4=gdVe(#y^0Y~+G6GJBWb=~<-@ zJ!-Bfh~4v3XDGTaR>v91lZGqhpk_VtH2B4&E_9=my-xRw<}-TlLwK-gtheu}e0*ZV z!gGVf_Jr4p;7i&Gy$oKwFZQT=xLnzz;VsM;?Du&3B-;#c5q*+v%6@C)jg|hwU)O9i zYE0c3i5{z&Vme#0*xR8j%hn@XcKPjlv(3mG*i$v-rqhr4g!4YF`Yr|DyK5{y*rUwN z3(;xxp&xirhTfRuckZH1+7WwHY+z-FN_(aF-LOR??a_4y(8(#-D%1L!k#ua86;)<5 z1)80}-uvU6*Nqj)KKo;I*lWv8w|$Obtypea|JhgfbX_)eMc2`vk+p`ZcO!nj6`CRY zb=C@O<&o$(U`Ixx<A7~V10S(J53tTSFiF|KVt)$!@B#3`28}$&SYEwdkE{T%=LVaR zb>M}6BYGp_l($MRd~fc{d<U}GnGV0Ct|itYmwl(T=&-?h^rl_vo#>6wY-?Y>88H_f zI9RtoA%1;ptzqf#(AIut_+xBOvA;jY_5?PudTG?x!|kCP?S{n$1$MYSxY16iJ?(vh z-u(oAzkjbDIcWMVY`(||a67Ty3}OGeQ`hT7zD>=A-#kmst7lFa2Om1@ypFCTuF>1; zp_IKI(R0|dqSvHt(QR^u-kEM1k!g%$<8@|a`cc2cEvo)c14rtSHz-~9+QK)1V`IJ^ z#ts!6)VDGZLZ|OD7QTEvdJQ<%?$@I^;Mg>rvo*-&<=f53HSkmBcD<-%>(5*tI*$Dv zCnsR!m6%_uy`Bv8w&=JH`KIVJaKf+097mhZ>r0KuR%9}xz>K^OZpC%F>i<@7qaN`r z*nrUIeq=z}nE-CUjy!^Ga_J&7I$;894)hwfw7nhO@gQ>1iT(4b;5K%z>GVxThwRmz z5^VAkbOZjrNHMsSqpM56o4S!=`bVrz)CV5ik9Imrf6Gj_6E>bNANz5s;dWT#jdw|b zDe*yWMmD*P%5-7@Go8l1y5tEUCa|~ctJ!^aBOfX^fsYuTEXA|<(C4?)(wsphdflsh zdx2QZ`6IN9x)EAt9d(G=OrP6M>rKq&nDb*cAM7~3&nNd2J4wvuOZSiOvw9lW#B3Hm zJigCACUZ^9=89X#_xUQHYhpHU>oUGinag!XQP$%2<NHjQ!*ym+R?q73ecpS4>#U-z zvHQmN`LD~l?w!b=&>EL_!MM%=lm0Knb>@_wUiwu$t}~}Jwx>v9IwiLA+v7U-T>ig^ z>y&nvcyXPNHT>`5I<H;u|504$vH!otbrSoTNqnbH?5C97i1#FRPQ{0Imuv1_Mx89m z4C+XEIrp>Tb$ZA(_pYE$Z^}&SNO>jqd&ld1Pp-Mwvsn8#jqx;Fd9_kAFAzgI=S&P~ zzb)k8TX#+jX}2>mq^CcIPil*`InUDWc{$*QR`9LbXOoWIQ$IX_Z#C0h^7khspNJQq z+E2dyep2!P7i$BO3YYS&xU6<f<5p~JaO?Xt%J=-NjipaW9tQF*q*M2l<@O*)-nH)n zGeh_Qxc%)~FGmOPj~e@kO(u6DIU%%{U%{>;K307<xI)uBn0-%HeD51A^EKuba-LOu zLQYU}PSgIFis{4!2Z)ER$p~1p$yraHZ|l<nlf0*zb+}l!whz;D$w6stO?t<jLw-fc z?^$g~UhmAz737Wcf5Ueua|WoK#`k6f$=jg5t*G*Jl6$aie%!V=12bK|ttWBjZE=p{ zJF*gdujE^xR@48(+1bEFRi%&r4h%RT+GwMZVvdOhii(BpAgE(%A)_r8tX8HFSYle5 z)?&>tgJ6NZET)zwD*nt?TXS`@UCsBh(z4%LnX6@qW}B96TDD;@bN}Dx+&h3}?Qj3^ zxt}}t?VRU4Z|6DBdCqf)CwvQdA64+C`pCQLFVB&9??l&&!1czp4u83kXT0nhd`cs8 za%A5^fy2xbu}yLy{t_Ir55>>xPu`~5_a^O|K>K=K>+sI&-?zG$SmU*twPjg?|0cdN zaSzQMMmv&K9!GMeXn`pl<m2!JmsUYXdzLm&^8fyfcO?EjKt2h{wc_2@yF~b>D|>~S z<)wN;FO-pk*~)pg;4a;*>*PYQam0}yTJn0t`$it`%WoUGMRjsS+p@H(M(V0-f^(?B zBb1%UehVeurQJ(1R_l!!0rEK3g?T24y^FMzie=!Q_-J?~LGsghg3s+!`4`EPOa5$) zZ!AXs5At%?u$M^zeHZyxs52nA$t{lhHe4_HNZhhlruX^YC1IR5<0@&C@H_7W;ITC7 zj`t0_RqDIVTS$(J!Xu>ukKD`BuGk&EH@Q&d?<B8cgUy%dA*bT<8Imi-z;RXFrRW20 z)&8aiPOsTdUPksj4AsJu9obV><=v#NO7i)r-}%&G=CPLCw9{Dw5CQIG4-jz79t|T$ z9`etN7oG%W&ojPWT$g8oGyO2{827T}UXJ7@IY7RWqe46KWm|=IlxHD_jl&aqDUW-a zx7f&yO`dFvv_o=tW@(k~U*H#MO9FJWnC;PMPiD*Z07F(6V($Iq=Ja*XGWPnGy!~F` zqv!i`wsB4tI>I+ra+Pa-^0|-)b3gan39Rsu;;k(0u?@h{oWCaA@58Uak)rr%Ywr^8 zQS!r3Ue}#r-t7r37jN{=?o3<A;gd;Tmyus$_nZpDlg6I1R^c(pfu5x~HmV$+@SVIX zde6U>+(+BV4Zl_8^h}lVxpwfJ9HT1#%sR8(k-`IETF%c<u(Mv{QHlBA73N3DoxP)= zDd*F0@}1hei{MXk-bn6j@4qulo!w*GoX^O4$@-1b&$iNzXHTaOBQJ6>doZKJXph}D zHhz6xvh#XhGHZU=iv<05R`Q_xlW%>-pFZZ0KRs&<bg^YP!O0Spb6xWn*Y)*{JmE0+ zTL=tXN*<l1d$ns9>U!zIm3DtxtqWPG7rdDDjwbhx<PkmDZ;>YZiSIFUq;I3I3+HUk zlsxz72u<=wx!6Oo^v##aIe!AUB=42Ao8T2$a|o`UUdw*LT?C(z0m?v^pKz2VH<hJw z=1biz%W6>ux+PNO=a=sS=toaz<#C~5c~>d(@+$EyNV(M|=w_pAm0up%`PMQ@p7mQQ zxtvcp*r(D;-g?cwBch)BR)6L@C4D<+mOkWRMVEz2XM3J0ojLMQ>CC-3180J(n#F2= z33=CdT^2T=$~|lIFCfoQjqH_eN$Z+m;MzCxHF#}TUw_qJWYD5D<8;vl?;{GQXUIvr zf9O-%UdsCqxP0xGap{wGM@Y_maQWJQiA&4=@OK6-YZob8`lZbFgIE)3;PMf{r7Am& zOGnuR^cVTD=f}#smJL!)zZ&qm^s^Fq7d>Sa8K&(uMjg8hxmzCE2LHwht_KGA2EIZM zM)IEQ{cPi1tAAb=-wD06{C*1+?=bhes-&yez^&qs<Rg9kF&|;4v|Ch8-O$^RW#+ND zS5`fnHE6WMTlkTK@r~8YO(ko(!flA7UeT|os8e*JvDS;<o>2Q~;cw->C)82wyfBT_ z9zgQk<WbGwcePflCBG+1yOkcn_VQNooP13lz1~N?l3RSbJeT}#E%<-9$WjabS7o>0 z|6eLInKC<4rtGJHoPXrVcm&>tH!||geACEYlYW9O+?V|IvPMhgbYoXTXO=d{iN0Fn zssnE}GbdYtHeBqxGW4$42-O8D7g-wDtWWDK*Qs9g@BD6>i+c`i)>P>i=wGyqPrKP% zE3qN}*&w=lJnv+(FYLK+ZsM@+6u5wWVGA59JrKaQkaAqL$R2yQ2p$A?rk-|p$%G#! zf<qbCHtP_V;82a%e)6rUhvEfSQnxGL(Am@-&-|sbb;V952i_5$NnbdQy<k%WCt-Yu z4wp4t3MWIs(+Af{e>mR9+98#{dPwUM@2t)xf?w4?YLZ{AYkdZ=2p{Gp+Xo^WtbNkZ z-P!@)(2@5EJOfv<7w;U)8DuHGi;H&UvOnhA^q;+&`p^3GL*!?3DqM|2cf_GP=wq~$ zv6LBj3c8~Qy&JRo0{;c0t$H2LU9v|F=S1^8B`4;4@3nZ(?q5<ZHq{#RiLKOTaWa;6 zlwGe`tCCf2x4!7`S!0Xs1JRoiz7I$Cg~u#`hv4bp{E>OzI0yUc+Bx&Ssl%_^$-#Y< z+n;BwgOu@vmS*mmMV|1@sy{#`$5Un;<*7YAq}(UFL*FWuQ|+i+XRyzMv>|ux7a`ee zx^Il8<*q#z>cczUS9_OCUrQev%qa1-A68PTX+2Y{n%2h#Pt<8W%hJ#Zi^Z-8Z3ukY zV1<vYDsQ*SRk+b7`;EA^sl6E)GbNGR4L&Gsh?Bg3p3uT2)H_c4=JExi+ms$k5nEGu zQso8@Ru}uLJ}Vjc3i;dJlvS$@;+gCRxIy^GC}-6<!EyCW;HCe@9y`dpjAMlVu$M<F zde+YEpjp||K*P5u`%=U$K1~~9hLt?QeqfSU-q^E8KeKqPalfns_Wdc%D*IdUev-dZ z;Z*YLk4JaLEe1a_9;s@jX-i^^-%qxpoJxh;gU?aE<m8uk{PUD89gsGN+$<TXV2T@B z6{=t@V|}_`8&~$YzR6c!hK}%wO*6fvJnR^%jT3ngxz6hXf8VLK_qkYanyp=rPSAYW z+5u!_A@Y&yMLvAp#@uJvjtQrHorjfBZ^wbhh5xbVRxt)yf!z*my+^Q#zR!RbHFvVV zo7?-4>NjQY0EIsTcM&IL{jDeXhcV_FU5C=2*4K^v?ZH2!Kd@G_D4RP|@v-n8V@i>8 zay>TRODO&1<&x5e-gnHI(11W`THnqJ51C_!u?JtF>=hEB$^JU7{0PRc^8NV^LR)CM zxAgUwfpbZo*ccgig3~)cD5)Bx>T_b3pM|GmIG^I&UDdx<av^Fd@(wno$@9QP&P~dw zH0%cbB)0omMMr4Dm|ze##z}K*km{c&wuR2#A(jL3Ta{ZW_p}^&SNPz$DuecN&KL<E zo<`3>V}ZYP^`B_NkL^U~sC&po>F3y+`nMyLUf5w_uM_=XMvP{W@BOjhH0E^$x5;OY zD)tHxo}zBG#{<`jufjYh*9OmN2?_>y&cutrDf){&sZ={QP*<JVC#Z3eD_`($u>!N$ zZFVNHQ;{!=YbR}Z^fSrL>Egbl^pAfkVP6*8g05<x`AmMN@;eRs%;kA_4;UHaIWKPK zxjT(^YVp)vtM=@ZT=`M2L(A$V{^u5pPOw)EH2B87Jd`4I9{7XaSU#b_Q9igK-V=JZ zAfwjclZxMCXBf6_N;7`z!{drL$w3JWHqq08XBnG^ss{+|$<r!&cMt6qUFWC*-v&-Y z^p~L|<gXg}+hgnl@Nfz8r^fL+>A#Vygzy^nj5_swri{JVw@LF(Y3@JpFT~0Ch4K^p zRrqeOYotGwvGq{)oRE5DEM|_wb_wq3|KhW>hf}HVS9}if_2^7zV0mb&C-jF&GJZ7Z z_OSTCn#XOHCLe$?W~*V`vxWVGz#VYQUP1Je@w)^!Y8^HE6=Z28%e=+iXQLMwFE=Fk zV@|E_w-|Zbq4rU6pueLsbp79gLy<w?NEBTlyy3s*9ccK}hqP;*_!|T!;T_orfpQl~ zz5R=H-8al~&_^tVuei?T&-O@Nqte}4Y}ebhSnSY_{uf6ca_!Xh@b`RsoBz2J4k^c5 zaf&^>kJGpP{`=k)T8yj_m%TzVo(CrB8%rCK{Kyn=j5hbSVsE2{6r*2wDxKe{vPYzh zKY1q^+#wGoGTzPcU6XvMrH*C&y&Jnjtwo3Co6x02GPd<DHph=2qbv3B`0<Jg1xFpW zo!;BbQEEvA&vw85)icOcqUr||rQRnu`d1uwOMU{;ZT^QpRx&R33b+$HBR;T}oUfJW z^`Z2&YsSbvpo#L^{gmdYRnOR0^F`TbRg0_S+WX@1^`+&jN=i>|6}xa8b&RGT7$^O_ z?EB@fIUss#jsLmRhh)4a<&_pLHQ#;WU3pjaOI0d2>nUig`=6_Kr#s=*8vTr`k+JY; zWA7G$gMA~```YKM_qD1_hkkK0vb2Dl<ymQLQ~uV&zHaQ7Q%2qa_T%uqK9iVN==kvA z98c(pmw<7lDZ4J<89w%Jw#+#@8q(%0Z*cYPqFLvZHe}A3pidq655|Yf$Y1bjgL|M; ze-_oyH@y!1uvGei&^qB0zE^u5VP6+P(+!4g{m_P%{>a?o8wXE+REx|h-qSay_=c-; zig&dYUsc#oCH_=HCOT}QEm@|2*6m%({)H17hLfvR%S*aZt>I=|VR5a-H_4on>{;oH zWqo!`cF7I&lhZ4;Nb>L=l(KWzwAzuo`s@zZJiXEN2EG@{k^K<8k99{Tv{4oKJ$=c{ z`}NFwRps`alG@i>oPF_iVRlJwao(%B>{aG{JFBnv%}yn``?!9SI<Zyddwda_MStbK z2rR>Ik^S9MWj~ofs9`uZN92?A8F@Vo*u8sAm|K}JYx+s?cjk4!QSxis$8_J*cTD#i zt{T&QSKFHdDrfLnZ()3WST@4=LMBX~rDHNWbBX97c`r+QQ1s=m=r4y0-T#uj&%2{| zw@&sD3YYJ#GIWP;_^m=4BX=^nAACJLGNws1XyhOVgucw1*joG_)`dmLk>te)KDwQ9 zv6*I_r`%IAcOyP;83&+a*gweW-U&a7tcgCtpXc<h>HdtX&baoz(e04<WPR6U*?rMN z?XF$uFhj?)j&dApSjMpC&BdH<e}}ROmXRZzz0><WuKMEye<gnFW%^;x($~iMtH#Oo zUjIDVe^X23Y}|hwUl#s3UvKJ(9cuS)cOj$w9eKm+wY*97rFri9Qt#uvnM1GFazE#H zY-EY|F|K#<J1S$gH#(9%PW5#Q==&C|(yUu)llTy!UpODjui(G^X7pf|Csg?%_V5W$ z@EPn8Y{tsw`Gzo!n`NSXWf`)_d&-x|el&~$v+##SZ<>*$N#5x*!b8+=Z{nHoc$WKO zt2XmXd!hd#nJ@7KE6R-iP-FidT`#*zpDH<Fq#p5YOKupk2ZVOm$f_@`8cE$*IqUPX zshhpmsQWPG)d@ctb0-hfr$lMm=sD09``;)F8z?4h7wP9krd<`vj(6N3^9V-yn!x_# zaBP8jsy=1Uqc`j1zH2qMyAyumTgpuIMWO?Tb7Z@7eA%rY6nj@>Q1qzSg~()`lq>#h z`98NIdNALK|66Rgc<cd-;L%^@6y1DA)se3$7(~Aa?A|I>m-wK`hmAj=FiYj`5gZ7N ze0PerpAlXU%g@f0@SThee4Ulw*pL_dUf_$PKN4N(^aRUeq<-w72cZLfuzpJQk-<54 zf=6=>YQ{R=O%R?Py&Sy67&a1ho>j09GhmRmrYGv`JFVBbO!$>dhv`4mpue)2%9Rf} zQS1W~E|(`b$0y?$bnbAm6}g@!yy3r7jbWSYNAVL#zXa?-v)^DJsXEQS^FR(c!jFnP zi|k7o?8SQWBAg%}CJ!bI322L@{KA@N0tO71ZK52vKdAcSxFNOL;==9E1PoZJ-Xrfg zeqF_1@szueaxW=cQl?p+j7PD_B2_;MUS^v)%g+jrQpUL4$G#YxJMXQ*xmBwM`&!+? zTGecF#I_pT#im6kyr@NaE3bBRv1;$;*<K7K?A2nuk2-S__GvNjMe1T?o)~0wP%n-f zItX2b9>PBf|J2^i{o=(?msWhUH#H|O%a-YDbptuH=nrB&vlqXv#%1z;guLG+i=0FF zGV-$bg%ZBhVr7qC_C-r2&wqq3HalE)r1|c<dD)cRON$lW^Tjm1i!V{ZfPG6|scgO< z#yGi9i;`>b)oha%Fh?Q0IjFVh@|1<!H5>G>49SPz6-^$k6&w~m^5}|;Pur$cf1+8- zy5UzWGkk&6lj^THEV@(4I{nTTa9!sc{@FA0dCxoL_#t9}krQVQ_Z^v(Ep*JUc(m4| zUpSY0H+Y`{-iyI|w2Ak^X1tSEGt)b{lcP(diThLF@t*jcgwy0~0#CFlb+I4(6F=kq z0{jz$4X&H$B(Wb|VzoBjf4Xw=Z0!I31@AKkNT3{F5@Um#a&i=YCTbDPeH!?T)nd(i zR$o$94zixQWQfYS9|iAN;Tdey`{FN>sRC2RYt%efqLMB8NN+>f9*sK*U)ai*H;j{U zx9mm7o@p=5oI)QhJ`rS1cyvh@`aNuUekb|M>(N#9vVXhKQ1%YAPrWCg^?OX$!Mn^M zTV&5fkwN5Pujnz})zZ<+?rmDUJeM-Pjqdf{;L!E5-=Vq3;#uaT>e1!+hC|bRBkOZ~ z-Q!(SkJs195w2_6HBEJ?y$UHS4nCB<Cc@>M7x~W8rpcV&<gmWm(M=mKJmu>&On9mW zTa>*x(4C)PpVODi-lxJ-zBErs#;2_h`)<3nWZ*7zFuu0Q!t>e8#bqBUE&iQmnVGEF z#}0@V`_DEuUCW%Aq(uy@Q|}HJf0X#Ex^G8k*I24EZfCE%I<1f3j_<5|V>j>h=AMIZ z#lI3~-gEYQM(O=T##46DnQ~v=^H+T}o8KY%p6f(^<yUGSIr^H^jC{>PjxZbd1AG_D zclq~5kz1&=Vbnku_UCH$;K;}BTYaQ-;0X2~SQ|Z9=<Q3cbcsIq-I}#No$pIWEFfO# zPplCexn9OeS=y9W(77cte)3m!r#{&unK{M+^dx##_7CyDfG*Y>NBAF!XP@I*%|GSi z654Moowurlwzc#1Lhmwm^Nq-<2Nc~u;(Z79lC$4)#=ea3gdG|SPuObSf`;seNj>%O zc)iaCA0!bACVjkqgG2b9J%N=!<vAUmL}pBUB?-PLCv{0z<GDGew%_%NHtxBdYHm6L zc<jJ3d2D*CkZYf=Uzbj~>HF;c9%UQ}Y|!$0@#*20O>GI+ifjHeT)=Oay3KlR0!un_ z;9rW3w~RekKQ`)+y8M$rE=j-RVtH`wMlbD6U9WJ!cd{=icsS#qa=2b#^<{^qt8X94 zak=W~zx0nBB2(#Ic~5X?$d#?;RFfRkV|&%hcgVwHU-ulB5kFGAU-eDMx3AKiOQ3Eg z8;otLhK1+-ZQIb_vaj@T_7k+E4^#a*eo`$-_7@C<u)$in*UzwN!wsJZFbvZoT(ycn z7n|dvC&0@S@>_HR&thHhp?oX&@)jl^5}U<4rIYwpG~Z2>ccV5O8rdb*K<ehb+`JoG zJv{v#wfAmZdY0M~#L2yF{N88YxAVIWTW>Hp-{+r~<YqkjJbH24{6uBT*r}VC5aI}Q zJ@6A7^Z+u{a$Y5zyDx2i5AKVOzzz|Av(az2+TaP!4$qaa2dw@jFpd(NQpT{dj}QIL z%Cc_!MwboUq1T1&Fyu19H$>@f<}6V_%k@3rIF|D^iJ=hOK&#X&ZE}vHQP?&z>C<c* zw@MH?@ogV)By*6mS8E?)Ar1fwW1dhq%CS?9gK|za(b=^5#9nWvbM(P5ohv^x>HL_c z=*)FQ;8T4n{nYyDUqELgR;VSNcbRnFM7^6@(iwi#(rHiGa(${xGwey<h%tw}?<95f zewBPkVD`RE3~aHBSjhg4%Gbg5nbh^ugBQ_1mvW18^;Qqh3>x%z{nMa7_qOqSpLyTT z@4DPCq6g!5-{(CQnl7<R{(xI>yxBk3CF3i6=K8woq89uhaV5GwZYy{Z``cG^N6WEM zpsDY$;IE<Y0RI)rw<G)@{V4Nn18cP&^b-R!Xru54{_@m}PoruE=4*ZD(02Thw819x zoIRkw<U7Q+j%t)XSZI|IAm?BPeu4(%t4iz5JDK>Ddeg6pf7Hpf>}}uOl!a7&_u-z5 z4@5TM6)mxlu@CLoz}d=q4QCnm)^c`pUd&nc^sP=GsUKjk;uy+K<GXn5$XIL-i`bRu z8^t^5Ev@Pr>937<(OpM*cO3QgVoxaP<409ZgjXB12y@@#gtD&q1xDhB!X8+{GqGX# z#*UBIijK0*pQu^OkZ;iw^bK)7n|1)0?3Hgp^Dl`pbLu+rSA8jaG50L#H*xf&e(}wR zVNF){4}L24kWMyXbrPKOC9u53yN_xyCak%X)k|cW^0Fu^qEgqi-j8XrM{`2p7;A)1 zW24b-Y%a~$vl&*`Y0X-#18Xw(ugR+SenJ0}>~cvR@cv{)i^sI7oKv`#IHg3+w{uS5 z{4i$+=UKixZY^=`Qn*Uu8u`g6$(Vw^XFNw)GG`=v6UT8cg1&H6)g4Nf?;E;2vId;q z2b`J6WFh5E<+_mTc&_1}$X%SrxtB*m6RVBiMcmuVxtM$O&5@$BXY!rUd8YZ@{k*e~ z`_p;nd3=nbHy$+0Le3+r`OZ6&_&4;f@P&QJolW*$eA+4cA~$=sGUw$+hk{p&?0IkY zPltsUsLQ~u{u4g9rWv<kK1kck_#OO;9EeRxc}~i8z;|K;NM2EO-?RhH)6P9Vqu-Y; z=y&5S2Cu<mt}hMx5!0cGJ@1PeR^sbP-owY#oX}~?n)Tn7H76E%psxmJqrqzmZ5<6> z?Ocx}HUfNVUVazzY&z#@+^ZJ31D|ea8!di3@proFl-{v<-^SiN;98&i#__?qZ?+oj z{U~+4_tm8Ji{FMHUxb(6)*_&T@KF?H#y!V1_acQ~@fGY@%HGV-Fiz?Kt_bS99$u=L z`55)pVMClY>)U14hkR9@r4#*}`o5q(>hk{RS}%1ih8KBeX?n(e1<RLOB+nxRp9+>o zp|1gp;5dqLqGh06ivXVIm$p*%2oBPKqk1519f<6Ct1H*bd>?B<U5vSyFF7~B^)0mL zn!Yj9`}_DD*Xz>v)4zfvp}qI*&C31}yNR;T_nWUpmfq4y{FHIeJ)mg=Z-EZn8`xiD zNv~bn-k`JeyJ1?7eJq;!s&9jompZm4dV}oAUN{dPqYTd7;4_=>hO3r&{OIx$aE9*u z?uh7ezOjkjEBe@%mbHGyHCiidu(Qm&yM@oiz6kUB|4HYG9=YvQjxir<X>67&i^S@R zy`BXf8LMcSoFh1=Jhxr-2jM;2B!{lVw(-oeP2?rx5g89yHt;?BzA3)Kel>J5Z5$^s zVjG2kGg|uB+&7~KFFuA%EV_@mxZJmqoj0`zxhLzcDI=a(4J*3474yO_c+FOQOtS{y zkHFiSmAcX>U+F6;oA*z0eY@;+Cv@TW!_@1}eF5AEpIlszrA0k<sfY5ds{FU%b!b3& z2PtEglubFVFn$Hryc?VQ6p8QUT|4^Qntr3vrv%<q-&gbfWWF8s-+ViB9<~kN!{6*F zX&p@eILrHHt2F9x|9_SveQv7vjnH)AFaJEzIp@lRuS}j&G<7fkp<Z+x_F2F?`&3Sr zHo=9Bwl{2R;8RT%TLYO%LN`XpxK8>q&N1oTG<Wq%wWna5*cx2hGd>Nbx>l<B#!S|) zC$L7`iOeP9-$<bhc>9NR>T*$!je2&qsK;g2lPWs>C-r2JOCW*o!}Y{xeA>8I<gA+g z;DNzOU5V6{L|rM=m8R+n&0OTl*J3@P2S$7J)2qdXrSE9+84J(;+-KaF%N%0PvXNQ` z->{5l@QWzFk#{os0Y6GjvCIYDN<U@HKbZb&<v%X#u4&VH_4~HpywKOsKapz(Hp6Ai zm$~>I&+m5dV+t@Sf2r}Vr9JODd7g+(Blh7*Z1@W|2k_nI>;E>-KgiiE&rW%Xz8+UI z26u{|8JpiIPuA@CtCTPQEbrRH{`FR5GxtcIaD0tY1~{n0zG<Ep8ETBRz+<8sU*LN{ z4y@t$Yh#SjkOMEx6`wc!DSBd4`6_tEsehl*0Pkn=`%YblPi?esG58ywm(85c$Q<T+ z@E;{dzHoEE>XdyjW!{$Z#r_*0V^h<QUZi}=JU4M5HeQmN<K>>f!~0R@yMjxNdgJ_h zwnM$c+^KhKJurrjhkdM+9XVFl1}<n+GAVmY#=v)`pY;ye>$1uB%-qdv_&~*KfrkXi zTVb^O$5HNp;8$-19_Nf+n#_@%7yhQMEz~7?|0MBe5+4_zrQMPCe=GOG`ClowfO7Fo zwk-Gdqm+BmxX?#@nT$!97jl|ofi&iN6O@01u_63#w&B9!q4<BmUpv8#j30@`vvKbU z<|{R|o>gL%Xp_)~I3B@a1iCbZGqEU)vy65gHs_{ung3Vw1roOjUWN~STHj{e!)}I$ zRXiv0VNy2F6XmRY$*dRXw?eOn-|bSCdk6hn9eprxgTGW6vl_7rw}~GdJ_X+9F{d%7 z)<gMV6BqRex37K;wD?@{ra>$5Pua`5srXHykNB_Y({5W#nTJKUG?lrMc>;8s#2P{O zltn|ZSJ00J?dx-u-emrs^5=SsI?o;&Aa2qqSK@nQ%p>Isui9JzY*2ijUgip@D@ovQ zsweFCl(9Q;OEP{Jd21fS|8T|=oYE%)Jo~+ebNqgZO@*!!TP|@X__jR3d$$Yypoc@` zM&{xfU({vPDc!B!&C<rLxm3NXF52alSPEh=jrRR83*YJ(_(A-3i2>r*{d1L%ns|JC zY19i$xY`wsf`UV1o@(51!DCa~OdJaS1b5AQ@&2IpFHn2mt`vD`r~>{-;7=945}r_e zu!1(#XbIHg;J%gEr~SecX1(7FPK|oU9z^cr!ul+%%bMUYaje=Zc$T&z2VUYGjQ0M! zk{G4}Q-?_$w0&%i^LnL2^b;yRw9Jn#yA%HPX;y3l8`p93@8FskS%ZhhW-&Kw_eC-{ zfzA~e#cz;XOng0K%(9VuLwu?4CXe_gPnj?__oWu*sEl!YCb8WLS1NuDpRWPq_b2i9 zZ#QAw=FMzflF>!8EMy%7b$Jbb)AH4x$}6Ck#2@JwzQzY2^H5n5XKch97S9)60l#U! zbYfwUN$@^d>D~aogVjRY;$`MLcJm!K?+jNuTKuTOb9%#*qAx^th41NWjCnxh7<i0$ zsTzGMy5$TyQqfFk1+M7de`kkJnsjVfze;&3cF$tyS^93(r)PY6{*)(pPjaA)c@yq= z@9tb8Wg&aJDG%M6clbZ@Ha-vokLMSc7YfhS&oFVBsbra0Hh3UL?jg%b(k``!_4X5D z)7xFp-4ncfwXAiK-?R~ZrEq6c_n^7K2YGH_`497H=i{KwvasF=5O*N$*}5AYV`Cmy z*+Pw*DbJpz<;ps!|4`m{+bD1Ke<*LVS>C#fa1TzEo&!I~M^hY_fvfMJ--XfAPKB$0 z^7AK2duhLuH8(b|x06HWJiw8Pktd$c;C%xh&?Z;<y=I+YX|gF&RDVSLmiHsZnN9ON z-!=+eDZfJL8nFu|iJwv*jSf+~9FQ0z^bo%MHnOj?Cpf8%zg*&h;L*s}OZ>zn8S$KV zuQvHOh4M0`9n7oB9I*5)-}PH+&~HHlHbbp~J3d?|Fev_}-u>Xs+;{rcakQmbcds<( z{zSKl?q>as=oqmPntAuzR8O#IT9|kJUo?~`{>AR5j?)Iu+$z4$OVZe&!@0w}t7Kp1 zU(hRY(gx8p22F3dnE(GzaGhK12^M~MX}EORD~5jYmWym5i8E2W!W@g@6`5~olB;v> z!19KC;OZadLxoH9iNx-^>WEd;b=7B>aKjt7#9xHZp=S9~E`6oa*Q^&XaB#K`czcNL zY0&=sMpJ(Gvz}J-lXnAM)(<|c5m|Btw0<7_Sb@1t#^%2R{U^Kx-*|TtuchnB3eGuN zK*8x(JocdUQ?y~c^rKR)Q6}SiLr;!xQFhctWlLWy@qEYVqZM!d*uzhm!n0z}QKnOP z%q&xEdGW`H{n)@+jq?qh=ZL&F_Y2)jJA^(9d}J!0uK07C`mS&G;}cM_PhVZFbW#nz zU*@AT-1>J5krm1xRVKKdS1&SR^FG&|_{ci>?F`F+^kx1PIchx$_DdGuxYd5=(jVyG zuQX}OUPXMjOy7h}qwL;(#GDM>0e&j<M#{5u|9fc<XR&!)hRu_cD0Ftw{-!>8x6$9p zT$0e)pz*)XLzl2EZ$}RkbD)1G<(YOgJo(#8#)c?<yvWA**E-62(mTnp%_O!>>3Mhn zUl+U>TE;W!kK#pkDYyC}ybm>P=Q1r`;a$qcK2o}>F+3;zuUz~$(l5oEyr{<0z^n9y z;x}}cv=Ln;w!7dwp$QJ~L45HD>G$Lt=|}xlLKnSG_1DU_D^TMW?(OHDI8_GoMZ$-I z-z@EBnImh~NkV6_TLoU)CAd}Va+_?suWLNPiJyq>%^0Tqn4{F(sPM0ffiIXLbs$G> zffG5>gs(lpf-19(YD@_%iT>@(qi#P{@7G!5xJv9!V6V|Pfp>|Uk+m<->*kb;;4|qi zdgEf+pJ@#2Xeh$2NEe-C;wsMIAM~uUwe>5*YiNzKN7r3cc9}U&<9pR^!2x4dgSXDq zdi1jlAvBxWj#1J++L02bhhf*~dHu@a=^8c05j?1Ip|VvKy}n%}unEm*>t2%%v~%>R zi(oP7(1d?r$(Y0#fHkK6JFYe349_^on<6pkN#12wJ3PS&`xt{Hss0Vx)0f)4*!$+Q zmlpVmPhWvOPJA#nxzp<>M~v~^e8yPL1rv!|0_S`OJfk*=O^i+IlsOac+TOFpHbth2 zB#u*TWq*Z=;mak@ht<0_HOIS#_>a#9I*d6eO>FtI-WT0DVVU(#Ax30vQcl<}Lfg!C zeB}oAHlo+TC-$%2DE2MqpqzmTJ7!eV_*eQ7zD-c}p4j2w1fIz=>EguxPV|0KmqQ$= zgSN<ewK(s-YaRIFq<!&Onn&n<APm=z-3HH7W|}Hf)_oktruZQ&r(dpt_I==a8K)f; zTelqh-4h)Dp^T?k7vdD&7u_ndfK02gfb_Ngt!iC<?wn)TJ1dw6VI7p}1K<UJ&v!~> ze-`fwXs3r3DP2DYIR^j!t>mo{n_K*AJ>DUH;cbV1EB;lUQSWIrUarwbQKrpxSc{Z0 zbKlekijMTxTrKfUao!at9MuxzuZQ*t?C5uA*>C9cS?ef%+6AmzS`edbQJa6;SE3J6 zrSHkovSqAyNqa)@W5~m4#ynq7GjZ+(X7NXf|7aZJ8+$<467ktw!*!1MkMX&(#sdEl zzI>iDF9x4T3@Cfp@!aW)y+OuFth;oJ-zgD3h=-Tk(Owx3B)|**HhJSbXITf?PV}6? z8`)w9T-rvIF@eOTLsMUuVI|%s-Fpg~Nbh2<EuJj+gKlN4<COVx4IOXKEo2Ng1iYtr zQuejjh3Mh0%{HgfW{E?z1EZ`NjWd78Ew~Nb&Svf767ajlu(ia_1lA<6FSE3fGUweq zeu1COv75ou*hdDAPbHNj-_Y+tv(9k_oac`Cm&Kzi$y))9$8HBs;P+O1=>T>WqbqSL z<~PFs5<7af8BX=vv;kE=i%eumKkzfV0h!2DeF1&G>c3<?R8x%q7Yp&}95H!oO%uO1 z^;zF{kUmN2yCUTqilhIEGuHOA7H=(cJ;&f(=_e}iO|RAl3J(MOl_u=sYl&OHTqQKe zXQa!VtkM68Y*3G~4UZ#>dSic6=O@tD$0-{goiDboCwSWyzGtkVXy7t<{H6mJ@yzZP z{q;)5kK%J^;`M(%Px<GhpJx1+V8WIuI5+y{^L?b9V&foV;r1oK4@xfcdLWm(;3;y4 z&_4|lKFHE;D!K^YmKNi8;aPY<)~1MVGkD>jiNFw+w}Vo*^538vWUYxu|K@uISAf_A z15X>|dB#e3OWsv>*p~(VtzQ{=@Z_H0k9R!!mm^sh8SIUZ2;1yrIr5r8o&@=B>?5X5 zA#a}RW6GNNn$k;*b;CTFC4Mg{%Qs|q-;5ub_Xwbar2L0JqE8yTPyI%A3}4f@KD-|x zG$%)a(3NqB9s(z>EbT_uMRKv*=#Q07Hf#~)KW!cxeQu}xG14dhWL&?N^5E$kwTsGQ z?B673(ziE_4NmTYF6~UZW`+B6=EBNM`!6*>f1~<U;P&oJ$`N|XSX*?r^r2fRn{jtM z<K6LMHyQPhknvBmOkIk`O?K5ucX@a5MUy{Q>1s=b;0+!7by&B;%a+^{=k@4Ri8n}` z56^+WRPVsnCC@&mVnPjCiyfw)dJuVtK}ViZGAQGZ8m*4+?2_jfU5#$GSkbvQpNqbH zp5&6y&htFZ$2_z0_19=8dG7R$B!AZs_yPYvI%gAg?ibz6+HP52?~w92i_Sja8}vRg z$gFoohb!H=Y_I%|_ucls!#C(7qn>5jWTCr%3w@jLiSUN<H~pYuQ=7-%c^3vb544eb z3X(%#QwQ?`^a<3-+0I$=FeGpmA78F7(}Ql+Mv0tr9-a}<Wo}f-sgf0V)T4hj$e^=+ z6#buBPWv)$M=#$_PMzD~?WOnuYINps^*zFqhOQV^>#J;D3n1TzZJ6fu04Kad%d}Mb z{Iqn&O_Hw%I;Hx$YX?~4GFf6}y;E36ZQAg_CHY&Xa+dX2(>dEX&k`Sw_-{=A-eKC= zJmx|7DBIlhDT`hfzp|kpPAJ<+@vgFUPxV0`m8d*6_}0QaK-;9xOfu}^8;-)CXQhsC z`+nZ8<2B@2m^Hr_e!2;v!^XLx#Jt{QUVE9BQL$$9^Ie%+O%wZ~MLRAn1540x^o!Cr zyJ~IGMmvsYmX|gJSj)G+d?|WF*&|(+rMqoHdkgmi^l{Pt#!e1jX6L>ei5teAi6$0D z*0WeSM{OL!d@#7dF1C4sw{8!wiFwwFjQX{<+*>O=CgpJ5p6ew|?+ge3e&jfK>)gO2 zw1GKZa(c`aULd>8;$PAy2JCgy!BIu|j?m%qP(w*stl&(y%lt)IHaJeYp~TlJCmkMf zmJQY?OKgbv1!UX{?JGQ?-{r}>^wSz^P%8q<^;zV^;CDlbtbfA}*kb6Fp)wx6q<v<< zaqJY|9}bt#7-XC)pYMaW&7j^!e94+GJ3goPyvr-$(aiEtXgYGP*31&yV4crz?k50K zr6-iPTlhm@A_viv@M&B%FagU2V8JeT*NBc|KCpAxp5EEb;8SHgV4s^Xjbr{!*0w(( zxsbqp0%g-LTh^^igvZgv;DR|1OAXf%{i<x>#Zt|FqY_UR&F>0+NAcUr?~?M;P(@jW zfj`zGPtF*w#f#jF4dN<*hBB`g9J5>AF?<(5y4>Pk32#U};6(h*5!_3mO(m`xcnV$< zKFruDdbRTw+8rT!L->jEqQ$-!e!;f`4~?0m#^=VIqtulrys2y%-sO6Pth*HbX2LQ+ zmA^#zsoenT-1HL~J+I(ip|v&Nj}p2|PF<m+5ksj3_(t)B=n-jyYlUhn_2sb6v_m`p zAF-u&G55BEq^<$JV;m^)?E;56SK3X!!S|{`_f66+zFi{Mj3uD4eTm3<nC7OOEBQBM zV6e!*nlP=mn|(C29<Tao{7e~<5vD)plc{q;4bRW{v|$Z0y^ghv8(7O&L#%e~oC*4Y z@(KExIfENEl@HcO&AF;!b6H4-pDer3SqYC5#|&N9v8FWvz8TKFXxh7&>uBL4u7!qE zIZNIaFZi6y@5}f`bY452ZQ_i*X~~yoe3!v@Nt_3|Yb?1u8^F7xIA71Z2RL8HyJ@_; zjo&x$ES2*x?m4-)+4tEa(x;%K^~vB*Vt=9eZwr9eCTq6oFU~L~>*`<sm8@Y+ka1wC zwOrX<(8K8o-STewE}pagTE6$aF%zH2Z@USeed#mSQ}!;tA9B(6iI0cBck}&|d_P3Z zvow8w^Kte4K=pk<)~^Cbk*s^=Jf8CW7nS$?pTgw@C~pwu`KvO)VU^NB?tbL&02eM< zUoN%<?_4Qxl0<!~g8AqJ*mE~elfGn0UrqY1IEj1mgvOkcxE=B1_*d+b{@z{*FM&Vo z^-vmoGcHTZl<~XZd3cz2b`EW_dD9FX@iB3pRu?fY;N6-^9OGB+W!5B_zZZQ@oTkJ9 zV52g3Qf0)9aYi>-t*qylm{RmdWIeypA96qPOa`_Caup}CXwYo*OX$Gy=!7^WSLFF2 zKCqU!z+K={y(>JA-ali$?;GSSoFnfSB;Q(S<^_`ZoU?}Q-1t3y>xHiT%PTVi;ty*d zL-|VfT(wdEDnE@3B72_TsNLv?{pc5UouzdYUrn@MXZ{19H0xWg5?XTZx^#t>z|qCf z*|%<&T#4y!aFEzqwZU8Hd1ixOOI&31RcVxcM05}EN`L0!dSAG`T;neowFMm5X_Jg? z;oDJb(JeK^hZVZ&bZHy${1zKWYrzTk2Q1btF<i&-JCbu-@G1AxU3J>6TwliT2+s0d zJAS)e$1FC!iCwzF(uR8ycM_LA#KK<Y*h89j{gNS;c<x`$Z!2fkH@rEWa|d72qjK)( zOS)0cSMbf1^g+Uh^4+ydMru(ikAr*{L#$dB-^Cz5S$r3xMf$S%4j%?%t!Tj!@Tql? z*kC%}s<k-2o>@7**i>0ZWMK`?P}<^lZ*PvnBsNg>eG-T1e<6o89Qs-K`Ha%t_@Tks zFl2bR=vL^qMbY;;{7;OxrGL)ST2Dd`1cc9;`NlKi=X_%spFT)C3r><~;{b5vAg_(^ zY7~0L&3$LpNMOvSeaW{t_$~3P$dG=J@|_o#pZ)pI%ZI*AeEH*@89|i`NyT0mbkE)> zvP*q}U+m9Njp>(!C$bmOt~B(URrpBqHZmrsZ^-uXUPYL9z{^zb6-z(o36A{G?1!YR z^CAy?8^BH&1V5gqzYfRt#nJC?^Mr<+gYOnYr)Zv6aBr8`iJs8tjqv&kPw@67EWZ;Q z12`J?aDRm0s%%2T;xc3sxS7Kb)o_-+K>BZqWjV~aI13$<nx(m9ymx@ImS0N8WYjWG zhm0D!=FooXOBQ&jYcIYqvAIs>v#8W;JI05Ct;40|IqTfT^4$JHlRPv3F7h0f<E1;b zuE2!-_1kkI%Oc0mJ`Zh>#jq?Rr{v-t*)A;OJQu%iiYJ&AY;jNQSLOq=PPe!x_9{9c z>%)t6K-L>V1D;hHH0iJw_zH<@pMxygI9hW(0GW&7cO1XdIbX&(g0r1Nav-{q!CU#= z9=RHz;%%MCRaZ+a_byMLXt9aBbF^K$)8a@U!l8*g5ZfGsOd)Un?5rG#Zw0pjY?ASU zhsUwIszwq+RkN#YUUuLrf6c8WTt^`bR{1UK{{1zc63L54f3w}>D{zHB(+3S-MK>$G zcGGd%)+C!@dBtAuVCdx5o3pgI*(T3LLg#AXH{^AtqUq9>GTdsV!9xSK!9%}dTOWKv z_{6lWt<o1!E;%E!;oZ1twA~Tz52z=Ie{2TjV%H3q^&iSj<J}SFyIJ@|^qT`_t^wP{ zYnQOKOuzX-Y`6xcr#zvd#lTfByel%<&x(vcrzMGwQTIz5&d4+1qdypN!5D`cIafrM z4BQF7XO1>tNZSLv%|6w#roLMF#Uuts<jIhw4=QBdP-sh8@v1EBR%nCo^6j$R!sx;B z-0MBPUY?g9*KFZ=Os;Ji%#~uRM4?+G=4mta;~z`QycE7<oY36<56Fw>o*_C6dnZrI z6c}doq8##pR{EKPWqj!C&KR>09-Bz;zj20_)OD1c1wL6%lv{XN2>eJq4)nTC+JC@1 zmoaKH{*%=B8~+@-Smq#1yXE}=G(YRnKkN~1yC;+pMLFoC>%6L*miZhWRWX68EGeUT z4*Y$W%o$LY__%GH>m~MB>hkCZ_sQ94tD5(hvYp{^yWr~QWB2z?3hhl^723qnU%8}g z;jf?g8a6bwvjCro%mIoY5;}{oK*c-BxNW7D1kAYx-QQbWUfOUF+;;=EB<LNja?J!s zOf&n1=@~2FEg1)?v6b{EBgUA|-0EJL@g4Wm&HG8nQ=@8U=%yus(ncfCRp_QC`E4aG zH^~#asqEr!haI6!v!K7-r2S-Q-OiV+Xx!dBUv8d>8CCZ?$eDZ%gXu?P48DspQU&)i zW|Fm@2HrmyqiiWfgWx$}FlZ3EF^KOe)%-R*r&$Xh8+cycsQl}J<&Adny_#i3sdH$M zinoK;CH6q(sC5(W{QnQQ#rKsY^=9}b_lE8kzJVs00-x|>c-#j+=45H9GWT^!{nqU7 z{`)#laOj1ys~YOcC|v9@Sx*R#5`>=?oML|CG`d1>!0y4f$9fsoJf#^qKJ@cEOQY{l zu_gEo_@<#w<Wl&M>ol%Ui4Oul1A8B67DFee<^q@4;7$H6A91KV$_yVcJU5&e)Hs2W zvfKv${oP(Rp`lLfb;hjqa`pso$%97Z70$fPjL*QgLO-bNlD4bS`%b<&fG<<%lpy%= z1V^`1`ml!dOr?$Sv?+!1$Y&;FgYY|jzBk`N-!}@*84ET#J)z;>BLj8i4d4kKCphAM zqUc7R&4sqR#1FyyN4cL=KA|y1o|O-7OfA1ERF9t6I49JYHs{ku*PI=VnRAvmy2Xz{ z8;9~;Ro?{KMvgJzGm&2z|50uq6<Z;CFEsqYp-<y$r5!3CT+rP`!HG^^P|vy#H9i{_ zRC<a2#G`L}(v-6}BVXLG<E%e$$@5aihtO2@4N{jHM}~&&F4v)12K<G7#<xow_38Mz zi-D2&_hF;UpbNaE=KGBp+rIg~#A62C-pwixh3W%-qpuPimvtx4wGqqRjrPhMrSOHs z?xKtP%Dli??_~5*vn~$LnVEgzez7s?#U3}?mmo3gqQ8As)<%s~apK*CZX$0+xqW_7 z77RG|*Z!nTiBVH|L5Vs4X;}+_@l+FhD~-7Z8Mnf_31)e@@W60SDBYBQ`a<v^?KSm? z@Kr84Bg+#UoM+Hc<<E47^$NUuQt^8-K32YC&BJlz>7>Y$loKAG!sitx4n+>(>6Ej; zcc2Nrf+ioG*@wNesbyc`-XT88#zgE2;oTaM;qubPOySM))98aio)Y{;E)_4jQu?P0 zitnJM1KZ3l>nEf?pdEu0{|o{)gLn2zo6C1%XZyKF+$3~jj=`Xhq8;-ECJ#iwW0KQa z@WLFhv^TU&wR4%`!(ApV=?hbA7vZ1!r4MVy{o4mywhuUKJ)!IR(5|DRmqf3aGUni( z@}2st;+6c<AD!`pT#V}*j#k58@?7+v`gSC=Lq8(-@mr}g0Il(R$IILhIZ%g7TLo9; zD~$FA(9@n^=IkaOg=W;BCjLF4C$c5;5@G{Ev)-;>@893Hw&YJ>5S=vYC;hstOR<E@ z`MHg-ZyUUlDc^`54*TqH{*SijKE`j2_=m4Q7j6rD`-CT$vCQCGnfFdu1l>}M_tGUs zTkr&a^-N%jkotHoeJ6S4d*&H3*=tl7R+0Hj&$aBcmkn;r$HqhdH|Cn<*n~DeZF{(^ zpSOGO9?GbY_eE!f+Z}%Ym+RiUP`>-W)ZHX&)ZsVmsTMi-_hwPfc*>DEyd)WG3V(Oi zBZ*ZWx{qgGX^)H-{krEFu1kdH3>+mV34A{-A6_?g;ajJ`d9^1rAP>HlnAaj`v(OV9 zXfbIeI%cua_oaU=eXe<bFZXNA`yX;Y{Qd^B|4{4LJo=88%sf(ynFqcS_)CCqs_39_ zf6jdi_mr<X9CO9J<AJ+Gh8q}@=@s(6$PTjTh96Y!dcG-=F?b7`H367%T=~~X9K=h4 zBUwj6ovD0d>_-593s0GR5D!mGmH8H9PE((ZJdHQ-c8%!3vr@({<L*u3{(@y@J>Sb& z{OHu(-z;MtK1_13FlX(gz2wGnZ^M@a48qH+$rs^EzQJMUc{!ig%SwK{ioxQ~$?H`y z*js#yBe&2x_&>|no6Ps?OQcSj_nls>hrIb(&)mYUj8U!;`X9!Z-KMD>Eyri{IYxi; z2KK+6CVa&Cpzs)TzGwM;)V1p}z4o-GO+78^YKT{pxK7q?qfd^mjA5-=jB#IdO1gHL zzH*Sn+(ezmhwk9F1K(0d*YheLMEtZ~ygRQ<=qUHwa{t?O_hk~Zp8|~SsMDMKMbzMa zk6lJRmgy_+)Y?*pop;;w?!WS~qXy@`6@D)3zb}(G4_jVr)L{QS7dpd|Df2;;pTHTv zuB9pF&ZB=m7vESyZ|0w<$FU0ExPNXPbKMp-#?0##eLXzpro8&R<W^$qN6`k;w}<_r zhkPdQ9~RpjKey>4{moo#z>2bN%)h`(CZEc@xWEA}R4mH#^l{=dmha*`!QYHo$y^b! z2(}r$hUm!MEN~FO##jDoU~uxg128bo)g~jOwR{)v2@TxHd*i}!2QvQ1(mK7%z2Uq| zoRjQr(U@PWlOxTqCDg9aI@TUTk0!&1U+DE=yNUN5lpkZ1ukVF_D&Zf-(urqV>b0Ni z!q=q_IJ%PZ3|gwTu@>_(Juf+GFf!1-UzI@<ez*OJj%~Ji%9{IJ=}((uCtuH(@>i|Z zwENdK^HoOeW#U_nHuTN)_-ycD`;ED_vD>2tdxF>F7f|)uUk1NYH*F*?tW0}(r`C2O zu?pO`3w*Sb{xb1m8z5|hF$XF22u#iPz-tFQ!2v5<*2(pJ=oc5}XYg*P9#uZ|I(t_| zeTlzE?uB8A<2Uh&T1TV)?oS|>r_c){n&fhK)A%J}3G*1DGbFyB-xhv5Hg?w{#Fr=X zy6}1813!Ijl)wqTQiZofM{Xo{SXi&7JKY-JL`xnC%78{Z?@n$D73Y-pUJKg`pKhAD zzUAtA;HnG5H2t(@*;!!Nr{E(oOe+;97YxTd?%oXlvJVS6DBQ}Yo`7ypF)3rWTL&BS z(Rv5`*=h_0Eo6U~cKAJG(3i1{6|f0^JR<PD?AIL7sUx_GmwcGK+ll#$Sa9ad(yo?R zxMsVwo3SPWxJ<irH}&cp%8QY~rK+zuDEhZ4KB_T8)@C~-j$GQ|#%_gHtjW}MY_I)> zf15cM=Hq0~Yjpb<iGLBFqQq57z67-%^^r~zgZW8-Id|39!7mxNGe;dvTWQ)Y!)gCv z|LrG~t~dR~vkW^hv}pl!;`wyxgXm|m74=5ZyR0F25B`w8!71(VlDAjv4Px&5b6@PA z@OT6pwp*s@Grt<%i<6v(5_dkJ2Xhd#&t0p0#;TtYUXp$xjpt&E2%hDh^eay$s<|-q z6mybQ8fEF?qfuiW$pabYgRmZGwi|YC5dRZ%`4PhV;c+wHPJ>n=2f*uG2fZ#Di-~_I zFN$2M(T@(!YxU;fJX`eOOO!pCew;YE*CehR8aa!wA;dPxsRC!BYsiIgz|1=!xlok< zPx{_4yvRe-n(7uXgUi2m$t||ZdVTP4nJ)2#f(NO`h&Ajg{QoQV(vHoZP)aiGG<~&Q z_ws(TUNiLwb(-V29hK#w#>t*gPl?S^bCc#+p#+`2#uMuOiANvPPUJ;+fP3q>x6h;J z1mS_n=DiKvdxd+axo0=;ZQ|Za?tRF&HRip|z%_#FqZ^E}wsAdxZ;me5Ns@o=@yzi1 zA{QbH&@BM(NI%B-D|I_~KsR2cY@aYLe@>t6n`l!&+5^u>Iiu)vrW3!i0Y84%JQ;8H zqOJ*{&FL}Gn(Vof9up^LYkEw3eEsqA+r~S@IDY&RW1l6$lk+K0+1S{ou5QGmt8r22 zdGNbNo`>PtzPm|Jj#sfe`PwqWhS{EoJvVC(c47Gm$^(Y^{iV%~Q`51z=8qJ4a~FV< z9>hRCNge{_>)_l$$?Z0Q=bHy5uLXDtlwZ}jYwWA+A5kYh7(H{&r;X$0chhY6UiOsM zlXri4<KFV+p^7=ojm?=5dP22<Ne%SIx!%jPHba+1Xc9v$`^%X9uCwe~182yL6I$<w z4~xpKYr4nWSK|Thsr{b>w<6ozV@^-Y3>1(*ZqLiAe}Yy63|(WXAtp0f;y5LS3tHGs z8^ysl;$J%K30*7vnq>HBu9bCBagtA)`;*WupL0DNdBr}Cml!w~Z9ggN)kR-<^e<*} zFY)4gC--p=xonrtnK4P*Bju%y<L6w}=q(F1;ureY5ys0F?|n*U<=eyHU)k)eL4n@? zY6o0LJ)!>d`5t}qaY1u@4mtDlg-&Vb%2J_uaePi$KkV~z;smiL<-PeI3r-CmKpFT3 zPqI$j$ywI*1~|*yfVT`@5FS8RPc9FMjdQ*~eh7&*5T2E>W}WzafJ63c5ZOEF2_+&g zp)>qGC37HL_rRYb>(AkhuWtih#-yQo+G7!$3Z9ZaXRqjKo)HW9-Mivv;CCwgV1W-> z89b=(6?_g|My%D~#xuT=2QJD<fZUBEj_A_!7=|rkj@Mqz^aN9?WN#89Z=IGPF%Pu4 zpXvwD^VH2afcfci$^WaLG<0ZZ=fZBG7JABJ<hiA6u}P~f7E@nssS7L*Qb+Ika-X`o zNIOI}r%xfT<|^jmwrd0F%N^BzwSR$C@%<3S1gvple#VZTc6g_BobJoEEL8ayhK%X! z-`;V$f4gO&>MzU454qhwkg`X6{a-4Z!8h@A-}C}Y{Cw;e4jV@thm2?7<4*Vpe`ukT zZQ(Jp3A@e2&6Y&qzECze=patPh=r0^RbohqR~=u5P61CMQ{(t8cDDQ;#c#$6>bLv; z(|V|1)uXGRcY^tQHSeTS9({69#@}(~Z@cIduCeL#3Waln?)1^<y8;{XaV7m9a1&D% z)?LcS$Ub~KcN=Xma36+$^JL&pzXbe6z%MX|;m>UWe^v|lGx;rYAni(}oOt2WKxr@z zA6p_i-f8H-ULOjKCd>l6X;%o$@$`TH4a|Sr<O%kgdkL6xfmvV+!#tedVVt}89maV| z*@R%cf-!*d5g0{ggUQ=}1xEb;{}qhHekbGm{25=214f~L7)F6N45Q#O3}Y(4!+1>u z)|4<lDYxpE;k-iV-z;-wCf|M{dobD5`VDemI3%Zx(SQAQD!6b+{DRDftNyE-VYk!o z$h><5XFEr{k};WM!!91XT4X6%{2CiXuCS-$%i#gmsHBT;Rm~|CGJnnbX-_ceh{@Nr z@OWYi9%qjl#osp0cCpzNU({;%qpunz)<a@iL??1xAJ`}5pJ(l^4SS*EHu~tzq6dV} z;kkCMUFZ~SiOhV>BJFdn)NJ{MkJe(NMOIt1QMAFv5yv6zagZy=$r(RJ=)C~X>Ho8& z|GzmP^V;9Ez@gpr)!J2#5d&|pBzc0@NG@)r5AYdXIrFp@x!^PAAy%o}vhn`Y=%ZxI zLSWM*zS?)^$i8X}jZfKFb9l{eSzjV>df)6go&8)F3hcnVI`>U-Lj{=6*v^`?H%{fq zbKp!)FR;`04!eM_g>Gts&(ukqDh037SD3z&Os?aNYoi~^I1Y_uZi&1Q)MGW)_QvOg z>o@8PZlONpv%|RmjE_z6o?y>O&G`5+2Av)!vL*Hs&puT62@=n~T}y<Q{tx)+x$+nA zv&zJe^<w-4V+{N_YJs;dtp9cv*j2xiA$TVCMQBiMu_wyhu|dn1Co?~A8}Ozmc%doq z_7L7$KpcmxNu)1IqMu0-{CGd9&w)m(z+1HNxq++3C#l=X9+?;O&Puax@J*d+ENayG zmowyO_`Io3g`*xD!HrYZaqLvMjwnSNMgK;V{+BcN|3lp+b$o$Mwbj(|W}NF^Dm=j+ zdGNqb`>1v3qFVG!SQpjsJFJVU`5o3p6~y^ERX*kAT1izmEvY;dOe$Zg@;3F8c@pG0 zleV}$!NhiQ&G|N^1DFpNoXb7gXOR2viVZLOhWeKsk+{-$^hJ`q%d?H@S=H(Fzo6g1 zZ~I-p?kn0@O*>P?FCn?>h{u$8+*<Apzf@kPOz0_cCNd{|lX)E>^xe9fJ__6*+l%== zNv_4_GVj$jKX07Hb7LIQ^t|x^_nh)RXSF}E=rQBlU{Uk8!Gq!7hTi$%6g*he#Jger z4Sxtt#V;Uw+~A=N%!7CLQT|WqdJ4Lp5xQp79X@CF&8Nb&6}r+_hiNP8V^lvQ_6In? zcc}XEO~k=C{kqCyyH48DLVqL<a%)iq*$#5b-+IWG#a^oT9Vs)8ekzM`C-YW8XS(Ll zgbuRq#TPs5P#2p6pSN4R2YtJHLOnJzUOQ8k30{_IMbtMrFa_RVeTcv6M~Amq`i`rY ziLEQ;_~+G0?5=YG@Cn~!)G3>nHY!_)oEL}BN#7uPjX3d|Umqj?xd>amUislG1a`(v z6X2Uz_=Y&k-j%{PmNVQNCHuuFS^GSLcCZHvIpfXwKqafP$FcAac?8}=*GDiessI<P zH?ph~elnl0;`v5-hL2hLgh+6d$~)7&Co|B){~m2VE0J*(x+e-5lf1Hw*@HQ>ce453 z5%awqd5<whChst&4(2j$c!lp|&OxrnaZNlyFj0*eh6v6q2}T(|5X++AV7<MRq3RKP zXguG{pbXgqS#T_I_9|{wu7##z%cZ-mil=$L$tbVkL8Clk(<#q{Ctt=fw39VsI`hcE zB&8Sh?-o&xCiAP+#n4pZH1+Sws7Dij!IJK>FGc7iF_RbY$DCLFNq(yX_|eCx_=RQ6 zy$UZ1KYaP4L&i72A^Q$@q^?#xOYPm2vDgwV9ypkP3nnsLi%|XmU=jGY;x7qUTF!$u zY%qKfZKuLBE&5gD&6uM#`_-3HX@^U6l-Nqh$yI_EBgQUR<Oy{j0Gu(vlLjvFzjW^* zZI*T<6t+6x;_&DvtCSwGwDdPLq#EO;HsS-R6W(Z&|AJ;es3G&~L>3dvmp3*FPFc%y zUfRU?uqHe&B{}JMCqZB%)*Kr^$uskLvi2vK7FZsfDmj1!_jys|sEo!Z)(YR4?M8Ah z{@Efhi=OcWuM#_cx{Omjp{rk_T`HFl`jR!U&wVcWLFmWTdRLD=c(-dQc9)m-@;&dy zHJ8(6OEdk?EfU%TUkm!5Yob3s(F%hHj;|Hp0`<?L?*8BqdoXC&O`)s11(vfuDbZ*f zdJF#n>zI<8u9MI!HDz6?Cma1k-g;lJ9GArZ@UG}6uP4;)6JSW<cK{i37&c~5Q-0%6 zx82NPgvab+dspOEWTo)UTDc$C5zKVu69^&q^rwd!WA|XCF?R1ZSLp3hJbPjpWBRim z{rG#-<$|t^_laK)s4+*hLAPKk_m!VWY}|Br<SDuD33lnf723n6iS!vx!!LC~<_~^_ zKVPi&=$|Bm3z@%;6rPf@i1S>0kuEH2;%l=Xd2yTvw!^RV1i08>;(ehf<lF+UJYmdj z(uVPh&koBP0fVpgSqfJDpXg|KOQ(G`@D6JR1dn3(i7v*bNx-L5g^VZA_SlVvFWw@) zc*6$$Yz)uHsX`1rb5WuTICqdU?{?%6nXeY#y!hprLvXC5T^lEAon+o&qu@*btPL=1 z5?q?T@9F0I9bNgRA1K%zpJ&+bz4wSA^RW{5y0=N*=o?L$&um_QyH@<($}WO`#8#60 zZF}Hxm-NZ_GR4kiKBF`7<Dn;7_yMG^t1;;jjwg6R;;Urt$yF|MNj6RFBlN~;<{x4? zqBABM<*9rPvR=%O4HE3Uh`FE&sYk_F1v}3bTpIX0(T*5y2j6ydvG<#_JGY{~G>j|w z@0@qZ336d7{B<;PKzuxg_PesQn90A+8*3OlFuwsk(Oq{!hdr)3_yC;aCrR)JWj~Ox zon;X^k^BGW`7fcRrF?ntsBci`z8O221C=q5=>Fi9%OqCP6YP`>ubq@R1OImN85qyX zxOa**1JUphYuc`yLHWD5cSfEIkEwX|)t+ZO`impYZ)D89iFeKloZw5%L)7krFT>^P zFLsffUS3`0z9<4VEALtbHon~;dPH~>`eyMgin7kjGk!<PedqzL<3HycSwE6!zC#?1 zdMBdAJG*)33d-Cja&PLGy#hD)HXGyF&sQ6K*y;>)Xdbf+ZIV&bhJRs`d?T>=@t&}D z2p?x~kMxhS24D8~HT9pYJHsa(+^cMxN0rVK-jy{8V%xRC);WcbkabECbt{K3UiFFp zN!BYxRGRMzk4N&}F4|Wj^&nSKLbvh>!Tt2Lu_E`}-z&BlbZz9lRF_|`H)8zau`g7g zqiiwwROrB5_OcEe9;QCxseOa$bNp50T&&UeZ>6ml>$%|c-t;BFC+i_2Xv+rRQNDHL zX%yForETV%cP7{C47&|Iiv3o0Rd7G|4z9E@?zRQ43VcZ)Kt2!kY(j92_&9)fxUAR0 zHi*SGeWnZf_f6YW=8>>XJ9pq6XSzFL9<im*bjgmG*KFg4=np%Oq>er2x(~s*;8^7e z7aR(l@I{2wC3q5;1y|ft?GTvNGvGAe*&zIZpIFM0xh*So;On-y!0!giIIQ$<4D_Gp zrXRB;nlz||HnH$%O?fG_*{(O5_jids5GWS8J=#HR?3H&whZX1###*wEi!XW1A;FXC zBZ>bITim}a+Yy+8ep0sg72S~imbSM|+Q4||y_Ffju}rO_uPF}&pO^lCJ`4L6yN=(q zA%!-8r%tMjz>bjeQ7RdL=e!l3XA&xiCDI?q#t6lELRVg(9U^nsP9b|Oye6>n{Q%(s zftQ>Bvd0l~7$FDmGhcOR5Z_=&H^tTn-r{+NzyISh<jP5&`6rO8U+FVfjRyy7TKd1Z zu2r%lV;byD^lk#>Iw^N8<t788o9jfbnfFrqsK&taM=x=`$CN{nxA>pidOt1%E_^Ch z>qYYZGdu5p_E1NXCuHw$&aK2Z%h6KNgPS%$Ti(GgvA4OzJEH}*YTki9y8<iN8=xZc z3-HI-Ae8C}#eX8Yb3U{X8<KuY_-EVW%iz~!_^<{(g~sr4uIk%&1P@ToQE-vgWIKlK zMzJB4?fCo~YTlYYA9)XWf|q~78Y4gTxr})E_+oIU;z(%AKq=3oS1%)GQ}U81--vu~ ze!Eh><$aZF%%i6jum;*9&#E7R_o##NeIifT3Vx6NkJ*&BjkZ)6_6z$0hpu1@5fWMr zS7XW-=x;(-eEt*LF%AA{X*(vCbpZzxFJ(7|7~5X4+Lf=xip}T=b!3edI4KQ{;{KCj z8=CVx*o>hZ!)CnVLAekA=klFtGgeA2so0D<WG2)Ro{_nq&^W_>ykZ2u8HaUb-c{*c zi+m?CO&>Xid(Ts+ntKKAv&!b@8TV^{F87DK1WJR8!Hs;kH{Gp`2$#k68W}s$rv}rV zaVmxk+(t7W{Y;nSIAacs{>D{k)r5z5e}nX4#y9O3iN5CEe)OXzcB<H?8-YV?RbqZO zX#9oubnG?)|H3?Y3EA~d$w~EAq@;R_Q&N4yiG4Qb!fB%Bou?fTdU}fz$xC6(k#oE0 z?~>)s%T4tbCZ&3-l2U!cI+w^;`{sb=%;zib6tleY_|)+I`S0kP=YOSdd%Cs0>*?P5 zo~J$f-ly-?_dor(e&Fdp=?9;FM?d`ZSIk|v*6SAZ)=w@VQOSaP^)m||*Uv8a6Ke<F z(d!p{W#s=VqpUK@nnPK0C~FR7&7rJ0lr@L4=1|rg$||R<a>^>Fta8dKr>t_yDyOVK zYt33td4fM*!5s>A3;SOge^%oZ;uL{mOmk?ueqy?=pL80>i7ey#MA}cT$D7xjo8H;P z?}O&CkaI1^Ui12Zu7AU}Ti=Z1@NzuQaf)r#t2wxT<|xM*UH=+@zK-We<lz3-xoj<+ z#Ic71Z_E!oSHI;t>F%Og6YnlAd2sr~X_Kbi|G?~tcNN@s?@UdbIPw0wC(e4H;J%qt z3uaB4SWr~-z@(YnpE+sP#G*-e7d$w1*2GEoJ*2K@O}$H-R5B~=?wLG#=z&QEMND4b zFOMfqDw%%&1GAvBd0jlM`TDN=@1ONh$wVOFxh?#cB!A(H=5ww6;y-KCpLu_%`m<c( z&v@Ym^%rr8KY4BggkSypY5iucO{YuLE4S?C{YzA<ZrQ^RG|iHtX%XWz&5B&c<ZJj) zHLXVg=?5-0xzmpG%4?b)+?&La%HiU0bBy8`&r!*-m}4EsHje!qhxt%@CbiY?QwrMt z>(wzaORn5At<@jSPnkYob>Zn%i;9+CTlsO@=Qkgnebwm?>ne}D|7`D3e~sDh-B{YH z&*m@YciCB8WdB>2Z=D;aWX;&}-KRr$RQL{l)ak2}pG+I`%E9w*&HbSKcZ;W9zH80B zMGs%ND|lw#q<Oy`Z*d%%8eLd8=&~QbZ)1CMuk*f)3HIVqCx_;L_`r;N{^z}uk(oCg z#5AAV=KXtLiCz8UnpXx)UHq3D4(;3evHQZdb)QW=eC>ndkB#_yn?px$8}#0v)}<cl zIZ*p_Okm7E_I4~du=ADko4R%1^YZVOEPD0tm#yBudHLpuBwJ<F#J?Pgdo%HL>y3|j z@9)=c)Z}r0>Qb<KP@lX1T0QjWL(wxnwrq30zqptE!*8nQZk*BemA^)>KDl$nbq6<} z`k#HRO42T9mp!#6=9&1#ZI5qlGsWL$&@|h#Q;X(X#uxtc{Fr<1y{lkq!r|0Ob8pt} z`u6KZ(NiB;ZRx!Gylu|dJ(qp|=8+APa!&uP{g<0}JnpUB(s-=PCwGnP^HGQIydOL< zY1F}naRq-F{l8;g88}PZw(3Oc)`LS=AItv7qQirx?RoF{hVzF$m~y&!SmTlV(r&E0 z=cNOi^FNx|$2$D;E|J$w92NWGK5v^(GG|2Pyf`%C8oRyqjz^tw`+B@GdF;z`?{~%= zynD-vlLi0V_QIzV7VkTfeD&f38#b-^$6Hqndil1pHk<lpjNksZm!`hD%UQnp>%YFd z^SQVae~o<Z{f)EIZ~E}dKmY#yWgU8cY%TA2bY}b3g`ZVq6fGP)Wm=mxw@-Pv_21i` zT&Bk?xMn>*faR@x!xvn3_Wf11$0mPkxhnKpbn%^I@A~1LdnN^DTtD^7FQV_g@1f2I zLv_7BsJi{(kL>%iKe^}rV_Pm<_-4mb!*=}biVvUKkbi2`p+lt$-dnlnwZpDkzCHHa zbN6h0@1C*SUic*Xl_8$%|C04l?>2`=b&mb>zq2E+&wtoD^!0D@kL4Y^XU#WH-PeEi zj^Z1ic)8%6PUUxRt9}3e9@n3ke9NNW$L){2srA+^9V4#p*E1?_N5-pfB(>iDm#1&v z)Z04c<?(;i|M6P?zaMzz@#RNSx~%{7jt#FBE$#Vj;hCCMQyz?6FfC$jbWF{V>)U=c z_nuY{Ts~Hdnv=bAk>labC)W4g_=v0XU*ncO_5Rasc6|8x-@ZBO?RM<r)(7AJ;L#gS z96VS5@+Xt;EB~nLyB&9w-O+Q)zmNZZ!~MU%>2LA>yxmqgeadC}+ZoY!k8f>hr!SxM zhvM~j)qkMhTQK79Q#+QNh^_tC`)&S_TW-DiwU=@C^t|VfKXlALF#4wAksts5zQNg3 z-dlh4_CrVRZhg#sHskPbZe71^?HkLte(L}GUv4_Bzml5p?e^{SUVHWJ)CDi!`ogMB ziBZ=dcy&SaKi*9q`)TgZdyaJP`|#Z_Z_X~*6VZ9{oeO*4-|II!T5nqURNU*Gk44@7 z<Tnw0M9CITD;hLw(#%=TKKD7VPMk4m+Jh7Co%Fzclcp-Qezmh_Pp7;#&H1xu&OXjW z=^;e@Ph>|Sd97&D)PmWA`fGO;JXrJqeZ!#s{Rdo|nyO8`zo2O5#7Tvd?;oT+z<bjR zW=$T{@BZnt`rUW;Ou3=HzPotpq(KjkoK|qpB=v=qJg9%F`V(E1;$)E8|Jv))23-Fe zSNhN!h7BKaqaJ)=vmX3oJO{e&k98d9FFw{d_2AhjIM9D*pXWgTojuHPijXTSM;b>y z$3l)h9QAte+f+UDNRoNX;w;BzBIM)QPGKQOEyub`9K18P#qn6C9+G430gj^_r#Q~* zp&49XbTo4Plj8xG9=hlNh6m(WV;nPS*W>8%$Is}&C)^yg?Md46WVPUmKNm+5M^?cD z_ZP~InMEac6;Go-b=t5)mZox4aO9ikb(~us70tLVxT}zkUCPiy!A*KdAEoP>jf3|s zi5%D$5sP&_lCrE$jx(f5c5^(zfvplfi{remw+e7@w$<x;Yix`*l+$K|uD9K+>z84V zTvn&+c8%>mtQ@r*lzI8d5jnXxji#&9gI5)CtkZ)DlR2vOU}snJk&siTjnL}I$@kO0 zz)x@dm)Cl5Yz_xJGIlygKo8y)$C>)oxt8A>ICeSBKPg@h-UYwi#XEP=_uj=fca?DP z{atG~CNovp&3Qv=p}Qhyb^e>vzbLcKPhOe5@!s7}y!X=a|2_9j`~DI3YiC}4%Pp_m zu<(H&?mDy}y*&QqM^@eb!S>f{zSBSZH1V#qVOFQZQuNPRZw-Gwckb#buXyGrEsFX4 zU*G@zjddSBdHt<DAL!UFI`yG{-2Lz0ExK{j-|qP1!_Qv%nCpjQUxfa#?5%BCd&Ye} z`O%U;+T8I4NfEB@`}QCC`t(y5{#=!{q<C%Ymfp92pMCJ*zfF0j(~Q`hf!FnF|8el0 zqYXR1TE2Al<Kwnw{HfE_7rc*+IywH0l&do%<MI=Re!V{Uhj-6>^6pE$wzqzA^0JYo z&))af2_N2ke(>deuf1wa+v)m>Z+0B}<nN6;JO6p$irfBBGQYBH?Z&rPe)V45?mp*k zK7PMFpsh@O&G}i5)!k$IjrsSKZ&|Q-Rm004y*}uJgwOonO^DdozWVC#u6_T80k=5r z`uzjHd*#d3?<`s~x9a=*KL729DQ~n%JCXRhqt;qB>+YhPaubI~{qf_!{rK3DXE%Q_ z@rTm4y8I)v=Lgq+8$G|{hP%f;^w5nRewTJ+)V^sK+Me#WWN+2!E%Vm?Y25IvNhQ&f zuZiDfJMNm3wCWw-$K$^m(s0$|7nUCW)7GueWj}a(?v&p=+%fiCrvtrS9{6;y@7I@o zGWFfj+h2U?@nxr;+~@5%wbl5dQ6n<{C#5{0E^hZXUG>3#zw?;)&r5f{`iCPc>hHUv z^!l6gCd}%)VDMkszIPQn#c2^*q-NEkv{qV-)<$cmU8!}``fEeA0<BEjjcr&KVTrU@ zEzuU6B@SaT-r}^RTHKa=i(+59X8gC~%l7<V&cB2I4*YlI{|f%&`M;9?PW*S~KY{-) z{JS-`Jxa4&5oNJl9;LPG9A&q(i_)U5jIvrfL}^32M7b?IkBpCsusEW$ZV6FNOZzA- zrc;#7(lJUaa}(pu^9a5#<NGT+N5#wct*(rUmhTI?{6F^IKR&AJ&i_9MSeV)^wsy;I z-R%X937APjh)NMH`2|TyASOXkz%ZGaBqNiVaehEzX*Vibs#v0B6)P$#wzOhJr7hdq zUD~=W-L<=Xw(e)yt*h9&UApUT14EUzw0xiMbI!eUCqK~rd>-HbK7rSqbMN_m&ilO2 z`@GMOJ9V9epE7gmWC=g-!l_jf{(XNu^*jmx9SLvCelDe-M)?Ekz0|?`Da!}R_ea!6 z)kW%3HD6t+>Q#pdtBkr`J)yp*em04Dlv3;XQXb*jz>Eu~smur7Lx^cA1*(Yc;0(UT zj(r_)c;1C6{)fO~o{!>wF7{PmCeOnkd=Dv2Qv+ZD&xg-{4>_5p`al`a`!MC-7J$NC zjSzkc_D*oYho-5Y5&lx_Sx|%fA;P~8djwp}^Bzp`zZo>}e2nlC-x_cs&pR%752a)w z0W9MA2<7=O_Bbf#`2gm5U@K_h`4r(NV{Zo^ApIvupR*b&4XSZ}k@Vk-y&KHtc{k=c zfU|(Aj^{TBFFCjY{4vklNuT|b>K3q&=a)(UgV=8Zb9vs6DfM|5_yo@<2|pG4wcrmI zQ@5l)ANvMyIqol!{`;}_fJ=DZiz)SeCs@Msn}nZ^{YLPo*mjbB82hKe)jYpK`X9lb z02MsHfcXdDb6`2or)~RR!}Ix+|90E{H}gCX_wN$F<d?M_`qXswIOZg9E2!o9r?^Xg zt_Od_^L@7c2YLP&&;MZCKgRPMo}a^%{C*ZRV>>~3Y0s75Lo=pLI>)wuj_1p8{~O!> zQJzb9{tBkl*Bzjd=l>wQwEtT0Cp>?_w*RMizKZ96vF+c_bCBn6VhTOo16q0h4dJEz zg=RiT`M+n|Kg08U+`n(zU+VNCp1+7G{%;5MJpY{Vl7rRYBRt=4+y9e1U&-_Tw(Y;3 z=SzA1I;POm-C!BdZxLR~a~=5b;zIjx<oOER|IW65FVCese-%^G`wUph^M4aw>az=c z6x$=V{r`+-))dvNw*8YlSMvOqm_kq6zzUv!Z`*&O{{J1~m-cu2|6|zw{r`2`rTyLh zf3IzSxBvey+x~s{k^cWIru^Fir2ii$ytMyB{r`uy{Ui91{{Ll6@xK{J|NjNyB|f+R zKWN+E?f?I5+u!Z~e}P|r|Nk}Nr9CI=|9@@U-|hcT;@98*|BdjH1GoSGxov;9|No<H z|C{h5{r_v2QlEDL>HohXytMyB{r^X{{d@2u{r_o9sqZ_1^#A`NytKdD{~xyP@Am(H zwe9cr|8L{h-~WGS+kc|||2^WD{JQ=B3GDv<|1;brKW_j3{HXr_W83~Q{7C<Q9#iuB zSs?vCPk3q1iTeNF+V+p)NBaL$m{MPN0O|k#NqA|0xBow6+u!Z~Ke6ra_Wy6;*Wdqt zOL%GjiTeK!Z2O1tBmMtNnBxC-ApQT}2`@Qt`~L&B{oVfmPqzKt{{Id9`uqRegqQM6 z)c^n9wtp{vr2jvIDd~L%NdNyO;iW#^{{N_Lf4Bd?X4~KG|9^#FfB)yaz^H#B1-X)t zD-F34kt-F6WHdwlP`${n$V|c!Bp>HOD^n>SxA#&@@1v*u0o3w-+>8HGeS^VpGLeXe zv$13%m>o<-)y<jS{#Z<<^^dX2Z!i{7X>Calc-E}8X1il*K>G}|B*US&Q<uv)^~ppw zos7q$X{SBf8_Q&)=}bV?wU<PuR}GX@Em$>uMZq3WEp_$nu0u<GyK4`q#&kNFUg(r$ z%H}wAp@_4xt<{MoBGCb-BvS0UJn8g@vf;j1qSvWw52)T)DA5y2tL{iJlMQA1RC>Tz zg7Ijg@DPg(sGdx`Jeti!!_^9vZY&(_(p3>o<y1D-AMFlhqQRbY^yXYN5gt_Cxs2~A z9qm=&crv`+_fFzV-8?_Y>rfo;CV_Z&SS2#^F2C%uD*d8A6$`6KFdPc^MT6ZsicIX5 zsQ0S)f&8i1SkLY&?b&+}&yopS2f<V}6_k>sb$QaGvf2}m4unIA;D&h>Ri-RmQd%8D zYF^d6s-X3ut_!6T)bBzkoXo`|P9m9gB2k*QKbD9(QcX^MeMh@v_2)Dc&QhOFHXV%y z3c*(f>rjypOQI*%n@dL{G_VuOdI3w~@qzL{cP{H>`=b6hoW4-TiQzHph@XIx^i*Xi z9wYG#`uTJ$6tA-8JSCyMMp&7Mg_G&1lS%euH-@kz6HY&x{a6ZZ0_y%`+Q|$;sQt5M z1v-;XG!g2KNAZ!xiw@YGi&1FQ22$Gk70Z`2FYRh=BM)sWOCk#$M=Tf)YMpB#ce)gW z8>uLXlsjdb=m+NDnJkFk=w)b;<flK3p&u@n-<65=iR8wF3am`9oIuZ{auT`zZaPx3 zhZ<vHLSik4*aw_gMt6gHAs*>+x;8`7nHQ>nox9i9*DWjw)?}R4rd!IDec8~^?!9!% zsQlK>%8U~UWkZf=x#pmlGNtlDI?_kIFuKPsbaE!MPMP%C)%7jQ8k(<N>s;kXX{+N> z+?IJ#BTj>%TxWi@vn*C;>o($Mv3Yz~)l#hkt4J&(Z9#|cBono*gwLj9Q5cF?1|1Tk z{;!pKaT?o}>*N;<IPI<#N^zuvEL0^_UN>wcE05wG8nAIhgs4n21(Xwy_GBque<+ob zbn8R$I03`!StJV6ehL;AU*)Lf&26Nr?W-EwU2BVHYj0fI!P}J6*<P!C){vEkTGu_G zT05+Lz-erh@bd<oHvJ0A5*-9ftLxO<UP;SoZ{jtembSH<(yRJ(3_6AVHYZYaoW_B0 zG$oXvT469kv9KAagg$B1p-z7?60MM;<ucG%_n=eOlTP+K{ozb{4kZ-RHst~m8Xb$I zk%}b(syUI#rgM4(aWpS;QX#T3=tPBe2ULR)m37Ev`p)876ifz@m@jIVr`TA<xt+B) zk7fAYUq|xM@f`eF)wB+8cC+b4IG%%vag=X=Y{f<P;wpaK3a`4#P?$4a9@?wi$AEsE z=RV?E>v|2S{-Oqi^(Nqp$)wX4>+K7uj`gt=4bkg_bLlj+Y-+8X+R5fLx5lrbYvGrL zw?fTDPPOq^Z=zpfDA3N_xlS{Kc&{d_LOai$8&Ej4rDGe=aQ8w!{>refo#{|&%=@-< zvNs*-cj`4U77~)NoxYWlPS{otg);y+x^IYO1AH)<zKWNO`7UAmNI4aj0QB+R1UW5< z;E7R5?9B-*>0HWJsCP<2IkEK3PIGPjvZ}=;RhJE1C6Y!%v^&?^3lnxTxmZ#pH|^~! z+MSKDY@Y**V7!+uC!E@LvTnj^@gUO`OLX=3-J-6mZC~EJeCa|6^rl=UD=in=5Q@dk zXrq^<rCH7%JBu7~`gA~5nuTnJ6$a!)see3fhf!*=pfZEDysf@@q2n>qfO*zKw%fCG zij}NrWRQ=%_!#UWj(y93ABjq}vq}<Bvb0hzYa~HaR{g@i)}nliDI$&Zr@{*^tEmd6 z!Z9lV$@2nvj;czet&A$En9C1%pC+(QsJuUv7<5AE-i%YmkXJ$L&T)joyww?Pqe4`Z z2nKjwA03n$%w&_0Q!bknpHNhF#F2$}ZC-Sd(`Y2i*(I6TR*;c#o#tXR3?h#N0%~Q3 zg`0%|UZ|jhd`V5gW0OKxebG3PyX^)WEeX!e=wR*$&RE?~-Xl(FNv4z-WuPjRV5OQ| zlJHMTm6Hyaae5Fw;z-FtIWp8}8NiJ}vQkk|@y-zkRH?3&QYRgS8;As=<uef?MDp<E zrw59QGHB{rpiU{Q9m|ohgqC}gaM8Ygo%?`ls_kg%YOP(>)zG}Ov7@uAqxptLCrVF@ zMr@Ty31lD~aLB5)U3Jyfj>`0fsxP}-h122r)haWX$Rf8`W?hoGih4#;ftS>FvvtDl zPYWGG*1BPAzmjz3eth*B)8!UAoqbVcI3%Eu(;H8+YRy2tA(l=W7Pf)GME5A&HAN20 zg!-dSf*)xt!~og3kxaw~9oH*w$&PATNl}-t=xV&Sw#BQIiQAH5Gk!Xy>0F}JZ7>GK zB^}C{9#Cs8E}gBeykyfw>dK2R*~GpPNK~X|Dbq&SrWtWVbg7sgwKEV%oD42%Ufv07 zS=rWkHI*+py0)>sqj|-0RaH?nk2+0mB-<*Lj=`?AgzNM%xa#0ufigx03_8Z!hEO~g z&A1dcj`x6#R@ag=qn6K#f=lSJA)QjG*HRI;6Dk^y_3)F4svf#|GOafDL28OYD;8&C z4F3~RRlh!y>sJGVx3t1h`gMQP@<=(PSk|$kX-=h>ovXB2U%Pw`VncX6(;D$W(^>Ja zJ|rwJ6c+K_k;PWkkxZut%N-l9u4=cFI)l-y>SPv#)R)VuM!F`Y(V>VZOvOhdsyRV5 z#iU_EOlo>neS1C355bB28nRV&TH4N->0s2pbbF7cY{tg9j_F~LHoU3<UMxbtyNWEF zk;#wDkcIoI<xv=vObW7n`dL<&wFN%akqxEID3MCV5%BZ?<BF=tpwdnXf3-emGbKZi zXP%G_8!0ZnDxjD=PzP<%H0{#wv^RD%c1j&c_dwiN%#+hpr!OMXk$gz?mWriR$*;2- z&Ls)2wG{F$0$N!=70P5}$SWm=QisW$#{*S>LTIr--1VBdp60nc1)<z=S`bCTgHB9V z)M1*r1WbX~B0aQ*dShW{xt=O{FPrG(4B9$cT2Q}dZWikqltkRunq|51XnB=p52zK( zwErc|oy7@CYW|mL^bWI7Ztz+&PkOWG%zKwK+)P{VvlwF*Ld>4mjOGlPTuL^L32%V4 z*s-G@K>@0#@tp2tD2=F;<T0Gw5KWUnWk}CVEBliD(aI3wRZnF)8jms~u9Pvl5~)5@ znbVsiDut0H6O{~?T{2YkSA<o2XJc!JP!IxJBGUr}OWj!Vl$5jwr_4tSn$gcOq}Lwm zN339Cq1yz0%p6q<Tx36HdXtPjuD(Fa6Crq%^s*xDKwCVN;Dn|q1vKqT{-BP`*|KKB zOqe$r{WWc>L=tusk7{}7n&qpc$JKQ-oGohO11SPh3s%EqH6=|{3$z48CGpjfZK*&j z0BR0z$#y)VUYRJgcx{@QS{7Lsm57M!$d}hKpt-%F6aAc~3Iq~6AQgL9La(NkgmC;` zw2X?*Ml;J^Xvk(ww;1$exTrXoHWcO8IIl@EC7b}MVjR~M9pk)|N^=<q&Nd^i*1)7D ztcXmHNz_csQ%M=&(9oo!>Fl5+QA|m;C_c~lfg`MHZj(9?SwtRN$cQwG@72nLS0JCm z(v{0^kU4$Mb1j$ABADz6B9b`NtaQ4KdWNZaJ!6;doral??w!*6*##PpikL^A_L4+0 zlM-vm%bO9%L<{a_Yeeg&bO=UFnb+wK<|dzwCcFwwL^ryD#&{~upK$uId5k4u*>t4K z^c4FLO)!g+$qfn<OVLRN0g+|PL<Fa!%joJ6Z$M>o-IgjxyL6^CyM>iR2M|nUa_$na zRIUs`$uxXApa!EERZFLZB4Fl{usE7RS^i_^vW0=q=8~pG$VZ%{4|cd?=7xdmlIitY zx2PxHGMV%-9Z%(B#8w^F4N@3G1L|56jk-RWOFJp{2ul-{W}I7^?LeeSIF=D<#H$gJ zHy}nS#4Y;QX^ACr18yKwC?f#sS)Ym_ar7juP}gThE_ox7iztt+XmHjsxC62b%f1oW zh<xuh65(=I$jI7(x_H=^NuLqPuS8m)?PG~>JQs;(n3}`*T(QK+5;g`?Kp97%UOju0 z0ov#?%b7rFekv2BRA^8$3Rlj`%+b{qF_mWbUza<vif9GmOfKQ*Sq?*3srJ!t{Q1R} zv2`m6Br^)BP6jJw=g%w-WU23HO7(=+M-^id5{Xo^nW!n5uG#i*Nt-f<(=n}CtIWy# zPz9#DB62rM$sXv-^C845(>WVB6VTH}H!6|bys+re^^}a+gvd4oEVceh6*ExQGs0n~ ztYc+IqamX?PEExX71d64)x7zr=odJv@er)(x+2)kFdpthKG+b`Gr)NtyNrErYta=h zU+JL0E)%m3QbZunT<O4B6FS;?)fMySIMo%^^DE{BY^jkIVrX8<H5+35gaBzUR1ff7 zX?jUORiJf@cO#!?7J9bwik^6=H?vUxmb-HALf4}81~MQol<pyxa%mwUx`nQ#Jd=fI zFNA<HN!)pYSNI>{zuu!S6Rs4!us>8T%)nc;a0Rh(=ZTsdmzIP}H4}JuVeG`CAF(|t z^Lz>Hg<Q^x8r>=p5qZs>qDY-o=+yvGj+;7?JT@9-gsv?!FzC*pClMkH2u*5D#iFZ> zStj{~--U^$5Z;XB>{(?|M*AD<=#C$*domtD78B0tK)F5EJ~mvK`LY+Oh`Mk-uRB}e z*K}!S`sP_{QoSeBCnejATm2~%#2vaL1r(YU5rP>%jGr7dr{|z18c#sBW1K6nXh~8J zNdC|g9g`M2X6Oh_G+M52Lb)+UhA`c=kiO*G6|5{LDF{}xGmHV@=xn!7o0`(Yng|#+ zF2*V?BQq*$?@HK~b@Q|QlHk1Rj9D*XJt3gV^q3mW&QWk%GaeVbR4j;#A90a&LWqSK zzc6lV^<E}>dSsrLf!i5(Z4>8Me}9@oFHFvLzY}sqbEWf8a=Bh23Md3Fz5Iu|Tbp(y zkkT=eoL?R6j-jY=L&2G1DJ`!fafykvCH{nExxL-Kxjg4|r+Cfe1Vt%cVZXi+uTIZw zni=pIj$}mv!dES>Qp}sho8ddNP_nRq^{*;cdP>6bkB@c1t_nk_<s5dvM+ks*`NmVV zhLtzeokqEcaAN%{ncZdzliTt9T<NR{>ycgrVn#tEFww_KSA?3Q@li61%%83Nq3Okt zsHw_#@SW|+rp6J8tVB{Q8u^kjb2H%#h<xmR&pNHO^{yzc<+E@y6+<GW+{>?Z&`%gi zMK=rltgNcM$_&F=K_XLCw4j;v28C5#p{zh##;a&rM1Yj)(~oG6v!V=A*@S-96+(YZ zIE^h!Om54W_A?h3dg_iPLg_(WB`dXBK&VnG(kWXk6~+?cyOHU<!ghFKOtB8b*1hNN z9d#wlyd*0d22>q}<I04(>-x*0P=!FqRQy^5Z7s#vXBolWU|!KHbgYnviFQnM1u;vl z4yHB*iPei=L<OCI7n?}0p0l$d7IK&;>D3h@Tp@D>Q*#2-9htU>Gdmo#AX#um)DoSf zQA`^Cggsj=2`QbLX(FvAGup}!%R|{}{lYAlt3_}OR7xz2UhOQRd#+x{x>t7X)h2Tk zLFh$@0&DjmXER*2(U=5EU7w{Utx{qul{MN@FNsnsT|&2RO&iUW2_c#H<*mY$CZn`+ zU1Ar}mEj>0Lw|x~!>XqhFrCUdXDNy2-^;r&CKI7<#__Uhk}CDWma0zXUv9RIuq<mS zGMTcf5~pnW%9fTnsPy8oZgG+|6fFyMnN};)JwickvINNJU9Mw5k+g`(r28Iz<h{RI z-p?*~W~;f<r&7*p-5mzjszu7!N-}JmVi|b=3+YJ)Rpneqa^mO-IKrNp?9Qz`OA$&g z5?vhwFw;>Qyq7gGoh>NLtaEuU5$1anEHET`iwi2UDC=a|q$#Bl4H`P#)d08VVAOWs zNQKj;6<xx+&8vV+ahDLr^(=%xTWV5XIE(D-tGxldBA}NZ$P1IT{-i(m)XplZb#(sa zHB3wvEKCXd*ZW&bjskI>REA(SEupJs85Tw>1EQ}@$wwCwkF2P<g|)itW(wnK%P1Dy zHEU%#-<FVYUx=LubUQ0{`eG(s(U-WfS{J=^C(?!0n(CHcrF653x<gMG^@<51U=A4# z4=I0!(GU5fh4)K|N-|hJDQ(Wq85vEI47br#QT3E$K6Rz>X$`~!0t$t#XmjRP7F49@ z+Jr>e9#&LW2()g}qpK08F1HS~n-)tKPM<Ej$)Lq7I>fk$OT3adT6qyrG*1^D%g7nl z$^Vvi%@n;x=;}&mHn1PWdu^vbJj?PK!WbPD6<L?}US7*6(#6tdEYihpJK{9ik{sC# zn54$MM*i_qvipB*9=zAYt<vlYlkITR;qqn{uWfqaH=u(5!@r_hr@`fzv=m!tN!PAO zawP-PMd%WEmZE?{+M@&d=u?_(v@<#>5n{8b3ZNpthDK(ovYW)6LaU2x4-U$T4a#Au zN^2KhY1CInYCw|64V0TVG8aQq_H=E9J|<fAu|6rT=1smBL?!la!sE|`HoRNb(@lQH z32diT?gG0`bR2JzM<FGVO#L}Clj5MT9J}ew8nFBcqA^AF1vK%kG~3-6R&yyPKv9t; zw9XZ0WWRD50FdaUA1@Ro4!fZ^Ixh^~ECXj)`$$K^urtvQ^fQBF>l>R;q)UjnsMld- z#|kW~wXt<Y`}JLQwab@v$g1+kO{^08IGJ{<2%2HMmYSqt#_=b0q`4B#NU&P!r5do7 zn8h@`P8wu4P0*5%iu8wqXiIvd%z`MEOlyUzgaM;)l}WeZ+Cl`WKIRXsFq%2GBxc_@ zB{|c)$@QT@1({{p$l&g@K(WNKr~CxTi?_PSaAZ6Z5-#N_4g8dEv{8D3s|VqX$m*_` zpxL>p33pGXKdg4vL1n{a!jqMx=3M_{H(}Zss6?x4l?g?O-izs+Z8N5kfVEE&u=12* z7maT+=9_rQ(23T!x&4|98~F5?LrvQnqlAoVvVeq8l1!j|@9A0Vt)U4?h7jAdB3kyI z*>xn@W419CLE^};XA*^^D3e)A$z+*r$^gvvi(Is_hp|BK`;<gvH;+(fh-v2Pitci! z0-32I4n*vpyH<~b^PEM=6q2lctX9EzRt0+j8)UD#N(Gtp&ALi0x|)|!bu}*_kwsU@ zM6gqa9;XBLBwSPG#4vf8tui@|ICUZjv-bgyOJZqc$reOzr&eT?f<6Gp7RD8`eld>Y z1WB+eOd6>AY$76Oo5RYIFWEMy7a5$6p!84FQxSHYYGGVdlHzBqixzie4~Do3D>d2i zmrRrs;!0OX|L9Hrp<2qz%wJEy^%9cPDBBy%bWGCK3ulFV**Qnqplng>pHs*lQRzCQ zfTCg1vFa>KBm>2Tb0Zme*O3&}jT;<AC(P{K<bmLIdOquvjR{m#d+(-xI_e9xW2ebx z4kr3LCUUaRSw<~p%BGg|_K7)awe%MU`qlOCc(WBDE?Xp-wCGi=qG&XKHd3ooipk<U z!<g5IrD7``J0%>O9aG;nJJK%Q?<SO~F<&UAY?5b>5Xa56TU<RSwA16WhcM%iznrYw z!xN<A!R;1W`hq8;ZI=Dt8|fcPX056(6z|bbhCdoY6oK-hs<|jCoLQpu@~<elE^J%Y ztbhrhbV|-LWac;<W%rWIRb*dMK-~~cC*4WY$3HFuqRgchDy`p=-<kpWt>*XR4poy( zA@`vHm7T8gB$H%2s<DHc5zWui)_P7xl9bzSlHE5k0nS)GKO9v?G&crQKgHXJirw_! zXhvjDGz;kMgoL%tF*e5WLdmG62~N4|Kde;8!#SiuSzK_FHAAviceq3?%v%-{*{s37 zaxe7iOlSkMY*U)GEcK*BWhztsak#yynt8h9#3AE;!FOt~xE75r*AXd<%Cep}y8g|g za2bRerymvultS(65ye@p1Fltxem5i>ip>K~nJ6GxG4R@9{Ag7Fn1Hg+A;^+kTCX!R zqi|bN>yf4CjIOL(jw+8^x2rD_ZIz{nwJH;52FEate}p?(uyt1-Gwd*N<RFP!ZrgY~ zU(2B-iV{Kpv|Lmh+>;bWj~?%GX3d&4NA)6IZVU~gGDI!eA7VAmy+A`n5*c1cSpJPA zl-|^Ac2QmFh+a{;mtA&7Hrhb1@x8TgB#=VjjyTQrt!++Yebb7r_Qq>gvT0EWjTGs^ z>veQGfm+k=6}NWixtdj|iqgRKo70-f<x4t5B+e$o$+%iAyvYWI*RGa)G`C50E?g^O zx-cuP@KTY!aO&(4H#F6^Rdz1vY%4@BI$w$A>;a3zi2rv;scyxJ&e2K1#VTqB^eFDL zmISNkYmIe9HJs34r7sbIMKm`cSB(8L0mYvcAm7m+9Z_$M<?s}$AqKRfXbbTf85teQ zc;19nlXpqiTk9M*W$|aq5oVSyduQ0iT$G|Ilko>b&#<V*Y&zHNOdOyPDO4d!SFO<Y z)RbQQ1%KuYgdVdeOkC21@yR(e-Os#eOb+=i#AjE~^}^-Y2n+t|nxXx%9&C&Se?^<Y zt44<qe{v4QK_+0lbXmu|cj>SCUHY5<F8$TKOMjP5>@UoGRZeQuH`B9an^6%R7RoDh zU^Lz1^#k!|h|uS695O8U<5(B_?1ZJZuV^i<O<Jjtt~U`fa^9#G6n}=O3;tk!ql@dK z7YNi@ifoV_<3~uL5T6_@Yq2yqD$yc;Xbk&Vy<uj^4AY!Y^La1CX9k0beER(5(5SK? zD9VSiar*q}!A0Wp_Y{|h6#O->FqP}eloZtd75Os?i*Y>`{1wV!*;0{z@n`733LCnc z6nW7pkMTD_+68~in0lfzqZ&8jiTxEvJh4BWQFfgg@)v)mpN~%0#OHb}_;c&oxXinp zc?R2k+>#g4#h*WlQ63Ba*hLdz2MiK~?2q;$^0k|(=Wr+$>K5f7Cjm$M^3!v@?dM}@ zRHBr0O+Rw|jYn1E`SUkNfn65r#f{JUGiCQYPUufJM}e(Q=+DIGc^vD{Z5J=eQS|5L z&-EwDImh!X@tJz|`5RRRxBe#ZR}|s6@r^3$gz;&AI=Z6rPLQtWXTtbQIf^1I<PSc6 z7I~-0-&y3Hg1@$UN2<`7cR3wnLVoXViZ!D;$NJc=D`%}a4cBbtD$Z^sG-s5B1xBuh z=!PY1E8(!QNN3FvipwjGTl=g|y%u?-CLE_D*B#W)0d73~zxb2cY4t#b_e0bwutav_ z`*N#is|7#o*U)RQqE)cFp`>K>{zJ=72d6xuXzY4@ibGHM^Jx&7`x?bxGQ|!XHaiWZ z(qfK(1PBeNOthKbbJ|;GI#B{Mv(c(3nPV1B)<kai^nIh%f4-URxVy;AK^U276sIUp zl4_2@%{}&9$bhG`MBy^16^<2-(K|u}PIuI~q}<t5?%Y`JTw3k~%bmI9P9+CnbY_rK zMZ?IHR39ai36eh5)E^BA`Sj%CPK=!hvZlu@Hxa2sj@M7sgo)ZHEQ_*29qhDh?wo+F z*NH2~R)*Ho=pFqzIUGpY<-r`kQlfTcLMJ;;<YtC)q-uRyhkV5c(TmGDA-{8u?eIPi z$Sg8*bo7Oe@!0yPQ;8O<lG_~IO*$%=RKbu6-hwI?rL5=x>ys(H-&l4bh>}pR&)dD# zW<QrG4-4l?TIF<w(HkREh}OxKZp{h+Ly?)TXdRg-5%jJfHWSJ2U$eWcS#JbxBSozP zb+e#V@GumUtj<VbJ6mxs>b*r@y|HcdrZhKMksHk>I#>B^;?~mu$#1NGfHSIL@<F$3 zp)|ro+^RrXs`tYeZ+<UwH9O!Py{npC1}1h{IF_0b1+YwRrGk{3l48?^q)5B#nCM|4 zbF)HFhn6;JG#ea+sSy>V&*Hhix1tGe^c~+5nr3MvQYi{Ey=O#MtG9Mx*BGQ|($~m< zsFv6#t-aaAcxw&;d#WMh$86Y_lSp=%l>9ZbZEPXbE63Vp|DWkqX!LH$AzQ%AZ&~G! zx*H-v?ZiF?eZ{lhrzv$~_oDlYQsiTyETgd;BTE2*fDnM30jiYiP5zJ1@vuXHW2qeE zp%}7?rMo{z287ei4tC4Vk6?JV>;ak`%+7X?9v0W9xidf)++EHS?YgW{$W9Y>FLLlq z3P>95at=u!aiQwn%`-l3=&vVqVfyg6Z@a=(?B((JgE?v_J6m-qv$jTuXQ@uB_st@S zOFy&^ns1%7-VEz<8NE1}Na};y!nL@m+cpFdj!$oAZ3r5hg{ci)-MJoTwObEsp)__T zO6Ig0Q!`Or$2#}Y2HcuJP3gU!mSvdTMsml**rTb6>^rOJk*+>d_K3<r;SZ|^j&TBu z3b~XBN+%rlSUwB(tTh#E@+vDO@B|ukH60-w>y8hubtW7&3qu*{FnY*(M5!JW5*r*Z z>ah``5tQA><CWMwC)&%7dugOhG{lLgalK0J6V4_lxIuop$tOoX>FtFwXlcTqiVWOW znXINlEUB?W*<J@!Y681k$7Tl;vlmiuow!Rwx}w+)KRdX=?<hxRue772bS5ucHv^gp zqZdkax{RB)Kg=<Dbt$AdiQ&(vo1~O6<Tk$Xwi@bMYsP2qr0%#u1KK}MrhyC9V&XB? zAfnDVwBt5|kSy*>%yB&`sZ!g*6MFJu^QEMh%B8tnQWkA8RH2h%xX{<)3l%ViXuHm} zJ~nGvJVYv+4vg+~JSM}YA+47k-|he4NF+5O`*%3;04tqk8T=?dVtKi*QqRgqW)<=N z!k&eCT3KqRtE+D#(_A*L6|Mw8!0+J<rdfT9(oc)K65^d4TxZX$8&s8F$)*EFdHH2s zT?_^p*2c}{IqXNa!<wEOutMc-rDng|3QknO5o8NKLG|D_jxWYj*B3D}keGQ-aa5v! z?(gDQyVhFwcgYZLt?Zi8Pq0$GBF*sUt>~}l@T~shkKW5>5v;tYdMkX1)LxR&Zq9Ou zRI(>`N61DJ^R`o;kDzEQ8kqk^uUnF7km0>U3m8)Ll8gvRg#|!aqL*kI_0>Xcq8KE0 z_bu}k`b<`DKj*}RJ*O<!KS@ITt<W3)jLcxRLk4BgbOkY4v2)xbvsxZJ%h^y`r9~eZ zBWgE{E*-l#^tsTYm(G%c1T=ASqfZr{C3&-Ps!OKH?!hU#r5>Ekfiz7FMRKN_AtVDW zU^6l^-}7W`$J?<%v(p7~14<WAR)V@S5ye(1&gDl#&Wesk#d=lZV~V5D{TXFWFDtWU zMQs?6MVySfIWgcxSleFT!~rh$<fvNx8%p=9+V)mFWTSCsV8P`o7P`DfHP`affBAy- zs`c^(%T#|XoKAMfL(pogSnIU4KbFd<*5<Yj+*26>h~2roh6VntO2m?xYHog7(cv^V zs}%P*q*L6lB4%5?N@35;|5%l3u4{EV#L|&NwbrCE$i`vS(MCp%ooMxw8!x#CuSfRh zf&ps@ZAf!xM(wrj{IZ<J@A8HYev|2W>(vT|(Dr8b3CMl&D#O&SJ2{{_tV!vKzgD^w zW{8tux*s)!Hn2<>b869fn>S04=B;*HlNREAx__hWiD6rcvB<_eHY=(nm{!BUS@CF8 z^`=Z5oz2d&C|9S6(Am+}VmgIdCOfdWfk!9I`o3JjpGe9qqR7eN%!{5|2uGC5A?B#{ z8_k4CEsLesZ%lHwst)F2V`A1}b50gAEEO~9tY}^3_u|fsOwyX-Rjb_e7L?N3cvxgC zWPe3#ZJW;eb#jx>(l!TTN_C?q66UkSOQ@}`#h(tRCK}}EyGf@*A7_I7(gdM61yLQI zm8+8UB9UTGfr->@iIqfY-t-UHMk=J&x~jvUUP2-*oJ@|gG2xb2s@nX@SZgPys+ZUL z$Nw^ZOMghoPw~qn@8s-@7ubr<vX$I-vRMSt(I<!5D+I@5GRzqeX+7CxZB+@PwUPVp zWTMEuO`NZl5kTA6m?hQfE#*ou*>-Li%@X$%q>WI&H4>2)yN!m+(4QHGn4UzV6EP+u zB=`a`7|ID=?j)4i7aNr|gF=l&NnEb!_b!~w^CjY^BY9<`3VRI9;<T`L=^Bg+(TKl) z7{$Z543=3mk=PYHZ+dFATH0;Q%bcdN;#w=b^R=ISsV8&pa=Byc*gL&WW+%=!mr-`> z>M;YDC5Q$tY>>&6R!=}g<_fCui>|9vI<2#oe^q|jdE_O!s+Yj5;$Wh%jHPMDI@ zYU3w^7iR6WtE4HkC;M{@;b~dK7Rudtt2a#Aou;-~edl=fwV8BmwvtrpI5J8m56Z1| z5l4^;(t}EBonfdqsl@@tZLy1V;wam?m7?OZcYFjCcU1*N$_}C(lf8;J=Qx-WQS7)? zPMP~S$Bj&j^;#6mB|I@sgcZ^J8jX?ebw(I*MIcEX2}TP?4%#vA8V8YU>{}xg$-X`v zy^e9Toa8uu3C-+z6^|=AbOB8=UX0S23R0EMW3foZhAQ-Uaw1ddi`(>hzYY$D__o-Z z-LLLWWTatp1A%TWBhPWY)I8N6xy*Nqg~Y4tU3OIHJ<OvW?JUuC_20qa1=iPJ6)tr# zLD<$Y>Xk2QLtR1vm72u3>QnZy!W782r$f=~igAF>5!9z(qAHk?JN)pcE=4=1rK(wS z>zG$wohe;txR<UIla{<HIu2`yQ`B&fBfXW44%)k^E4o^}++`%4Qlc!2qD7EIL?_v- znX>I!`W7$UyPEv|jGvO6-Xnp?%XKp5*o~G4GrB)uW#61`ZzBP?#Gzj``{dsO1#w=- z_2p5j<jL0sjeuR00ZsS~=JRaD3keJD{$T2`c!9xYU6<@yHc^^;fTWC$$ceo)`k-O* zKABxwLT<*KsFvy=baBI<u79agbPr6gM(K2mYD>3{&WIVKbUPLK7!%%8B%5}ps_e}g zIxNY%9^^!g$7G6nZ9q}iHk%9%E(3$*_$M1grE7Xj4t!~7H7R9eQOT6Lc)%eUU)S)5 z6A94OuoIrirMcnRKQ`%laff39>-vYEYo$FyvbE|<0;T$`Bw#mx+e@+t$A5bprO#L4 zy>vno6y1ZI+%1lW9x0(^cb&LP6r$kPcL2I;Ht&#@9(hEU;mZo?6r#!M{qKGs*Y$DT zfg^&YB<jktg%BksS0=--C5C0sQFw+d!`VWQ4Xl?5W|vgV=TkgR8JZY2fjYCzylOT& z=#Q+f1$CevG#Jio6rPj;ijgB!;cS{)Hkl{SVM8BH7?mlA^k(i8G*`x4tFy)2ZoL*6 z<dSG}3E^0;e9S2#^9@Q$#S-ooGr2T^ppE<@Ib(scLiDYzdNZe+EH2}uZxqS)a6xnB z3M-b5m(?P#>^tFrh-^uNM~>&)y+cAyQ_J`|o}Ui)f@wY3H`2s-{@R+ZH_CLWSA79^ zG~yPks5ToL+hnT{zN`!}uCKxg9y>*kIyRtDDZN7=Q7hR1<NCC5735OMjokG`%Z?ks z5k~5*-fm<SR(fqsA6M|W8+_?t_FbWVSXo{uE6d~kSVgR(5=<E(F0O-#av*B4#3Cn8 z2k0BU(S%%&UF^V8Gba@XIO4-*C5c`1ix?cxqs7gJX|5qf<DcouCcD_r$*D|lRYzRp zl|I5J?s${MBGdWAh5J&@>POE0>C2hz%A(J|O;Vo@oG8w5{fv#XPG3;oZM256y51h$ zP|cn0t$L}8V>2@CVu-Of^UEb@dN-`^6>LZL3HyENnKQR0vL)8?O49@Ve(KDg9qZnK z-V+wa;L=}F<V$uAT4e)rSuDjNtxy~dO+oRf8o0__<P+IrC1N!bXLC8b>L3J5!PJF6 zPOaYI=3<d|eC6n1xe6sK3lYAT_36P>R_5WUKCUjYnQiE3Bhjdwl9IU%tC(CNtM`2> zHsW&`ZCH8aSivo?hIDF#KG`@cj9W`!-pq*f<h~lco>gbR8mQN@H~=G_ym7hMM?aM= z&aCzuT{(+wu=te;`d6|y!32hd?1HXF^Kr}N3msqgVe#b~Z3?btgZe0E1|t~-b=;)P z<c@?SV!D!9|I?8ocb3F+4yrh(OjUAR&UKYYnM^{tt_N}rPqo#_SmYgluW*MYoP9Nc z&qVMRIsagfW!PeAU5&0*J)|-Gh(jZbx-_+x8gvbHG_#zXt?n_3al=QQG7iPY($2g& zb}i8`VJ`z`55vVldI9o(6lj#^hO^|Vdcu6YQ>gz@BGnTV{_KfV&l!~n%DoBecjA(~ zQ>gz@A`_M5?1>bY#O2nqDFFJ>!!7shHZ-?$NAaSL>s!U(Yz;=qyec`RgQ#qDQOKM9 zkf3Z^D85`m4$DE7x`VKMl8G_h@<cJ|4v4Yz22*|R*P`{E01UNynx{!x{J7DWw?Q|5 zV;$t2xlTkb>M;WlXFE_d%2zg6pyrb&>@f?kAL}aH-o3ZN8sWW__DTlpW{2}4#S{uh z?>1_8#}wj}TzTciwvq0Z+^E$oo_DL<LV3&x%_=jOsfFY&RxX5c`eUr4vpDNTpqoSQ zYw=#8PL>aY7#EYxjFJ-S3&Cx^nY((W&kXi=Cpi)BR*T-|Zv*NKxDK)n&xV(U=up-R zQd}!0+ioZ~9rvwUS9;o`r6QtnU)t!+>jbxClTCg13fq>^5JNHCCd_ei&5U)Mdv9er zq}51<LWnfOieQX8(xE`3T}5coYlJ4Cq{=B)J?-}HWSdvPZEo(|ik)+^sZ|8*YE6Fb zl@zjL#Z14fmkC^D<|8^~(NRcwy<ok$1h3so9L)?cVaW$iW-?IdMxJ1*<uyCLbaNfl zMkB$|pV%=tKOPa?qz&y;mzfoPOMK?2o``Ubtb*GeMYdwRof?SIx8%x^8Bm5uEAYh1 zsacloVo@`!??g4*O5~CaPPor@(8Td^1<?uU$(ir4xt?byqO1`>$c%XG*wA}4xywWz zO}r$-0x=@7cShX=V~`!?NA99zSzN@On8?rpx#$m;5@)2<3#DiQ;Ud%tHNquVu{u!; zmQ>A^qpr4s9I@F;P|O{q1x-CpusFHK<!boULUT@ip;OD1Rm@`9NVZO{^R%oONr!aR zBEwV6P;A-5)oKv}x286%E<do(O!T{GDy~fLT(V;2@&-{b=ogKvIC#?GJuY9tYFB-u z_gq)ouwuy)ZlLzRX{+sQ@;`TU)^-+xbhfWtUeAj{8bs1syR^C9AI7~Y-OUGnItW?c zxw5?w6)#(AuV1mUQz*^bR^}Z|)6_ykYQhnrEy~WaKy7;)BDGxPuaEFSbmjv5D@9s0 z`;tPvA^9juHyy_EfD&^vkH{)>9gig7_e|%6PFX4HMV}Ut<(3dL6uDfrXv<ZT9DS2T zZq+V=TASSUu!0X-h~AsC<LKIoVm8`#yMvhzQq#^NHM=sN$;Zlsxy^v}3XY#SL?`3` zdD0|}?Uj7{LNda|<>DHSYu>}5eWW?MhPykmB-LDFyexE@mvdb{$6j=Uu_aQDnmOHR zR6SuCuq3X)yQ?}z7WNXVl2j`+Yj18S$><G-bu0O7hLEdVi71*%Z}S|T=YO*0gXQK* z(qW?qQO+_~L~t*JsA1*7wFW%Gpt*ear$zZxQc~`E)q@y2n`_M}LaD$GJ5#sXa2Aia zS<UC}+dCo@VBCumG7acU&S<~Lvz@X~z51#=rf(A|O}Ne7Ig9f+PWm%4vcr$^vl|C$ zb5^&tH@7yfRfXK)X7gaS9l<2o>dDG>ST2ml)#ul+6`>c|V&*H3_Q**}MkH5Q&?+|3 z3o4FT%4PsAZD62GBGf2zkW+Vpb|#^sZjeZY_z>0P^IGP=N^D@mfbI)+<j@C5U1F7q zL@$R%>73GCte17NbSX2@QZqM`ZtizBR~wG+$jpfn>uW}g){W829~MVReEh)ca5cp3 zb2m3p(Y$)!C3|Ykb?opVbDcvON)85BxjK|v-TaB!8I=}Oi*jKda@Hjv3+zQ6^el@L z<m+=O-L;AwI|lnj&0-xoQTW@h+gCCrUgbwctiM-h$m=qU7#`En)N-X=2$a##-MvM> zGShH`ZJD;ZW!Bf#$&p*F_%)5Bo1FV<xq{hVH7VDV(1(N+6g(J#N`}&GUpkrND2rw0 z#yKF-%R-y146xs}v_hGyIS7w1GEmr<#77Ka-j-~%kb!2&s-hP<bEl~!noN%7#@CB( zmwP88C1IO+;pTES+&oI>ka2)@6+ZN5{i}dJwyVd^g>Y}V`NN2~WJJ&Z+4{QPna79_ zkIV^l6pt&kyFa*=E95qAbLpw>G}M4>22_X=V~3^jIIz;EjU`pRXeCc_!khVw(rMWT zogwD`bL^nST`AJ9^#*-z1G-9YL&2TP4&*E|4f}3dO`2ENmfJM6%Xsx){N2j`|DN*u zmCFC{6~2e9)X4eZqr26Jqtr=0w|gq(@SSSh|7nfNzdE4uwI2uTz@W<4odf2p{3rei zbCt^1JD>|Z2fhIgf<xdi_*a#0xEv7vscy`rAPm-n6xawp1#Sm-1Hw1Fr1HyGVE$C) zAKj($jpu<s0hfYyunjz*@_e{2-}o4K*7$FHUFDbXeb*&_WS*DI#Xb*^uO(^l0{BO8 zQstKt=hBaW8qf)FUrPE*zXHAsegb~0@=X_jIe>gO-3aan`vG}t`kl%*pAX8xCjjMZ zz6I<CKcs%n1%C{x!L=X)hQV{x?Ms0A!EWmEn<mdvx668X|DS+7ER*K|2!g8t^|I^+ za1;0>VXpumAg-6ysq-&Zr%D!pMPRYYUp7PK=O4h{KpWB?%WegCs{C^ot9%W0zw9os z7knN3C7}M6{R00@Du3xrb&@Z4pFH;!b?OqHTc(2d1Ip9V2(C2ow6<aYg39kBo=3lE z%Fyx%@4ll(BBb-`OW04Vd@F6zx<KXAk7_?7vAt>}b{If^H;<@OWlf+3w1G}_Y7TVu z+7!$+V6!?kcQfHbAPF|;eCAtkQ~57W=9xUSLMIQ?F0D_3W8n8DFUx74<x@=l64cf8 z&+yy~TER7dc3Hj}tOK6~_k$;>pJSxC#f01X2P(fJ21xs|3o-YBpMp2RDV1-djoLl{ zO29(ieV4owwvBpgqa1C--9~t+_qG8r1jPMb@E0n7l;@*Ip=bPFLtnUt`n%?9;BNrw zTmzl8lZSTFXukwp1y)iAv|D=|i1{n<Tb1vq0oMcK>7dR!?g5mk<1qLa@UP(K&=z^_ z_z#n(j^irdNxnO4N$UXk5pgM=GvGebq24;52mc$qrSdD^2k46{7X$kJ%G&^Sw(<u6 zKP!Ks^4AjowH;sspuVnsTjj5#9j=3ht|R}~T?e4Y>+T?a+ED2HI{LzOf35PXCV`p2 z@n|rA!viXR!%pz3%2%h<$bpyD$X_hd^m+0<=c!W_^zCD`|LV)Zx75hD-c%#sroI>B zfBqh@19$pD#X;=kXZ82NKdAhga{=utZ8LueJNaGnb&v-?R{6E>rOedL+A<*KCjjlV zwh!QUEp52=OMrZ@Jp%q+<!?L>Tn26i@RS>An;V}5+riV|0QfHWJ3yElUkCK}uBm{! z?fQ_RksGO>F6z09GIddBT`NEj_$qzs4>4(*uK!l~b+sT0J`Z*P+Ik)IFKr)s510Yy ze<24@PKhrR1oOcnPzRQQb}#@QG;I+2Huis0`Cs%=Z!cm(YmpGx3cdm;gYfAHG!=oi zBCmm8nz|Hz5P`1vIBP!g8*p0XZ>N2uv~`p`M3;aZp#FL$fhhnw>sbdr4ZaCp2GmQM za`l{0`CjU^_k8Tc*-O13eB`S)W3C5bK-k_j;95{k+_S-Zv5SAowe3fk<h_^n>ir)0 z2LP@1o>BQe>a&kJ>4UHJwFCNVAN0@%-Stu5dv{_!r}D8`m|p|baqJv`|JV&+kg`H+ z{cn*!c-*B&RsNUI<E5u?+YO#KG#>ja?0*k_s`58cmYc}qP1K?Eft$Kao85FL_NM^# zf76SMq2ItH?>EuE*Ix{7G2_Onjo5F4|C0|HkJr;C!duq=5WE4%&wA=m>S6r|I0=X& zPF=*wTO2=oen37CseEu4&`<hl`~H1u<n6c`IdxKv{JKWvN2=7R>KDNwz_?X?7{DK^ z-vsdP>XYCUIIT|2M|PMG-=04W&@bmBN6aVBH|(H(=sUuH5^3;H;HN5|r2i#x7k-$m z16e@%l79iHt0Z)sx(alYj~e1C1Lc4`&6no|Dt|NmD?JnZ34lh@9|V_xRg43xF^MmI zH+Te)kMw<Dw@H%|oB3Q4Iw$QM^{M*?b(y0cbF@S59<UGp5?;c&aS(pP36<Xn-E6!X z^nlNSuY*@regL`~Af5rzAGjURo&!Gy)c@c`U>V4OhXAxV_@63&%Ll=gAPnvX&x4<+ z{3j=aOF;+tBzOY+Ey%0<rjLMnupWFKd<*<c<v;aaFdwW2w}Yp^kHK$M{?iwMWgr6{ z0^bAwsq%mJL2xAqgS)}=;3q0SG#Ok9I>09ZZbMIj|4{i`@qg<a!v}8tGW`)65`K9* zak^uPj3F|P$(SPJ*yhXOlN&IXVAB7Ef8PEU<`MAkyx#<#Hsi<Uzr+4>mA_*OC^7U? zzJRf^N#%b9O~3UfZA|;!aUFf=7np>-<6-b3cw6P~{3w7w-uY?pm*Brt{xh?|Qt&D8 z03fe29)9L;RDR2QOd4C>3(q27TPR=o43)q8&j5LnxbCKZA@iJ?kDN7svC3~f0Em0* zUo&PL#C!?7Y-oP#aqPcV`FlPLK8pVaK;GY`F5Z@Y(gNDBPgD8dlFo0psQl?Tpnu-8 z2vA4&Tm#?@!fWqY52(9)XoGv`tB*d3Nxtr(4EK=cJwF2{RsM4U5Crs{&pGhEo1pjK zs{Fl_`<};mw-QiiZX5aA=X2YTlU~RDE8zQtrOmeeF`(UKOp&ot<k-(o1@8mZpcl~3 zK7TuS2K+rZt@7J1F>St`u#(1h^1uBvU?<oIsI%?#m+k)o{#)h${13r0kOj{H%Jk>| zsq*)e&ixmWFZ|wrsmgze_PD=F<-^l4si*tv0A<@zf!PAqn)bUtjeQ7w7La$TLy<x6 zr|#~jeD{CDwA1~6gZ(IY3-`$?{{Znma3P><571r@tOf}%0B!^H9pNnx&_`N3F`<DS z)bWm6!A7260RIf$=J^Al1k`}#U^DnScunOWq|G0s98&)NMrim7o+-c7|ARLI>OtE0 z!MngCfI55dF!&GCU!*^M;k|(R{X!ccUtbsoUj>xu3vYnaD*q69c!=~LqWljL=R<cx zca%lOn1`MNN5F`oi-(|-owUQwkAMacrtNoO-T{bv=U(t5b^Px0)N%51d~X#vNPGgu zi5lehnpI$p%Ku&g#)2BgiW<fWPDAB|XIH<1yiT4NJMs@x=7+n%c0j%#-2?*QN|k?v zHhK6P0NQzE2A~X&5bq=8<&mfG^JQ?*(B$pk!A_k&nkSu$K^fz370<s@`CT6d#J6ib z*arRz{8Hr~I|qCSl!A`|Xy~ynumM2Jk9{6I3~1-asL#h}v&YEuW2aR9@%IzQKVg0l zd{`YnaUs|QUQx&M3&2)zlzfykw)SC?m&Yml<E@Nqb(l%!8N<A19J^{WpzojA!+Y}g zIO)llD6-q*BP##Id4PWR1o_O-9zw@5mde=v1a$L61l&a&TQQ#i&w_tb`Q7x}-IQtf zrvUA?n|gfme89UWDdUs8d-5mDqt3;IS3OC&o;*XHJ<dDISI&5QmE@7O`Qm)g4hZ+f zdsY65MJm4lET-RI@dD-np2fZiciQobF9Fi~(qjNR+VgQt>iSFc;XQLPNo&sq&;#}P z#ozNx{d{RHxEX8)f6aW0`1erndk%xV%72->f0?jfru;Q~m>*C-U)jO)?c{NXI<adN z_PfB>!OwA94ru$DKFmJ@cY@D@2f$AH`rVkj%{=dc#k3Q&^p&qbmsxe{YT}v?{e9(S zOv)#6*n^8nvkhIwWbj7-I=ear@ZUfkJw;je{wZiyC;od_o%q!P-tPcA!7kp@CVPoz zFXh||?e2XP{JCl8rzzXhHJ}-+B`j$!ew}c;!5**|>;wC8r+%I$?@vQ3PgDM{(pFzx z0Lb%K2YB~3<`fg}SD~q|{tz6aoI#a;hWCxr4S#$FzWU4`f~!Ft=!LG}MbFR%3V(|F zUwn)-4}cc{eZ1jCa0tAlPIc3-yGPWia3}Qw4TnklnL%(Hpsr<(r{g1^&rm<lJZoeu zPws-Ip7}QTOZqBh-`53ddHx=t{q{`-vjJ_l?=yzxMGm+$uJV7pPUSD$PMVv*5Rmk@ zfUN+U4O3U){eZlO(Pb#y)>DS{lwmz(Kt?{bp0dTMHyP8UFI`Gq?W6rK-HHhf@B0CG z9Z+}Ak{8+~|19nM>@4tc06%$l6ZjUO-k$w0;-cO@T0^|low#2Fjb746`s6FV7&L$; z(84?N8E*qpf0QM@3ar5n&BV*VIuHSU<mpA?rtHtZ2bzS2pSu*mvz}`LtH~qzeh%Is zJVNsP+~eSz;9dY7KliufhrB=cE8>8DpND3ioeOL^o~O;9Z{(S>JWn6jWuac4zk@J; zq)sIz&&Slr<DxU1g3gJ&&RC<4FNWsc8o^FpXGl5sV8+#n?}}Nbj$hG<nF3;7piVSx zSI0j-1N(U(OT5FxF@<ou)bVD*gjZo_4l;+jno$l0c>XHbjh(heH+fR+#9l?%U6@0l zMvc^qxmk?_PZ9q*?9}&+VU?eE5Wd=^Mw%9=6SHQL)`&WO3YwTf9naW_+W_V+HBv<$ z``^Uv4QTqLI`PdJ>Ug!pDS6#Zd1e^h=nQD2oN|iZVa8tI5H^mv2<&GJ1Tz}Q!#+&X zT{MGqX`|o0td9SBChuCnG;l!2apF5tmjb2oC&YwCXS9KX;6?JYmGYu5i<GGoYfq{C zQHMIZfOiL|%ZNI@v<ZKQiWJ59SLti7?f{hU)m>mWAm6XT?_b>q;32Ob051UQ=T&G+ zbak)33|;|8!5iQh7y+dF>S^>^<Pp7G{xxX&wF^NRpx?f>7_@*@AOccg6Z#qSi057m z%0M~qwt%f*7?8);$m44}!7i{HkjK~df_;EIzD6EjdjT8-FM>nhC2$y!*Vm4KSHMy5 z1~>-Z1S8-iI0a5qX9`RK)4+LP2Dkvs1P-_ul!0<k1!}+oum~&$4WJ3MfHu$xR)IBO z9f*KF5C<uc1p|OOm`wR6SAiO^K%Jbr2kZy5|5W(W<N>f5Yyq_Oq@4gillFpr#IXfz z2M54G@FF+_UQs9I-z0SQljuK_rU7Vl(uIINGKq92HGxjB3P@g$f)Q{MP%p1j7q8C% zGeH@k{IAyl%KLf~Xakh*b;|cTWqW-S7y{(!^&Ma**bVjr^7lIVd;KtYnX;w8CNKn~ zd}}}-hy&ctJqTU`hXMZ2eG`m;)AS3<bZ#3U%(?48M4ePez#HHg!0#l&Ogaj9H;H%W zGyuY!(+Q-!<zN9=1QvrKuoVo0?fBUNc7r`&FE|Wd0mOL@ah|gu90V_dL*#iHxB$!q z7aIM}FDdgcUjUT*m-w6f5;y{gXEO0j-UnU)#50+86J5(Msh?jS0Y||xFal1Y-%wy0 zm;q)22b2-+7&r+|fz#^blqp~aATLwM%M=Gt)+tq>1}p+iparynRUiWTK%BZGKk5)5 zuj(-G_JRX|_fyE{R0Ylhq%oB=CgC=TvP~k)B*IL=oboa_0$u@GFa$P(E%+G$r>QgI zIfuNSLtN*~1Q!AaKf_=r*addewl!ceXaG&5xd33FD)tt_lmYyl!~1g<5qAWn0O?K| zAPi}qyB+KR67L&;JWM$WP7w#`P9=`1<)8{|1^Atc->Kwb>S@AF1LX7E86XZM-c4W# zo=lsZpgm5Mfd!xmtO9*t0Biv}z#eb_90EtcF+lp~?gsn7e)9h&;N3Z-Ihj09CjH5{ zPu@d5jso1LlJ}|PeX95)59d(6bGCwE{83MnTR<D=1gnf5<X5K|gQ1_drU3f%TQdPP z`W7_wRvDmAzqJ4?0u7)IbOOS^wGPm?-%5cj*aWtKtza1J0QB*<_JF;BzW&xh06o8T z2pk5lfTMuApGv-_t^*O!2jb+N=X1nNfh?eYr@jadgO|Y(AaO`roCK%PiOc{OfSKSz zKv~|t7*L+K%Rv>W0Smw)uozIbx0^r<Xak*K6<7n-fe7dWagYL8FaS1zA+Q;20b9W^ z*ba7ponRN(4fcS&U?12I4uBWHLGU6t1YQD%!OP$Xcm*5<Z-8UqO)vsZf>YqM%AZnT z3YZ4Y12ez{U?#W_IN)MX2FgJdr~wPWBCr@VfF{ra+CV2*1=fIdAOiY89Hc-N41i5w z2y6yhz*aB}wu2pDC)fpcgFRp`*a!B51K<U45WENuftSEx@G>|8UI9nJ8{imt6O4e9 z;1oEm^1oJK3YZ4Y12ez{U?#W_IN)MX2FgJdr~wPWBCr@VfF{ra+CV2*1=fIdAOiY8 z9Hc-N41i5w2y6yhz*aB}wu2pDC)fpcgFRp`*a!B51K<U45WENuftSEx@G>|8UI9nJ z8{imt6O4e9;1oEm^1o4F3YZ4Y12ez{U?#W_IN)MX2FgJdr~wPWBCr@VfF{ra+CV2* z1=fIdAOiY89Hc-N41i5w2y6yhz*aB}wu2pDC)fpcgFRp`*a!B51K<U45WENuftSEx z@G>|8UI9nJ8{imt6O4e9;1oEG?o)v&U>Z0N8DI(!`%K_~i$OW40t>(*&;Xi18|VaU zz&g+e;vfqKz!2CBwt``>1MCF5!5**=><2G^gWwQ&3A_xBfTQ3I@Fo}mr_s?)0n@+? zZ~?dwIG_xagBn0SPcH@yparynRbUN>fIg4{S+EHVfh}Mw*bd0&>0Mwq*bDZ77r=|) z5I7882Csml;23xloCK$sb0{zcoCjurnczZjF(?C7pav`gi$N1;0iA$+{%#$JfH+8j z0k8>d23x=|*ba7rU0@H`3-*Hp;2?MryaWz|m%$P63U~v&2~L93R#!-ypZf|p%Djy9 z&yfBZ(m&G&$io@(aE5fxknS1MJ+lLl_8HPXvk#E&8PYxT0wC=(q<w~T&yemJ(mg}E zXC!XYK64C^{+SU#9?qNsj6X^N@}ZCk6m+N<&(tcg1~87P2w*HzjAe?kOfi<JO<;(8 zzX6UdxNJTPVZOhi8hMx`!0j@hi&8^Z==av`@=<Q`Xv5W16}#z2*KJ<0TiPFPR9>q6 zZaQOL*r6I<UTQ|=a~=YnmzOKNFk%^+=MT4Fl$$)-d|oyx&YOL1myar6%I`KRy__$- z%SWY`^N0JGJa~UYLt?dgxk6V&!R@G6rHqr?=JA<%d2;`Tj*Cr)6Stzu9{RT;x1vag z{>{s$gez)@p?@z5SJV(g$BV)h6@KV#f4J)6e7+%WZW*eJ^ZACv>A4l>^XEn3it~wF z=?hn!&o?AKFV3RI9eQK3=T<$sK7S^0n)<A+8dZj$ikpeEx~iDyZ<`@*Q^5P%a4Ra` zZ8Ic3<2HY^+xe0g<5n{|P6_6@Ehwtb+r$YzpwyYR%SM&qwprq4%5d4JGTi2fn<)cs z#rb4@Rd5?sKFOlVOJ_~>D7VGprvEx?<`vi3ZHsjw#1XgRj&xhC38dYsMwPEt@~G>j zu4X}TxI2fua7)L!dFd^!sTv(l>RSKR)zlQ1;m%uKC$)5}n-?eHipzKBt&&guS65R# z+RaO^bKa=7y~DAgs2ALd+TjkzOHbU2`okTLmmY4#>D@8QA7^pf-Z9G`XLWI$vkGxm zk7|cI3RKsLTX8-MPjwyjADcJ7;8)#g=#LCdGHwOGxXGX7$GZ7)bEob{lAp;Eu9}P1 zyuUjy5UX~pul|@XLf+n?ed#!H^99mw4!^Ej5ep%lWLmq~TLpNue`n5|ajonxJs->f zQvf>Z+RH!ypsTKB?Wh+0b?qEb14Q?IF~QI1HCUw_b>b0|%1G}FHPZ7k7|`pqLgOdC zc0lJ~qz7GbbOazbtXM+Y<ZBw~t@t>0Dfa^G4VZ>!<X1Ffmp<a~emSOe;7Qo8!8})~ znF{+#>?o}QVqc9No+0+!UD(gl(dJi#uus=f<yS<o<AHca9$>H9L+rhM0KIzI9yPL~ zoM-gxjfd69Cl;uYhE6r|os+yn*UsGcc>OEt#J-pC|Ard5bO$Eoe5g!~d;xQ(gs%Zj zpbc#2{U%KG$2;}|{5*)hdS?n?KG+Agf_3=281o3&L%x(6d6+mJCH`I0F!A>=c$Byw zor0aXA32D*7!bDNO-$l^WB_;Kc%(@k-+U4ieR~6CtK;3nl<(nPYGf(T4-e=xbUI&r zvtVC*v1gyiGV=V8b{hF2d3ciYJaOR|uOqvW>DXIp{%BumFInRO@|VB<U$m*)p0+A> zd)?;-E&9W;PH+AsPN&%I`d|3m7LRf}?sFR&<@T$B8_^b}cl~b)Zjfe?+x<e9@<$-Z z)90o?9mgl>)A|zOwQKFYw)%`hD3ywHJ%c#}rSCzqr%yT1V~$(~rptZda=gI3X+PtX z+PF%ubT;;J1YV-jJ{*0irDN_qEDuZ<kEL?fP)_&D@jUlX3b&c?QmzR}ySK?tzi#5F zNG2BU<GiuHB}|Uq$hl5?f+8r_;030KNFYXRZZ_qBgnN&e4bPiVncy)n-5kWw(a4d6 z?h3wOYL0MlkR@wNQ@E(MINy{qm!V)zX^<0z9EX$?%olUKtW-G7J<eb<$Kfe`)Is0C zZu2V{?~d^G<{r)qaaR_Hd^U1<xKx;U;|L6gG_#x_4ov4u6DE2-a&NAg=QtkM2q)x# ztiAls+`#0NaV^svx3;61z;u0~A#v(c;6%znB970-a}j-8g^h#gxx_(#PTr72PA;vI z6ABB-CP#V}F47k*^>%R!TYvOwCur|D@a4l?iBxnSkqLXzB8l4#DVK2<r!^|bN-CAF zDND7;bsAhPDS7VY<b_nQz5`osc^=>hxR9P#5rOGC2ha#1ic;X~$pP+c3fk!85TZ1Q zoLiUMbtGCL<bGQ3<{Td)i}EdsPH9Yk7+a5lSSFLxZKK2S`6kZAn)AG6v1}<<Sg)7p z<y?#Q$*pYhqKM{Dqx$S59g~XnchBi^9xTZTIs08tu3Obb3QSLj`Z<if9)~nXhv~Ld zk?um~ND3$H>@(kYr&N{3v5VtDf$4G^p#1s5`udQ*n=LTiz1lFy)pp)JPhS0VB1(T9 zTdpOc&MP?vlS>7rcY87W13}Xq*Ee^V;2Ac;k#my)zc>BXUff~}B?mI0#NK3JdT&za znM|9y;__U@2QYMnnZm7JD2I2}@-0FNSj^iDFS@090=6bi>+uS%<`-5}Don#WIw}-o zsWMu`IReuyy_ir`x@DGd4q`1t;C`E=ROgZ}%W}QOMtY-(Re!5P$WGstMU?He*VzWF z2>d^G_zvvQj&*91{WR)yD4XvHxStR4&X1XoiUx45mD^OgG|aFldn<#>80Cfs_^9Tw za;KeTq?WB}lG9#YuBjOz*9rwZ9w}rXttlaep^U>YRVBHe{tkaqFhk<O@LE2HBX&N- zy~rG^zM5C`hYrgK`KGGA)o880VpKB)=|Auu6E2`{9+gwGy0@C{H2OE_G{}I5r=ZJ) z^%*yMw*=Q$zLF8_S38Rsd`ynq43Qi8>We8m-o3On3+@l`?HajUh+81|a;d~eP0O{U z6aEF|axn2Bo{3G{FNIM@%rVELQ?p*zu8z&z`|m8`B8WbzCb{}jSCWliVhiWe8B&KI zam9h}%zD-a(-G-0g<?(|QJW6Vc*_y@4czdonUWTKiXxIh3QEgG9qtsM>1>Q9XXGmA zEX9X@<T`@Et93nTxl2e$htV05c=YkW;%K;XBsy@l7mxM<x#>GE7g<Nmy5t^_u`z1W zDvnWCnN*j_nc=nKPtKVV^}EZeZl<D$3yonTmPRE$^In&It+0ANP^YtR2JLZbLJnN= zS6q>+Nh@wz+VlrsHdhM~YG+-O{aoaNq~nH{2dO~s4+`dH5{6Ux`0Ykhm7yLkim^d- zB=l<eI}3d@m@j|`6VT~Vv_hVA9G2;L36HkW6YV`@)~5(SI;4mu;Z)996pIvP-HpLi zffnlV7K@m2o6kR67P3fMs3<TzF%qd<nd1JEs2##|&P{nU8<+yvKI10iGfA;8xzV9- z={r}&ukcWgm1q3np(B@v6=y&vPL2Bl`oo#az$mXv?rzf5k*VjRpeD_*+)0;!z%&ih z^^kpvnSm5IX9_Is<X(f^&6#s%7?y?W8HJnPJDE1EN}U#6$O;8I2bH96SQWQ~G%h6P z@=Z(XD-5m0V_XZzQRzV^+0PA-`UJPI7W3t*(#lfq=&tCk&}`6fF8A1dRfP-^dXG3~ zeMZ=eH1b+jjl7PoB5@He=dhpim&Qz#Vxl|Y?3FPu#UyM(h9WUVZ^L{zA!`j{ijG{& zMVRbyOf0r$JtlgQ#8PeQd8S&tnoH@Bz2qtncV3z4lP_FB`uctkS5P14V}7NCEe&ve zpnL05cSWSa`-HlXmhA&@j6!fnf>oF)TSX6d!pq#%M1yQBSNIiuw@t@sWNerjSuOhF zx19>xfI5|;DTBG;!6~a>vUHBlX@dFFIPqIvX`?e=HJ6(h<vcwEu%6F~JH(+Wfo$lg zjIVc$jL}!VkzVe|WvtMa{nYuG==2?T6USx-B%48VA0E;9@<gkec9-P^^jKQo<<bSZ zEcaQ{mFU1H192C+LXYJ=3w?<$%XJs}dav(U=o1~7=Pq>hKHsy@>mT@@g%00upP|>M zML#0?76H$<@8?(abnf#vu$#28;Qmd1QHW?i^89V=qO+4Q@_dkAQGia7Ml`d*)m*=v zb?KQF*WY-9@28P}^t}x7ZLjd46(ms+SO#mRoFWP_`bZpC2Xv%*w(N`_tDQ-^;-raR z1W+TTo-J}R?S2GEf0im3g8TTsa3$PWlq5YN`TV2r{*{2t6y5haC~}JVBG-5^xSws3 zPj68&*d{j&y1})eld&=C4`7`wLd(>BG3t=|8%tV{2|5#gZ^`&HAJAJJ%<9i$$qz#E z>L9l+Fu1MNJ<M4x#o;oDwUlO@FYZa{<r_={8}Cb7`paa59Q%<jodf%6qt(HPq+65? z-Po&5M&tv6W4`q#DH~4C2e8PyF0#$2<?w}%N$J#NO5<-FdG-_-j8<sTd<`pJV{)&u z4lAwieXp#bVUW(L#}2p89Ir(8?bmDGeFHx9qJTO+$LLALU5C3ngkk#5@hey(FACR# zoAfoMj?dpb%B`Qb66Yl1WSzYzT$=aNCkYo^G|Fv|w>I3RM~dCH)Ol_r*Qbiz_FQ7! zh?6B7e|m1Y@u2@k{_-U$kzPA+-{~`WZ=(x-8=bGlOiY1eQHCiXZjA+)g2fh1n1VKo zRhWWx7JZn4l*It1V8~(%reN4&2c}?`#U4z-K8pjGf`b-^Fa?J#j$jIoS{%a^j98q) z1gDh6G)%z^i<y`L$D#~VP-U?IQ?S^g2~*H!u?kbL&Y}-fkg^!S6bxBx!4wQz?7$T4 zve<(u*k^G7Q*hAY5T@X;#Su)wQHx`kf)R^TnBdpSVj8AkhQ&-wfn!mIDX6kofGJpP z(S#{zvsi^GSZC3PDM(oiU<!sTwqOc|Ep}iEc3JGf6zsD&fGId=aR^gz*y0GL;Hbqh zOu>l7DNOJiWibs?FvDUdrogc%!xU6mEWi{jwrIi>v{|ge6s)u8!xW?}1~3If7F#d{ z!xlR*1-mTvU<&qG9KaMDv^az*IBanQQ*hMc7^Yyv;uI$Mt<v!Lz_xCz$idtCK?Xar z^)}8labJc~oR!)(1U6&;Fy=kH{}gu4GH&Bc4)<^<#Tw?e2f;4ve}MTVeV>K!wEVVb z@c(nOX6f-m&R`9b&*9hc&)J?Z=X!?o*vZ4a$lv#htTYXiwD0{>?8JX>B@nrdyvdo- zdt0%S*1b1?KJ1+Dy7x0+7(45y_wEKyV>f^Kdw+mM;{HeQ6YS?<!lUn%%^s|^-bbG9 z`$O!^BjhaVeKL1ASLM5ZkNqm_$bt7YfEC!^i`fm<W2cPweG1$;s*Kd}eUF0O_#w~t zJqtu`lXz&e`+kI-wC?*?@KfyM?Y<M>tugW7NIgE!FJZSG1mDLlZS)d2jGcJ4aTaUa z%h-u$+pFMb*eT;S+JD=BVV8Cx{%ya*PCXA(zr*jtP8o-3%i%x5PCX2l0FiHLmtoGT z4PR;P_0}%omVy@EQ|Gtu!M+kZbw0cX2rW@R!+juyo%$K3eunSFPCE{71AmVF0?dcN zW7t{e9{v*8i~WO`oZ%Y&E_T{~_-}xe5!xHR5k!jW$A1=Gsb0>_o`c^w=DC<RVTvda z!=(JbryhYCA}=#s6Pa2+Gp1`3xnG;e``Sc~*CutPP2_fMBCl)n5^EBnem>utAF$@2 zH9urc)`7LZP1d~8nqAghXHDov`};?0K55MttohH@{1<D|C$;}iTl3GX`4`r_+nQUg z`2}nK*qUFn=Ka>(Va;z^^IKGy{uBKNcePi!&+7PZg%*%Oe$QFp-*FC@J&(tKdr}=g zy;ELW|MSGI|BkcQRsN3uelLFeFsI=6V(^lFFSIRxC#D@#C*H%E(rFi~6Vo}H#vaHM zA6hI<G#cU0G=Kpx1hxRq)t%YFx!G$$kCBJ=+>Ct__$=5Cpw~TL6SpCW<Nx+A{}lT& zo@xZ0AObe%DDzL<iTwfaWdJ=t^&{|8+$L%IrN3|zioXwTk-`e({n$V8BYo?}pJR$Q zWXp5k;2dvW<ufv8gr>Vv`n|Y~ya<2j+NjH}-L^ecaC`g}cpLrCm2<EE?8I)}-MGmd zQ>l@^-3=e4FLgsh{N=BImS5>Wr1vcR;QDW<{OhlX6L*9NotU}l@%O`DH+%<_8Mkg} zcPRsL{;-Pp=<D4wcP8AbPJV5i`yHO)>p$OX+%kr*>9W6PG393L$o#u;>pF;O(i{0c zyszs}p?n)8PWrXf+4PwzpM}?D>6iS;T?U@pw0*?)Y4CaDwxJ!<EyGdre_f#riGRh- z=JWf<Nbk7HuM=KFoOk^<zovY8-f-7j+?_E)jjW}tpEYBJ&P(}z-ZKZtA28uKd+E0A z$d4|dPJUe|Ls;evCjOBhL0@6`Som@iE==FG<s13YcHT1vM6?rpS!lxK^Z0DS-EQbo zT;=Ws$W5$j<nU?sjliFOF|42SdXI%I->w%qlh0nGYc4WwpY6pIH~OB;Z$6s@?4^<N z-5~F6xUZG-3{St|GVM3N3ZCS;J+Yg%y#wqwZg*5*+BPaV%pE3IP%rXKKKnQGYvxQN zd3bt%8f>#}t(d|Fpuwsk-mfgwS^wYh-o!ET)(g1341R6G-FywEv@K=-9d&&(ZJYY8 ze$L<g8B9x`vY-8CWSyIZ*2xR^^Av}hRS1{N7Q3bHE4ZciST|^J3Ur%(8W=v8U*_v8 z0in+ygP-D`^s-;%SMox*^A7S1AIaV;PMGugwROf>u6*`#@CoCV`wgZ`yOcYJ{Nnb% zY(H*poCgS#0ya+W;4^hidKYfxjvL0>kp(u+?-s(%SVf#a07C2J<*sG?nsz@fbJx2% z0sEqaCLTZEa~lzwxE@+^dC#qP;%4*W5a+F*E4Z~C#Z9w#eYQE@_Va?<==t!LCEQt) zFzIoxjYpp{AKtPb{GD;TmGRB?qvNySS+{;0yv;kxuw2^6((X;`c-{vN8@HVFJ-5!_ zExGf+T;q0QhjoLNzV{|P8lH7bb9LzL?{TyBGCNEEyB9oV!fg;bbKB???K50xquYh| zxZ&c2`Tr`rnw5ruAUsWz27eBEQ@jKOv0xW%3-#w>6G~6gNT~&_v{Iycuq}<fcoI(@ z`XIi5Cw&iJz!wnpYW==!R(f?{c4l|KOg71~S#~FrW_%2j&nG^Iq|ZN35YG+sEOS4@ z4t(YAb^L?*CDgqlX52f*ryu$7agG+A$qV{Qi1*~l1a>gbiPtEta@gPwjEE20fuvHl zq^d!%?`_r_^@?_P%6dgrQh5(<%>{S`?|NswZZ}tKmvYIb!U%tsj<_qkvj?}~{JGTX z!)8@#5z{hGwcP8E<F?P))}kdUx`HPVLa>Xv#p<J|(SQNwA?fuYN@vDxZuYdfz%GjF zum>4MqQWpxl_OtWU>}H$S6nc{-u9oO*mzY75z|lM)C#}w99<*g_hp2}{D&3*<~`3K z1^_g0dTnLK0G}0!eVsVW%MnY`2Fv3ED-zP<k;p3Y#9_{kA<*V9xZX-I6vUA|aDsbl zi4B%)2W5tgy$uv-9KUmQz>*0K2-4sR2@cnhXkvZM;An$%0A}Av;~RU72)w+Ghr|%; zNQYpTN=%N+ce|%Eacb-xBS(EZE_K{3NI%wf!aDM4A`PyOJZ%~>xSPRr`fUouaqpn( Xce*Yljzp=)dFC9KeI9e<KZ<d`mb_>8 literal 0 HcmV?d00001 diff --git a/roms/Makefile b/roms/Makefile index 2721b02..610b534 100644 --- a/roms/Makefile +++ b/roms/Makefile @@ -31,6 +31,7 @@ find-cross-gcc = $(firstword $(wildcard $(patsubst %ld,%gcc,$(call find-cross-ld find-cross-prefix = $(subst gcc,,$(notdir $(call find-cross-gcc,$(1)))) powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64) +powerpc_cross_prefix := $(call find-cross-prefix,powerpc) x86_64_cross_prefix := $(call find-cross-prefix,x86_64) # @@ -55,6 +56,7 @@ default: @echo " efirom -- update nic roms (bios+efi, this needs" @echo " the EfiRom utility from edk2 / tianocore)" @echo " slof -- update slof.bin" + @echo " u-boot.e500 -- update u-boot.e500" bios: build-seabios-config-seabios-128k build-seabios-config-seabios-256k cp seabios/builds/seabios-128k/bios.bin ../pc-bios/bios.bin @@ -132,6 +134,12 @@ slof: $(MAKE) -C SLOF CROSS=$(powerpc64_cross_prefix) qemu cp SLOF/boot_rom.bin ../pc-bios/slof.bin +u-boot.e500: + $(MAKE) -C u-boot O=build.e500 qemu-ppce500_config + $(MAKE) -C u-boot CROSS_COMPILE=$(powerpc_cross_prefix) \ + O=build.e500 + $(powerpc_cross_prefix)strip u-boot/build.e500/u-boot -o \ + ../pc-bios/u-boot.e500 clean: rm -rf seabios/.config seabios/out seabios/builds @@ -141,3 +149,4 @@ clean: rm -f sgabios/.depend $(MAKE) -C ipxe/src veryclean $(MAKE) -C SLOF clean + rm -rf u-boot/build.e500 diff --git a/roms/u-boot b/roms/u-boot new file mode 160000 index 0000000..2072e72 --- /dev/null +++ b/roms/u-boot @@ -0,0 +1 @@ +Subproject commit 2072e7262965bb48d7fffb1e283101e6ed8b21a8 -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 072/118] PPC: e500: Move to u-boot as firmware 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (70 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 071/118] PPC: Add u-boot firmware for e500 Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 073/118] spapr: Add support for time base offset migration Alexander Graf ` (3 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: qemu-devel Almost all platforms QEMU emulates have some sort of firmware they can load to expose a guest environment that closely resembles the way it would look like on real hardware. This patch introduces such a firmware on our e500 platforms. U-boot is the default firmware for most of these systems and as such our preferred choice. For backwards compatibility reasons (and speed and simplicity) we skip u-boot when you use -kernel and don't pass in -bios. For all other combinations like -kernel and -bios or no -kernel you get u-boot as firmware. This allows you to modify the boot environment, execute a networked boot through the e1000 emulation and execute u-boot payloads. Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/ppc/e500.c | 114 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 73 insertions(+), 41 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 5321f06..a973c18 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -39,7 +39,6 @@ #define EPAPR_MAGIC (0x45504150) #define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb" -#define UIMAGE_LOAD_BASE 0 #define DTC_LOAD_PAD 0x1800000 #define DTC_PAD_MASK 0xFFFFF #define DTB_MAX_SIZE (8 * 1024 * 1024) @@ -408,7 +407,7 @@ typedef struct DeviceTreeParams { static void ppce500_reset_device_tree(void *opaque) { DeviceTreeParams *p = opaque; - ppce500_load_device_tree(&p->machine, &p->params, p->addr, p->initrd_base, + ppce500_load_device_tree(p->machine, &p->params, p->addr, p->initrd_base, p->initrd_size, p->kernel_base, p->kernel_size, false); } @@ -620,15 +619,18 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) MemoryRegion *ram = g_new(MemoryRegion, 1); PCIBus *pci_bus; CPUPPCState *env = NULL; - uint64_t elf_entry; - uint64_t elf_lowaddr; - hwaddr entry=0; - hwaddr loadaddr=UIMAGE_LOAD_BASE; - target_long kernel_size=0; - target_ulong dt_base = 0; - target_ulong initrd_base = 0; - target_long initrd_size = 0; - target_ulong cur_base = 0; + uint64_t loadaddr; + hwaddr kernel_base = -1LL; + int kernel_size = 0; + hwaddr dt_base = 0; + hwaddr initrd_base = 0; + int initrd_size = 0; + hwaddr cur_base = 0; + char *filename; + hwaddr bios_entry = 0; + target_long bios_size; + struct boot_info *boot_info; + int dt_size; int i; /* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and * 4 respectively */ @@ -758,29 +760,24 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) /* Register spinning region */ sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL); + if (cur_base < (32 * 1024 * 1024)) { + /* u-boot occupies memory up to 32MB, so load blobs above */ + cur_base = (32 * 1024 * 1024); + } + /* Load kernel. */ if (machine->kernel_filename) { - kernel_size = load_uimage(machine->kernel_filename, &entry, - &loadaddr, NULL); - if (kernel_size < 0) { - kernel_size = load_elf(machine->kernel_filename, NULL, NULL, - &elf_entry, &elf_lowaddr, NULL, 1, - ELF_MACHINE, 0); - entry = elf_entry; - loadaddr = elf_lowaddr; - } - /* XXX try again as binary */ + kernel_base = cur_base; + kernel_size = load_image_targphys(machine->kernel_filename, + cur_base, + ram_size - cur_base); if (kernel_size < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", machine->kernel_filename); exit(1); } - cur_base = loadaddr + kernel_size; - - /* Reserve space for dtb */ - dt_base = (cur_base + DTC_LOAD_PAD) & ~DTC_PAD_MASK; - cur_base += DTB_MAX_SIZE; + cur_base += kernel_size; } /* Load initrd. */ @@ -798,25 +795,60 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) cur_base = initrd_base + initrd_size; } - /* If we're loading a kernel directly, we must load the device tree too. */ - if (machine->kernel_filename) { - struct boot_info *boot_info; - int dt_size; - - dt_size = ppce500_prep_device_tree(machine, params, dt_base, - initrd_base, initrd_size, - loadaddr, kernel_size); - if (dt_size < 0) { - fprintf(stderr, "couldn't load device tree\n"); + /* + * Smart firmware defaults ahead! + * + * We follow the following table to select which payload we execute. + * + * -kernel | -bios | payload + * ---------+-------+--------- + * N | Y | u-boot + * N | N | u-boot + * Y | Y | u-boot + * Y | N | kernel + * + * This ensures backwards compatibility with how we used to expose + * -kernel to users but allows them to run through u-boot as well. + */ + if (bios_name == NULL) { + if (machine->kernel_filename) { + bios_name = machine->kernel_filename; + } else { + bios_name = "u-boot.e500"; + } + } + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + + bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL, + 1, ELF_MACHINE, 0); + if (bios_size < 0) { + /* + * Hrm. No ELF image? Try a uImage, maybe someone is giving us an + * ePAPR compliant kernel + */ + kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL); + if (kernel_size < 0) { + fprintf(stderr, "qemu: could not load firmware '%s'\n", filename); exit(1); } - assert(dt_size < DTB_MAX_SIZE); + } + + /* Reserve space for dtb */ + dt_base = (loadaddr + bios_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; - boot_info = env->load_info; - boot_info->entry = entry; - boot_info->dt_base = dt_base; - boot_info->dt_size = dt_size; + dt_size = ppce500_prep_device_tree(machine, params, dt_base, + initrd_base, initrd_size, + kernel_base, kernel_size); + if (dt_size < 0) { + fprintf(stderr, "couldn't load device tree\n"); + exit(1); } + assert(dt_size < DTB_MAX_SIZE); + + boot_info = env->load_info; + boot_info->entry = bios_entry; + boot_info->dt_base = dt_base; + boot_info->dt_size = dt_size; if (kvm_enabled()) { kvmppc_init(); -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 073/118] spapr: Add support for time base offset migration 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (71 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 072/118] PPC: e500: Move to u-boot as firmware Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 074/118] spapr: Add ibm, chip-id property in device tree Alexander Graf ` (2 subsequent siblings) 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: Alexey Kardashevskiy, qemu-devel From: Alexey Kardashevskiy <aik@ozlabs.ru> This allows guests to have a different timebase origin from the host. This is needed for migration, where a guest can migrate from one host to another and the two hosts might have a different timebase origin. However, the timebase seen by the guest must not go backwards, and should go forwards only by a small amount corresponding to the time taken for the migration. This is only supported for recent POWER hardware which has the TBU40 (timebase upper 40 bits) register. That includes POWER6, 7, 8 but not 970. This adds kvm_access_one_reg() to access a special register which is not in env->spr. This requires kvm_set_one_reg/kvm_get_one_reg patch. The feature must be present in the host kernel. This bumps vmstate_spapr::version_id and enables new vmstate_ppc_timebase only for it. Since the vmstate_spapr::minimum_version_id remains unchanged, migration from older QEMU is supported but without vmstate_ppc_timebase. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/ppc/ppc.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/ppc/spapr.c | 4 +-- include/hw/ppc/spapr.h | 1 + target-ppc/cpu-qom.h | 16 ++++++++++ target-ppc/kvm.c | 5 ++++ trace-events | 3 ++ 6 files changed, 106 insertions(+), 2 deletions(-) diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 71df471..bec82cd 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -29,9 +29,11 @@ #include "sysemu/cpus.h" #include "hw/timer/m48t59.h" #include "qemu/log.h" +#include "qemu/error-report.h" #include "hw/loader.h" #include "sysemu/kvm.h" #include "kvm_ppc.h" +#include "trace.h" //#define PPC_DEBUG_IRQ //#define PPC_DEBUG_TB @@ -49,6 +51,8 @@ # define LOG_TB(...) do { } while (0) #endif +#define NSEC_PER_SEC 1000000000LL + static void cpu_ppc_tb_stop (CPUPPCState *env); static void cpu_ppc_tb_start (CPUPPCState *env); @@ -829,6 +833,81 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq) cpu_ppc_store_purr(cpu, 0x0000000000000000ULL); } +static void timebase_pre_save(void *opaque) +{ + PPCTimebase *tb = opaque; + uint64_t ticks = cpu_get_real_ticks(); + PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); + + if (!first_ppc_cpu->env.tb_env) { + error_report("No timebase object"); + return; + } + + tb->time_of_the_day_ns = get_clock_realtime(); + /* + * tb_offset is only expected to be changed by migration so + * there is no need to update it from KVM here + */ + tb->guest_timebase = ticks + first_ppc_cpu->env.tb_env->tb_offset; +} + +static int timebase_post_load(void *opaque, int version_id) +{ + PPCTimebase *tb_remote = opaque; + CPUState *cpu; + PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); + int64_t tb_off_adj, tb_off, ns_diff; + int64_t migration_duration_ns, migration_duration_tb, guest_tb, host_ns; + unsigned long freq; + + if (!first_ppc_cpu->env.tb_env) { + error_report("No timebase object"); + return -1; + } + + freq = first_ppc_cpu->env.tb_env->tb_freq; + /* + * Calculate timebase on the destination side of migration. + * The destination timebase must be not less than the source timebase. + * We try to adjust timebase by downtime if host clocks are not + * too much out of sync (1 second for now). + */ + host_ns = get_clock_realtime(); + ns_diff = MAX(0, host_ns - tb_remote->time_of_the_day_ns); + migration_duration_ns = MIN(NSEC_PER_SEC, ns_diff); + migration_duration_tb = muldiv64(migration_duration_ns, freq, NSEC_PER_SEC); + guest_tb = tb_remote->guest_timebase + MIN(0, migration_duration_tb); + + tb_off_adj = guest_tb - cpu_get_real_ticks(); + + tb_off = first_ppc_cpu->env.tb_env->tb_offset; + trace_ppc_tb_adjust(tb_off, tb_off_adj, tb_off_adj - tb_off, + (tb_off_adj - tb_off) / freq); + + /* Set new offset to all CPUs */ + CPU_FOREACH(cpu) { + PowerPCCPU *pcpu = POWERPC_CPU(cpu); + pcpu->env.tb_env->tb_offset = tb_off_adj; + } + + return 0; +} + +const VMStateDescription vmstate_ppc_timebase = { + .name = "timebase", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .pre_save = timebase_pre_save, + .post_load = timebase_post_load, + .fields = (VMStateField []) { + VMSTATE_UINT64(guest_timebase, PPCTimebase), + VMSTATE_INT64(time_of_the_day_ns, PPCTimebase), + VMSTATE_END_OF_LIST() + }, +}; + /* Set up (once) timebase frequency (in Hz) */ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq) { diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 57e9578..fba8686 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -817,7 +817,7 @@ static int spapr_vga_init(PCIBus *pci_bus) static const VMStateDescription vmstate_spapr = { .name = "spapr", - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, .minimum_version_id_old = 1, .fields = (VMStateField []) { @@ -825,7 +825,7 @@ static const VMStateDescription vmstate_spapr = { /* RTC offset */ VMSTATE_UINT64(rtc_offset, sPAPREnvironment), - + VMSTATE_PPC_TIMEBASE_V(tb, sPAPREnvironment, 2), VMSTATE_END_OF_LIST() }, }; diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 5fdac1e..9f8bb89 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -29,6 +29,7 @@ typedef struct sPAPREnvironment { target_ulong entry_point; uint32_t next_irq; uint64_t rtc_offset; + struct PPCTimebase tb; bool has_graphics; uint32_t epow_irq; diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h index 47dc8e6..d926d93 100644 --- a/target-ppc/cpu-qom.h +++ b/target-ppc/cpu-qom.h @@ -120,6 +120,22 @@ int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, int cpuid, void *opaque); #ifndef CONFIG_USER_ONLY extern const struct VMStateDescription vmstate_ppc_cpu; + +typedef struct PPCTimebase { + uint64_t guest_timebase; + int64_t time_of_the_day_ns; +} PPCTimebase; + +extern const struct VMStateDescription vmstate_ppc_timebase; + +#define VMSTATE_PPC_TIMEBASE_V(_field, _state, _version) { \ + .name = (stringify(_field)), \ + .version_id = (_version), \ + .size = sizeof(PPCTimebase), \ + .vmsd = &vmstate_ppc_timebase, \ + .flags = VMS_STRUCT, \ + .offset = vmstate_offset_value(_state, _field, PPCTimebase), \ +} #endif #endif diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 0744f51..ca31027 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -35,6 +35,7 @@ #include "hw/sysbus.h" #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" +#include "hw/ppc/ppc.h" #include "sysemu/watchdog.h" #include "trace.h" @@ -865,6 +866,8 @@ int kvm_arch_put_registers(CPUState *cs, int level) DPRINTF("Warning: Unable to set VPA information to KVM\n"); } } + + kvm_set_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset); #endif /* TARGET_PPC64 */ } @@ -1089,6 +1092,8 @@ int kvm_arch_get_registers(CPUState *cs) DPRINTF("Warning: Unable to get VPA information from KVM\n"); } } + + kvm_get_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset); #endif } diff --git a/trace-events b/trace-events index ffe6e62..ea6c5fd 100644 --- a/trace-events +++ b/trace-events @@ -1195,6 +1195,9 @@ spapr_iommu_get(uint64_t liobn, uint64_t ioba, uint64_t ret, uint64_t tce) "liob spapr_iommu_xlate(uint64_t liobn, uint64_t ioba, uint64_t tce, unsigned perm, unsigned pgsize) "liobn=%"PRIx64" 0x%"PRIx64" -> 0x%"PRIx64" perm=%u mask=%x" spapr_iommu_new_table(uint64_t liobn, void *tcet, void *table, int fd) "liobn=%"PRIx64" tcet=%p table=%p fd=%d" +# hw/ppc/ppc.c +ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)" + # util/hbitmap.c hbitmap_iter_skip_words(const void *hb, void *hbi, uint64_t pos, unsigned long cur) "hb %p hbi %p pos %"PRId64" cur 0x%lx" hbitmap_reset(void *hb, uint64_t start, uint64_t count, uint64_t sbit, uint64_t ebit) "hb %p items %"PRIu64",%"PRIu64" bits %"PRIu64"..%"PRIu64 -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 074/118] spapr: Add ibm, chip-id property in device tree 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (72 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 073/118] spapr: Add support for time base offset migration Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers Alexander Graf 2014-06-05 19:10 ` [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Peter Maydell 75 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: Alexey Kardashevskiy, qemu-devel From: Alexey Kardashevskiy <aik@ozlabs.ru> This adds a "ibm,chip-id" property for CPU nodes which should be the same for all cores in the same CPU socket. The recent guest kernels use this information to associate threads with sockets. Refer to the kernel commit 256f2d4b463d3030ebc8d2b54f427543814a2bdc for more details. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/ppc/spapr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index fba8686..877e1f0 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -313,6 +313,9 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base, uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)}; int i, smt = kvmppc_smt_threads(); unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80}; + QemuOpts *opts = qemu_opts_find(qemu_find_opts("smp-opts"), NULL); + unsigned sockets = opts ? qemu_opt_get_number(opts, "sockets", 0) : 0; + uint32_t cpus_per_socket = sockets ? (smp_cpus / sockets) : 1; fdt = g_malloc0(FDT_MAX_SIZE); _FDT((fdt_create(fdt, FDT_MAX_SIZE))); @@ -470,6 +473,9 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base, page_sizes_prop, page_sizes_prop_size))); } + _FDT((fdt_property_cell(fdt, "ibm,chip-id", + cs->cpu_index / cpus_per_socket))); + _FDT((fdt_end_node(fdt))); } -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (73 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 074/118] spapr: Add ibm, chip-id property in device tree Alexander Graf @ 2014-06-04 12:44 ` Alexander Graf 2014-06-20 14:29 ` Mark Cave-Ayland 2014-06-05 19:10 ` [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Peter Maydell 75 siblings, 1 reply; 94+ messages in thread From: Alexander Graf @ 2014-06-04 12:44 UTC (permalink / raw) To: qemu-ppc; +Cc: Mark Cave-Ayland, qemu-devel From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Currently the macio DMA routines assume that all DMA requests are for read/write block transfers. This is not always the case for ATAPI, for example when requesting a TOC where the response is generated directly in the IDE buffer. Detect these non-block ATAPI DMA transfers (where no lba is specified in the command) and copy the results directly into RAM as indicated by the DBDMA descriptor. This fixes CDROM access under MorphOS. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/ide/macio.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 1c20616..af57168 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -337,6 +337,27 @@ static void pmac_ide_transfer(DBDMA_io *io) s->io_buffer_size = 0; if (s->drive_kind == IDE_CD) { + + /* Handle non-block ATAPI DMA transfers */ + if (s->lba == -1) { + s->io_buffer_size = MIN(io->len, s->packet_transfer_size); + bdrv_acct_start(s->bs, &s->acct, s->io_buffer_size, + BDRV_ACCT_READ); + MACIO_DPRINTF("non-block ATAPI DMA transfer size: %d\n", + s->io_buffer_size); + + /* Copy ATAPI buffer directly to RAM and finish */ + cpu_physical_memory_write(io->addr, s->io_buffer, + s->io_buffer_size); + ide_atapi_cmd_ok(s); + m->dma_active = false; + + MACIO_DPRINTF("end of non-block ATAPI DMA transfer\n"); + bdrv_acct_done(s->bs, &s->acct); + io->dma_end(io); + return; + } + bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ); pmac_ide_atapi_transfer_cb(io, 0); return; -- 1.8.1.4 ^ permalink raw reply related [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-04 12:44 ` [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers Alexander Graf @ 2014-06-20 14:29 ` Mark Cave-Ayland 2014-06-20 19:17 ` BALATON Zoltan 2014-06-23 21:30 ` BALATON Zoltan 0 siblings, 2 replies; 94+ messages in thread From: Mark Cave-Ayland @ 2014-06-20 14:29 UTC (permalink / raw) To: Alexander Graf, BALATON Zoltan; +Cc: qemu-ppc@nongnu.org, qemu-devel [-- Attachment #1: Type: text/plain, Size: 1752 bytes --] On 04/06/14 13:44, Alexander Graf wrote: > From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> > > Currently the macio DMA routines assume that all DMA requests are for read/write > block transfers. This is not always the case for ATAPI, for example when > requesting a TOC where the response is generated directly in the IDE buffer. > > Detect these non-block ATAPI DMA transfers (where no lba is specified in the > command) and copy the results directly into RAM as indicated by the DBDMA > descriptor. This fixes CDROM access under MorphOS. > > Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> > Signed-off-by: Alexander Graf <agraf@suse.de> I've just done a complete round of OpenBIOS tests and it looks as if this patch introduces random hang failures (60% or so) into my Darwin image boot tests. The issue seems to be related as to the timing of the DMA callback relative to reception of the IDE command; if the IDE transfer is invoked first (as happens in Darwin) then we hang after sending the IDE command which is likely because the DMA is not being completed correctly. There is also another difference with MorphOS in that when the IDE transfer callback is invoked first then s->packet_transfer_size == 0 and so the memory copy would always copy 0 bytes. After some experimentation, I've come up with the attached patch which should retain the DMA memory copy, but instead invokes a further round of pmac_ide_atapi_transfer_cb() with io->len == 0 and s->io_buffer_size == 0 which should terminate the DMA request correctly. At the very least it seems to fix the hang on boot with my Darwin images. Zoltan, please can you test the attached patch to see if this still allows MorphOS to boot? ATB, Mark. [-- Attachment #2: qemu-macio-ppc.patch --] [-- Type: text/x-diff, Size: 1485 bytes --] diff --git a/hw/ide/macio.c b/hw/ide/macio.c index c14a1dd..39bc7fd 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -367,27 +367,21 @@ static void pmac_ide_transfer(DBDMA_io *io) s->io_buffer_size = 0; if (s->drive_kind == IDE_CD) { + bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ); + /* Handle non-block ATAPI DMA transfers */ if (s->lba == -1) { - s->io_buffer_size = MIN(io->len, s->packet_transfer_size); - bdrv_acct_start(s->bs, &s->acct, s->io_buffer_size, - BDRV_ACCT_READ); MACIO_DPRINTF("non-block ATAPI DMA transfer size: %d\n", - s->io_buffer_size); + io->len); - /* Copy ATAPI buffer directly to RAM and finish */ + /* Copy ATAPI buffer directly to RAM */ cpu_physical_memory_write(io->addr, s->io_buffer, - s->io_buffer_size); - ide_atapi_cmd_ok(s); - m->dma_active = false; - - MACIO_DPRINTF("end of non-block ATAPI DMA transfer\n"); - bdrv_acct_done(s->bs, &s->acct); - io->dma_end(io); - return; + io->len); + + /* Finish on next callback */ + io->len = 0; } - bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ); pmac_ide_atapi_transfer_cb(io, 0); return; } ^ permalink raw reply related [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-20 14:29 ` Mark Cave-Ayland @ 2014-06-20 19:17 ` BALATON Zoltan 2014-06-20 19:27 ` Mark Cave-Ayland 2014-06-23 21:30 ` BALATON Zoltan 1 sibling, 1 reply; 94+ messages in thread From: BALATON Zoltan @ 2014-06-20 19:17 UTC (permalink / raw) To: Mark Cave-Ayland; +Cc: qemu-ppc@nongnu.org, Alexander Graf, qemu-devel On Fri, 20 Jun 2014, Mark Cave-Ayland wrote: > Zoltan, please can you test the attached patch to see if this still allows > MorphOS to boot? Unfortunately it seems MorphOS cannot boot with this patch. It hangs while trying to read the TOC from the CD. Debug output with DEBUG_MACIO and DEBUG_DBDMA enabled shows: DBDMA: writel 0x0000000000000d0c <= 0x00e51970 DBDMA: channel 0x1a reg 0x3 DBDMA: dbdma_cmdptr_load 0x00e51970 DBDMA: DBDMA_run_bh DBDMA: writel 0x0000000000000d00 <= 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00008400 DBDMA: readl 0x0000000000000d00 => 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: DBDMA_run_bh DBDMA: channel_run dbdma_cmd 0x7f0997120f28 req_count 0x0324 command 0x3000 phy_addr 0x00e7b0bc cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: start_input DBDMA: addr 0xe7b0bc key 0x0 non-block ATAPI DMA transfer size: 804 io_buffer_size = 0 remainder: 0 io->len: 0 size: 20 end of DMA done DMA DBDMA: dbdma_end DBDMA: conditional_wait DBDMA: dbdma_cmdptr_save 0x00e51970 DBDMA: xfer_status 0x00008400 res_count 0x0000 DBDMA: conditional_interrupt DBDMA: conditional_branch DBDMA: dbdma_cmdptr_load 0x00e51980 DBDMA: channel_run dbdma_cmd 0x7f0997120f28 req_count 0x0000 command 0x7000 phy_addr 0x00000000 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 and no further ide activity from here whereas without the patch when it boots I see these logs: DBDMA: writel 0x0000000000000d0c <= 0x00e50090 DBDMA: channel 0x1a reg 0x3 DBDMA: dbdma_cmdptr_load 0x00e50090 DBDMA: DBDMA_run_bh DBDMA: writel 0x0000000000000d00 <= 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00008400 DBDMA: readl 0x0000000000000d00 => 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: DBDMA_run_bh DBDMA: channel_run dbdma_cmd 0x7f56695a7f28 req_count 0x0324 command 0x3000 phy_addr 0x00e4f8fc cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: start_input DBDMA: addr 0xe4f8fc key 0x0 non-block ATAPI DMA transfer size: 20 end of non-block ATAPI DMA transfer DBDMA: dbdma_end DBDMA: conditional_wait DBDMA: dbdma_cmdptr_save 0x00e50090 DBDMA: xfer_status 0x00008400 res_count 0x0324 DBDMA: conditional_interrupt DBDMA: conditional_branch DBDMA: dbdma_cmdptr_load 0x00e500a0 DBDMA: channel_run dbdma_cmd 0x7f56695a7f28 req_count 0x0000 command 0x7000 phy_addr 0x00000000 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: writel 0x0000000000000d00 <= 0x98000000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00000000 DBDMA: writel 0x0000000000000d0c <= 0x00e50090 DBDMA: channel 0x1a reg 0x3 DBDMA: dbdma_cmdptr_load 0x00e50090 DBDMA: writel 0x0000000000000d00 <= 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00008400 DBDMA: readl 0x0000000000000d00 => 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: DBDMA_run_bh DBDMA: channel_run dbdma_cmd 0x7f56695a7f28 req_count 0x0800 command 0x3000 phy_addr 0x00e8d7c0 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: start_input DBDMA: addr 0xe8d7c0 key 0x0 io_buffer_size = 0 remainder: 0 io->len: 2048 size: 2048 io->len = 0x800 set remainder to: 0 sector_num=64 size=2048, cmd_cmd=0 io_buffer_size = 0x800 remainder: 0 io->len: 0 size: 0 end of transfer end of DMA done DMA DBDMA: dbdma_end DBDMA: conditional_wait DBDMA: dbdma_cmdptr_save 0x00e50090 DBDMA: xfer_status 0x00008400 res_count 0x0000 DBDMA: conditional_interrupt DBDMA: conditional_branch DBDMA: dbdma_cmdptr_load 0x00e500a0 DBDMA: channel_run dbdma_cmd 0x7f56695a7f28 req_count 0x0000 command 0x7000 phy_addr 0x00000000 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 and a lot of similar stuff after this. If this is not enough to understand the problem and you need more details please tell me what to look for. Regards, BALATON Zoltan ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-20 19:17 ` BALATON Zoltan @ 2014-06-20 19:27 ` Mark Cave-Ayland 2014-06-21 0:57 ` BALATON Zoltan 2014-06-23 16:31 ` Alexander Graf 0 siblings, 2 replies; 94+ messages in thread From: Mark Cave-Ayland @ 2014-06-20 19:27 UTC (permalink / raw) To: BALATON Zoltan; +Cc: qemu-ppc@nongnu.org, Alexander Graf, qemu-devel On 20/06/14 20:17, BALATON Zoltan wrote: > On Fri, 20 Jun 2014, Mark Cave-Ayland wrote: >> Zoltan, please can you test the attached patch to see if this still >> allows MorphOS to boot? > > Unfortunately it seems MorphOS cannot boot with this patch. It hangs > while trying to read the TOC from the CD. Debug output with DEBUG_MACIO > and DEBUG_DBDMA enabled shows: And also with ATAPI debugging enabled? I suspect the problem is with the interaction between the DMA/ATAPI systems again. > DBDMA: writel 0x0000000000000d0c <= 0x00e51970 > DBDMA: channel 0x1a reg 0x3 > DBDMA: dbdma_cmdptr_load 0x00e51970 > > DBDMA: DBDMA_run_bh > DBDMA: writel 0x0000000000000d00 <= 0x80008000 > DBDMA: channel 0x1a reg 0x0 > DBDMA: status 0x00008400 > DBDMA: readl 0x0000000000000d00 => 0x80008000 > DBDMA: channel 0x1a reg 0x0 > DBDMA: DBDMA_run_bh > DBDMA: channel_run > dbdma_cmd 0x7f0997120f28 > req_count 0x0324 > command 0x3000 > phy_addr 0x00e7b0bc > cmd_dep 0x00000000 > res_count 0x0000 > xfer_status 0x0000 > DBDMA: start_input > DBDMA: addr 0xe7b0bc key 0x0 > > non-block ATAPI DMA transfer size: 804 > io_buffer_size = 0 > remainder: 0 io->len: 0 size: 20 > end of DMA > done DMA > DBDMA: dbdma_end > DBDMA: conditional_wait > DBDMA: dbdma_cmdptr_save 0x00e51970 > DBDMA: xfer_status 0x00008400 res_count 0x0000 > DBDMA: conditional_interrupt > DBDMA: conditional_branch > DBDMA: dbdma_cmdptr_load 0x00e51980 > DBDMA: channel_run > dbdma_cmd 0x7f0997120f28 > req_count 0x0000 > command 0x7000 > phy_addr 0x00000000 > cmd_dep 0x00000000 > res_count 0x0000 > xfer_status 0x0000 > > and no further ide activity from here whereas without the patch when it > boots I see these logs: > > DBDMA: writel 0x0000000000000d0c <= 0x00e50090 > DBDMA: channel 0x1a reg 0x3 > DBDMA: dbdma_cmdptr_load 0x00e50090 > > DBDMA: DBDMA_run_bh > DBDMA: writel 0x0000000000000d00 <= 0x80008000 > DBDMA: channel 0x1a reg 0x0 > DBDMA: status 0x00008400 > DBDMA: readl 0x0000000000000d00 => 0x80008000 > DBDMA: channel 0x1a reg 0x0 > DBDMA: DBDMA_run_bh > DBDMA: channel_run > dbdma_cmd 0x7f56695a7f28 > req_count 0x0324 > command 0x3000 > phy_addr 0x00e4f8fc > cmd_dep 0x00000000 > res_count 0x0000 > xfer_status 0x0000 > DBDMA: start_input > DBDMA: addr 0xe4f8fc key 0x0 > > non-block ATAPI DMA transfer size: 20 > end of non-block ATAPI DMA transfer > DBDMA: dbdma_end > DBDMA: conditional_wait > DBDMA: dbdma_cmdptr_save 0x00e50090 > DBDMA: xfer_status 0x00008400 res_count 0x0324 > DBDMA: conditional_interrupt > DBDMA: conditional_branch > DBDMA: dbdma_cmdptr_load 0x00e500a0 > DBDMA: channel_run > dbdma_cmd 0x7f56695a7f28 > req_count 0x0000 > command 0x7000 > phy_addr 0x00000000 > cmd_dep 0x00000000 > res_count 0x0000 > xfer_status 0x0000 > DBDMA: writel 0x0000000000000d00 <= 0x98000000 > DBDMA: channel 0x1a reg 0x0 > DBDMA: status 0x00000000 > DBDMA: writel 0x0000000000000d0c <= 0x00e50090 > DBDMA: channel 0x1a reg 0x3 > DBDMA: dbdma_cmdptr_load 0x00e50090 > > DBDMA: writel 0x0000000000000d00 <= 0x80008000 > DBDMA: channel 0x1a reg 0x0 > DBDMA: status 0x00008400 > DBDMA: readl 0x0000000000000d00 => 0x80008000 > DBDMA: channel 0x1a reg 0x0 > DBDMA: DBDMA_run_bh > DBDMA: channel_run > dbdma_cmd 0x7f56695a7f28 > req_count 0x0800 > command 0x3000 > phy_addr 0x00e8d7c0 > cmd_dep 0x00000000 > res_count 0x0000 > xfer_status 0x0000 > DBDMA: start_input > DBDMA: addr 0xe8d7c0 key 0x0 > > io_buffer_size = 0 > remainder: 0 io->len: 2048 size: 2048 > io->len = 0x800 > set remainder to: 0 > sector_num=64 size=2048, cmd_cmd=0 > io_buffer_size = 0x800 > remainder: 0 io->len: 0 size: 0 > end of transfer > end of DMA > done DMA > DBDMA: dbdma_end > DBDMA: conditional_wait > DBDMA: dbdma_cmdptr_save 0x00e50090 > DBDMA: xfer_status 0x00008400 res_count 0x0000 > DBDMA: conditional_interrupt > DBDMA: conditional_branch > DBDMA: dbdma_cmdptr_load 0x00e500a0 > DBDMA: channel_run > dbdma_cmd 0x7f56695a7f28 > req_count 0x0000 > command 0x7000 > phy_addr 0x00000000 > cmd_dep 0x00000000 > res_count 0x0000 > xfer_status 0x0000 > > and a lot of similar stuff after this. If this is not enough to > understand the problem and you need more details please tell me what to > look for. I'm afraid as you're the only person that can boot MorphOS this far then we need you to diagnose and suggest a suitable alternative by comparing the before and after output. Since MacOS is already a supported client then if no solution can be found then it is likely that this patch will be reverted :( In order for a patch to be accepted then it will need to both pass your MorphOS tests and also boot darwinppc-602.iso which should cover the two cases of either the ATAPI or the DMA transfer occurring first. HTH, Mark. ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-20 19:27 ` Mark Cave-Ayland @ 2014-06-21 0:57 ` BALATON Zoltan 2014-06-23 16:31 ` Alexander Graf 1 sibling, 0 replies; 94+ messages in thread From: BALATON Zoltan @ 2014-06-21 0:57 UTC (permalink / raw) To: Mark Cave-Ayland; +Cc: qemu-ppc@nongnu.org, Alexander Graf, qemu-devel On Fri, 20 Jun 2014, Mark Cave-Ayland wrote: > And also with ATAPI debugging enabled? I suspect the problem is with the > interaction between the DMA/ATAPI systems again. I forgot that one. I've now rerun with DEBUG_IDE_ATAPI enabled. Here is with the patch failing: DBDMA: writel 0x0000000000000d0c <= 0x00e599f0 DBDMA: channel 0x1a reg 0x3 DBDMA: dbdma_cmdptr_load 0x00e599f0 ATAPI limit=0x8000 packet: 43 00 00 00 00 00 00 03 24 00 00 00 DBDMA: DBDMA_run_bh DBDMA: writel 0x0000000000000d00 <= 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00008400 DBDMA: readl 0x0000000000000d00 => 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: DBDMA_run_bh DBDMA: channel_run dbdma_cmd 0x7f4cf1325228 req_count 0x0324 command 0x3000 phy_addr 0x00e57d74 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: start_input DBDMA: addr 0xe57d74 key 0x0 non-block ATAPI DMA transfer size: 804 io_buffer_size = 0 remainder: 0 io->len: 0 size: 20 end of DMA done DMA DBDMA: dbdma_end DBDMA: conditional_wait DBDMA: dbdma_cmdptr_save 0x00e599f0 DBDMA: xfer_status 0x00008400 res_count 0x0000 DBDMA: conditional_interrupt DBDMA: conditional_branch DBDMA: dbdma_cmdptr_load 0x00e59a00 DBDMA: channel_run dbdma_cmd 0x7f4cf1325228 req_count 0x0000 command 0x7000 phy_addr 0x00000000 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 and without the patch when it works: DBDMA: writel 0x0000000000000d0c <= 0x00e89ce0 DBDMA: channel 0x1a reg 0x3 DBDMA: dbdma_cmdptr_load 0x00e89ce0 ATAPI limit=0x8000 packet: 43 00 00 00 00 00 00 03 24 00 00 00 DBDMA: DBDMA_run_bh DBDMA: writel 0x0000000000000d00 <= 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00008400 DBDMA: readl 0x0000000000000d00 => 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: DBDMA_run_bh DBDMA: channel_run dbdma_cmd 0x7fc4dcef2228 req_count 0x0324 command 0x3000 phy_addr 0x00e8ff94 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: start_input DBDMA: addr 0xe8ff94 key 0x0 non-block ATAPI DMA transfer size: 20 end of non-block ATAPI DMA transfer DBDMA: dbdma_end DBDMA: conditional_wait DBDMA: dbdma_cmdptr_save 0x00e89ce0 DBDMA: xfer_status 0x00008400 res_count 0x0324 DBDMA: conditional_interrupt DBDMA: conditional_branch DBDMA: dbdma_cmdptr_load 0x00e89cf0 DBDMA: channel_run dbdma_cmd 0x7fc4dcef2228 req_count 0x0000 command 0x7000 phy_addr 0x00000000 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: readl 0x0000000000000d04 => 0x00008000 DBDMA: channel 0x1a reg 0x1 DBDMA: writel 0x0000000000000d00 <= 0x98000000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00000000 DBDMA: writel 0x0000000000000d0c <= 0x00e89ce0 DBDMA: channel 0x1a reg 0x3 DBDMA: dbdma_cmdptr_load 0x00e89ce0 ATAPI limit=0x8000 packet: 28 00 00 00 00 10 00 00 01 00 00 00 read dma: LBA=16 nb_sectors=1 DBDMA: writel 0x0000000000000d00 <= 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00008400 DBDMA: readl 0x0000000000000d00 => 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: DBDMA_run_bh DBDMA: channel_run dbdma_cmd 0x7fc4dcef2228 req_count 0x0800 command 0x3000 phy_addr 0x00e7bc20 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: start_input DBDMA: addr 0xe7bc20 key 0x0 io_buffer_size = 0 remainder: 0 io->len: 2048 size: 2048 io->len = 0x800 set remainder to: 0 sector_num=64 size=2048, cmd_cmd=0 io_buffer_size = 0x800 remainder: 0 io->len: 0 size: 0 end of transfer end of DMA done DMA DBDMA: dbdma_end DBDMA: conditional_wait DBDMA: dbdma_cmdptr_save 0x00e89ce0 DBDMA: xfer_status 0x00008400 res_count 0x0000 DBDMA: conditional_interrupt DBDMA: conditional_branch DBDMA: dbdma_cmdptr_load 0x00e89cf0 DBDMA: channel_run dbdma_cmd 0x7fc4dcef2228 req_count 0x0000 command 0x7000 phy_addr 0x00000000 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: writel 0x0000000000000d00 <= 0x98000000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00000000 ATAPI limit=0x8000 packet: 00 00 00 00 00 00 00 00 00 00 00 00 DBDMA: writel 0x0000000000000d0c <= 0x00e89ce0 DBDMA: channel 0x1a reg 0x3 DBDMA: dbdma_cmdptr_load 0x00e89ce0 ATAPI limit=0x8000 packet: 43 00 00 00 00 00 00 03 24 00 00 00 DBDMA: writel 0x0000000000000d00 <= 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00008400 DBDMA: readl 0x0000000000000d00 => 0x80008000 DBDMA: channel 0x1a reg 0x0 DBDMA: DBDMA_run_bh DBDMA: channel_run dbdma_cmd 0x7fc4dcef2228 req_count 0x0324 command 0x3000 phy_addr 0x00e98dd4 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: start_input DBDMA: addr 0xe98dd4 key 0x0 non-block ATAPI DMA transfer size: 20 end of non-block ATAPI DMA transfer DBDMA: dbdma_end DBDMA: conditional_wait DBDMA: dbdma_cmdptr_save 0x00e89ce0 DBDMA: xfer_status 0x00008400 res_count 0x0324 DBDMA: conditional_interrupt DBDMA: conditional_branch DBDMA: dbdma_cmdptr_load 0x00e89cf0 DBDMA: channel_run dbdma_cmd 0x7fc4dcef2228 req_count 0x0000 command 0x7000 phy_addr 0x00000000 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: writel 0x0000000000000d00 <= 0x98000000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00000000 DBDMA: writel 0x0000000000000d0c <= 0x00e89ce0 DBDMA: channel 0x1a reg 0x3 DBDMA: dbdma_cmdptr_load 0x00e89ce0 ATAPI limit=0x8000 packet: 28 00 00 00 00 10 00 00 01 00 00 00 read dma: LBA=16 nb_sectors=1 The only difference in the common part I can see is the different transfer size. > I'm afraid as you're the only person that can boot MorphOS this far then we > need you to diagnose and suggest a suitable alternative by comparing the > before and after output. Since MacOS is already a supported client then if no > solution can be found then it is likely that this patch will be reverted :( Unfortunately I can't make sense of the mess in macio.c so I cannot suggest a solution as I don't understand what's happening and how should it work. I can help in testing and trying things you tell me to do but I cannot solve it by myself. (It would probably help if the unaligned hacks could be removed if this is already possible with the current block layer as that should simplify the code so it could be understood. I can't do that either though as I don't know what needs to be done for this.) I wish more people could boot MorphOS by now but that still needs the patches I've sent for OpenBIOS and QEMU that are not merged yet and there's also the problem with the MMU exceptions that we don't have a solution for yet. Regards, BALATON Zoltan ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-20 19:27 ` Mark Cave-Ayland 2014-06-21 0:57 ` BALATON Zoltan @ 2014-06-23 16:31 ` Alexander Graf 2014-06-23 19:26 ` BALATON Zoltan 1 sibling, 1 reply; 94+ messages in thread From: Alexander Graf @ 2014-06-23 16:31 UTC (permalink / raw) To: Mark Cave-Ayland, BALATON Zoltan; +Cc: qemu-ppc@nongnu.org, qemu-devel On 20.06.14 21:27, Mark Cave-Ayland wrote: > On 20/06/14 20:17, BALATON Zoltan wrote: > >> On Fri, 20 Jun 2014, Mark Cave-Ayland wrote: >>> Zoltan, please can you test the attached patch to see if this still >>> allows MorphOS to boot? >> >> Unfortunately it seems MorphOS cannot boot with this patch. It hangs >> while trying to read the TOC from the CD. Debug output with DEBUG_MACIO >> and DEBUG_DBDMA enabled shows: > > And also with ATAPI debugging enabled? I suspect the problem is with > the interaction between the DMA/ATAPI systems again. > >> DBDMA: writel 0x0000000000000d0c <= 0x00e51970 >> DBDMA: channel 0x1a reg 0x3 >> DBDMA: dbdma_cmdptr_load 0x00e51970 >> >> DBDMA: DBDMA_run_bh >> DBDMA: writel 0x0000000000000d00 <= 0x80008000 >> DBDMA: channel 0x1a reg 0x0 >> DBDMA: status 0x00008400 >> DBDMA: readl 0x0000000000000d00 => 0x80008000 >> DBDMA: channel 0x1a reg 0x0 >> DBDMA: DBDMA_run_bh >> DBDMA: channel_run >> dbdma_cmd 0x7f0997120f28 >> req_count 0x0324 >> command 0x3000 >> phy_addr 0x00e7b0bc >> cmd_dep 0x00000000 >> res_count 0x0000 >> xfer_status 0x0000 >> DBDMA: start_input >> DBDMA: addr 0xe7b0bc key 0x0 >> >> non-block ATAPI DMA transfer size: 804 >> io_buffer_size = 0 >> remainder: 0 io->len: 0 size: 20 >> end of DMA >> done DMA >> DBDMA: dbdma_end >> DBDMA: conditional_wait >> DBDMA: dbdma_cmdptr_save 0x00e51970 >> DBDMA: xfer_status 0x00008400 res_count 0x0000 >> DBDMA: conditional_interrupt >> DBDMA: conditional_branch >> DBDMA: dbdma_cmdptr_load 0x00e51980 >> DBDMA: channel_run >> dbdma_cmd 0x7f0997120f28 >> req_count 0x0000 >> command 0x7000 >> phy_addr 0x00000000 >> cmd_dep 0x00000000 >> res_count 0x0000 >> xfer_status 0x0000 >> >> and no further ide activity from here whereas without the patch when it >> boots I see these logs: >> >> DBDMA: writel 0x0000000000000d0c <= 0x00e50090 >> DBDMA: channel 0x1a reg 0x3 >> DBDMA: dbdma_cmdptr_load 0x00e50090 >> >> DBDMA: DBDMA_run_bh >> DBDMA: writel 0x0000000000000d00 <= 0x80008000 >> DBDMA: channel 0x1a reg 0x0 >> DBDMA: status 0x00008400 >> DBDMA: readl 0x0000000000000d00 => 0x80008000 >> DBDMA: channel 0x1a reg 0x0 >> DBDMA: DBDMA_run_bh >> DBDMA: channel_run >> dbdma_cmd 0x7f56695a7f28 >> req_count 0x0324 >> command 0x3000 >> phy_addr 0x00e4f8fc >> cmd_dep 0x00000000 >> res_count 0x0000 >> xfer_status 0x0000 >> DBDMA: start_input >> DBDMA: addr 0xe4f8fc key 0x0 >> >> non-block ATAPI DMA transfer size: 20 >> end of non-block ATAPI DMA transfer >> DBDMA: dbdma_end >> DBDMA: conditional_wait >> DBDMA: dbdma_cmdptr_save 0x00e50090 >> DBDMA: xfer_status 0x00008400 res_count 0x0324 >> DBDMA: conditional_interrupt >> DBDMA: conditional_branch >> DBDMA: dbdma_cmdptr_load 0x00e500a0 >> DBDMA: channel_run >> dbdma_cmd 0x7f56695a7f28 >> req_count 0x0000 >> command 0x7000 >> phy_addr 0x00000000 >> cmd_dep 0x00000000 >> res_count 0x0000 >> xfer_status 0x0000 >> DBDMA: writel 0x0000000000000d00 <= 0x98000000 >> DBDMA: channel 0x1a reg 0x0 >> DBDMA: status 0x00000000 >> DBDMA: writel 0x0000000000000d0c <= 0x00e50090 >> DBDMA: channel 0x1a reg 0x3 >> DBDMA: dbdma_cmdptr_load 0x00e50090 >> >> DBDMA: writel 0x0000000000000d00 <= 0x80008000 >> DBDMA: channel 0x1a reg 0x0 >> DBDMA: status 0x00008400 >> DBDMA: readl 0x0000000000000d00 => 0x80008000 >> DBDMA: channel 0x1a reg 0x0 >> DBDMA: DBDMA_run_bh >> DBDMA: channel_run >> dbdma_cmd 0x7f56695a7f28 >> req_count 0x0800 >> command 0x3000 >> phy_addr 0x00e8d7c0 >> cmd_dep 0x00000000 >> res_count 0x0000 >> xfer_status 0x0000 >> DBDMA: start_input >> DBDMA: addr 0xe8d7c0 key 0x0 >> >> io_buffer_size = 0 >> remainder: 0 io->len: 2048 size: 2048 >> io->len = 0x800 >> set remainder to: 0 >> sector_num=64 size=2048, cmd_cmd=0 >> io_buffer_size = 0x800 >> remainder: 0 io->len: 0 size: 0 >> end of transfer >> end of DMA >> done DMA >> DBDMA: dbdma_end >> DBDMA: conditional_wait >> DBDMA: dbdma_cmdptr_save 0x00e50090 >> DBDMA: xfer_status 0x00008400 res_count 0x0000 >> DBDMA: conditional_interrupt >> DBDMA: conditional_branch >> DBDMA: dbdma_cmdptr_load 0x00e500a0 >> DBDMA: channel_run >> dbdma_cmd 0x7f56695a7f28 >> req_count 0x0000 >> command 0x7000 >> phy_addr 0x00000000 >> cmd_dep 0x00000000 >> res_count 0x0000 >> xfer_status 0x0000 >> >> and a lot of similar stuff after this. If this is not enough to >> understand the problem and you need more details please tell me what to >> look for. > > I'm afraid as you're the only person that can boot MorphOS this far > then we need you to diagnose and suggest a suitable alternative by > comparing the before and after output. Since MacOS is already a > supported client then if no solution can be found then it is likely > that this patch will be reverted :( So should I revert the patch for now? We're already in soft freeze. Alex ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-23 16:31 ` Alexander Graf @ 2014-06-23 19:26 ` BALATON Zoltan 2014-06-23 22:41 ` Mark Cave-Ayland 0 siblings, 1 reply; 94+ messages in thread From: BALATON Zoltan @ 2014-06-23 19:26 UTC (permalink / raw) To: Alexander Graf; +Cc: qemu-ppc@nongnu.org, Mark Cave-Ayland, qemu-devel On Mon, 23 Jun 2014, Alexander Graf wrote: > On 20.06.14 21:27, Mark Cave-Ayland wrote: >> On 20/06/14 20:17, BALATON Zoltan wrote: >> >>> On Fri, 20 Jun 2014, Mark Cave-Ayland wrote: >>>> Zoltan, please can you test the attached patch to see if this still >>>> allows MorphOS to boot? >>> >>> Unfortunately it seems MorphOS cannot boot with this patch. It hangs >>> while trying to read the TOC from the CD. Debug output with DEBUG_MACIO >>> and DEBUG_DBDMA enabled shows: >> >> And also with ATAPI debugging enabled? I suspect the problem is with the >> interaction between the DMA/ATAPI systems again. >> >>> DBDMA: writel 0x0000000000000d0c <= 0x00e51970 >>> DBDMA: channel 0x1a reg 0x3 >>> DBDMA: dbdma_cmdptr_load 0x00e51970 >>> >>> DBDMA: DBDMA_run_bh >>> DBDMA: writel 0x0000000000000d00 <= 0x80008000 >>> DBDMA: channel 0x1a reg 0x0 >>> DBDMA: status 0x00008400 >>> DBDMA: readl 0x0000000000000d00 => 0x80008000 >>> DBDMA: channel 0x1a reg 0x0 >>> DBDMA: DBDMA_run_bh >>> DBDMA: channel_run >>> dbdma_cmd 0x7f0997120f28 >>> req_count 0x0324 >>> command 0x3000 >>> phy_addr 0x00e7b0bc >>> cmd_dep 0x00000000 >>> res_count 0x0000 >>> xfer_status 0x0000 >>> DBDMA: start_input >>> DBDMA: addr 0xe7b0bc key 0x0 >>> >>> non-block ATAPI DMA transfer size: 804 >>> io_buffer_size = 0 >>> remainder: 0 io->len: 0 size: 20 >>> end of DMA >>> done DMA >>> DBDMA: dbdma_end >>> DBDMA: conditional_wait >>> DBDMA: dbdma_cmdptr_save 0x00e51970 >>> DBDMA: xfer_status 0x00008400 res_count 0x0000 >>> DBDMA: conditional_interrupt >>> DBDMA: conditional_branch >>> DBDMA: dbdma_cmdptr_load 0x00e51980 >>> DBDMA: channel_run >>> dbdma_cmd 0x7f0997120f28 >>> req_count 0x0000 >>> command 0x7000 >>> phy_addr 0x00000000 >>> cmd_dep 0x00000000 >>> res_count 0x0000 >>> xfer_status 0x0000 >>> >>> and no further ide activity from here whereas without the patch when it >>> boots I see these logs: >>> >>> DBDMA: writel 0x0000000000000d0c <= 0x00e50090 >>> DBDMA: channel 0x1a reg 0x3 >>> DBDMA: dbdma_cmdptr_load 0x00e50090 >>> >>> DBDMA: DBDMA_run_bh >>> DBDMA: writel 0x0000000000000d00 <= 0x80008000 >>> DBDMA: channel 0x1a reg 0x0 >>> DBDMA: status 0x00008400 >>> DBDMA: readl 0x0000000000000d00 => 0x80008000 >>> DBDMA: channel 0x1a reg 0x0 >>> DBDMA: DBDMA_run_bh >>> DBDMA: channel_run >>> dbdma_cmd 0x7f56695a7f28 >>> req_count 0x0324 >>> command 0x3000 >>> phy_addr 0x00e4f8fc >>> cmd_dep 0x00000000 >>> res_count 0x0000 >>> xfer_status 0x0000 >>> DBDMA: start_input >>> DBDMA: addr 0xe4f8fc key 0x0 >>> >>> non-block ATAPI DMA transfer size: 20 >>> end of non-block ATAPI DMA transfer >>> DBDMA: dbdma_end >>> DBDMA: conditional_wait >>> DBDMA: dbdma_cmdptr_save 0x00e50090 >>> DBDMA: xfer_status 0x00008400 res_count 0x0324 >>> DBDMA: conditional_interrupt >>> DBDMA: conditional_branch >>> DBDMA: dbdma_cmdptr_load 0x00e500a0 >>> DBDMA: channel_run >>> dbdma_cmd 0x7f56695a7f28 >>> req_count 0x0000 >>> command 0x7000 >>> phy_addr 0x00000000 >>> cmd_dep 0x00000000 >>> res_count 0x0000 >>> xfer_status 0x0000 >>> DBDMA: writel 0x0000000000000d00 <= 0x98000000 >>> DBDMA: channel 0x1a reg 0x0 >>> DBDMA: status 0x00000000 >>> DBDMA: writel 0x0000000000000d0c <= 0x00e50090 >>> DBDMA: channel 0x1a reg 0x3 >>> DBDMA: dbdma_cmdptr_load 0x00e50090 >>> >>> DBDMA: writel 0x0000000000000d00 <= 0x80008000 >>> DBDMA: channel 0x1a reg 0x0 >>> DBDMA: status 0x00008400 >>> DBDMA: readl 0x0000000000000d00 => 0x80008000 >>> DBDMA: channel 0x1a reg 0x0 >>> DBDMA: DBDMA_run_bh >>> DBDMA: channel_run >>> dbdma_cmd 0x7f56695a7f28 >>> req_count 0x0800 >>> command 0x3000 >>> phy_addr 0x00e8d7c0 >>> cmd_dep 0x00000000 >>> res_count 0x0000 >>> xfer_status 0x0000 >>> DBDMA: start_input >>> DBDMA: addr 0xe8d7c0 key 0x0 >>> >>> io_buffer_size = 0 >>> remainder: 0 io->len: 2048 size: 2048 >>> io->len = 0x800 >>> set remainder to: 0 >>> sector_num=64 size=2048, cmd_cmd=0 >>> io_buffer_size = 0x800 >>> remainder: 0 io->len: 0 size: 0 >>> end of transfer >>> end of DMA >>> done DMA >>> DBDMA: dbdma_end >>> DBDMA: conditional_wait >>> DBDMA: dbdma_cmdptr_save 0x00e50090 >>> DBDMA: xfer_status 0x00008400 res_count 0x0000 >>> DBDMA: conditional_interrupt >>> DBDMA: conditional_branch >>> DBDMA: dbdma_cmdptr_load 0x00e500a0 >>> DBDMA: channel_run >>> dbdma_cmd 0x7f56695a7f28 >>> req_count 0x0000 >>> command 0x7000 >>> phy_addr 0x00000000 >>> cmd_dep 0x00000000 >>> res_count 0x0000 >>> xfer_status 0x0000 >>> >>> and a lot of similar stuff after this. If this is not enough to >>> understand the problem and you need more details please tell me what to >>> look for. >> >> I'm afraid as you're the only person that can boot MorphOS this far then we >> need you to diagnose and suggest a suitable alternative by comparing the >> before and after output. Since MacOS is already a supported client then if >> no solution can be found then it is likely that this patch will be reverted >> :( > > So should I revert the patch for now? We're already in soft freeze. It would be nicer if it could be fixed instead of reverting. You could help detangling the macio.c code for a start. Regards, BALATON Zoltan ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-23 19:26 ` BALATON Zoltan @ 2014-06-23 22:41 ` Mark Cave-Ayland 2014-06-24 10:35 ` Kevin Wolf 2014-06-24 10:53 ` BALATON Zoltan 0 siblings, 2 replies; 94+ messages in thread From: Mark Cave-Ayland @ 2014-06-23 22:41 UTC (permalink / raw) To: BALATON Zoltan, Alexander Graf Cc: Kevin Wolf, qemu-ppc@nongnu.org, qemu-devel On 23/06/14 20:26, BALATON Zoltan wrote: (add Kevin to CC) >>> I'm afraid as you're the only person that can boot MorphOS this far >>> then we need you to diagnose and suggest a suitable alternative by >>> comparing the before and after output. Since MacOS is already a >>> supported client then if no solution can be found then it is likely >>> that this patch will be reverted :( >> >> So should I revert the patch for now? We're already in soft freeze. Well let's see if Zoltan can make any headway with debugging over the next few days; if there's no progress by the weekend then sadly my recommendation would be to revert in time for -rc0 as this definitely causes intermittent boot failures in Darwin for me. > It would be nicer if it could be fixed instead of reverting. You could > help detangling the macio.c code for a start. Just to clarify here: the macio/DBDMA code is quite complicated, but this is because this device has to work around to the fact that currently the DMA I/O routines currently need sector alignment whereas macio requires byte-level alignment. There has been quite a lot of work at the lower levels to support byte-level alignment (see Kevin's series at http://lists.gnu.org/archive/html/qemu-devel/2014-01/msg02163.html) but until we can specify transfers to byte granularity in the dma_bdrv_*() APIs then there isn't much we can do to clean up the macio.c code. Kevin, are there any plans to bubble the byte-granularity block layer changes up to the dma_bdrv_*() APIs in the near future? Please bear in mind that QEMU supports a large number of OSs, and there is already an enthusiastic group of people using Alex's OS X work (see emaculation for many examples) so introducing an intermittent fault on a supported OS is not an option here. I should also re-emphasise that Alex/Andreas work on many different parts of QEMU, and my work is currently unsponsored so while we are all keen to improve QEMU to the point where it can emulate new OSs such as MorphOS, it's not the case that we can simply drop what we are doing at the time to focus on an issue that affects a single OS which is new and currently unsupported. Now I think it's fair to say that I've spent quite a few hours helping you and coming up with the original version of this patch, and I'm glad that you are now seeing success with this. But what is important to us right now heading towards a release is that patches don't cause any regressions. All I can say is that debugging this stuff isn't easy, particularly with MorphOS which has some rather unusual behaviours. But what we really need from you now over the next few days is for you to compare the debug output between the working and non-working cases and figure out if we can fix this in time for the 2.1 release. You have everything you need (including my acceptance test of booting both MorphOS and Darwin ISOs), so time to take a deep breath and begin what should be a challenging yet ultimately rewarding debugging process :) ATB, Mark. ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-23 22:41 ` Mark Cave-Ayland @ 2014-06-24 10:35 ` Kevin Wolf 2014-06-24 10:53 ` BALATON Zoltan 1 sibling, 0 replies; 94+ messages in thread From: Kevin Wolf @ 2014-06-24 10:35 UTC (permalink / raw) To: Mark Cave-Ayland; +Cc: qemu-devel, qemu-ppc@nongnu.org, Alexander Graf Am 24.06.2014 um 00:41 hat Mark Cave-Ayland geschrieben: > On 23/06/14 20:26, BALATON Zoltan wrote: > > (add Kevin to CC) > > >>>I'm afraid as you're the only person that can boot MorphOS this far > >>>then we need you to diagnose and suggest a suitable alternative by > >>>comparing the before and after output. Since MacOS is already a > >>>supported client then if no solution can be found then it is likely > >>>that this patch will be reverted :( > >> > >>So should I revert the patch for now? We're already in soft freeze. > > Well let's see if Zoltan can make any headway with debugging over > the next few days; if there's no progress by the weekend then sadly > my recommendation would be to revert in time for -rc0 as this > definitely causes intermittent boot failures in Darwin for me. > > >It would be nicer if it could be fixed instead of reverting. You could > >help detangling the macio.c code for a start. > > Just to clarify here: the macio/DBDMA code is quite complicated, but > this is because this device has to work around to the fact that > currently the DMA I/O routines currently need sector alignment > whereas macio requires byte-level alignment. There has been quite a > lot of work at the lower levels to support byte-level alignment (see > Kevin's series at > http://lists.gnu.org/archive/html/qemu-devel/2014-01/msg02163.html) > but until we can specify transfers to byte granularity in the > dma_bdrv_*() APIs then there isn't much we can do to clean up the > macio.c code. > > Kevin, are there any plans to bubble the byte-granularity block > layer changes up to the dma_bdrv_*() APIs in the near future? Not to my knowledge. Block devices allowing byte-granularity accesses (or can you even call them block devices any more then?) seem to be something rather uncommon. So far this macio thing seems to be the only one that needs such functionality. Which probably means that if you guys don't do the conversion, nobody will. > Please bear in mind that QEMU supports a large number of OSs, and > there is already an enthusiastic group of people using Alex's OS X > work (see emaculation for many examples) so introducing an > intermittent fault on a supported OS is not an option here. > > I should also re-emphasise that Alex/Andreas work on many different > parts of QEMU, and my work is currently unsponsored so while we are > all keen to improve QEMU to the point where it can emulate new OSs > such as MorphOS, it's not the case that we can simply drop what we > are doing at the time to focus on an issue that affects a single OS > which is new and currently unsupported. > > Now I think it's fair to say that I've spent quite a few hours > helping you and coming up with the original version of this patch, > and I'm glad that you are now seeing success with this. But what is > important to us right now heading towards a release is that patches > don't cause any regressions. Yes, I think you're making an important point here. Kevin ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-23 22:41 ` Mark Cave-Ayland 2014-06-24 10:35 ` Kevin Wolf @ 2014-06-24 10:53 ` BALATON Zoltan 2014-06-24 11:02 ` Alexander Graf 2014-06-25 20:17 ` Mark Cave-Ayland 1 sibling, 2 replies; 94+ messages in thread From: BALATON Zoltan @ 2014-06-24 10:53 UTC (permalink / raw) To: Mark Cave-Ayland Cc: Kevin Wolf, qemu-ppc@nongnu.org, Alexander Graf, qemu-devel On Mon, 23 Jun 2014, Mark Cave-Ayland wrote: > On 23/06/14 20:26, BALATON Zoltan wrote: > > (add Kevin to CC) > >>>> I'm afraid as you're the only person that can boot MorphOS this far >>>> then we need you to diagnose and suggest a suitable alternative by >>>> comparing the before and after output. Since MacOS is already a >>>> supported client then if no solution can be found then it is likely >>>> that this patch will be reverted :( >>> >>> So should I revert the patch for now? We're already in soft freeze. > > Well let's see if Zoltan can make any headway with debugging over the next > few days; if there's no progress by the weekend then sadly my recommendation > would be to revert in time for -rc0 as this definitely causes intermittent > boot failures in Darwin for me. > >> It would be nicer if it could be fixed instead of reverting. You could >> help detangling the macio.c code for a start. > > Just to clarify here: the macio/DBDMA code is quite complicated, but this is > because this device has to work around to the fact that currently the DMA I/O > routines currently need sector alignment whereas macio requires byte-level > alignment. There has been quite a lot of work at the lower levels to support > byte-level alignment (see Kevin's series at > http://lists.gnu.org/archive/html/qemu-devel/2014-01/msg02163.html) but until > we can specify transfers to byte granularity in the dma_bdrv_*() APIs then > there isn't much we can do to clean up the macio.c code. > > Kevin, are there any plans to bubble the byte-granularity block layer changes > up to the dma_bdrv_*() APIs in the near future? > > Please bear in mind that QEMU supports a large number of OSs, and there is > already an enthusiastic group of people using Alex's OS X work (see > emaculation for many examples) so introducing an intermittent fault on a > supported OS is not an option here. > > I should also re-emphasise that Alex/Andreas work on many different parts of > QEMU, and my work is currently unsponsored so while we are all keen to > improve QEMU to the point where it can emulate new OSs such as MorphOS, it's > not the case that we can simply drop what we are doing at the time to focus > on an issue that affects a single OS which is new and currently unsupported. I also work unsponsored on this and not sure how long can I still find time for it. I've already spent much more with this than I originally planned as I'm doing it since end of this February already. So I'd like my work so far to get upstream so that if I have to finish it's not lost and others could use and build on it. If there's no chance that this can be achieved by 2.1 then you could revert this patch and get back to it in 2.2 but that would delay things by months again. My patches are on the list for quite some time so it's not like I'm asking you to work on this in the last minute and this bug was reported on May 4th. I appreciate your help so far very much and don't exepct this to be highest priority but I'd like to make some progress too. > Now I think it's fair to say that I've spent quite a few hours helping you > and coming up with the original version of this patch, and I'm glad that you Now doubt about that, thank you very much again. > are now seeing success with this. But what is important to us right now > heading towards a release is that patches don't cause any regressions. > > All I can say is that debugging this stuff isn't easy, particularly with > MorphOS which has some rather unusual behaviours. But what we really need > from you now over the next few days is for you to compare the debug output > between the working and non-working cases and figure out if we can fix this > in time for the 2.1 release. You have everything you need (including my > acceptance test of booting both MorphOS and Darwin ISOs), so time to take a > deep breath and begin what should be a challenging yet ultimately rewarding > debugging process :) I'm still working on finding a solution for the exception problems with OpenBIOS that prevent MorphOS from working and I failed to understand the whole working of macio, DBDMA and the whole block layer so far but I can try to debug it. Can you tell how to reproduce the problem with Darwin? The Darwin images don't seem to work with -M mac99 either before or after the patch so no regressions there. Regards, BALATON Zoltan ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-24 10:53 ` BALATON Zoltan @ 2014-06-24 11:02 ` Alexander Graf 2014-06-24 11:22 ` Kevin Wolf 2014-06-25 20:17 ` Mark Cave-Ayland 1 sibling, 1 reply; 94+ messages in thread From: Alexander Graf @ 2014-06-24 11:02 UTC (permalink / raw) To: BALATON Zoltan, Mark Cave-Ayland Cc: Kevin Wolf, qemu-ppc@nongnu.org, qemu-devel On 24.06.14 12:53, BALATON Zoltan wrote: > On Mon, 23 Jun 2014, Mark Cave-Ayland wrote: >> On 23/06/14 20:26, BALATON Zoltan wrote: >> >> (add Kevin to CC) >> >>>>> I'm afraid as you're the only person that can boot MorphOS this far >>>>> then we need you to diagnose and suggest a suitable alternative by >>>>> comparing the before and after output. Since MacOS is already a >>>>> supported client then if no solution can be found then it is likely >>>>> that this patch will be reverted :( >>>> >>>> So should I revert the patch for now? We're already in soft freeze. >> >> Well let's see if Zoltan can make any headway with debugging over the >> next few days; if there's no progress by the weekend then sadly my >> recommendation would be to revert in time for -rc0 as this definitely >> causes intermittent boot failures in Darwin for me. >> >>> It would be nicer if it could be fixed instead of reverting. You could >>> help detangling the macio.c code for a start. >> >> Just to clarify here: the macio/DBDMA code is quite complicated, but >> this is because this device has to work around to the fact that >> currently the DMA I/O routines currently need sector alignment >> whereas macio requires byte-level alignment. There has been quite a >> lot of work at the lower levels to support byte-level alignment (see >> Kevin's series at >> http://lists.gnu.org/archive/html/qemu-devel/2014-01/msg02163.html) >> but until we can specify transfers to byte granularity in the >> dma_bdrv_*() APIs then there isn't much we can do to clean up the >> macio.c code. >> >> Kevin, are there any plans to bubble the byte-granularity block layer >> changes up to the dma_bdrv_*() APIs in the near future? >> >> Please bear in mind that QEMU supports a large number of OSs, and >> there is already an enthusiastic group of people using Alex's OS X >> work (see emaculation for many examples) so introducing an >> intermittent fault on a supported OS is not an option here. >> >> I should also re-emphasise that Alex/Andreas work on many different >> parts of QEMU, and my work is currently unsponsored so while we are >> all keen to improve QEMU to the point where it can emulate new OSs >> such as MorphOS, it's not the case that we can simply drop what we >> are doing at the time to focus on an issue that affects a single OS >> which is new and currently unsupported. > > I also work unsponsored on this and not sure how long can I still find > time for it. I've already spent much more with this than I originally > planned as I'm doing it since end of this February already. So I'd > like my work so far to get upstream so that if I have to finish it's > not lost and others could use and build on it. If there's no chance > that this can be achieved by 2.1 then you could revert this patch and > get back to it in 2.2 but that would delay things by months again. My > patches are on the list for quite some time so it's not like I'm > asking you to work on this in the last minute and this bug was > reported on May 4th. I appreciate your help so far very much and don't > exepct this to be highest priority but I'd like to make some progress > too. > >> Now I think it's fair to say that I've spent quite a few hours >> helping you and coming up with the original version of this patch, >> and I'm glad that you > > Now doubt about that, thank you very much again. > >> are now seeing success with this. But what is important to us right >> now heading towards a release is that patches don't cause any >> regressions. >> >> All I can say is that debugging this stuff isn't easy, particularly >> with MorphOS which has some rather unusual behaviours. But what we >> really need from you now over the next few days is for you to compare >> the debug output between the working and non-working cases and figure >> out if we can fix this in time for the 2.1 release. You have >> everything you need (including my acceptance test of booting both >> MorphOS and Darwin ISOs), so time to take a deep breath and begin >> what should be a challenging yet ultimately rewarding debugging >> process :) > > I'm still working on finding a solution for the exception problems > with OpenBIOS that prevent MorphOS from working and I failed to > understand the whole working of macio, DBDMA and the whole block layer > so far That one's reasonably simple. On a real Mac, we have different chips implementing IDE and DMA. Traditionally in a non-DMA system, you would have an IDE controller that has a small buffer. When you issue a command, that buffer would get filled and you can poke the IDE controller byte-by-byte to retrieve that buffer. Then people realized that this doesn't perform too well, so they started implementing DMA controllers. The DBDMA controller does this task of poking the IDE controller for you. So instead of hogging the CPU with byte-by-byte transfers from the IDE controller, you now occupy the DMA controller with them, freeing the CPU to do other work. The way DBDMA works is that you put in something similar to a scatter-gather list: A list of chunks to read / write and where in memory those chunks live. DBDMA then goes over its list and does the pokes. So for example if the list is [ memaddr = 0x12000 | len = 500 ] [ memaddr = 0x13098 | len = 12 ] then it reads 500 bytes from IDE, writes them at memory offset 0x12000 and after that reads another 12 bytes from IDE and puts them at memory offset 0x13098. The reason we have such complicated code for real DMA is that we can't model this easily with our direct block-to-memory API. That one can only work on a 512 byte granularity. So when we see unaligned accesses like above, we have to split them out and handle them lazily. Alex ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-24 11:02 ` Alexander Graf @ 2014-06-24 11:22 ` Kevin Wolf 2014-06-24 11:27 ` Alexander Graf 0 siblings, 1 reply; 94+ messages in thread From: Kevin Wolf @ 2014-06-24 11:22 UTC (permalink / raw) To: Alexander Graf; +Cc: qemu-ppc@nongnu.org, Mark Cave-Ayland, qemu-devel Am 24.06.2014 um 13:02 hat Alexander Graf geschrieben: > The way DBDMA works is that you put in something similar to a > scatter-gather list: A list of chunks to read / write and where in > memory those chunks live. DBDMA then goes over its list and does the > pokes. So for example if the list is > > [ memaddr = 0x12000 | len = 500 ] > [ memaddr = 0x13098 | len = 12 ] > > then it reads 500 bytes from IDE, writes them at memory offset > 0x12000 and after that reads another 12 bytes from IDE and puts them > at memory offset 0x13098. > > The reason we have such complicated code for real DMA is that we > can't model this easily with our direct block-to-memory API. That > one can only work on a 512 byte granularity. So when we see > unaligned accesses like above, we have to split them out and handle > them lazily. Wait... What kind of granularity are you talking about? We do need disk accesses with a 512 byte granularity, because the API takes a sector number. This is also what real IDE disks do, they don't provide byte access. However, for the memory, I can't see why you couldn't pass a s/g list like what you wrote above to the DMA functions. This is not unusual at all and is the same as ide/pci.c does. There is no 512-byte alignment needed for the individual s/g list entries, only the total size should obviously be a multiple of 512 in the general case (otherwise the list would be too short or too long for the request). If this is really what we're talking about, then I think your problem is just that you try to handle the 500 byte and the 12 byte as individual requests instead of building up the s/g list and then sending a single request. Kevin ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-24 11:22 ` Kevin Wolf @ 2014-06-24 11:27 ` Alexander Graf 2014-06-24 12:07 ` Kevin Wolf 0 siblings, 1 reply; 94+ messages in thread From: Alexander Graf @ 2014-06-24 11:27 UTC (permalink / raw) To: Kevin Wolf; +Cc: qemu-ppc@nongnu.org, Mark Cave-Ayland, qemu-devel On 24.06.14 13:22, Kevin Wolf wrote: > Am 24.06.2014 um 13:02 hat Alexander Graf geschrieben: >> The way DBDMA works is that you put in something similar to a >> scatter-gather list: A list of chunks to read / write and where in >> memory those chunks live. DBDMA then goes over its list and does the >> pokes. So for example if the list is >> >> [ memaddr = 0x12000 | len = 500 ] >> [ memaddr = 0x13098 | len = 12 ] >> >> then it reads 500 bytes from IDE, writes them at memory offset >> 0x12000 and after that reads another 12 bytes from IDE and puts them >> at memory offset 0x13098. >> >> The reason we have such complicated code for real DMA is that we >> can't model this easily with our direct block-to-memory API. That >> one can only work on a 512 byte granularity. So when we see >> unaligned accesses like above, we have to split them out and handle >> them lazily. > Wait... What kind of granularity are you talking about? > > We do need disk accesses with a 512 byte granularity, because the API > takes a sector number. This is also what real IDE disks do, they don't > provide byte access. > > However, for the memory, I can't see why you couldn't pass a s/g list > like what you wrote above to the DMA functions. This is not unusual at > all and is the same as ide/pci.c does. There is no 512-byte alignment > needed for the individual s/g list entries, only the total size should > obviously be a multiple of 512 in the general case (otherwise the list > would be too short or too long for the request). > > If this is really what we're talking about, then I think your problem is > just that you try to handle the 500 byte and the 12 byte as individual > requests instead of building up the s/g list and then sending a single > request. The 500 and 12 byte requests can come in as separate requests that require previous requests to have finished. What Mac OS X does for example is [ memaddr = 0x2000 | len = 1024 ] [ memaddr = 0x1000 | len = 510 ] <wait for ack> [ memaddr = 0x10fe | len = 2 ] [ memaddr = 0x3000 | len = 2048 ] If it was as simple as creating a working sglist, I would've certainly done so long ago :). Alex ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-24 11:27 ` Alexander Graf @ 2014-06-24 12:07 ` Kevin Wolf 2014-06-24 12:10 ` Alexander Graf 0 siblings, 1 reply; 94+ messages in thread From: Kevin Wolf @ 2014-06-24 12:07 UTC (permalink / raw) To: Alexander Graf; +Cc: qemu-ppc@nongnu.org, Mark Cave-Ayland, qemu-devel Am 24.06.2014 um 13:27 hat Alexander Graf geschrieben: > > On 24.06.14 13:22, Kevin Wolf wrote: > >Am 24.06.2014 um 13:02 hat Alexander Graf geschrieben: > >>The way DBDMA works is that you put in something similar to a > >>scatter-gather list: A list of chunks to read / write and where in > >>memory those chunks live. DBDMA then goes over its list and does the > >>pokes. So for example if the list is > >> > >> [ memaddr = 0x12000 | len = 500 ] > >> [ memaddr = 0x13098 | len = 12 ] > >> > >>then it reads 500 bytes from IDE, writes them at memory offset > >>0x12000 and after that reads another 12 bytes from IDE and puts them > >>at memory offset 0x13098. > >> > >>The reason we have such complicated code for real DMA is that we > >>can't model this easily with our direct block-to-memory API. That > >>one can only work on a 512 byte granularity. So when we see > >>unaligned accesses like above, we have to split them out and handle > >>them lazily. > >Wait... What kind of granularity are you talking about? > > > >We do need disk accesses with a 512 byte granularity, because the API > >takes a sector number. This is also what real IDE disks do, they don't > >provide byte access. > > > >However, for the memory, I can't see why you couldn't pass a s/g list > >like what you wrote above to the DMA functions. This is not unusual at > >all and is the same as ide/pci.c does. There is no 512-byte alignment > >needed for the individual s/g list entries, only the total size should > >obviously be a multiple of 512 in the general case (otherwise the list > >would be too short or too long for the request). > > > >If this is really what we're talking about, then I think your problem is > >just that you try to handle the 500 byte and the 12 byte as individual > >requests instead of building up the s/g list and then sending a single > >request. > > The 500 and 12 byte requests can come in as separate requests that > require previous requests to have finished. What Mac OS X does for > example is > > [ memaddr = 0x2000 | len = 1024 ] > [ memaddr = 0x1000 | len = 510 ] > > <wait for ack> > > [ memaddr = 0x10fe | len = 2 ] > [ memaddr = 0x3000 | len = 2048 ] > > If it was as simple as creating a working sglist, I would've > certainly done so long ago :). Thanks, that's the explanation that was missing for me (I'm sure you explained it more than once to me in the past few years, but I keep forgetting). This means, however, that exposing the byte access in the block layer is probably not what you want. Otherwise you would read the same sector twice from the image (assuming cache=none, so the backend must have 512-byte alignment). If you do the handling in the device emulation you can read the full request once and then only do the DMA part with a byte granularity. I suppose this is the complicated code that you have today? Kevin ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-24 12:07 ` Kevin Wolf @ 2014-06-24 12:10 ` Alexander Graf 0 siblings, 0 replies; 94+ messages in thread From: Alexander Graf @ 2014-06-24 12:10 UTC (permalink / raw) To: Kevin Wolf; +Cc: qemu-ppc@nongnu.org, Mark Cave-Ayland, qemu-devel On 24.06.14 14:07, Kevin Wolf wrote: > Am 24.06.2014 um 13:27 hat Alexander Graf geschrieben: >> On 24.06.14 13:22, Kevin Wolf wrote: >>> Am 24.06.2014 um 13:02 hat Alexander Graf geschrieben: >>>> The way DBDMA works is that you put in something similar to a >>>> scatter-gather list: A list of chunks to read / write and where in >>>> memory those chunks live. DBDMA then goes over its list and does the >>>> pokes. So for example if the list is >>>> >>>> [ memaddr = 0x12000 | len = 500 ] >>>> [ memaddr = 0x13098 | len = 12 ] >>>> >>>> then it reads 500 bytes from IDE, writes them at memory offset >>>> 0x12000 and after that reads another 12 bytes from IDE and puts them >>>> at memory offset 0x13098. >>>> >>>> The reason we have such complicated code for real DMA is that we >>>> can't model this easily with our direct block-to-memory API. That >>>> one can only work on a 512 byte granularity. So when we see >>>> unaligned accesses like above, we have to split them out and handle >>>> them lazily. >>> Wait... What kind of granularity are you talking about? >>> >>> We do need disk accesses with a 512 byte granularity, because the API >>> takes a sector number. This is also what real IDE disks do, they don't >>> provide byte access. >>> >>> However, for the memory, I can't see why you couldn't pass a s/g list >>> like what you wrote above to the DMA functions. This is not unusual at >>> all and is the same as ide/pci.c does. There is no 512-byte alignment >>> needed for the individual s/g list entries, only the total size should >>> obviously be a multiple of 512 in the general case (otherwise the list >>> would be too short or too long for the request). >>> >>> If this is really what we're talking about, then I think your problem is >>> just that you try to handle the 500 byte and the 12 byte as individual >>> requests instead of building up the s/g list and then sending a single >>> request. >> The 500 and 12 byte requests can come in as separate requests that >> require previous requests to have finished. What Mac OS X does for >> example is >> >> [ memaddr = 0x2000 | len = 1024 ] >> [ memaddr = 0x1000 | len = 510 ] >> >> <wait for ack> >> >> [ memaddr = 0x10fe | len = 2 ] >> [ memaddr = 0x3000 | len = 2048 ] >> >> If it was as simple as creating a working sglist, I would've >> certainly done so long ago :). > Thanks, that's the explanation that was missing for me (I'm sure you > explained it more than once to me in the past few years, but I keep > forgetting). > > This means, however, that exposing the byte access in the block layer is > probably not what you want. Otherwise you would read the same sector > twice from the image (assuming cache=none, so the backend must have > 512-byte alignment). If you do the handling in the device emulation you > can read the full request once and then only do the DMA part with a byte > granularity. I suppose this is the complicated code that you have today? Yes and no. We are trying to be slightly smarter than that. For all the aligned pieces in between the just have a fast path doing straight DMA to/from memory. For the tiny unaligned chunks, we read into a temporary buffer and do DMA byte-wise from that one manually. For writes it's the reverse - we only issue the full sector IDE transfer after our temporary buffer is fully filled. I think it's perfectly reasonable to read the sector twice from the image though if that makes the DBDMA emulation code easier to maintain ;). Right now there are just way too many tiny corner cases lingering. Alex ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-24 10:53 ` BALATON Zoltan 2014-06-24 11:02 ` Alexander Graf @ 2014-06-25 20:17 ` Mark Cave-Ayland 2014-06-25 21:48 ` BALATON Zoltan 1 sibling, 1 reply; 94+ messages in thread From: Mark Cave-Ayland @ 2014-06-25 20:17 UTC (permalink / raw) To: BALATON Zoltan Cc: Kevin Wolf, qemu-ppc@nongnu.org, Alexander Graf, qemu-devel On 24/06/14 11:53, BALATON Zoltan wrote: >> All I can say is that debugging this stuff isn't easy, particularly >> with MorphOS which has some rather unusual behaviours. But what we >> really need from you now over the next few days is for you to compare >> the debug output between the working and non-working cases and figure >> out if we can fix this in time for the 2.1 release. You have >> everything you need (including my acceptance test of booting both >> MorphOS and Darwin ISOs), so time to take a deep breath and begin what >> should be a challenging yet ultimately rewarding debugging process :) > > I'm still working on finding a solution for the exception problems with > OpenBIOS that prevent MorphOS from working and I failed to understand > the whole working of macio, DBDMA and the whole block layer so far but I > can try to debug it. Can you tell how to reproduce the problem with > Darwin? The Darwin images don't seem to work with -M mac99 either before > or after the patch so no regressions there. It's fairly simple to reproduce here: qemu-system-ppc -M g3beige -cdrom darwinppc-602.iso -boot d qemu-system-ppc -M g3beige -cdrom darwinppc-801.iso -boot d qemu-system-ppc -M mac99 -cdrom darwinppc-801.iso -boot d For -M g3beige then darwinppc-602.iso tends to hang just after the "ADB present" line just before it finds the CDROM. Rather annoyingly it seems to be a lot trickier to reproduce today than it was with my original tests, currently 1 in 8 boots compared to 1 in 3 when I did the OpenBIOS tests. Delays introduced by enabling debugging in pmac_ide_transfer() seem to make it easier to trigger, as does compiling with -O0 -g (slower) and also dropping the kernel FS cache. Maybe it's an existing timing bug that happens to be exacerbated by the patch? :/ Notes: Darwin 6.02 doesn't support -M mac99 (always hangs) AFAICT. Darwin 8.01 works but with -M mac99 IDE detection can take up to 30s or so. ATB, Mark. ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-25 20:17 ` Mark Cave-Ayland @ 2014-06-25 21:48 ` BALATON Zoltan 0 siblings, 0 replies; 94+ messages in thread From: BALATON Zoltan @ 2014-06-25 21:48 UTC (permalink / raw) To: Mark Cave-Ayland Cc: Kevin Wolf, qemu-ppc@nongnu.org, Alexander Graf, qemu-devel On Wed, 25 Jun 2014, Mark Cave-Ayland wrote: > On 24/06/14 11:53, BALATON Zoltan wrote: >>> All I can say is that debugging this stuff isn't easy, particularly >>> with MorphOS which has some rather unusual behaviours. But what we >>> really need from you now over the next few days is for you to compare >>> the debug output between the working and non-working cases and figure >>> out if we can fix this in time for the 2.1 release. You have >>> everything you need (including my acceptance test of booting both >>> MorphOS and Darwin ISOs), so time to take a deep breath and begin what >>> should be a challenging yet ultimately rewarding debugging process :) >> >> I'm still working on finding a solution for the exception problems with >> OpenBIOS that prevent MorphOS from working and I failed to understand >> the whole working of macio, DBDMA and the whole block layer so far but I >> can try to debug it. Can you tell how to reproduce the problem with >> Darwin? The Darwin images don't seem to work with -M mac99 either before >> or after the patch so no regressions there. > > It's fairly simple to reproduce here: > > qemu-system-ppc -M g3beige -cdrom darwinppc-602.iso -boot d > qemu-system-ppc -M g3beige -cdrom darwinppc-801.iso -boot d > qemu-system-ppc -M mac99 -cdrom darwinppc-801.iso -boot d > > For -M g3beige then darwinppc-602.iso tends to hang just after the "ADB > present" line just before it finds the CDROM. > > Rather annoyingly it seems to be a lot trickier to reproduce today than it > was with my original tests, currently 1 in 8 boots compared to 1 in 3 when I > did the OpenBIOS tests. Delays introduced by enabling debugging in > pmac_ide_transfer() seem to make it easier to trigger, as does compiling with > -O0 -g (slower) and also dropping the kernel FS cache. > > Maybe it's an existing timing bug that happens to be exacerbated by the > patch? :/ For me darwinppc-602.iso seems to more consistently hang although it did boot once but I had no debug logs that time. The diff between a boot with the last two patches reverted (your non-block ATAPI patch and Alex's async remainder) and HEAD shows this in case it gives a hint to someone: --- debug-console.log.nopatch +++ debug-console.log.fail ATAPI limit=0x0 packet: bb 00 ff ff 00 00 00 00 00 00 00 00 ATAPI limit=0xfffe packet: 43 02 00 00 00 00 00 ff fe 80 00 00 reply: tx_size=48 elem_tx_size=0 index=0 byte_count_limit=65534 status=0x58 reply: tx_size=0 elem_tx_size=0 index=48 status=0x50 ATAPI limit=0x30 packet: 43 02 00 00 00 00 00 00 30 80 00 00 reply: tx_size=48 elem_tx_size=0 index=0 byte_count_limit=48 status=0x58 reply: tx_size=0 elem_tx_size=0 index=48 status=0x50 DBDMA: readl 0x0000000000000d04 => 0x00000000 DBDMA: channel 0x1a reg 0x1 DBDMA: writel 0x0000000000000d08 <= 0x00000000 DBDMA: channel 0x1a reg 0x2 DBDMA: writel 0x0000000000000d0c <= 0x011f8010 DBDMA: channel 0x1a reg 0x3 DBDMA: dbdma_cmdptr_load 0x011f8010 DBDMA: writel 0x0000000000000d00 <= 0x90009000 DBDMA: channel 0x1a reg 0x0 DBDMA: status 0x00009400 DBDMA: DBDMA_run_bh DBDMA: channel_run -dbdma_cmd 0x7fc7142f0560 +dbdma_cmd 0x7f58257f4b48 req_count 0x0930 command 0x2000 - phy_addr 0x017ca000 + phy_addr 0x017cb000 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: start_input -DBDMA: addr 0x17ca000 key 0x0 +DBDMA: addr 0x17cb000 key 0x0 -waiting for data (0x3 - 0x930 - 50) -ATAPI limit=0x930 packet: be 00 00 00 00 00 00 00 01 f8 00 00 -read dma: LBA=0 nb_sectors=1 - -DBDMA: DBDMA_run_bh -DBDMA: channel_run -dbdma_cmd 0x7fc7142f0560 - req_count 0x0930 - command 0x2000 - phy_addr 0x017ca000 - cmd_dep 0x00000000 - res_count 0x0000 - xfer_status 0x0000 -DBDMA: start_input -DBDMA: addr 0x17ca000 key 0x0 - -io_buffer_size = 0 -remainder: 0 io->len: 2352 size: 2352 -precopying unaligned 304 bytes to 0x17ca800 -io->len = 0x800 -set remainder to: 0 -sector_num=0 size=2352, cmd_cmd=0 -io_buffer_size = 0x930 -remainder: 0 io->len: 0 size: 0 -end of transfer -end of DMA -done DMA +non-block ATAPI DMA transfer size: 0 +end of non-block ATAPI DMA transfer DBDMA: dbdma_end DBDMA: conditional_wait DBDMA: dbdma_cmdptr_save 0x011f8010 -DBDMA: xfer_status 0x00008400 res_count 0x0000 +DBDMA: xfer_status 0x00008400 res_count 0x0930 DBDMA: conditional_interrupt DBDMA: conditional_branch DBDMA: dbdma_cmdptr_load 0x011f8020 DBDMA: channel_run -dbdma_cmd 0x7fc7142f0560 +dbdma_cmd 0x7f58257f4b48 req_count 0x0000 command 0x6030 phy_addr 0x00000000 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 DBDMA: conditional_wait DBDMA: dbdma_cmdptr_save 0x011f8020 DBDMA: xfer_status 0x00008400 res_count 0x0000 DBDMA: conditional_interrupt DBDMA: conditional_interrupt: raise DBDMA: conditional_branch DBDMA: dbdma_cmdptr_load 0x011f8030 DBDMA: DBDMA_run_bh DBDMA: channel_run -dbdma_cmd 0x7fc7142f0560 +dbdma_cmd 0x7f58257f4b48 req_count 0x0000 command 0x7000 phy_addr 0x00000000 cmd_dep 0x00000000 res_count 0x0000 xfer_status 0x0000 -DBDMA: writel 0x0000000000000d00 <= 0xa0002000 -DBDMA: channel 0x1a reg 0x0 -DBDMA: status 0x00000000 -DBDMA: readl 0x0000000000000d04 => 0x00000000 -DBDMA: channel 0x1a reg 0x1 -DBDMA: readl 0x0000000000000d04 => 0x00000000 -DBDMA: channel 0x1a reg 0x1 -DBDMA: writel 0x0000000000000d08 <= 0x00000000 -DBDMA: channel 0x1a reg 0x2 -DBDMA: writel 0x0000000000000d0c <= 0x011f8010 -DBDMA: channel 0x1a reg 0x3 -DBDMA: dbdma_cmdptr_load 0x011f8010 -DBDMA: writel 0x0000000000000d00 <= 0x90009000 -DBDMA: channel 0x1a reg 0x0 -DBDMA: status 0x00009400 -DBDMA: DBDMA_run_bh -DBDMA: channel_run -dbdma_cmd 0x7fc7142f0560 - req_count 0x0800 - command 0x2000 - phy_addr 0x01526800 - cmd_dep 0x00000000 - res_count 0x0000 - xfer_status 0x0000 -DBDMA: start_input -DBDMA: addr 0x1526800 key 0x0 - -waiting for data (0x1 - 0x800 - 58) -ATAPI limit=0x800 packet: 28 00 00 00 00 00 00 00 01 00 00 00 +ATAPI limit=0x930 packet: be 00 00 00 00 00 00 00 01 f8 00 00 read dma: LBA=0 nb_sectors=1 DBDMA: DBDMA_run_bh -DBDMA: channel_run -dbdma_cmd 0x7fc7142f0560 - req_count 0x0800 - command 0x2000 - phy_addr 0x01526800 - cmd_dep 0x00000000 - res_count 0x0000 - xfer_status 0x0000 -DBDMA: start_input -DBDMA: addr 0x1526800 key 0x0 - -io_buffer_size = 0 -remainder: 0 io->len: 2048 size: 2048 -io->len = 0x800 -set remainder to: 0 -sector_num=0 size=2048, cmd_cmd=0 -io_buffer_size = 0x800 -remainder: 0 io->len: 0 size: 0 -end of transfer -end of DMA -done DMA -DBDMA: dbdma_end -DBDMA: conditional_wait -DBDMA: dbdma_cmdptr_save 0x011f8010 -DBDMA: xfer_status 0x00008400 res_count 0x0000 -DBDMA: conditional_interrupt -DBDMA: conditional_branch I'm not sure but could it be that it mistakes a transfer to a non-block transfer for some reason? > Notes: > Darwin 6.02 doesn't support -M mac99 (always hangs) AFAICT. > Darwin 8.01 works but with -M mac99 IDE detection can take up to 30s or so. I thought both of these hung but I did not wait 30 seconds. Regards, BALATON Zoltan ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers 2014-06-20 14:29 ` Mark Cave-Ayland 2014-06-20 19:17 ` BALATON Zoltan @ 2014-06-23 21:30 ` BALATON Zoltan 1 sibling, 0 replies; 94+ messages in thread From: BALATON Zoltan @ 2014-06-23 21:30 UTC (permalink / raw) To: Mark Cave-Ayland; +Cc: qemu-ppc@nongnu.org, Alexander Graf, qemu-devel On Fri, 20 Jun 2014, Mark Cave-Ayland wrote: > On 04/06/14 13:44, Alexander Graf wrote: > >> From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> >> >> Currently the macio DMA routines assume that all DMA requests are for >> read/write >> block transfers. This is not always the case for ATAPI, for example when >> requesting a TOC where the response is generated directly in the IDE >> buffer. >> >> Detect these non-block ATAPI DMA transfers (where no lba is specified in >> the >> command) and copy the results directly into RAM as indicated by the DBDMA >> descriptor. This fixes CDROM access under MorphOS. >> >> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> >> Signed-off-by: Alexander Graf <agraf@suse.de> > > I've just done a complete round of OpenBIOS tests and it looks as if this > patch introduces random hang failures (60% or so) into my Darwin image boot > tests. > > The issue seems to be related as to the timing of the DMA callback relative > to reception of the IDE command; if the IDE transfer is invoked first (as > happens in Darwin) then we hang after sending the IDE command which is likely > because the DMA is not being completed correctly. There is also another > difference with MorphOS in that when the IDE transfer callback is invoked > first then s->packet_transfer_size == 0 and so the memory copy would always > copy 0 bytes. > > After some experimentation, I've come up with the attached patch which should > retain the DMA memory copy, but instead invokes a further round of > pmac_ide_atapi_transfer_cb() with io->len == 0 and s->io_buffer_size == 0 > which should terminate the DMA request correctly. At the very least it seems > to fix the hang on boot with my Darwin images. > > Zoltan, please can you test the attached patch to see if this still allows > MorphOS to boot? Also this patch seems to slow down Finnix boot very much. Regards, BALATON Zoltan ^ permalink raw reply [flat|nested] 94+ messages in thread
* Re: [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf ` (74 preceding siblings ...) 2014-06-04 12:44 ` [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers Alexander Graf @ 2014-06-05 19:10 ` Peter Maydell 75 siblings, 0 replies; 94+ messages in thread From: Peter Maydell @ 2014-06-05 19:10 UTC (permalink / raw) To: Alexander Graf; +Cc: qemu-ppc@nongnu.org, QEMU Developers On 4 June 2014 13:43, Alexander Graf <agraf@suse.de> wrote: > Hi Peter, > > This is my current patch queue for ppc. Please pull. > > Alex > > > The following changes since commit e00fcfeab3d452cba3d0a08991a39ab15df66424: > > Merge remote-tracking branch 'remotes/awilliam/tags/vfio-pci-for-qemu-20140602.0' into staging (2014-06-03 14:37:43 +0100) > > are available in the git repository at: > > > git://github.com/agraf/qemu.git tags/signed-ppc-for-upstream > > for you to fetch changes up to fbe4d727461729382e651279388400b1382caac6: > > PPC: spapr: Expose /hypervisor node in device tree (2014-06-04 14:38:17 +0200) Hi. I'm afraid this fails 'make check': TEST: tests/qom-test... (pid=25249) /ppc/qom/ref405ep: OK /ppc/qom/none: OK /ppc/qom/virtex-ml507: OK /ppc/qom/ppce500: Bad address qemu: could not load firmware '(null)' Broken pipe FAIL GTester: last random seed: R02S83419a7cef60f55bf4050349c6e03e1d (pid=25258) /ppc/qom/mpc8544ds: Bad address qemu: could not load firmware '(null)' Broken pipe FAIL GTester: last random seed: R02Sc9c3ce565772a4200caed8dc47dae1c6 (pid=25262) /ppc/qom/bamboo: OK /ppc/qom/g3beige: OK /ppc/qom/prep: OK /ppc/qom/mac99: OK /ppc/qom/taihu: OK FAIL: tests/qom-test make: *** [check-qtest-ppc] Error 1 make: Leaving directory `/home/petmay01/linaro/qemu-for-merges/build/all' thanks -- PMM ^ permalink raw reply [flat|nested] 94+ messages in thread
end of thread, other threads:[~2014-06-25 21:49 UTC | newest] Thread overview: 94+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-06-04 12:43 [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 001/118] target-ppc: Fix target_disas Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 002/118] monitor: QEMU Monitor Instruction Disassembly Incorrect for PowerPC LE Mode Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 003/118] Fix typo in eTSEC Ethernet controller Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 004/118] spapr_nvram: Correct max nvram size Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 005/118] target-ppc: extract register length calculation in gdbstub Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 006/118] target-ppc: gdbstub allow byte swapping for reading/writing registers Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 007/118] target-ppc: Create versionless CPU class per family if KVM Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 008/118] target-ppc: Move alias lookup after class lookup Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 009/118] target-ppc: Remove redundant POWER7 declarations Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 010/118] spapr-pci: remove io ports workaround Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 011/118] spapr_pci: Fix number of returned vectors in ibm, change-msi Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 012/118] target-ppc: Eliminate Magic Number MSR Masks Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 013/118] target-ppc: Remove PVR check from migration Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 014/118] mac99: Added FW_CFG_PPC_BUSFREQ to match CLOCKFREQ and TBFREQ already there Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 015/118] libdecnumber: Introduce libdecnumber Code Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 016/118] libdecnumber: Eliminate #include *Symbols.h Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 017/118] libdecnumber: Prepare libdecnumber for QEMU include structure Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 018/118] libdecnumber: Modify dconfig.h to Integrate with QEMU Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 019/118] libdecnumber: Change gstdint.h to stdint.h Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 020/118] libdecnumber: Eliminate redundant declarations Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 021/118] libdecnumber: Eliminate Unused Variable in decSetSubnormal Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 022/118] target-ppc: Enable Building of libdecnumber Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 023/118] libdecnumber: Introduce decNumberFrom[U]Int64 Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 024/118] libdecnumber: Introduce decNumberIntegralToInt64 Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 025/118] libdecnumber: Fix decNumberSetBCD Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 026/118] target-ppc: Define FPR Pointer Type for Helpers Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 027/118] target-ppc: Introduce Generator Macros for DFP Arithmetic Forms Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 028/118] target-ppc: Introduce Decoder Macros for DFP Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 029/118] target-ppc: Introduce DFP Helper Utilities Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 030/118] target-ppc: Introduce DFP Post Processor Utilities Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 031/118] target-ppc: Introduce DFP Add Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 032/118] target-ppc: Introduce DFP Subtract Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 033/118] target-ppc: Introduce DFP Multiply Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 034/118] target-ppc: Introduce DFP Divide Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 035/118] target-ppc: Introduce DFP Compares Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 036/118] target-ppc: Introduce DFP Test Data Class Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 037/118] target-ppc: Introduce DFP Test Data Group Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 038/118] target-ppc: Introduce DFP Test Exponent Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 039/118] target-ppc: Introduce DFP Test Significance Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 040/118] target-ppc: Introduce DFP Quantize Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 041/118] target-ppc: Introduce DFP Reround Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 042/118] target-ppc: Introduce DFP Round to Integer Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 043/118] target-ppc: Introduce DFP Convert to Long/Extended Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 044/118] target-ppc: Introduce Round to DFP Short/Long Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 045/118] target-ppc: Introduce DFP Convert to Fixed Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 046/118] " Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 047/118] target-ppc: Introduce DFP Decode DPD to BCD Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 048/118] target-ppc: Introduce DFP Encode BCD to DPD Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 049/118] target-ppc: Introduce DFP Extract Biased Exponent Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 050/118] target-ppc: Introduce DFP Insert " Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 051/118] target-ppc: Introduce DFP Shift Significand Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 052/118] spapr_pci: fix MSI limit Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 053/118] util: Add S-Box and InvS-Box Arrays to Common AES Utils Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 054/118] util: Add AES ShiftRows and InvShiftRows Tables Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 055/118] util: Add InvMixColumns Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 056/118] target-i386: Use Common ShiftRows and InvShiftRows Tables Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 057/118] target-arm: Use Common Tables in AES Instructions Alexander Graf 2014-06-04 12:43 ` [Qemu-devel] [PULL 058/118] target-ppc: Refactor " Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 059/118] KVM: PPC: Don't secretly add 1T segment feature to CPU Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 060/118] PPC: e500: some pci related cleanup Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 061/118] PPC: e500: implement PCI INTx routing Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 062/118] PPC: Fix TCG chunks that don't free their temps Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 063/118] PPC: Fail on leaking temporaries Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 064/118] PPC: Make all e500 CPUs SVR aware Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 065/118] PPC: Add definitions for GIVORs Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 066/118] PPC: Fix SPR access control of L1CFG0 Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 067/118] PPC: Add L1CFG1 SPR emulation Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 068/118] PPC: Properly emulate L1CSR0 and L1CSR1 Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 069/118] PPC: Add dcbtls emulation Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 070/118] PPC: e500: Expose kernel load address in dt Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 071/118] PPC: Add u-boot firmware for e500 Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 072/118] PPC: e500: Move to u-boot as firmware Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 073/118] spapr: Add support for time base offset migration Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 074/118] spapr: Add ibm, chip-id property in device tree Alexander Graf 2014-06-04 12:44 ` [Qemu-devel] [PULL 075/118] macio: handle non-block ATAPI DMA transfers Alexander Graf 2014-06-20 14:29 ` Mark Cave-Ayland 2014-06-20 19:17 ` BALATON Zoltan 2014-06-20 19:27 ` Mark Cave-Ayland 2014-06-21 0:57 ` BALATON Zoltan 2014-06-23 16:31 ` Alexander Graf 2014-06-23 19:26 ` BALATON Zoltan 2014-06-23 22:41 ` Mark Cave-Ayland 2014-06-24 10:35 ` Kevin Wolf 2014-06-24 10:53 ` BALATON Zoltan 2014-06-24 11:02 ` Alexander Graf 2014-06-24 11:22 ` Kevin Wolf 2014-06-24 11:27 ` Alexander Graf 2014-06-24 12:07 ` Kevin Wolf 2014-06-24 12:10 ` Alexander Graf 2014-06-25 20:17 ` Mark Cave-Ayland 2014-06-25 21:48 ` BALATON Zoltan 2014-06-23 21:30 ` BALATON Zoltan 2014-06-05 19:10 ` [Qemu-devel] [PULL 00/118] ppc patch queue 2014-06-04 Peter Maydell
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).